summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/templates/build-msvc.yml2
-rw-r--r--CMakeLists.txt78
-rw-r--r--dist/icons/overlay/arrow_left.pngbin0 -> 1490 bytes
-rw-r--r--dist/icons/overlay/arrow_left_dark.pngbin0 -> 712 bytes
-rw-r--r--dist/icons/overlay/arrow_right.pngbin0 -> 1394 bytes
-rw-r--r--dist/icons/overlay/arrow_right_dark.pngbin0 -> 683 bytes
-rw-r--r--dist/icons/overlay/button_A.pngbin0 -> 3494 bytes
-rw-r--r--dist/icons/overlay/button_A_dark.pngbin0 -> 3167 bytes
-rw-r--r--dist/icons/overlay/button_B.pngbin0 -> 3375 bytes
-rw-r--r--dist/icons/overlay/button_B_dark.pngbin0 -> 2975 bytes
-rw-r--r--dist/icons/overlay/button_L.pngbin0 -> 796 bytes
-rw-r--r--dist/icons/overlay/button_L_dark.pngbin0 -> 745 bytes
-rw-r--r--dist/icons/overlay/button_R.pngbin0 -> 1841 bytes
-rw-r--r--dist/icons/overlay/button_R_dark.pngbin0 -> 1835 bytes
-rw-r--r--dist/icons/overlay/button_X.pngbin0 -> 3968 bytes
-rw-r--r--dist/icons/overlay/button_X_dark.pngbin0 -> 3530 bytes
-rw-r--r--dist/icons/overlay/button_Y.pngbin0 -> 3337 bytes
-rw-r--r--dist/icons/overlay/button_Y_dark.pngbin0 -> 2883 bytes
-rw-r--r--dist/icons/overlay/button_minus.pngbin0 -> 2401 bytes
-rw-r--r--dist/icons/overlay/button_minus_dark.pngbin0 -> 1969 bytes
-rw-r--r--dist/icons/overlay/button_plus.pngbin0 -> 2497 bytes
-rw-r--r--dist/icons/overlay/button_plus_dark.pngbin0 -> 2066 bytes
-rw-r--r--dist/icons/overlay/button_press_stick.pngbin0 -> 5225 bytes
-rw-r--r--dist/icons/overlay/button_press_stick_dark.pngbin0 -> 3636 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon.pngbin0 -> 7312 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon_dark.pngbin0 -> 5889 bytes
-rw-r--r--dist/icons/overlay/controller_handheld.pngbin0 -> 4645 bytes
-rw-r--r--dist/icons/overlay/controller_handheld_dark.pngbin0 -> 3745 bytes
-rw-r--r--dist/icons/overlay/controller_pro.pngbin0 -> 9493 bytes
-rw-r--r--dist/icons/overlay/controller_pro_dark.pngbin0 -> 7488 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left.pngbin0 -> 7489 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_a.pngbin0 -> 2609 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_a_dark.pngbin0 -> 2564 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_b.pngbin0 -> 2559 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_b_dark.pngbin0 -> 2383 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_dark.pngbin0 -> 6768 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_x.pngbin0 -> 2541 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_x_dark.pngbin0 -> 2392 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_y.pngbin0 -> 2641 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_y_dark.pngbin0 -> 2639 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right.pngbin0 -> 7497 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right_dark.pngbin0 -> 6729 bytes
-rw-r--r--dist/icons/overlay/osk_button_B.pngbin0 -> 741 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_dark.pngbin0 -> 767 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_dark_disabled.pngbin0 -> 781 bytes
-rw-r--r--dist/icons/overlay/osk_button_B_disabled.pngbin0 -> 791 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y.pngbin0 -> 726 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_dark.pngbin0 -> 502 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_dark_disabled.pngbin0 -> 694 bytes
-rw-r--r--dist/icons/overlay/osk_button_Y_disabled.pngbin0 -> 699 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace.pngbin0 -> 2919 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace_dark.pngbin0 -> 2958 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus.pngbin0 -> 626 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_dark.pngbin0 -> 676 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_dark_disabled.pngbin0 -> 645 bytes
-rw-r--r--dist/icons/overlay/osk_button_plus_disabled.pngbin0 -> 664 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift.pngbin0 -> 1876 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_dark.pngbin0 -> 2003 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_lock_off.pngbin0 -> 281 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_lock_on.pngbin0 -> 274 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_on.pngbin0 -> 1573 bytes
-rw-r--r--dist/icons/overlay/osk_button_shift_on_dark.pngbin0 -> 1937 bytes
-rw-r--r--dist/icons/overlay/overlay.qrc64
-rw-r--r--dist/qt_themes/default/style.qss377
-rw-r--r--dist/qt_themes/qdarkstyle/style.qss399
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qss439
-rw-r--r--externals/CMakeLists.txt10
m---------externals/dynarmic0
-rw-r--r--externals/find-modules/FindLibzip.cmake72
-rw-r--r--externals/find-modules/Findlibzip.cmake72
-rw-r--r--externals/find-modules/Findopus.cmake2
-rw-r--r--externals/opus/CMakeLists.txt2
-rw-r--r--src/audio_core/audio_out.cpp2
-rw-r--r--src/audio_core/audio_renderer.cpp2
-rw-r--r--src/audio_core/cubeb_sink.cpp2
-rw-r--r--src/audio_core/stream.cpp2
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/assert.cpp14
-rw-r--r--src/common/assert.h14
-rw-r--r--src/common/common_sizes.h43
-rw-r--r--src/common/logging/backend.cpp28
-rw-r--r--src/common/logging/backend.h4
-rw-r--r--src/common/logging/filter.cpp4
-rw-r--r--src/common/logging/filter.h4
-rw-r--r--src/common/logging/log.h35
-rw-r--r--src/common/logging/text_formatter.cpp4
-rw-r--r--src/common/logging/text_formatter.h4
-rw-r--r--src/common/nvidia_flags.h2
-rw-r--r--src/common/settings.cpp (renamed from src/core/settings.cpp)15
-rw-r--r--src/common/settings.h (renamed from src/core/settings.h)17
-rw-r--r--src/common/settings_input.cpp (renamed from src/input_common/settings.cpp)2
-rw-r--r--src/common/settings_input.h (renamed from src/input_common/settings.h)1
-rw-r--r--src/common/threadsafe_queue.h10
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp37
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp44
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h5
-rw-r--r--src/core/core.cpp13
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/crypto/key_manager.cpp2
-rw-r--r--src/core/file_sys/control_metadata.cpp8
-rw-r--r--src/core/file_sys/control_metadata.h2
-rw-r--r--src/core/file_sys/patch_manager.cpp2
-rw-r--r--src/core/frontend/applets/profile_select.cpp2
-rw-r--r--src/core/frontend/applets/software_keyboard.cpp148
-rw-r--r--src/core/frontend/applets/software_keyboard.h118
-rw-r--r--src/core/frontend/emu_window.cpp2
-rw-r--r--src/core/frontend/framebuffer_layout.cpp2
-rw-r--r--src/core/frontend/input_interpreter.cpp15
-rw-r--r--src/core/frontend/input_interpreter.h3
-rw-r--r--src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc20
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc52
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp164
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.h28
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/secure_monitor.h26
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp8
-rw-r--r--src/core/hle/kernel/hle_ipc.h10
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp43
-rw-r--r--src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp199
-rw-r--r--src/core/hle/kernel/k_memory_layout.cpp166
-rw-r--r--src/core/hle/kernel/k_memory_layout.h397
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp12
-rw-r--r--src/core/hle/kernel/k_memory_manager.h18
-rw-r--r--src/core/hle/kernel/k_memory_region.h350
-rw-r--r--src/core/hle/kernel/k_memory_region_type.h338
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp13
-rw-r--r--src/core/hle/kernel/k_resource_limit.h12
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp22
-rw-r--r--src/core/hle/kernel/k_scheduler.h11
-rw-r--r--src/core/hle/kernel/k_scheduler_lock.h11
-rw-r--r--src/core/hle/kernel/k_scoped_lock.h13
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h4
-rw-r--r--src/core/hle/kernel/k_spin_lock.h6
-rw-r--r--src/core/hle/kernel/k_system_control.cpp42
-rw-r--r--src/core/hle/kernel/k_system_control.h18
-rw-r--r--src/core/hle/kernel/k_thread.h6
-rw-r--r--src/core/hle/kernel/k_trace.h12
-rw-r--r--src/core/hle/kernel/kernel.cpp362
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/kernel/process.cpp26
-rw-r--r--src/core/hle/kernel/process_capability.cpp5
-rw-r--r--src/core/hle/kernel/process_capability.h2
-rw-r--r--src/core/hle/kernel/svc.cpp134
-rw-r--r--src/core/hle/service/acc/acc.cpp17
-rw-r--r--src/core/hle/service/acc/acc_su.cpp36
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp28
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp118
-rw-r--r--src/core/hle/service/am/am.h2
-rw-r--r--src/core/hle/service/am/applets/applets.cpp18
-rw-r--r--src/core/hle/service/am/applets/applets.h10
-rw-r--r--src/core/hle/service/am/applets/controller.cpp5
-rw-r--r--src/core/hle/service/am/applets/controller.h4
-rw-r--r--src/core/hle/service/am/applets/error.cpp5
-rw-r--r--src/core/hle/service/am/applets/error.h4
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp14
-rw-r--r--src/core/hle/service/am/applets/general_backend.h11
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp4
-rw-r--r--src/core/hle/service/am/applets/profile_select.h3
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp1153
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h187
-rw-r--r--src/core/hle/service/am/applets/software_keyboard_types.h295
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp5
-rw-r--r--src/core/hle/service/am/applets/web_browser.h4
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp4
-rw-r--r--src/core/hle/service/apm/controller.cpp2
-rw-r--r--src/core/hle/service/audio/audin_a.cpp8
-rw-r--r--src/core/hle/service/audio/audin_u.cpp14
-rw-r--r--src/core/hle/service/audio/audout_a.cpp12
-rw-r--r--src/core/hle/service/audio/audout_u.cpp6
-rw-r--r--src/core/hle/service/audio/audrec_a.cpp4
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp7
-rw-r--r--src/core/hle/service/audio/audren_a.cpp12
-rw-r--r--src/core/hle/service/audio/audren_u.cpp6
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/audio/codecctl.cpp26
-rw-r--r--src/core/hle/service/audio/hwopus.cpp4
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp2
-rw-r--r--src/core/hle/service/bcat/module.cpp4
-rw-r--r--src/core/hle/service/bpc/bpc.cpp4
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp19
-rw-r--r--src/core/hle/service/btm/btm.cpp1
-rw-r--r--src/core/hle/service/caps/caps_a.cpp1
-rw-r--r--src/core/hle/service/caps/caps_u.cpp1
-rw-r--r--src/core/hle/service/erpt/erpt.cpp7
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp19
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h2
-rw-r--r--src/core/hle/service/friend/friend.cpp14
-rw-r--r--src/core/hle/service/glue/arp.cpp11
-rw-r--r--src/core/hle/service/glue/arp.h2
-rw-r--r--src/core/hle/service/glue/bgtc.cpp27
-rw-r--r--src/core/hle/service/glue/bgtc.h8
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h2
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h2
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h2
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp14
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp108
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/hid/xcd.cpp2
-rw-r--r--src/core/hle/service/ldr/ldr.cpp32
-rw-r--r--src/core/hle/service/nfc/nfc.cpp2
-rw-r--r--src/core/hle/service/nifm/nifm.cpp2
-rw-r--r--src/core/hle/service/nim/nim.cpp99
-rw-r--r--src/core/hle/service/npns/npns.cpp3
-rw-r--r--src/core/hle/service/ns/ns.cpp43
-rw-r--r--src/core/hle/service/ns/pl_u.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp17
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/hle/service/olsc/olsc.cpp1
-rw-r--r--src/core/hle/service/pcie/pcie.cpp2
-rw-r--r--src/core/hle/service/pctl/module.cpp251
-rw-r--r--src/core/hle/service/pctl/module.h19
-rw-r--r--src/core/hle/service/pctl/pctl.cpp5
-rw-r--r--src/core/hle/service/pctl/pctl.h3
-rw-r--r--src/core/hle/service/service.cpp6
-rw-r--r--src/core/hle/service/set/set.cpp2
-rw-r--r--src/core/hle/service/set/set_sys.cpp6
-rw-r--r--src/core/hle/service/sm/sm.cpp9
-rw-r--r--src/core/hle/service/sockets/ethc.cpp1
-rw-r--r--src/core/hle/service/sockets/nsd.cpp1
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp4
-rw-r--r--src/core/hle/service/spl/module.cpp2
-rw-r--r--src/core/hle/service/spl/spl.cpp3
-rw-r--r--src/core/hle/service/time/clock_types.h8
-rw-r--r--src/core/hle/service/time/time.cpp48
-rw-r--r--src/core/hle/service/time/time.h2
-rw-r--r--src/core/hle/service/time/time_manager.cpp8
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp1
-rw-r--r--src/core/hle/service/time/time_zone_types.h4
-rw-r--r--src/core/hle/service/usb/usb.cpp42
-rw-r--r--src/core/hle/service/vi/vi.cpp10
-rw-r--r--src/core/hle/service/wlan/wlan.cpp7
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/perf_stats.cpp2
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/core/telemetry_session.cpp2
-rw-r--r--src/input_common/CMakeLists.txt2
-rwxr-xr-xsrc/input_common/analog_from_button.cpp2
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp2
-rw-r--r--src/input_common/mouse/mouse_input.cpp2
-rw-r--r--src/input_common/mouse/mouse_poller.cpp2
-rw-r--r--src/input_common/sdl/sdl_impl.cpp28
-rw-r--r--src/input_common/sdl/sdl_impl.h4
-rw-r--r--src/input_common/touch_from_button.cpp2
-rw-r--r--src/input_common/udp/client.cpp149
-rw-r--r--src/input_common/udp/client.h44
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h2
-rw-r--r--src/video_core/command_classes/codecs/vp9.cpp16
-rw-r--r--src/video_core/engines/engine_interface.h3
-rw-r--r--src/video_core/engines/fermi_2d.h2
-rw-r--r--src/video_core/engines/kepler_memory.h2
-rw-r--r--src/video_core/engines/maxwell_dma.cpp2
-rw-r--r--src/video_core/engines/maxwell_dma.h2
-rw-r--r--src/video_core/gpu.cpp6
-rw-r--r--src/video_core/gpu.h4
-rw-r--r--src/video_core/gpu_thread.cpp64
-rw-r--r--src/video_core/gpu_thread.h15
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt1
-rw-r--r--src/video_core/host_shaders/StringShaderHeader.cmake22
-rw-r--r--src/video_core/host_shaders/astc_decoder.comp1339
-rw-r--r--src/video_core/host_shaders/source_shader.h.in4
-rw-r--r--src/video_core/macro/macro.cpp2
-rw-r--r--src/video_core/query_cache.h11
-rw-r--r--src/video_core/renderer_base.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/video_core/renderer_opengl/util_shaders.cpp76
-rw-r--r--src/video_core/renderer_opengl/util_shaders.h5
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp333
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h32
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp60
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h19
-rw-r--r--src/video_core/texture_cache/accelerated_swizzle.h4
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp2
-rw-r--r--src/video_core/texture_cache/util.cpp35
-rw-r--r--src/video_core/texture_cache/util.h5
-rw-r--r--src/video_core/textures/astc.cpp1710
-rw-r--r--src/video_core/textures/astc.h124
-rw-r--r--src/video_core/textures/decoders.cpp23
-rw-r--r--src/video_core/textures/decoders.h18
-rw-r--r--src/video_core/textures/texture.cpp2
-rw-r--r--src/video_core/video_core.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp13
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp8
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu/applets/controller.cpp16
-rw-r--r--src/yuzu/applets/controller.h3
-rw-r--r--src/yuzu/applets/error.cpp22
-rw-r--r--src/yuzu/applets/error.h2
-rw-r--r--src/yuzu/applets/software_keyboard.cpp1712
-rw-r--r--src/yuzu/applets/software_keyboard.h283
-rw-r--r--src/yuzu/applets/software_keyboard.ui3503
-rw-r--r--src/yuzu/bootmanager.cpp2
-rw-r--r--src/yuzu/configuration/config.cpp20
-rw-r--r--src/yuzu/configuration/config.h4
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp2
-rw-r--r--src/yuzu/configuration/configuration_shared.h2
-rw-r--r--src/yuzu/configuration/configure_audio.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu.h2
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.h2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp10
-rw-r--r--src/yuzu/configuration/configure_debug.ui29
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp4
-rw-r--r--src/yuzu/configuration/configure_filesystem.cpp2
-rw-r--r--src/yuzu/configuration/configure_general.cpp2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp23
-rw-r--r--src/yuzu/configuration/configure_graphics.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.ui41
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player.h2
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h2
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp11
-rw-r--r--src/yuzu/configuration/configure_motion_touch.h3
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp2
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp4
-rw-r--r--src/yuzu/configuration/configure_service.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.cpp4
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp4
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp2
-rw-r--r--src/yuzu/configuration/configure_web.cpp2
-rw-r--r--src/yuzu/debugger/console.cpp8
-rw-r--r--src/yuzu/debugger/controller.cpp2
-rw-r--r--src/yuzu/main.cpp285
-rw-r--r--src/yuzu/main.h35
-rw-r--r--src/yuzu/util/overlay_dialog.cpp249
-rw-r--r--src/yuzu/util/overlay_dialog.h107
-rw-r--r--src/yuzu/util/overlay_dialog.ui404
-rw-r--r--src/yuzu_cmd/config.cpp6
-rw-r--r--src/yuzu_cmd/default_ini.h6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp2
-rw-r--r--src/yuzu_cmd/yuzu.cpp10
362 files changed, 15464 insertions, 3321 deletions
diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml
index 721179550..74e688c12 100644
--- a/.ci/templates/build-msvc.yml
+++ b/.ci/templates/build-msvc.yml
@@ -8,7 +8,7 @@ steps:
8 displayName: 'Install vulkan-sdk' 8 displayName: 'Install vulkan-sdk'
9- script: python -m pip install --upgrade pip conan 9- script: python -m pip install --upgrade pip conan
10 displayName: 'Install conan' 10 displayName: 'Install conan'
11- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 --config Release -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cd .. 11- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cmake --install . --config Release && cd ..
12 displayName: 'Configure CMake' 12 displayName: 'Configure CMake'
13- task: MSBuild@1 13- task: MSBuild@1
14 displayName: 'Build' 14 displayName: 'Build'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac7c3ce90..a4a6da2e1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,7 @@ project(yuzu)
11# Set bundled sdl2/qt as dependent options. 11# Set bundled sdl2/qt as dependent options.
12# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON 12# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
14CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
14 15
15option(ENABLE_QT "Enable the Qt frontend" ON) 16option(ENABLE_QT "Enable the Qt frontend" ON)
16option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) 17option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
@@ -166,12 +167,12 @@ macro(yuzu_find_packages)
166 # Cmake Pkg Prefix Version Conan Pkg 167 # Cmake Pkg Prefix Version Conan Pkg
167 "Catch2 2.13 catch2/2.13.0" 168 "Catch2 2.13 catch2/2.13.0"
168 "fmt 7.1 fmt/7.1.2" 169 "fmt 7.1 fmt/7.1.2"
169 # can't use until https://github.com/bincrafters/community/issues/1173
170 #"libzip 1.5 libzip/1.5.2@bincrafters/stable"
171 "lz4 1.8 lz4/1.9.2" 170 "lz4 1.8 lz4/1.9.2"
172 "nlohmann_json 3.8 nlohmann_json/3.8.0" 171 "nlohmann_json 3.8 nlohmann_json/3.8.0"
173 "ZLIB 1.2 zlib/1.2.11" 172 "ZLIB 1.2 zlib/1.2.11"
174 "zstd 1.4 zstd/1.4.8" 173 "zstd 1.4 zstd/1.4.8"
174 # can't use opus until AVX check is fixed: https://github.com/yuzu-emu/yuzu/pull/4068
175 #"opus 1.3 opus/1.3.1"
175 ) 176 )
176 177
177 foreach(PACKAGE ${REQUIRED_LIBS}) 178 foreach(PACKAGE ${REQUIRED_LIBS})
@@ -249,22 +250,44 @@ if(ENABLE_QT)
249 if (ENABLE_QT_TRANSLATION) 250 if (ENABLE_QT_TRANSLATION)
250 find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) 251 find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
251 endif() 252 endif()
252 if (NOT Qt5_FOUND)
253 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable")
254 endif()
255endif() 253endif()
256# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package 254# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
257if(ENABLE_SDL2) 255if (ENABLE_SDL2)
258 if(EXISTS ${CMAKE_BINARY_DIR}/sdl2Config.cmake) 256 if (YUZU_USE_BUNDLED_SDL2)
259 include(${CMAKE_BINARY_DIR}/sdl2Config.cmake) 257 # Detect toolchain and platform
260 list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}") 258 if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
261 list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}") 259 set(SDL2_VER "SDL2-2.0.14")
262 endif() 260 else()
263 find_package(SDL2) 261 message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
264 if (NOT SDL2_FOUND) 262 endif()
265 # otherwise add this to the list of libraries to install 263
266 list(APPEND CONAN_REQUIRED_LIBS "sdl2/2.0.14@bincrafters/stable") 264 if (DEFINED SDL2_VER)
265 download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX)
266 endif()
267
268 set(SDL2_FOUND YES)
269 set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers")
270 set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library")
271 set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll")
272
273 add_library(SDL2 INTERFACE)
274 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
275 target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
276 else()
277 find_package(SDL2 REQUIRED)
278
279 # Some installations don't set SDL2_LIBRARIES
280 if("${SDL2_LIBRARIES}" STREQUAL "")
281 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
282 set(SDL2_LIBRARIES "SDL2::SDL2")
283 endif()
284
285 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
286 add_library(SDL2 INTERFACE)
287 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
267 endif() 288 endif()
289else()
290 set(SDL2_FOUND NO)
268endif() 291endif()
269 292
270# Install any missing dependencies with conan install 293# Install any missing dependencies with conan install
@@ -285,9 +308,6 @@ if (CONAN_REQUIRED_LIBS)
285 ) 308 )
286 309
287 conan_check(VERSION 1.24.0 REQUIRED) 310 conan_check(VERSION 1.24.0 REQUIRED)
288 # Add the bincrafters remote
289 conan_add_remote(NAME bincrafters
290 URL https://api.bintray.com/conan/bincrafters/public-conan)
291 311
292 # Manually add iconv to fix a dep conflict between qt and sdl2 312 # Manually add iconv to fix a dep conflict between qt and sdl2
293 # We don't need to add it through find_package or anything since the other two can find it just fine 313 # We don't need to add it through find_package or anything since the other two can find it just fine
@@ -338,11 +358,6 @@ if (CONAN_REQUIRED_LIBS)
338 find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets) 358 find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
339 endif() 359 endif()
340 endif() 360 endif()
341 if(ENABLE_SDL2)
342 list(APPEND CMAKE_MODULE_PATH "${CONAN_SDL2_ROOT_RELEASE}")
343 list(APPEND CMAKE_PREFIX_PATH "${CONAN_SDL2_ROOT_RELEASE}")
344 find_package(SDL2 REQUIRED)
345 endif()
346 361
347endif() 362endif()
348 363
@@ -358,23 +373,6 @@ elseif (TARGET Boost::boost)
358 add_library(boost ALIAS Boost::boost) 373 add_library(boost ALIAS Boost::boost)
359endif() 374endif()
360 375
361if (TARGET sdl2::sdl2)
362 # imported from the conan generated sdl2Config.cmake
363 set_target_properties(sdl2::sdl2 PROPERTIES IMPORTED_GLOBAL TRUE)
364 add_library(SDL2 ALIAS sdl2::sdl2)
365elseif(SDL2_FOUND)
366 # found through the system package manager
367 # Some installations don't set SDL2_LIBRARIES
368 if("${SDL2_LIBRARIES}" STREQUAL "")
369 message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
370 set(SDL2_LIBRARIES "SDL2::SDL2")
371 endif()
372
373 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
374 add_library(SDL2 INTERFACE)
375 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
376endif()
377
378# Ensure libusb is properly configured (based on dolphin libusb include) 376# Ensure libusb is properly configured (based on dolphin libusb include)
379if(NOT APPLE) 377if(NOT APPLE)
380 include(FindPkgConfig) 378 include(FindPkgConfig)
diff --git a/dist/icons/overlay/arrow_left.png b/dist/icons/overlay/arrow_left.png
new file mode 100644
index 000000000..a5d4fecfe
--- /dev/null
+++ b/dist/icons/overlay/arrow_left.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_left_dark.png b/dist/icons/overlay/arrow_left_dark.png
new file mode 100644
index 000000000..f73672a59
--- /dev/null
+++ b/dist/icons/overlay/arrow_left_dark.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_right.png b/dist/icons/overlay/arrow_right.png
new file mode 100644
index 000000000..e47ee94bd
--- /dev/null
+++ b/dist/icons/overlay/arrow_right.png
Binary files differ
diff --git a/dist/icons/overlay/arrow_right_dark.png b/dist/icons/overlay/arrow_right_dark.png
new file mode 100644
index 000000000..91cf83d2c
--- /dev/null
+++ b/dist/icons/overlay/arrow_right_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_A.png b/dist/icons/overlay/button_A.png
new file mode 100644
index 000000000..fd90f8b42
--- /dev/null
+++ b/dist/icons/overlay/button_A.png
Binary files differ
diff --git a/dist/icons/overlay/button_A_dark.png b/dist/icons/overlay/button_A_dark.png
new file mode 100644
index 000000000..d6b5514fa
--- /dev/null
+++ b/dist/icons/overlay/button_A_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_B.png b/dist/icons/overlay/button_B.png
new file mode 100644
index 000000000..e8927addc
--- /dev/null
+++ b/dist/icons/overlay/button_B.png
Binary files differ
diff --git a/dist/icons/overlay/button_B_dark.png b/dist/icons/overlay/button_B_dark.png
new file mode 100644
index 000000000..3acbeddcd
--- /dev/null
+++ b/dist/icons/overlay/button_B_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_L.png b/dist/icons/overlay/button_L.png
new file mode 100644
index 000000000..77838369e
--- /dev/null
+++ b/dist/icons/overlay/button_L.png
Binary files differ
diff --git a/dist/icons/overlay/button_L_dark.png b/dist/icons/overlay/button_L_dark.png
new file mode 100644
index 000000000..c96a5e868
--- /dev/null
+++ b/dist/icons/overlay/button_L_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_R.png b/dist/icons/overlay/button_R.png
new file mode 100644
index 000000000..4e5553954
--- /dev/null
+++ b/dist/icons/overlay/button_R.png
Binary files differ
diff --git a/dist/icons/overlay/button_R_dark.png b/dist/icons/overlay/button_R_dark.png
new file mode 100644
index 000000000..ed13199c4
--- /dev/null
+++ b/dist/icons/overlay/button_R_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_X.png b/dist/icons/overlay/button_X.png
new file mode 100644
index 000000000..fe70fb685
--- /dev/null
+++ b/dist/icons/overlay/button_X.png
Binary files differ
diff --git a/dist/icons/overlay/button_X_dark.png b/dist/icons/overlay/button_X_dark.png
new file mode 100644
index 000000000..b2c83d0c1
--- /dev/null
+++ b/dist/icons/overlay/button_X_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_Y.png b/dist/icons/overlay/button_Y.png
new file mode 100644
index 000000000..ca0de569d
--- /dev/null
+++ b/dist/icons/overlay/button_Y.png
Binary files differ
diff --git a/dist/icons/overlay/button_Y_dark.png b/dist/icons/overlay/button_Y_dark.png
new file mode 100644
index 000000000..0f3e4df25
--- /dev/null
+++ b/dist/icons/overlay/button_Y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_minus.png b/dist/icons/overlay/button_minus.png
new file mode 100644
index 000000000..7b315fe79
--- /dev/null
+++ b/dist/icons/overlay/button_minus.png
Binary files differ
diff --git a/dist/icons/overlay/button_minus_dark.png b/dist/icons/overlay/button_minus_dark.png
new file mode 100644
index 000000000..6dfcdc1b5
--- /dev/null
+++ b/dist/icons/overlay/button_minus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_plus.png b/dist/icons/overlay/button_plus.png
new file mode 100644
index 000000000..4d8090d7d
--- /dev/null
+++ b/dist/icons/overlay/button_plus.png
Binary files differ
diff --git a/dist/icons/overlay/button_plus_dark.png b/dist/icons/overlay/button_plus_dark.png
new file mode 100644
index 000000000..abe8b9c95
--- /dev/null
+++ b/dist/icons/overlay/button_plus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/button_press_stick.png b/dist/icons/overlay/button_press_stick.png
new file mode 100644
index 000000000..6d0254d50
--- /dev/null
+++ b/dist/icons/overlay/button_press_stick.png
Binary files differ
diff --git a/dist/icons/overlay/button_press_stick_dark.png b/dist/icons/overlay/button_press_stick_dark.png
new file mode 100644
index 000000000..757d0ab29
--- /dev/null
+++ b/dist/icons/overlay/button_press_stick_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon.png b/dist/icons/overlay/controller_dual_joycon.png
new file mode 100644
index 000000000..8e8b5ad41
--- /dev/null
+++ b/dist/icons/overlay/controller_dual_joycon.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon_dark.png b/dist/icons/overlay/controller_dual_joycon_dark.png
new file mode 100644
index 000000000..63e03eb4e
--- /dev/null
+++ b/dist/icons/overlay/controller_dual_joycon_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld.png b/dist/icons/overlay/controller_handheld.png
new file mode 100644
index 000000000..deb375011
--- /dev/null
+++ b/dist/icons/overlay/controller_handheld.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld_dark.png b/dist/icons/overlay/controller_handheld_dark.png
new file mode 100644
index 000000000..1f5317aa0
--- /dev/null
+++ b/dist/icons/overlay/controller_handheld_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro.png b/dist/icons/overlay/controller_pro.png
new file mode 100644
index 000000000..67cf86d5c
--- /dev/null
+++ b/dist/icons/overlay/controller_pro.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro_dark.png b/dist/icons/overlay/controller_pro_dark.png
new file mode 100644
index 000000000..7be655b96
--- /dev/null
+++ b/dist/icons/overlay/controller_pro_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left.png b/dist/icons/overlay/controller_single_joycon_left.png
new file mode 100644
index 000000000..340ddc71b
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_a.png b/dist/icons/overlay/controller_single_joycon_left_a.png
new file mode 100644
index 000000000..e0f5c2ad4
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_a.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_a_dark.png b/dist/icons/overlay/controller_single_joycon_left_a_dark.png
new file mode 100644
index 000000000..53e04781e
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_a_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_b.png b/dist/icons/overlay/controller_single_joycon_left_b.png
new file mode 100644
index 000000000..7429450a3
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_b.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_b_dark.png b/dist/icons/overlay/controller_single_joycon_left_b_dark.png
new file mode 100644
index 000000000..3bd97a8eb
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_b_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_dark.png b/dist/icons/overlay/controller_single_joycon_left_dark.png
new file mode 100644
index 000000000..24ed2c44c
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_x.png b/dist/icons/overlay/controller_single_joycon_left_x.png
new file mode 100644
index 000000000..4615172a3
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_x.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_x_dark.png b/dist/icons/overlay/controller_single_joycon_left_x_dark.png
new file mode 100644
index 000000000..119e3091a
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_x_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_y.png b/dist/icons/overlay/controller_single_joycon_left_y.png
new file mode 100644
index 000000000..24421d8b9
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_y.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_y_dark.png b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
new file mode 100644
index 000000000..fdf177c12
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right.png b/dist/icons/overlay/controller_single_joycon_right.png
new file mode 100644
index 000000000..5b8fc0eff
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_right.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right_dark.png b/dist/icons/overlay/controller_single_joycon_right_dark.png
new file mode 100644
index 000000000..afa80e6ef
--- /dev/null
+++ b/dist/icons/overlay/controller_single_joycon_right_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B.png b/dist/icons/overlay/osk_button_B.png
new file mode 100644
index 000000000..f4a041178
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_dark.png b/dist/icons/overlay/osk_button_B_dark.png
new file mode 100644
index 000000000..2d2bffcca
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_dark_disabled.png b/dist/icons/overlay/osk_button_B_dark_disabled.png
new file mode 100644
index 000000000..93c102b1b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_B_disabled.png b/dist/icons/overlay/osk_button_B_disabled.png
new file mode 100644
index 000000000..5900982f6
--- /dev/null
+++ b/dist/icons/overlay/osk_button_B_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y.png b/dist/icons/overlay/osk_button_Y.png
new file mode 100644
index 000000000..b08b4e26b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_dark.png b/dist/icons/overlay/osk_button_Y_dark.png
new file mode 100644
index 000000000..1fba9ca93
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_dark_disabled.png b/dist/icons/overlay/osk_button_Y_dark_disabled.png
new file mode 100644
index 000000000..6ce53f9e4
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_Y_disabled.png b/dist/icons/overlay/osk_button_Y_disabled.png
new file mode 100644
index 000000000..25db07f66
--- /dev/null
+++ b/dist/icons/overlay/osk_button_Y_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace.png b/dist/icons/overlay/osk_button_backspace.png
new file mode 100644
index 000000000..4ad284720
--- /dev/null
+++ b/dist/icons/overlay/osk_button_backspace.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace_dark.png b/dist/icons/overlay/osk_button_backspace_dark.png
new file mode 100644
index 000000000..19ac8847e
--- /dev/null
+++ b/dist/icons/overlay/osk_button_backspace_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus.png b/dist/icons/overlay/osk_button_plus.png
new file mode 100644
index 000000000..5baa5201e
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_dark.png b/dist/icons/overlay/osk_button_plus_dark.png
new file mode 100644
index 000000000..4cadb438b
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_dark_disabled.png b/dist/icons/overlay/osk_button_plus_dark_disabled.png
new file mode 100644
index 000000000..b8eb8dc3d
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_dark_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_plus_disabled.png b/dist/icons/overlay/osk_button_plus_disabled.png
new file mode 100644
index 000000000..c23e9d95d
--- /dev/null
+++ b/dist/icons/overlay/osk_button_plus_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift.png b/dist/icons/overlay/osk_button_shift.png
new file mode 100644
index 000000000..f03e30697
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_dark.png b/dist/icons/overlay/osk_button_shift_dark.png
new file mode 100644
index 000000000..c9cc5cd9a
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_lock_off.png b/dist/icons/overlay/osk_button_shift_lock_off.png
new file mode 100644
index 000000000..585500b3a
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_lock_off.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_lock_on.png b/dist/icons/overlay/osk_button_shift_lock_on.png
new file mode 100644
index 000000000..09077ab01
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_lock_on.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_on.png b/dist/icons/overlay/osk_button_shift_on.png
new file mode 100644
index 000000000..e7c1187f9
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_on.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_shift_on_dark.png b/dist/icons/overlay/osk_button_shift_on_dark.png
new file mode 100644
index 000000000..58e0d9cf4
--- /dev/null
+++ b/dist/icons/overlay/osk_button_shift_on_dark.png
Binary files differ
diff --git a/dist/icons/overlay/overlay.qrc b/dist/icons/overlay/overlay.qrc
new file mode 100644
index 000000000..d5a21ce10
--- /dev/null
+++ b/dist/icons/overlay/overlay.qrc
@@ -0,0 +1,64 @@
1<RCC>
2 <qresource prefix="overlay">
3 <file>arrow_left.png</file>
4 <file>arrow_left_dark.png</file>
5 <file>arrow_right.png</file>
6 <file>arrow_right_dark.png</file>
7 <file>button_minus.png</file>
8 <file>button_minus_dark.png</file>
9 <file>button_plus.png</file>
10 <file>button_plus_dark.png</file>
11 <file>button_A.png</file>
12 <file>button_A_dark.png</file>
13 <file>button_B.png</file>
14 <file>button_B_dark.png</file>
15 <file>button_X.png</file>
16 <file>button_X_dark.png</file>
17 <file>button_Y.png</file>
18 <file>button_Y_dark.png</file>
19 <file>button_L.png</file>
20 <file>button_L_dark.png</file>
21 <file>button_R.png</file>
22 <file>button_R_dark.png</file>
23 <file>button_press_stick.png</file>
24 <file>button_press_stick_dark.png</file>
25 <file>osk_button_B.png</file>
26 <file>osk_button_B_disabled.png</file>
27 <file>osk_button_B_dark.png</file>
28 <file>osk_button_B_dark_disabled.png</file>
29 <file>osk_button_Y.png</file>
30 <file>osk_button_Y_disabled.png</file>
31 <file>osk_button_Y_dark.png</file>
32 <file>osk_button_Y_dark_disabled.png</file>
33 <file>osk_button_backspace.png</file>
34 <file>osk_button_backspace_dark.png</file>
35 <file>osk_button_plus.png</file>
36 <file>osk_button_plus_disabled.png</file>
37 <file>osk_button_plus_dark.png</file>
38 <file>osk_button_plus_dark_disabled.png</file>
39 <file>osk_button_shift.png</file>
40 <file>osk_button_shift_dark.png</file>
41 <file>osk_button_shift_on.png</file>
42 <file>osk_button_shift_on_dark.png</file>
43 <file>osk_button_shift_lock_on.png</file>
44 <file>osk_button_shift_lock_off.png</file>
45 <file>controller_dual_joycon.png</file>
46 <file>controller_dual_joycon_dark.png</file>
47 <file>controller_pro.png</file>
48 <file>controller_pro_dark.png</file>
49 <file>controller_handheld.png</file>
50 <file>controller_handheld_dark.png</file>
51 <file>controller_single_joycon_left.png</file>
52 <file>controller_single_joycon_left_dark.png</file>
53 <file>controller_single_joycon_right.png</file>
54 <file>controller_single_joycon_right_dark.png</file>
55 <file>controller_single_joycon_left_a.png</file>
56 <file>controller_single_joycon_left_a_dark.png</file>
57 <file>controller_single_joycon_left_b.png</file>
58 <file>controller_single_joycon_left_b_dark.png</file>
59 <file>controller_single_joycon_left_x.png</file>
60 <file>controller_single_joycon_left_x_dark.png</file>
61 <file>controller_single_joycon_left_y.png</file>
62 <file>controller_single_joycon_left_y_dark.png</file>
63 </qresource>
64</RCC>
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss
index 836dd25ca..3bc92b69d 100644
--- a/dist/qt_themes/default/style.qss
+++ b/dist/qt_themes/default/style.qss
@@ -281,3 +281,380 @@ QWidget#controllerPlayer7,
281QWidget#controllerPlayer8 { 281QWidget#controllerPlayer8 {
282 background: transparent; 282 background: transparent;
283} 283}
284
285QDialog#QtSoftwareKeyboardDialog,
286QStackedWidget#topOSK {
287 background: rgba(51, 51, 51, .9);
288}
289
290
291QDialog#OverlayDialog,
292QStackedWidget#stackedDialog {
293 background: rgba(51, 51, 51, .7);
294}
295
296QWidget#boxOSK,
297QWidget#lineOSK,
298QWidget#richDialog,
299QWidget#lineDialog {
300 background: transparent;
301}
302
303QStackedWidget#bottomOSK,
304QWidget#contentDialog,
305QWidget#contentRichDialog {
306 background: rgba(240, 240, 240, 1);
307}
308
309QWidget#contentDialog,
310QWidget#contentRichDialog {
311 margin: 5px;
312 border-radius: 6px;
313}
314
315QWidget#buttonsDialog,
316QWidget#buttonsRichDialog {
317 margin: 5px;
318 border-top: 2px solid rgba(44, 44, 44, 1);
319}
320
321QWidget#legendOSKnum {
322 border-top: 1px solid rgba(44, 44, 44, 1);
323}
324
325QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical {
326 background: #cdcdcd;
327 width: 15px;
328 margin: 15px 3px 15px 3px;
329 border: 1px transparent;
330 border-radius: 4px;
331}
332
333QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal {
334 background: #cdcdcd;
335 height: 15px;
336 margin: 3px 15px 3px 15px;
337 border: 1px transparent;
338 border-radius: 4px;
339}
340
341QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle {
342 background: #fff;
343 border-radius: 4px;
344 min-height: 5px;
345 min-width: 5px;
346}
347
348QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line,
349QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
350QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page,
351QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page {
352 background: none;
353}
354
355QWidget#inputOSK {
356 border-bottom: 3px solid rgba(255, 255, 255, .9);
357}
358
359QWidget#inputOSK QLineEdit {
360 background: transparent;
361 border: none;
362 color: #ccc;
363}
364
365QWidget#inputBoxOSK {
366 border: 2px solid rgba(255, 255, 255, .9);
367}
368
369QWidget#inputBoxOSK QTextEdit {
370 background: transparent;
371 border: none;
372 color: #ccc;
373}
374
375QWidget#richDialog QTextBrowser {
376 background: transparent;
377 border: none;
378 padding: 35px 65px;
379}
380
381
382QWidget#lineOSK QLabel#label_header {
383 color: #f0f0f0;
384}
385
386QWidget#lineOSK QLabel#label_sub,
387QWidget#lineOSK QLabel#label_characters,
388QWidget#boxOSK QLabel#label_characters_box {
389 color: #ccc;
390}
391
392QWidget#contentDialog QLabel#label_title,
393QWidget#contentRichDialog QLabel#label_title_rich {
394 color: #888;
395}
396
397QWidget#contentDialog QLabel#label_dialog {
398 padding: 20px 65px;
399}
400
401QWidget#contentDialog QLabel#label_title,
402QWidget#contentRichDialog QLabel#label_title_rich {
403 padding: 0px 65px;
404}
405
406QDialog#OverlayDialog QPushButton {
407 color: rgba(49, 79, 239, 1);
408 background: transparent;
409 border: none;
410 padding: 0px;
411 min-width: 0px;
412}
413
414QDialog#OverlayDialog QPushButton:focus,
415QDialog#OverlayDialog QPushButton:hover {
416 color: rgba(49, 79, 239, 1);
417 background: rgba(255, 255, 255, 1);
418 border: 5px solid rgba(148, 250, 202, 1);
419 border-radius: 6px;
420 outline: none;
421}
422
423QDialog#OverlayDialog QPushButton:pressed {
424 color: rgba(240, 240, 240, 1);
425 background: rgba(150, 150, 150, 1);
426 border: 5px solid rgba(148, 250, 202, 1);
427 border-radius: 6px;
428 outline: none;
429}
430
431QDialog#QtSoftwareKeyboardDialog QPushButton {
432 background: rgba(232, 232, 232, 1);
433 border: 2px solid rgba(240, 240, 240, 1);
434}
435
436QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
437QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
438QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
439QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
440QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
441QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
442 background: rgba(218, 218, 218, 1);
443 border: 2px solid rgba(240, 240, 240, 1);
444}
445
446QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
447QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
448QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
449 color: rgba(240, 240, 240, 1);
450 background: rgba(44, 44, 44, 1);
451 border: 2px solid rgba(240, 240, 240, 1);
452}
453
454QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
455QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
456QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
457 color: rgba(240, 240, 240, 1);
458 background: rgba(49, 79, 239, 1);
459 border: 2px solid rgba(240, 240, 240, 1);
460}
461
462QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
463QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
464QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
465QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
466QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
467QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
468QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
469QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
470QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
471QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
472QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
473QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
474QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
475
476QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
477QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
478QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
479QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
480QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
481QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
482QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
483QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
484QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
485QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
486QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
487QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
488QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
489 color: rgba(0, 0, 0, 1);
490 background: rgba(255, 255, 255, 1);
491 border: 5px solid rgba(148, 250, 202, 1);
492 border-radius: 6px;
493 outline: none;
494}
495
496QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
497QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
498QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
499QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
500QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
501QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
502QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
503QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
504QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
505QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
506QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
507QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
508QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
509 color: rgba(240, 240, 240, 1);
510 background: rgba(150, 150, 150, 1);
511 border: 5px solid rgba(148, 250, 202, 1);
512 border-radius: 6px;
513}
514
515QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
516QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
517QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
518 background-position: right top;
519 background-repeat: no-repeat;
520 background-origin: content;
521 background-image: url(:/overlay/osk_button_B.png);
522 qproperty-icon: url(:/overlay/osk_button_backspace.png);
523 qproperty-iconSize: 36px;
524}
525
526QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
527QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
528 background-position: right top;
529 background-repeat: no-repeat;
530 background-origin: content;
531 background-image: url(:/overlay/osk_button_Y.png);
532}
533
534QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
535QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
536QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
537 background-position: right top;
538 background-repeat: no-repeat;
539 background-origin: content;
540 background-image: url(:/overlay/osk_button_plus.png);
541}
542
543QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
544 background-position: left top;
545 background-repeat: no-repeat;
546 background-origin: content;
547 background-image: url(:/overlay/osk_button_shift_lock_off.png);
548 qproperty-icon: url(:/overlay/osk_button_shift.png);
549 qproperty-iconSize: 36px;
550}
551
552QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
553 background-position: left top;
554 background-repeat: no-repeat;
555 background-origin: content;
556 background-image: url(:/overlay/osk_button_shift_lock_off.png);
557 qproperty-icon: url(:/overlay/osk_button_shift_on.png);
558 qproperty-iconSize: 36px;
559}
560
561QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
562QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
563QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
564QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
565 padding-bottom: 7px;
566}
567
568QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
569 background: transparent;
570 color: #ccc;
571}
572
573QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
574QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
575QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
576 image: url(:/overlay/button_L.png);
577}
578
579QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
580QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
581QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
582 image: url(:/overlay/arrow_left.png);
583}
584
585QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
586QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
587QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
588 image: url(:/overlay/button_R.png);
589}
590
591QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
592QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
593QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
594 image: url(:/overlay/arrow_right.png);
595}
596
597QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
598QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
599 image: url(:/overlay/button_press_stick.png);
600}
601
602QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
603QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
604QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
605 image: url(:/overlay/button_X.png);
606}
607
608QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
609QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
610QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
611 image: url(:/overlay/button_A.png);
612}
613
614QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
615QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
616QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
617QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
618QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
619QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
620QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
621QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
622QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
623QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
624 color: rgba(164, 164, 164, 1);
625 background-color: rgba(218, 218, 218, 1);
626}
627
628QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
629QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
630QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
631QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
632QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
633QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
634QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
635QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
636QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
637QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
638QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
639QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
640QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
641QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
642 color: rgba(164, 164, 164, 1);
643}
644
645QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
646QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
647QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
648 background-image: url(:/overlay/osk_button_plus_disabled.png);
649}
650
651QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
652QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
653QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
654 background-image: url(:/overlay/osk_button_B_disabled.png);
655}
656
657QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
658QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
659 background-image: url(:/overlay/osk_button_Y_disabled.png);
660}
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss
index 2a1e8ddeb..8ce6d75f7 100644
--- a/dist/qt_themes/qdarkstyle/style.qss
+++ b/dist/qt_themes/qdarkstyle/style.qss
@@ -1560,7 +1560,400 @@ QWidget#controllerPlayer8 {
1560 background: transparent; 1560 background: transparent;
1561} 1561}
1562 1562
1563/* touchscreen mapping widget */ 1563QDialog#QtSoftwareKeyboardDialog,
1564TouchScreenPreview { 1564QStackedWidget#topOSK {
1565 qproperty-dotHighlightColor: #3daee9; 1565 background: rgba(41, 41, 41, .9);
1566}
1567
1568
1569QDialog#OverlayDialog,
1570QStackedWidget#stackedDialog {
1571 background: rgba(41, 41, 41, .7);
1572}
1573
1574QWidget#boxOSK,
1575QWidget#lineOSK,
1576QWidget#richDialog,
1577QWidget#lineDialog {
1578 background: transparent;
1579}
1580
1581QStackedWidget#bottomOSK,
1582QWidget#contentDialog,
1583QWidget#contentRichDialog {
1584 background: rgba(71, 69, 71, 1);
1585}
1586
1587QWidget#contentDialog,
1588QWidget#contentRichDialog {
1589 margin: 5px;
1590 border-radius: 6px;
1591}
1592
1593QWidget#buttonsDialog,
1594QWidget#buttonsRichDialog {
1595 margin: 5px;
1596 border-top: 2px solid rgba(255, 255, 255, .9);
1597}
1598
1599QWidget#legendOSKnum {
1600 border-top: 1px solid rgba(255, 255, 255, 1);
1601}
1602
1603QStackedWidget#stackedDialog QTextBrowser QWidget {
1604 background: transparent;
1605}
1606
1607QStackedWidget#stackedDialog QTextBrowser QScrollBar {
1608 background: #2a2929;
1609}
1610
1611QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
1612QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
1613 border-image: none;
1614}
1615
1616QWidget#inputOSK {
1617 border-bottom: 3px solid rgba(255, 255, 255, .9);
1618}
1619
1620QWidget#inputOSK QLineEdit {
1621 background: transparent;
1622 border: none;
1623 color: #ccc;
1624 padding: 0px;
1625}
1626
1627QWidget#inputBoxOSK {
1628 border: 2px solid rgba(255, 255, 255, .9);
1629}
1630
1631QWidget#inputBoxOSK QTextEdit {
1632 background: transparent;
1633 border: none;
1634 color: #ccc;
1635}
1636
1637QWidget#richDialog QTextBrowser {
1638 background: transparent;
1639 border: none;
1640 color: #fff;
1641 padding: 35px 65px;
1642}
1643
1644QWidget#lineOSK QLabel#label_header {
1645 color: #f0f0f0;
1646}
1647
1648QWidget#lineOSK QLabel#label_sub,
1649QWidget#lineOSK QLabel#label_characters,
1650QWidget#contentDialog QLabel#label_title,
1651QWidget#contentRichDialog QLabel#label_title_rich,
1652QWidget#boxOSK QLabel#label_characters_box {
1653 color: #ccc;
1654}
1655
1656QWidget#buttonsDialog,
1657QWidget#buttonsRichDialog,
1658QWidget#mainOSK,
1659QWidget#headerOSK,
1660QWidget#normalOSK,
1661QWidget#shiftOSK,
1662QWidget#numOSK,
1663QWidget#subOSK,
1664QWidget#inputOSK,
1665QWidget#inputBoxOSK,
1666QWidget#charactersOSK,
1667QWidget#charactersBoxOSK,
1668QWidget#legendOSK,
1669QWidget#legendOSK QWidget,
1670QWidget#legendOSKshift,
1671QWidget#legendOSKshift QWidget,
1672QWidget#legendOSKnum,
1673QWidget#legendOSKnum QWidget {
1674 background: transparent;
1675}
1676
1677QWidget#contentDialog QLabel,
1678QWidget#legendOSK QLabel,
1679QWidget#legendOSKshift QLabel,
1680QWidget#legendOSKnum QLabel {
1681 color: rgba(255, 255, 255, 1);
1682}
1683
1684QWidget#contentDialog QLabel#label_dialog {
1685 padding: 20px 65px;
1686}
1687
1688QWidget#contentDialog QLabel#label_title,
1689QWidget#contentRichDialog QLabel#label_title_rich {
1690 padding: 0px 65px;
1691}
1692
1693QDialog#OverlayDialog QPushButton {
1694 color: rgba(1, 253, 201, 1);
1695 background: transparent;
1696 border: none;
1697 padding: 0px;
1698 min-width: 0px;
1699}
1700
1701QDialog#OverlayDialog QPushButton:focus,
1702QDialog#OverlayDialog QPushButton:hover {
1703 color: rgba(1, 253, 201, 1);
1704 background: rgba(58, 61, 66, 1);
1705 border: 5px solid rgba(56, 189, 225, 1);
1706 border-radius: 6px;
1707 outline: none;
1708}
1709
1710QDialog#OverlayDialog QPushButton:pressed {
1711 color: rgba(240, 240, 240, 1);
1712 background: rgba(150, 150, 150, 1);
1713 border: 5px solid rgba(56, 189, 225, 1);
1714 border-radius: 6px;
1715 outline: none;
1716}
1717
1718QDialog#QtSoftwareKeyboardDialog QPushButton {
1719 color: rgba(255, 255, 255, 1);
1720 background: rgba(80, 79, 80, 1);
1721 border: 2px solid rgba(71, 69, 71, 1);
1722 padding: 0px;
1723 min-width: 0px;
1724}
1725
1726QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
1727QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
1728QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
1729QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
1730QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
1731QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
1732 background: rgba(95, 94, 95, 1);
1733 border: 2px solid rgba(71, 69, 71, 1);
1734}
1735
1736QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
1737QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
1738QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
1739 color: rgba(240, 240, 240, 1);
1740 background: rgba(255, 255, 255, 1);
1741 border: 2px solid rgba(71, 69, 71, 1);
1742}
1743
1744QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
1745QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
1746QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
1747 color: rgba(0, 0, 0, 1);
1748 background: rgba(1, 253, 201, 1);
1749 border: 2px solid rgba(71, 69, 71, 1);
1750}
1751
1752QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
1753QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
1754QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
1755QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
1756QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
1757QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
1758QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
1759QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
1760QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
1761QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
1762QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
1763QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
1764QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
1765
1766QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
1767QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
1768QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
1769QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
1770QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
1771QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
1772QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
1773QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
1774QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
1775QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
1776QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
1777QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
1778QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
1779 color: rgba(255, 255, 255, 1);
1780 background: rgba(58, 61, 66, 1);
1781 border: 5px solid rgba(56, 189, 225, 1);
1782 border-radius: 6px;
1783 outline: none;
1784}
1785
1786QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
1787QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
1788QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
1789QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
1790QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
1791QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
1792QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
1793QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
1794QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
1795QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
1796QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
1797QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
1798QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
1799 color: rgba(240, 240, 240, 1);
1800 background: rgba(150, 150, 150, 1);
1801 border: 5px solid rgba(56, 189, 225, 1);
1802 border-radius: 6px;
1803}
1804
1805QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
1806QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
1807QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
1808 background-position: right top;
1809 background-repeat: no-repeat;
1810 background-origin: content;
1811 background-image: url(:/overlay/osk_button_B_dark.png);
1812 qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
1813 qproperty-iconSize: 36px;
1814}
1815
1816QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
1817QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
1818 background-position: right top;
1819 background-repeat: no-repeat;
1820 background-origin: content;
1821 background-image: url(:/overlay/osk_button_Y_dark.png);
1822}
1823
1824QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
1825QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
1826QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
1827 color: rgba(44, 44, 44, 1);
1828 background-position: right top;
1829 background-repeat: no-repeat;
1830 background-origin: content;
1831 background-image: url(:/overlay/osk_button_plus_dark.png);
1832}
1833
1834QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
1835 background-position: left top;
1836 background-repeat: no-repeat;
1837 background-origin: content;
1838 background-image: url(:/overlay/osk_button_shift_lock_off.png);
1839 qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
1840 qproperty-iconSize: 36px;
1841}
1842
1843QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
1844 background-position: left top;
1845 background-repeat: no-repeat;
1846 background-origin: content;
1847 background-image: url(:/overlay/osk_button_shift_lock_off.png);
1848 qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
1849 qproperty-iconSize: 36px;
1850}
1851
1852QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
1853QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
1854QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
1855QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
1856 padding-bottom: 7px;
1857}
1858
1859QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
1860 background: transparent;
1861 color: #ccc;
1862}
1863
1864QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
1865QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
1866QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
1867 image: url(:/overlay/button_L_dark.png);
1868}
1869
1870QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
1871QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
1872QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
1873 image: url(:/overlay/arrow_left_dark.png);
1874}
1875
1876QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
1877QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
1878QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
1879 image: url(:/overlay/button_R_dark.png);
1880}
1881
1882QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
1883QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
1884QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
1885 image: url(:/overlay/arrow_right_dark.png);
1886}
1887
1888QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
1889QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
1890 image: url(:/overlay/button_press_stick_dark.png);
1891}
1892
1893QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
1894QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
1895QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
1896 image: url(:/overlay/button_X_dark.png);
1897}
1898
1899QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
1900QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
1901QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
1902 image: url(:/overlay/button_A_dark.png);
1903}
1904
1905QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
1906QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
1907QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
1908QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
1909QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
1910QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
1911QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
1912QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
1913QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
1914QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
1915 color: rgba(144, 144, 144, 1);
1916 background-color: rgba(95, 94, 95, 1);
1917}
1918
1919QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
1920QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
1921QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
1922QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
1923QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
1924QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
1925QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
1926QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
1927QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
1928QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
1929QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
1930QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
1931QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
1932QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
1933 color: rgba(144, 144, 144, 1);
1934}
1935
1936QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
1937QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
1938QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
1939 background-image: url(:/overlay/osk_button_plus_dark_disabled.png);
1940}
1941
1942QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
1943QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
1944QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
1945 background-image: url(:/overlay/osk_button_B_dark_disabled.png);
1946}
1947
1948QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
1949QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
1950 background-image: url(:/overlay/osk_button_Y_dark_disabled.png);
1951}
1952
1953QDialog#QtSoftwareKeyboardDialog QFrame,
1954QDialog#QtSoftwareKeyboardDialog QFrame[frameShape="0"],
1955QDialog#OverlayDialog QFrame,
1956QDialog#OverlayDialog QFrame[frameShape="0"] {
1957 border-radius: 0px;
1958 border: none;
1566} 1959}
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
index a64037455..64e1ecbcc 100644
--- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
@@ -1,10 +1,10 @@
1/* --------------------------------------------------------------------------- 1/* ---------------------------------------------------------------------------
2 2
3 Created by the qtsass compiler v0.1.1 3 Created by the qtsass compiler v0.1.1
4 4
5 The definitions are in the "qdarkstyle.qss._styles.scss" module 5 The definitions are in the "qdarkstyle.qss._styles.scss" module
6 6
7 WARNING! All changes made in this file will be lost! 7 WARNING! All changes made in this file will be lost!
8 8
9--------------------------------------------------------------------------- */ 9--------------------------------------------------------------------------- */
10/* QDarkStyleSheet ----------------------------------------------------------- 10/* QDarkStyleSheet -----------------------------------------------------------
@@ -15,34 +15,34 @@ It is based on three selecting colors, three greyish (background) colors
15plus three whitish (foreground) colors. Each set of widgets of the same 15plus three whitish (foreground) colors. Each set of widgets of the same
16type have a header like this: 16type have a header like this:
17 17
18 ------------------ 18 ------------------
19 GroupName -------- 19 GroupName --------
20 ------------------ 20 ------------------
21 21
22And each widget is separated with a header like this: 22And each widget is separated with a header like this:
23 23
24 QWidgetName ------ 24 QWidgetName ------
25 25
26This makes more easy to find and change some css field. The basic 26This makes more easy to find and change some css field. The basic
27configuration is described bellow. 27configuration is described bellow.
28 28
29 BACKGROUND ----------- 29 BACKGROUND -----------
30 30
31 Light (unpressed) 31 Light (unpressed)
32 Normal (border, disabled, pressed, checked, toolbars, menus) 32 Normal (border, disabled, pressed, checked, toolbars, menus)
33 Dark (background) 33 Dark (background)
34 34
35 FOREGROUND ----------- 35 FOREGROUND -----------
36 36
37 Light (texts/labels) 37 Light (texts/labels)
38 Normal (not used yet) 38 Normal (not used yet)
39 Dark (disabled texts) 39 Dark (disabled texts)
40 40
41 SELECTION ------------ 41 SELECTION ------------
42 42
43 Light (selection/hover/active) 43 Light (selection/hover/active)
44 Normal (selected) 44 Normal (selected)
45 Dark (selected disabled) 45 Dark (selected disabled)
46 46
47If a stranger configuration is required because of a bugfix or anything 47If a stranger configuration is required because of a bugfix or anything
48else, keep the comment on the line above so nobody changes it, including the 48else, keep the comment on the line above so nobody changes it, including the
@@ -2483,3 +2483,404 @@ QWidget#controllerPlayer7,
2483QWidget#controllerPlayer8 { 2483QWidget#controllerPlayer8 {
2484 background: transparent; 2484 background: transparent;
2485} 2485}
2486
2487QDialog#QtSoftwareKeyboardDialog,
2488QStackedWidget#topOSK {
2489 background: rgba(15, 25, 34, .9);
2490}
2491
2492QDialog#OverlayDialog,
2493QStackedWidget#stackedDialog {
2494 background: rgba(15, 25, 34, .7);
2495}
2496
2497QWidget#boxOSK,
2498QWidget#lineOSK,
2499QWidget#richDialog,
2500QWidget#lineDialog {
2501 background: transparent;
2502}
2503
2504QStackedWidget#bottomOSK,
2505QWidget#contentDialog,
2506QWidget#contentRichDialog {
2507 background: rgba(31, 41, 51, 1);
2508}
2509
2510QWidget#contentDialog,
2511QWidget#contentRichDialog {
2512 margin: 5px;
2513 border-radius: 6px;
2514}
2515
2516QWidget#buttonsDialog,
2517QWidget#buttonsRichDialog {
2518 margin: 5px;
2519 border-top: 2px solid rgba(255, 255, 255, .9);
2520}
2521
2522QWidget#legendOSKnum {
2523 border-top: 1px solid rgba(255, 255, 255, 1);
2524}
2525
2526QStackedWidget#stackedDialog QTextBrowser QWidget {
2527 background: transparent;
2528}
2529
2530QStackedWidget#stackedDialog QTextBrowser QScrollBar {
2531 background: #19232d;
2532 border: none;
2533}
2534
2535QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
2536QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line {
2537 border-image: none;
2538}
2539
2540QWidget#mainOSK QStackedWidget,
2541QDialog#OverlayDialog QStackedWidget {
2542 border: none;
2543 padding: 0px;
2544}
2545
2546QWidget#inputOSK {
2547 border-bottom: 3px solid rgba(255, 255, 255, .9);
2548}
2549
2550QWidget#inputOSK QLineEdit {
2551 background: transparent;
2552 border: none;
2553 color: #ccc;
2554 padding: 0px;
2555}
2556
2557QWidget#inputBoxOSK {
2558 border: 2px solid rgba(255, 255, 255, .9);
2559}
2560
2561QWidget#inputBoxOSK QTextEdit {
2562 background: transparent;
2563 border: none;
2564 color: #ccc;
2565}
2566
2567QWidget#richDialog QTextBrowser {
2568 background: transparent;
2569 border: none;
2570 color: #fff;
2571 padding: 35px 65px;
2572}
2573
2574QWidget#lineOSK QLabel#label_header {
2575 color: #f0f0f0;
2576}
2577
2578QWidget#lineOSK QLabel#label_sub,
2579QWidget#lineOSK QLabel#label_characters,
2580QWidget#contentDialog QLabel#label_title,
2581QWidget#contentRichDialog QLabel#label_title_rich,
2582QWidget#boxOSK QLabel#label_characters_box {
2583 color: #ccc;
2584}
2585
2586QWidget#buttonsDialog,
2587QWidget#buttonsRichDialog,
2588QWidget#mainOSK,
2589QWidget#headerOSK,
2590QWidget#normalOSK,
2591QWidget#shiftOSK,
2592QWidget#numOSK,
2593QWidget#subOSK,
2594QWidget#inputOSK,
2595QWidget#inputBoxOSK,
2596QWidget#charactersOSK,
2597QWidget#charactersBoxOSK,
2598QWidget#legendOSK,
2599QWidget#legendOSK QWidget,
2600QWidget#legendOSKshift,
2601QWidget#legendOSKshift QWidget,
2602QWidget#legendOSKnum,
2603QWidget#legendOSKnum QWidget {
2604 background: transparent;
2605}
2606
2607QWidget#contentDialog QLabel,
2608QWidget#legendOSK QLabel,
2609QWidget#legendOSKshift QLabel,
2610QWidget#legendOSKnum QLabel {
2611 color: rgba(255, 255, 255, 1);
2612}
2613
2614QWidget#contentDialog QLabel#label_dialog {
2615 padding: 20px 65px;
2616}
2617
2618QWidget#contentDialog QLabel#label_title,
2619QWidget#contentRichDialog QLabel#label_title_rich {
2620 padding: 0px 65px;
2621}
2622
2623QDialog#OverlayDialog QPushButton {
2624 color: rgba(1, 253, 201, 1);
2625 background: transparent;
2626 border: none;
2627 padding: 0px;
2628 min-width: 0px;
2629}
2630
2631QDialog#OverlayDialog QPushButton:focus,
2632QDialog#OverlayDialog QPushButton:hover {
2633 color: rgba(1, 253, 201, 1);
2634 background: rgba(18, 33, 46, 1);
2635 border: 5px solid rgba(56, 189, 225, 1);
2636 border-radius: 6px;
2637 outline: none;
2638}
2639
2640QDialog#OverlayDialog QPushButton:pressed {
2641 color: rgba(240, 240, 240, 1);
2642 background: rgba(110, 122, 130, 1);
2643 border: 5px solid rgba(56, 189, 225, 1);
2644 border-radius: 6px;
2645 outline: none;
2646}
2647
2648QDialog#QtSoftwareKeyboardDialog QLabel {
2649 padding: 0px;
2650}
2651
2652QDialog#QtSoftwareKeyboardDialog QPushButton {
2653 color: rgba(255, 255, 255, 1);
2654 background: rgba(40, 51, 60, 1);
2655 border: 2px solid rgba(31, 41, 51, 1);
2656 border-radius: 0px;
2657 padding: 0px;
2658 min-width: 0px;
2659}
2660
2661QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
2662QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
2663QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
2664QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
2665QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
2666QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
2667 background: rgba(55, 66, 75, 1);
2668 border: 2px solid rgba(31, 41, 51, 1);
2669}
2670
2671QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
2672QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
2673QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
2674 color: rgba(240, 240, 240, 1);
2675 background: rgba(255, 255, 255, 1);
2676 border: 2px solid rgba(31, 41, 51, 1);
2677}
2678
2679QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
2680QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
2681QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
2682 color: rgba(0, 0, 0, 1);
2683 background: rgba(1, 253, 201, 1);
2684 border: 2px solid rgba(31, 41, 51, 1);
2685}
2686
2687QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
2688QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
2689QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
2690QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
2691QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
2692QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
2693QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
2694QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
2695QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
2696QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
2697QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
2698QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
2699QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
2700
2701QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
2702QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
2703QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
2704QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
2705QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
2706QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
2707QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
2708QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
2709QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
2710QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
2711QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
2712QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
2713QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
2714 color: rgba(255, 255, 255, 1);
2715 background: rgba(18, 33, 46, 1);
2716 border: 5px solid rgba(56, 189, 225, 1);
2717 border-radius: 6px;
2718 outline: none;
2719}
2720
2721QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
2722QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
2723QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
2724QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
2725QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
2726QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
2727QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
2728QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
2729QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
2730QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
2731QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
2732QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
2733QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
2734 color: rgba(240, 240, 240, 1);
2735 background: rgba(110, 122, 130, 1);
2736 border: 5px solid rgba(56, 189, 225, 1);
2737 border-radius: 6px;
2738}
2739
2740QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
2741QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
2742QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
2743 background-position: right top;
2744 background-repeat: no-repeat;
2745 background-origin: content;
2746 background-image: url(:/overlay/osk_button_B_dark.png);
2747 qproperty-icon: url(:/overlay/osk_button_backspace_dark.png);
2748 qproperty-iconSize: 36px;
2749}
2750
2751QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
2752QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
2753 background-position: right top;
2754 background-repeat: no-repeat;
2755 background-origin: content;
2756 background-image: url(:/overlay/osk_button_Y_dark.png);
2757}
2758
2759QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
2760QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
2761QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
2762 color: rgba(44, 44, 44, 1);
2763 background-position: right top;
2764 background-repeat: no-repeat;
2765 background-origin: content;
2766 background-image: url(:/overlay/osk_button_plus_dark.png);
2767}
2768
2769QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
2770 background-position: left top;
2771 background-repeat: no-repeat;
2772 background-origin: content;
2773 background-image: url(:/overlay/osk_button_shift_lock_off.png);
2774 qproperty-icon: url(:/overlay/osk_button_shift_dark.png);
2775 qproperty-iconSize: 36px;
2776}
2777
2778QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
2779 background-position: left top;
2780 background-repeat: no-repeat;
2781 background-origin: content;
2782 background-image: url(:/overlay/osk_button_shift_lock_off.png);
2783 qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png);
2784 qproperty-iconSize: 36px;
2785}
2786
2787QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
2788QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
2789QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
2790QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
2791 padding-bottom: 7px;
2792}
2793
2794QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
2795 background: transparent;
2796 color: #ccc;
2797}
2798
2799QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
2800QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
2801QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
2802 image: url(:/overlay/button_L_dark.png);
2803}
2804
2805QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
2806QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
2807QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
2808 image: url(:/overlay/arrow_left_dark.png);
2809}
2810
2811QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
2812QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
2813QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
2814 image: url(:/overlay/button_R_dark.png);
2815}
2816
2817QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
2818QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
2819QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
2820 image: url(:/overlay/arrow_right_dark.png);
2821}
2822
2823QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
2824QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
2825 image: url(:/overlay/button_press_stick_dark.png);
2826}
2827
2828QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
2829QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
2830QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
2831 image: url(:/overlay/button_X_dark.png);
2832}
2833
2834QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
2835QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
2836QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
2837 image: url(:/overlay/button_A_dark.png);
2838}
2839
2840QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
2841QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
2842QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
2843QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
2844QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
2845QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
2846QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
2847QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
2848QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
2849QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
2850 color: rgba(144, 144, 144, 1);
2851 background-color: rgba(55, 66, 75, 1);
2852}
2853
2854QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
2855QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
2856QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
2857QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
2858QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
2859QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
2860QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
2861QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
2862QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
2863QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
2864QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
2865QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
2866QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
2867QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
2868 color: rgba(144, 144, 144, 1);
2869}
2870
2871QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
2872QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
2873QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
2874 background-image: url(:/overlay/osk_button_plus_dark_disabled.png);
2875}
2876
2877QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
2878QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
2879QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
2880 background-image: url(:/overlay/osk_button_B_dark_disabled.png);
2881}
2882
2883QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
2884QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
2885 background-image: url(:/overlay/osk_button_Y_dark_disabled.png);
2886}
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index c629bbc5c..891a47c3c 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -64,8 +64,8 @@ endif()
64add_subdirectory(sirit) 64add_subdirectory(sirit)
65 65
66# libzip 66# libzip
67find_package(Libzip 1.5) 67find_package(libzip 1.5)
68if (NOT LIBZIP_FOUND) 68if (NOT libzip_FOUND)
69 message(STATUS "libzip 1.5 or newer not found, falling back to externals") 69 message(STATUS "libzip 1.5 or newer not found, falling back to externals")
70 add_subdirectory(libzip EXCLUDE_FROM_ALL) 70 add_subdirectory(libzip EXCLUDE_FROM_ALL)
71endif() 71endif()
@@ -97,4 +97,8 @@ if (ENABLE_WEB_SERVICE)
97endif() 97endif()
98 98
99# Opus 99# Opus
100add_subdirectory(opus) 100find_package(opus 1.3)
101if (NOT opus_FOUND)
102 message(STATUS "opus 1.3 or newer not found, falling back to externals")
103 add_subdirectory(opus EXCLUDE_FROM_ALL)
104endif()
diff --git a/externals/dynarmic b/externals/dynarmic
Subproject c28f13af9797c0319d9a38b5b5c8470ff906e2c Subproject b2a4da5e65985e6b0a20ac8ac37d14425a2a39d
diff --git a/externals/find-modules/FindLibzip.cmake b/externals/find-modules/FindLibzip.cmake
deleted file mode 100644
index f36b1687a..000000000
--- a/externals/find-modules/FindLibzip.cmake
+++ /dev/null
@@ -1,72 +0,0 @@
1
2find_package(PkgConfig QUIET)
3pkg_check_modules(PC_LIBZIP QUIET libzip)
4
5find_path(LIBZIP_INCLUDE_DIR
6 NAMES zip.h
7 PATHS ${PC_LIBZIP_INCLUDE_DIRS}
8 "$ENV{LIB_DIR}/include"
9 "$ENV{INCLUDE}"
10 /usr/local/include
11 /usr/include
12)
13find_path(LIBZIP_INCLUDE_DIR_ZIPCONF
14 NAMES zipconf.h
15 HINTS ${PC_LIBZIP_INCLUDE_DIRS}
16 "$ENV{LIB_DIR}/include"
17 "$ENV{LIB_DIR}/lib/libzip/include"
18 "$ENV{LIB}/lib/libzip/include"
19 /usr/local/lib/libzip/include
20 /usr/lib/libzip/include
21 /usr/local/include
22 /usr/include
23 "$ENV{INCLUDE}"
24)
25find_library(LIBZIP_LIBRARY
26 NAMES zip
27 PATHS ${PC_LIBZIP_LIBRARY_DIRS}
28 "$ENV{LIB_DIR}/lib" "$ENV{LIB}" /usr/local/lib /usr/lib
29)
30
31if (LIBZIP_INCLUDE_DIR_ZIPCONF)
32 FILE(READ "${LIBZIP_INCLUDE_DIR_ZIPCONF}/zipconf.h" _LIBZIP_VERSION_CONTENTS)
33 if (_LIBZIP_VERSION_CONTENTS)
34 STRING(REGEX REPLACE ".*#define LIBZIP_VERSION \"([0-9.]+)\".*" "\\1" LIBZIP_VERSION "${_LIBZIP_VERSION_CONTENTS}")
35 endif()
36 unset(_LIBZIP_VERSION_CONTENTS)
37endif()
38
39set(LIBZIP_VERSION ${LIBZIP_VERSION} CACHE STRING "Version number of libzip")
40
41include(FindPackageHandleStandardArgs)
42find_package_handle_standard_args(Libzip
43 FOUND_VAR LIBZIP_FOUND
44 REQUIRED_VARS
45 LIBZIP_LIBRARY
46 LIBZIP_INCLUDE_DIR
47 LIBZIP_INCLUDE_DIR_ZIPCONF
48 LIBZIP_VERSION
49 VERSION_VAR LIBZIP_VERSION
50)
51
52if(LIBZIP_FOUND)
53 set(LIBZIP_LIBRARIES ${LIBZIP_LIBRARY})
54 set(LIBZIP_INCLUDE_DIRS ${LIBZIP_INCLUDE_DIR})
55 set(LIBZIP_DEFINITIONS ${PC_LIBZIP_CFLAGS_OTHER})
56endif()
57
58if(LIBZIP_FOUND AND NOT TARGET libzip::libzip)
59 add_library(libzip::libzip UNKNOWN IMPORTED)
60 set_target_properties(libzip::libzip PROPERTIES
61 IMPORTED_LOCATION "${LIBZIP_LIBRARY}"
62 INTERFACE_COMPILE_OPTIONS "${PC_LIBZIP_CFLAGS_OTHER}"
63 INTERFACE_INCLUDE_DIRECTORIES "${LIBZIP_INCLUDE_DIR}"
64 )
65endif()
66
67mark_as_advanced(
68 LIBZIP_INCLUDE_DIR
69 LIBZIP_INCLUDE_DIR_ZIPCONF
70 LIBZIP_LIBRARY
71 LIBZIP_VERSION
72)
diff --git a/externals/find-modules/Findlibzip.cmake b/externals/find-modules/Findlibzip.cmake
new file mode 100644
index 000000000..8934de3b8
--- /dev/null
+++ b/externals/find-modules/Findlibzip.cmake
@@ -0,0 +1,72 @@
1
2find_package(PkgConfig QUIET)
3pkg_check_modules(PC_libzip QUIET libzip)
4
5find_path(libzip_INCLUDE_DIR
6 NAMES zip.h
7 PATHS ${PC_libzip_INCLUDE_DIRS}
8 "$ENV{LIB_DIR}/include"
9 "$ENV{INCLUDE}"
10 /usr/local/include
11 /usr/include
12)
13find_path(libzip_INCLUDE_DIR_ZIPCONF
14 NAMES zipconf.h
15 HINTS ${PC_libzip_INCLUDE_DIRS}
16 "$ENV{LIB_DIR}/include"
17 "$ENV{LIB_DIR}/lib/libzip/include"
18 "$ENV{LIB}/lib/libzip/include"
19 /usr/local/lib/libzip/include
20 /usr/lib/libzip/include
21 /usr/local/include
22 /usr/include
23 "$ENV{INCLUDE}"
24)
25find_library(libzip_LIBRARY
26 NAMES zip
27 PATHS ${PC_libzip_LIBRARY_DIRS}
28 "$ENV{LIB_DIR}/lib" "$ENV{LIB}" /usr/local/lib /usr/lib
29)
30
31if (libzip_INCLUDE_DIR_ZIPCONF)
32 FILE(READ "${libzip_INCLUDE_DIR_ZIPCONF}/zipconf.h" _libzip_VERSION_CONTENTS)
33 if (_libzip_VERSION_CONTENTS)
34 STRING(REGEX REPLACE ".*#define LIBZIP_VERSION \"([0-9.]+)\".*" "\\1" libzip_VERSION "${_libzip_VERSION_CONTENTS}")
35 endif()
36 unset(_libzip_VERSION_CONTENTS)
37endif()
38
39set(libzip_VERSION ${libzip_VERSION} CACHE STRING "Version number of libzip")
40
41include(FindPackageHandleStandardArgs)
42find_package_handle_standard_args(libzip
43 FOUND_VAR libzip_FOUND
44 REQUIRED_VARS
45 libzip_LIBRARY
46 libzip_INCLUDE_DIR
47 libzip_INCLUDE_DIR_ZIPCONF
48 libzip_VERSION
49 VERSION_VAR libzip_VERSION
50)
51
52if(libzip_FOUND)
53 set(libzip_LIBRARIES ${libzip_LIBRARY})
54 set(libzip_INCLUDE_DIRS ${libzip_INCLUDE_DIR})
55 set(libzip_DEFINITIONS ${PC_libzip_CFLAGS_OTHER})
56endif()
57
58if(libzip_FOUND AND NOT TARGET libzip::libzip)
59 add_library(libzip::libzip UNKNOWN IMPORTED)
60 set_target_properties(libzip::libzip PROPERTIES
61 IMPORTED_LOCATION "${libzip_LIBRARY}"
62 INTERFACE_COMPILE_OPTIONS "${PC_libzip_CFLAGS_OTHER}"
63 INTERFACE_INCLUDE_DIRECTORIES "${libzip_INCLUDE_DIR}"
64 )
65endif()
66
67mark_as_advanced(
68 libzip_INCLUDE_DIR
69 libzip_INCLUDE_DIR_ZIPCONF
70 libzip_LIBRARY
71 libzip_VERSION
72)
diff --git a/externals/find-modules/Findopus.cmake b/externals/find-modules/Findopus.cmake
index de84bd995..2bce56122 100644
--- a/externals/find-modules/Findopus.cmake
+++ b/externals/find-modules/Findopus.cmake
@@ -28,7 +28,7 @@ if(opus_FOUND)
28endif() 28endif()
29 29
30if(opus_FOUND AND NOT TARGET Opus::Opus) 30if(opus_FOUND AND NOT TARGET Opus::Opus)
31 add_library(Opus::Opus UNKNOWN IMPORTED) 31 add_library(Opus::Opus UNKNOWN IMPORTED GLOBAL)
32 set_target_properties(Opus::Opus PROPERTIES 32 set_target_properties(Opus::Opus PROPERTIES
33 IMPORTED_LOCATION "${opus_LIBRARY}" 33 IMPORTED_LOCATION "${opus_LIBRARY}"
34 INTERFACE_COMPILE_OPTIONS "${PC_opus_CFLAGS_OTHER}" 34 INTERFACE_COMPILE_OPTIONS "${PC_opus_CFLAGS_OTHER}"
diff --git a/externals/opus/CMakeLists.txt b/externals/opus/CMakeLists.txt
index 94a86551f..16f5af9f2 100644
--- a/externals/opus/CMakeLists.txt
+++ b/externals/opus/CMakeLists.txt
@@ -252,3 +252,5 @@ PRIVATE
252 opus/silk/float 252 opus/silk/float
253 opus/src 253 opus/src
254) 254)
255
256add_library(Opus::Opus ALIAS opus)
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp
index fe3a898ad..20a756dce 100644
--- a/src/audio_core/audio_out.cpp
+++ b/src/audio_core/audio_out.cpp
@@ -7,7 +7,7 @@
7#include "audio_core/sink_details.h" 7#include "audio_core/sink_details.h"
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/settings.h" 10#include "common/settings.h"
11 11
12namespace AudioCore { 12namespace AudioCore {
13 13
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index d2ce8c814..ae2201c36 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -11,8 +11,8 @@
11#include "audio_core/info_updater.h" 11#include "audio_core/info_updater.h"
12#include "audio_core/voice_context.h" 12#include "audio_core/voice_context.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/settings.h"
14#include "core/memory.h" 15#include "core/memory.h"
15#include "core/settings.h"
16 16
17namespace { 17namespace {
18[[nodiscard]] static constexpr s16 ClampToS16(s32 value) { 18[[nodiscard]] static constexpr s16 ClampToS16(s32 value) {
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 043447eaa..93c35e785 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -11,7 +11,7 @@
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/ring_buffer.h" 13#include "common/ring_buffer.h"
14#include "core/settings.h" 14#include "common/settings.h"
15 15
16#ifdef _WIN32 16#ifdef _WIN32
17#include <objbase.h> 17#include <objbase.h>
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index b0f6f0c34..ad6c587c2 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -11,8 +11,8 @@
11#include "audio_core/stream.h" 11#include "audio_core/stream.h"
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/settings.h"
14#include "core/core_timing.h" 15#include "core/core_timing.h"
15#include "core/settings.h"
16 16
17namespace AudioCore { 17namespace AudioCore {
18 18
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 788516ded..88644eeb6 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -97,6 +97,7 @@ add_custom_command(OUTPUT scm_rev.cpp
97add_library(common STATIC 97add_library(common STATIC
98 algorithm.h 98 algorithm.h
99 alignment.h 99 alignment.h
100 assert.cpp
100 assert.h 101 assert.h
101 atomic_ops.h 102 atomic_ops.h
102 detached_tasks.cpp 103 detached_tasks.cpp
@@ -109,6 +110,7 @@ add_library(common STATIC
109 cityhash.h 110 cityhash.h
110 common_funcs.h 111 common_funcs.h
111 common_paths.h 112 common_paths.h
113 common_sizes.h
112 common_types.h 114 common_types.h
113 concepts.h 115 concepts.h
114 div_ceil.h 116 div_ceil.h
@@ -150,6 +152,10 @@ add_library(common STATIC
150 scm_rev.cpp 152 scm_rev.cpp
151 scm_rev.h 153 scm_rev.h
152 scope_exit.h 154 scope_exit.h
155 settings.cpp
156 settings.h
157 settings_input.cpp
158 settings_input.h
153 spin_lock.cpp 159 spin_lock.cpp
154 spin_lock.h 160 spin_lock.h
155 stream.cpp 161 stream.cpp
diff --git a/src/common/assert.cpp b/src/common/assert.cpp
new file mode 100644
index 000000000..72f1121aa
--- /dev/null
+++ b/src/common/assert.cpp
@@ -0,0 +1,14 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "common/common_funcs.h"
7
8#include "common/settings.h"
9
10void assert_handle_failure() {
11 if (Settings::values.use_debug_asserts) {
12 Crash();
13 }
14}
diff --git a/src/common/assert.h b/src/common/assert.h
index 06d7b5612..b3ba35c0f 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -4,10 +4,13 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstdlib>
8#include "common/common_funcs.h"
9#include "common/logging/log.h" 7#include "common/logging/log.h"
10 8
9// Sometimes we want to try to continue even after hitting an assert.
10// However touching this file yields a global recompilation as this header is included almost
11// everywhere. So let's just move the handling of the failed assert to a single cpp file.
12void assert_handle_failure();
13
11// For asserts we'd like to keep all the junk executed when an assert happens away from the 14// For asserts we'd like to keep all the junk executed when an assert happens away from the
12// important code in the function. One way of doing this is to put all the relevant code inside a 15// important code in the function. One way of doing this is to put all the relevant code inside a
13// lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to 16// lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to
@@ -17,15 +20,14 @@
17// enough for our purposes. 20// enough for our purposes.
18template <typename Fn> 21template <typename Fn>
19#if defined(_MSC_VER) 22#if defined(_MSC_VER)
20[[msvc::noinline, noreturn]] 23[[msvc::noinline]]
21#elif defined(__GNUC__) 24#elif defined(__GNUC__)
22[[gnu::cold, gnu::noinline, noreturn]] 25[[gnu::cold, gnu::noinline]]
23#endif 26#endif
24static void 27static void
25assert_noinline_call(const Fn& fn) { 28assert_noinline_call(const Fn& fn) {
26 fn(); 29 fn();
27 Crash(); 30 assert_handle_failure();
28 exit(1); // Keeps GCC's mouth shut about this actually returning
29} 31}
30 32
31#define ASSERT(_a_) \ 33#define ASSERT(_a_) \
diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h
new file mode 100644
index 000000000..7e9fd968b
--- /dev/null
+++ b/src/common/common_sizes.h
@@ -0,0 +1,43 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <limits>
8
9#include "common/common_types.h"
10
11namespace Common {
12
13enum : u64 {
14 Size_1_KB = 0x400ULL,
15 Size_64_KB = 64ULL * Size_1_KB,
16 Size_128_KB = 128ULL * Size_1_KB,
17 Size_1_MB = 0x100000ULL,
18 Size_2_MB = 2ULL * Size_1_MB,
19 Size_4_MB = 4ULL * Size_1_MB,
20 Size_5_MB = 5ULL * Size_1_MB,
21 Size_14_MB = 14ULL * Size_1_MB,
22 Size_32_MB = 32ULL * Size_1_MB,
23 Size_33_MB = 33ULL * Size_1_MB,
24 Size_128_MB = 128ULL * Size_1_MB,
25 Size_448_MB = 448ULL * Size_1_MB,
26 Size_507_MB = 507ULL * Size_1_MB,
27 Size_562_MB = 562ULL * Size_1_MB,
28 Size_1554_MB = 1554ULL * Size_1_MB,
29 Size_2048_MB = 2048ULL * Size_1_MB,
30 Size_2193_MB = 2193ULL * Size_1_MB,
31 Size_3285_MB = 3285ULL * Size_1_MB,
32 Size_4916_MB = 4916ULL * Size_1_MB,
33 Size_1_GB = 0x40000000ULL,
34 Size_2_GB = 2ULL * Size_1_GB,
35 Size_4_GB = 4ULL * Size_1_GB,
36 Size_6_GB = 6ULL * Size_1_GB,
37 Size_8_GB = 8ULL * Size_1_GB,
38 Size_64_GB = 64ULL * Size_1_GB,
39 Size_512_GB = 512ULL * Size_1_GB,
40 Size_Invalid = std::numeric_limits<u64>::max(),
41};
42
43} // namespace Common
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 2d4d2e9e7..bc82905c0 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -21,11 +21,11 @@
21#include "common/logging/backend.h" 21#include "common/logging/backend.h"
22#include "common/logging/log.h" 22#include "common/logging/log.h"
23#include "common/logging/text_formatter.h" 23#include "common/logging/text_formatter.h"
24#include "common/settings.h"
24#include "common/string_util.h" 25#include "common/string_util.h"
25#include "common/threadsafe_queue.h" 26#include "common/threadsafe_queue.h"
26#include "core/settings.h"
27 27
28namespace Log { 28namespace Common::Log {
29 29
30/** 30/**
31 * Static state as a singleton. 31 * Static state as a singleton.
@@ -37,8 +37,11 @@ public:
37 return backend; 37 return backend;
38 } 38 }
39 39
40 Impl(Impl const&) = delete; 40 Impl(const Impl&) = delete;
41 const Impl& operator=(Impl const&) = delete; 41 Impl& operator=(const Impl&) = delete;
42
43 Impl(Impl&&) = delete;
44 Impl& operator=(Impl&&) = delete;
42 45
43 void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, 46 void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
44 const char* function, std::string message) { 47 const char* function, std::string message) {
@@ -132,7 +135,7 @@ private:
132 std::mutex writing_mutex; 135 std::mutex writing_mutex;
133 std::thread backend_thread; 136 std::thread backend_thread;
134 std::vector<std::unique_ptr<Backend>> backends; 137 std::vector<std::unique_ptr<Backend>> backends;
135 Common::MPSCQueue<Log::Entry> message_queue; 138 MPSCQueue<Entry> message_queue;
136 Filter filter; 139 Filter filter;
137 std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; 140 std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
138}; 141};
@@ -146,16 +149,16 @@ void ColorConsoleBackend::Write(const Entry& entry) {
146} 149}
147 150
148FileBackend::FileBackend(const std::string& filename) : bytes_written(0) { 151FileBackend::FileBackend(const std::string& filename) : bytes_written(0) {
149 if (Common::FS::Exists(filename + ".old.txt")) { 152 if (FS::Exists(filename + ".old.txt")) {
150 Common::FS::Delete(filename + ".old.txt"); 153 FS::Delete(filename + ".old.txt");
151 } 154 }
152 if (Common::FS::Exists(filename)) { 155 if (FS::Exists(filename)) {
153 Common::FS::Rename(filename, filename + ".old.txt"); 156 FS::Rename(filename, filename + ".old.txt");
154 } 157 }
155 158
156 // _SH_DENYWR allows read only access to the file for other programs. 159 // _SH_DENYWR allows read only access to the file for other programs.
157 // It is #defined to 0 on other platforms 160 // It is #defined to 0 on other platforms
158 file = Common::FS::IOFile(filename, "w", _SH_DENYWR); 161 file = FS::IOFile(filename, "w", _SH_DENYWR);
159} 162}
160 163
161void FileBackend::Write(const Entry& entry) { 164void FileBackend::Write(const Entry& entry) {
@@ -182,7 +185,7 @@ void FileBackend::Write(const Entry& entry) {
182 185
183void DebuggerBackend::Write(const Entry& entry) { 186void DebuggerBackend::Write(const Entry& entry) {
184#ifdef _WIN32 187#ifdef _WIN32
185 ::OutputDebugStringW(Common::UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); 188 ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
186#endif 189#endif
187} 190}
188 191
@@ -212,6 +215,7 @@ void DebuggerBackend::Write(const Entry& entry) {
212 SUB(Service, ARP) \ 215 SUB(Service, ARP) \
213 SUB(Service, BCAT) \ 216 SUB(Service, BCAT) \
214 SUB(Service, BPC) \ 217 SUB(Service, BPC) \
218 SUB(Service, BGTC) \
215 SUB(Service, BTDRV) \ 219 SUB(Service, BTDRV) \
216 SUB(Service, BTM) \ 220 SUB(Service, BTM) \
217 SUB(Service, Capture) \ 221 SUB(Service, Capture) \
@@ -341,4 +345,4 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
341 instance.PushEntry(log_class, log_level, filename, line_num, function, 345 instance.PushEntry(log_class, log_level, filename, line_num, function,
342 fmt::vformat(format, args)); 346 fmt::vformat(format, args));
343} 347}
344} // namespace Log 348} // namespace Common::Log
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index da1c2f185..84a544ea4 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -11,7 +11,7 @@
11#include "common/logging/filter.h" 11#include "common/logging/filter.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13 13
14namespace Log { 14namespace Common::Log {
15 15
16class Filter; 16class Filter;
17 17
@@ -135,4 +135,4 @@ const char* GetLevelName(Level log_level);
135 * never get the message 135 * never get the message
136 */ 136 */
137void SetGlobalFilter(const Filter& filter); 137void SetGlobalFilter(const Filter& filter);
138} // namespace Log \ No newline at end of file 138} // namespace Common::Log \ No newline at end of file
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 2eccbcd8d..20a2dd106 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -7,7 +7,7 @@
7#include "common/logging/filter.h" 7#include "common/logging/filter.h"
8#include "common/string_util.h" 8#include "common/string_util.h"
9 9
10namespace Log { 10namespace Common::Log {
11namespace { 11namespace {
12template <typename It> 12template <typename It>
13Level GetLevelByName(const It begin, const It end) { 13Level GetLevelByName(const It begin, const It end) {
@@ -103,4 +103,4 @@ bool Filter::IsDebug() const {
103 }); 103 });
104} 104}
105 105
106} // namespace Log 106} // namespace Common::Log
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index 773df6f2c..f5673a9f6 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -9,7 +9,7 @@
9#include <string_view> 9#include <string_view>
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11 11
12namespace Log { 12namespace Common::Log {
13 13
14/** 14/**
15 * Implements a log message filter which allows different log classes to have different minimum 15 * Implements a log message filter which allows different log classes to have different minimum
@@ -51,4 +51,4 @@ public:
51private: 51private:
52 std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; 52 std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels;
53}; 53};
54} // namespace Log 54} // namespace Common::Log
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 835894918..1f0f8db52 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -7,7 +7,7 @@
7#include <fmt/format.h> 7#include <fmt/format.h>
8#include "common/common_types.h" 8#include "common/common_types.h"
9 9
10namespace Log { 10namespace Common::Log {
11 11
12// trims up to and including the last of ../, ..\, src/, src\ in a string 12// trims up to and including the last of ../, ..\, src/, src\ in a string
13constexpr const char* TrimSourcePath(std::string_view source) { 13constexpr const char* TrimSourcePath(std::string_view source) {
@@ -66,6 +66,7 @@ enum class Class : ClassType {
66 Service_ARP, ///< The ARP service 66 Service_ARP, ///< The ARP service
67 Service_Audio, ///< The Audio (Audio control) service 67 Service_Audio, ///< The Audio (Audio control) service
68 Service_BCAT, ///< The BCAT service 68 Service_BCAT, ///< The BCAT service
69 Service_BGTC, ///< The BGTC (Background Task Controller) service
69 Service_BPC, ///< The BPC service 70 Service_BPC, ///< The BPC service
70 Service_BTDRV, ///< The Bluetooth driver service 71 Service_BTDRV, ///< The Bluetooth driver service
71 Service_BTM, ///< The BTM service 72 Service_BTM, ///< The BTM service
@@ -147,28 +148,34 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
147 fmt::make_format_args(args...)); 148 fmt::make_format_args(args...));
148} 149}
149 150
150} // namespace Log 151} // namespace Common::Log
151 152
152#ifdef _DEBUG 153#ifdef _DEBUG
153#define LOG_TRACE(log_class, ...) \ 154#define LOG_TRACE(log_class, ...) \
154 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \ 155 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \
155 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 156 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
157 __VA_ARGS__)
156#else 158#else
157#define LOG_TRACE(log_class, fmt, ...) (void(0)) 159#define LOG_TRACE(log_class, fmt, ...) (void(0))
158#endif 160#endif
159 161
160#define LOG_DEBUG(log_class, ...) \ 162#define LOG_DEBUG(log_class, ...) \
161 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \ 163 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \
162 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 164 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
165 __VA_ARGS__)
163#define LOG_INFO(log_class, ...) \ 166#define LOG_INFO(log_class, ...) \
164 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \ 167 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \
165 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 168 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
169 __VA_ARGS__)
166#define LOG_WARNING(log_class, ...) \ 170#define LOG_WARNING(log_class, ...) \
167 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \ 171 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \
168 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 172 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
173 __VA_ARGS__)
169#define LOG_ERROR(log_class, ...) \ 174#define LOG_ERROR(log_class, ...) \
170 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \ 175 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \
171 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 176 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
177 __VA_ARGS__)
172#define LOG_CRITICAL(log_class, ...) \ 178#define LOG_CRITICAL(log_class, ...) \
173 ::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \ 179 Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \
174 ::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__) 180 Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
181 __VA_ARGS__)
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 6a0605c63..80ee2cca1 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -16,7 +16,7 @@
16#include "common/logging/text_formatter.h" 16#include "common/logging/text_formatter.h"
17#include "common/string_util.h" 17#include "common/string_util.h"
18 18
19namespace Log { 19namespace Common::Log {
20 20
21std::string FormatLogMessage(const Entry& entry) { 21std::string FormatLogMessage(const Entry& entry) {
22 unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000); 22 unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
@@ -108,4 +108,4 @@ void PrintColoredMessage(const Entry& entry) {
108#undef ESC 108#undef ESC
109#endif 109#endif
110} 110}
111} // namespace Log 111} // namespace Common::Log
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index b6d9e57c8..171e74cfe 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -7,7 +7,7 @@
7#include <cstddef> 7#include <cstddef>
8#include <string> 8#include <string>
9 9
10namespace Log { 10namespace Common::Log {
11 11
12struct Entry; 12struct Entry;
13 13
@@ -17,4 +17,4 @@ std::string FormatLogMessage(const Entry& entry);
17void PrintMessage(const Entry& entry); 17void PrintMessage(const Entry& entry);
18/// Prints the same message as `PrintMessage`, but colored according to the severity level. 18/// Prints the same message as `PrintMessage`, but colored according to the severity level.
19void PrintColoredMessage(const Entry& entry); 19void PrintColoredMessage(const Entry& entry);
20} // namespace Log 20} // namespace Common::Log
diff --git a/src/common/nvidia_flags.h b/src/common/nvidia_flags.h
index 75a0233ac..8930efcec 100644
--- a/src/common/nvidia_flags.h
+++ b/src/common/nvidia_flags.h
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
5namespace Common { 7namespace Common {
6 8
7/// Configure platform specific flags for Nvidia's driver 9/// Configure platform specific flags for Nvidia's driver
diff --git a/src/core/settings.cpp b/src/common/settings.cpp
index 2ae5196e0..702b6598d 100644
--- a/src/core/settings.cpp
+++ b/src/common/settings.cpp
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -7,10 +7,7 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h" 10#include "common/settings.h"
11#include "core/hle/service/hid/hid.h"
12#include "core/settings.h"
13#include "video_core/renderer_base.h"
14 11
15namespace Settings { 12namespace Settings {
16 13
@@ -32,14 +29,6 @@ std::string GetTimeZoneString() {
32 return timezones[time_zone_index]; 29 return timezones[time_zone_index];
33} 30}
34 31
35void Apply(Core::System& system) {
36 if (system.IsPoweredOn()) {
37 system.Renderer().RefreshBaseSettings();
38 }
39
40 Service::HID::ReloadInputDevices();
41}
42
43void LogSettings() { 32void LogSettings() {
44 const auto log_setting = [](std::string_view name, const auto& value) { 33 const auto log_setting = [](std::string_view name, const auto& value) {
45 LOG_INFO(Config, "{}: {}", name, value); 34 LOG_INFO(Config, "{}: {}", name, value);
diff --git a/src/core/settings.h b/src/common/settings.h
index d849dded3..d39b4aa45 100644
--- a/src/core/settings.h
+++ b/src/common/settings.h
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -11,16 +11,13 @@
11#include <optional> 11#include <optional>
12#include <string> 12#include <string>
13#include <vector> 13#include <vector>
14#include "common/common_types.h"
15#include "input_common/settings.h"
16 14
17namespace Core { 15#include "common/common_types.h"
18class System; 16#include "common/settings_input.h"
19}
20 17
21namespace Settings { 18namespace Settings {
22 19
23enum class RendererBackend { 20enum class RendererBackend : u32 {
24 OpenGL = 0, 21 OpenGL = 0,
25 Vulkan = 1, 22 Vulkan = 1,
26}; 23};
@@ -31,7 +28,7 @@ enum class GPUAccuracy : u32 {
31 Extreme = 2, 28 Extreme = 2,
32}; 29};
33 30
34enum class CPUAccuracy { 31enum class CPUAccuracy : u32 {
35 Accurate = 0, 32 Accurate = 0,
36 Unsafe = 1, 33 Unsafe = 1,
37 DebugMode = 2, 34 DebugMode = 2,
@@ -139,6 +136,7 @@ struct Values {
139 Setting<int> vulkan_device; 136 Setting<int> vulkan_device;
140 137
141 Setting<u16> resolution_factor{1}; 138 Setting<u16> resolution_factor{1};
139 Setting<int> fullscreen_mode;
142 Setting<int> aspect_ratio; 140 Setting<int> aspect_ratio;
143 Setting<int> max_anisotropy; 141 Setting<int> max_anisotropy;
144 Setting<bool> use_frame_limit; 142 Setting<bool> use_frame_limit;
@@ -222,6 +220,8 @@ struct Values {
222 bool quest_flag; 220 bool quest_flag;
223 bool disable_macro_jit; 221 bool disable_macro_jit;
224 bool extended_logging; 222 bool extended_logging;
223 bool use_debug_asserts;
224 bool use_auto_stub;
225 225
226 // Miscellaneous 226 // Miscellaneous
227 std::string log_filter; 227 std::string log_filter;
@@ -253,7 +253,6 @@ float Volume();
253 253
254std::string GetTimeZoneString(); 254std::string GetTimeZoneString();
255 255
256void Apply(Core::System& system);
257void LogSettings(); 256void LogSettings();
258 257
259// Restore the global state of all applicable settings in the Values struct 258// Restore the global state of all applicable settings in the Values struct
diff --git a/src/input_common/settings.cpp b/src/common/settings_input.cpp
index 557e7a9a0..bea2b837b 100644
--- a/src/input_common/settings.cpp
+++ b/src/common/settings_input.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "input_common/settings.h" 5#include "common/settings_input.h"
6 6
7namespace Settings { 7namespace Settings {
8namespace NativeButton { 8namespace NativeButton {
diff --git a/src/input_common/settings.h b/src/common/settings_input.h
index a59f5d461..609600582 100644
--- a/src/input_common/settings.h
+++ b/src/common/settings_input.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <string> 8#include <string>
9
9#include "common/common_types.h" 10#include "common/common_types.h"
10 11
11namespace Settings { 12namespace Settings {
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h
index a4647314a..ad04df8ca 100644
--- a/src/common/threadsafe_queue.h
+++ b/src/common/threadsafe_queue.h
@@ -83,11 +83,15 @@ public:
83 return true; 83 return true;
84 } 84 }
85 85
86 T PopWait() { 86 void Wait() {
87 if (Empty()) { 87 if (Empty()) {
88 std::unique_lock lock{cv_mutex}; 88 std::unique_lock lock{cv_mutex};
89 cv.wait(lock, [this]() { return !Empty(); }); 89 cv.wait(lock, [this]() { return !Empty(); });
90 } 90 }
91 }
92
93 T PopWait() {
94 Wait();
91 T t; 95 T t;
92 Pop(t); 96 Pop(t);
93 return t; 97 return t;
@@ -156,6 +160,10 @@ public:
156 return spsc_queue.Pop(t); 160 return spsc_queue.Pop(t);
157 } 161 }
158 162
163 void Wait() {
164 spsc_queue.Wait();
165 }
166
159 T PopWait() { 167 T PopWait() {
160 return spsc_queue.PopWait(); 168 return spsc_queue.PopWait();
161 } 169 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 17f251c37..532e418b0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -141,6 +141,9 @@ add_library(core STATIC
141 hardware_interrupt_manager.h 141 hardware_interrupt_manager.h
142 hle/ipc.h 142 hle/ipc.h
143 hle/ipc_helpers.h 143 hle/ipc_helpers.h
144 hle/kernel/board/nintendo/nx/k_system_control.cpp
145 hle/kernel/board/nintendo/nx/k_system_control.h
146 hle/kernel/board/nintendo/nx/secure_monitor.h
144 hle/kernel/client_port.cpp 147 hle/kernel/client_port.cpp
145 hle/kernel/client_port.h 148 hle/kernel/client_port.h
146 hle/kernel/client_session.cpp 149 hle/kernel/client_session.cpp
@@ -169,9 +172,13 @@ add_library(core STATIC
169 hle/kernel/k_memory_block.h 172 hle/kernel/k_memory_block.h
170 hle/kernel/k_memory_block_manager.cpp 173 hle/kernel/k_memory_block_manager.cpp
171 hle/kernel/k_memory_block_manager.h 174 hle/kernel/k_memory_block_manager.h
175 hle/kernel/k_memory_layout.cpp
176 hle/kernel/k_memory_layout.board.nintendo_nx.cpp
172 hle/kernel/k_memory_layout.h 177 hle/kernel/k_memory_layout.h
173 hle/kernel/k_memory_manager.cpp 178 hle/kernel/k_memory_manager.cpp
174 hle/kernel/k_memory_manager.h 179 hle/kernel/k_memory_manager.h
180 hle/kernel/k_memory_region.h
181 hle/kernel/k_memory_region_type.h
175 hle/kernel/k_page_bitmap.h 182 hle/kernel/k_page_bitmap.h
176 hle/kernel/k_page_heap.cpp 183 hle/kernel/k_page_heap.cpp
177 hle/kernel/k_page_heap.h 184 hle/kernel/k_page_heap.h
@@ -196,11 +203,11 @@ add_library(core STATIC
196 hle/kernel/k_spin_lock.h 203 hle/kernel/k_spin_lock.h
197 hle/kernel/k_synchronization_object.cpp 204 hle/kernel/k_synchronization_object.cpp
198 hle/kernel/k_synchronization_object.h 205 hle/kernel/k_synchronization_object.h
199 hle/kernel/k_system_control.cpp
200 hle/kernel/k_system_control.h 206 hle/kernel/k_system_control.h
201 hle/kernel/k_thread.cpp 207 hle/kernel/k_thread.cpp
202 hle/kernel/k_thread.h 208 hle/kernel/k_thread.h
203 hle/kernel/k_thread_queue.h 209 hle/kernel/k_thread_queue.h
210 hle/kernel/k_trace.h
204 hle/kernel/k_writable_event.cpp 211 hle/kernel/k_writable_event.cpp
205 hle/kernel/k_writable_event.h 212 hle/kernel/k_writable_event.h
206 hle/kernel/kernel.cpp 213 hle/kernel/kernel.cpp
@@ -266,6 +273,7 @@ add_library(core STATIC
266 hle/service/am/applets/profile_select.h 273 hle/service/am/applets/profile_select.h
267 hle/service/am/applets/software_keyboard.cpp 274 hle/service/am/applets/software_keyboard.cpp
268 hle/service/am/applets/software_keyboard.h 275 hle/service/am/applets/software_keyboard.h
276 hle/service/am/applets/software_keyboard_types.h
269 hle/service/am/applets/web_browser.cpp 277 hle/service/am/applets/web_browser.cpp
270 hle/service/am/applets/web_browser.h 278 hle/service/am/applets/web_browser.h
271 hle/service/am/applets/web_types.h 279 hle/service/am/applets/web_types.h
@@ -614,8 +622,6 @@ add_library(core STATIC
614 perf_stats.h 622 perf_stats.h
615 reporter.cpp 623 reporter.cpp
616 reporter.h 624 reporter.h
617 settings.cpp
618 settings.h
619 telemetry_session.cpp 625 telemetry_session.cpp
620 telemetry_session.h 626 telemetry_session.h
621 tools/freezer.cpp 627 tools/freezer.cpp
@@ -666,7 +672,7 @@ endif()
666create_target_directory_groups(core) 672create_target_directory_groups(core)
667 673
668target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) 674target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
669target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls opus zip) 675target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus zip)
670 676
671if (YUZU_ENABLE_BOXCAT) 677if (YUZU_ENABLE_BOXCAT)
672 target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) 678 target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT)
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 53d78de32..7aeb2a658 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -10,6 +10,7 @@
10#include "common/assert.h" 10#include "common/assert.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/page_table.h" 12#include "common/page_table.h"
13#include "common/settings.h"
13#include "core/arm/cpu_interrupt_handler.h" 14#include "core/arm/cpu_interrupt_handler.h"
14#include "core/arm/dynarmic/arm_dynarmic_32.h" 15#include "core/arm/dynarmic/arm_dynarmic_32.h"
15#include "core/arm/dynarmic/arm_dynarmic_cp15.h" 16#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
@@ -18,7 +19,6 @@
18#include "core/core_timing.h" 19#include "core/core_timing.h"
19#include "core/hle/kernel/svc.h" 20#include "core/hle/kernel/svc.h"
20#include "core/memory.h" 21#include "core/memory.h"
21#include "core/settings.h"
22 22
23namespace Core { 23namespace Core {
24 24
@@ -114,18 +114,17 @@ public:
114 static constexpr u64 minimum_run_cycles = 1000U; 114 static constexpr u64 minimum_run_cycles = 1000U;
115}; 115};
116 116
117std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, 117std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const {
118 std::size_t address_space_bits) const {
119 Dynarmic::A32::UserConfig config; 118 Dynarmic::A32::UserConfig config;
120 config.callbacks = cb.get(); 119 config.callbacks = cb.get();
121 // TODO(bunnei): Implement page table for 32-bit
122 // config.page_table = &page_table.pointers;
123 config.coprocessors[15] = cp15; 120 config.coprocessors[15] = cp15;
124 config.define_unpredictable_behaviour = true; 121 config.define_unpredictable_behaviour = true;
125 static constexpr std::size_t PAGE_BITS = 12; 122 static constexpr std::size_t PAGE_BITS = 12;
126 static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS); 123 static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS);
127 config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>( 124 if (page_table) {
128 page_table.pointers.data()); 125 config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>(
126 page_table->pointers.data());
127 }
129 config.absolute_offset_page_table = true; 128 config.absolute_offset_page_table = true;
130 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; 129 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS;
131 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; 130 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
@@ -138,6 +137,10 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
138 // Timing 137 // Timing
139 config.wall_clock_cntpct = uses_wall_clock; 138 config.wall_clock_cntpct = uses_wall_clock;
140 139
140 // Code cache size
141 config.code_cache_size = 512 * 1024 * 1024;
142 config.far_code_offset = 256 * 1024 * 1024;
143
141 // Safe optimizations 144 // Safe optimizations
142 if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { 145 if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
143 if (!Settings::values.cpuopt_page_tables) { 146 if (!Settings::values.cpuopt_page_tables) {
@@ -201,7 +204,8 @@ ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handle
201 : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, 204 : ARM_Interface{system, interrupt_handlers, uses_wall_clock},
202 cb(std::make_unique<DynarmicCallbacks32>(*this)), 205 cb(std::make_unique<DynarmicCallbacks32>(*this)),
203 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, 206 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index},
204 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} 207 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)},
208 jit(MakeJit(nullptr)) {}
205 209
206ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; 210ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
207 211
@@ -256,9 +260,6 @@ void ARM_Dynarmic_32::ChangeProcessorID(std::size_t new_core_id) {
256} 260}
257 261
258void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { 262void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
259 if (!jit) {
260 return;
261 }
262 Dynarmic::A32::Context context; 263 Dynarmic::A32::Context context;
263 jit->SaveContext(context); 264 jit->SaveContext(context);
264 ctx.cpu_registers = context.Regs(); 265 ctx.cpu_registers = context.Regs();
@@ -268,9 +269,6 @@ void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
268} 269}
269 270
270void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { 271void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
271 if (!jit) {
272 return;
273 }
274 Dynarmic::A32::Context context; 272 Dynarmic::A32::Context context;
275 context.Regs() = ctx.cpu_registers; 273 context.Regs() = ctx.cpu_registers;
276 context.ExtRegs() = ctx.extension_registers; 274 context.ExtRegs() = ctx.extension_registers;
@@ -284,23 +282,14 @@ void ARM_Dynarmic_32::PrepareReschedule() {
284} 282}
285 283
286void ARM_Dynarmic_32::ClearInstructionCache() { 284void ARM_Dynarmic_32::ClearInstructionCache() {
287 if (!jit) {
288 return;
289 }
290 jit->ClearCache(); 285 jit->ClearCache();
291} 286}
292 287
293void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { 288void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) {
294 if (!jit) {
295 return;
296 }
297 jit->InvalidateCacheRange(static_cast<u32>(addr), size); 289 jit->InvalidateCacheRange(static_cast<u32>(addr), size);
298} 290}
299 291
300void ARM_Dynarmic_32::ClearExclusiveState() { 292void ARM_Dynarmic_32::ClearExclusiveState() {
301 if (!jit) {
302 return;
303 }
304 jit->ClearExclusiveState(); 293 jit->ClearExclusiveState();
305} 294}
306 295
@@ -316,7 +305,7 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
316 LoadContext(ctx); 305 LoadContext(ctx);
317 return; 306 return;
318 } 307 }
319 jit = MakeJit(page_table, new_address_space_size_in_bits); 308 jit = MakeJit(&page_table);
320 LoadContext(ctx); 309 LoadContext(ctx);
321 jit_cache.emplace(key, jit); 310 jit_cache.emplace(key, jit);
322} 311}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index f6c4d4db9..d40aef7a9 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -68,8 +68,7 @@ public:
68 std::size_t new_address_space_size_in_bits) override; 68 std::size_t new_address_space_size_in_bits) override;
69 69
70private: 70private:
71 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table, 71 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
72 std::size_t address_space_bits) const;
73 72
74 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; 73 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
75 using JitCacheType = 74 using JitCacheType =
@@ -80,10 +79,10 @@ private:
80 79
81 std::unique_ptr<DynarmicCallbacks32> cb; 80 std::unique_ptr<DynarmicCallbacks32> cb;
82 JitCacheType jit_cache; 81 JitCacheType jit_cache;
83 std::shared_ptr<Dynarmic::A32::Jit> jit;
84 std::shared_ptr<DynarmicCP15> cp15; 82 std::shared_ptr<DynarmicCP15> cp15;
85 std::size_t core_index; 83 std::size_t core_index;
86 DynarmicExclusiveMonitor& exclusive_monitor; 84 DynarmicExclusiveMonitor& exclusive_monitor;
85 std::shared_ptr<Dynarmic::A32::Jit> jit;
87}; 86};
88 87
89} // namespace Core 88} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index b36b7d918..040529f4d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -9,6 +9,7 @@
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/page_table.h" 11#include "common/page_table.h"
12#include "common/settings.h"
12#include "core/arm/cpu_interrupt_handler.h" 13#include "core/arm/cpu_interrupt_handler.h"
13#include "core/arm/dynarmic/arm_dynarmic_64.h" 14#include "core/arm/dynarmic/arm_dynarmic_64.h"
14#include "core/arm/dynarmic/arm_exclusive_monitor.h" 15#include "core/arm/dynarmic/arm_exclusive_monitor.h"
@@ -19,7 +20,6 @@
19#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/svc.h" 21#include "core/hle/kernel/svc.h"
21#include "core/memory.h" 22#include "core/memory.h"
22#include "core/settings.h"
23 23
24namespace Core { 24namespace Core {
25 25
@@ -142,7 +142,7 @@ public:
142 static constexpr u64 minimum_run_cycles = 1000U; 142 static constexpr u64 minimum_run_cycles = 1000U;
143}; 143};
144 144
145std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table, 145std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table,
146 std::size_t address_space_bits) const { 146 std::size_t address_space_bits) const {
147 Dynarmic::A64::UserConfig config; 147 Dynarmic::A64::UserConfig config;
148 148
@@ -150,13 +150,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
150 config.callbacks = cb.get(); 150 config.callbacks = cb.get();
151 151
152 // Memory 152 // Memory
153 config.page_table = reinterpret_cast<void**>(page_table.pointers.data()); 153 if (page_table) {
154 config.page_table_address_space_bits = address_space_bits; 154 config.page_table = reinterpret_cast<void**>(page_table->pointers.data());
155 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; 155 config.page_table_address_space_bits = address_space_bits;
156 config.silently_mirror_page_table = false; 156 config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS;
157 config.absolute_offset_page_table = true; 157 config.silently_mirror_page_table = false;
158 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; 158 config.absolute_offset_page_table = true;
159 config.only_detect_misalignment_via_page_table_on_page_boundary = true; 159 config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
160 config.only_detect_misalignment_via_page_table_on_page_boundary = true;
161 }
160 162
161 // Multi-process state 163 // Multi-process state
162 config.processor_id = core_index; 164 config.processor_id = core_index;
@@ -175,6 +177,10 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
175 // Timing 177 // Timing
176 config.wall_clock_cntpct = uses_wall_clock; 178 config.wall_clock_cntpct = uses_wall_clock;
177 179
180 // Code cache size
181 config.code_cache_size = 512 * 1024 * 1024;
182 config.far_code_offset = 256 * 1024 * 1024;
183
178 // Safe optimizations 184 // Safe optimizations
179 if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { 185 if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
180 if (!Settings::values.cpuopt_page_tables) { 186 if (!Settings::values.cpuopt_page_tables) {
@@ -237,7 +243,8 @@ ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handle
237 std::size_t core_index) 243 std::size_t core_index)
238 : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, 244 : ARM_Interface{system, interrupt_handlers, uses_wall_clock},
239 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index}, 245 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index},
240 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} 246 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)},
247 jit(MakeJit(nullptr, 48)) {}
241 248
242ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; 249ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
243 250
@@ -294,9 +301,6 @@ void ARM_Dynarmic_64::ChangeProcessorID(std::size_t new_core_id) {
294} 301}
295 302
296void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { 303void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
297 if (!jit) {
298 return;
299 }
300 ctx.cpu_registers = jit->GetRegisters(); 304 ctx.cpu_registers = jit->GetRegisters();
301 ctx.sp = jit->GetSP(); 305 ctx.sp = jit->GetSP();
302 ctx.pc = jit->GetPC(); 306 ctx.pc = jit->GetPC();
@@ -308,9 +312,6 @@ void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
308} 312}
309 313
310void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { 314void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
311 if (!jit) {
312 return;
313 }
314 jit->SetRegisters(ctx.cpu_registers); 315 jit->SetRegisters(ctx.cpu_registers);
315 jit->SetSP(ctx.sp); 316 jit->SetSP(ctx.sp);
316 jit->SetPC(ctx.pc); 317 jit->SetPC(ctx.pc);
@@ -326,23 +327,14 @@ void ARM_Dynarmic_64::PrepareReschedule() {
326} 327}
327 328
328void ARM_Dynarmic_64::ClearInstructionCache() { 329void ARM_Dynarmic_64::ClearInstructionCache() {
329 if (!jit) {
330 return;
331 }
332 jit->ClearCache(); 330 jit->ClearCache();
333} 331}
334 332
335void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { 333void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) {
336 if (!jit) {
337 return;
338 }
339 jit->InvalidateCacheRange(addr, size); 334 jit->InvalidateCacheRange(addr, size);
340} 335}
341 336
342void ARM_Dynarmic_64::ClearExclusiveState() { 337void ARM_Dynarmic_64::ClearExclusiveState() {
343 if (!jit) {
344 return;
345 }
346 jit->ClearExclusiveState(); 338 jit->ClearExclusiveState();
347} 339}
348 340
@@ -358,7 +350,7 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
358 LoadContext(ctx); 350 LoadContext(ctx);
359 return; 351 return;
360 } 352 }
361 jit = MakeJit(page_table, new_address_space_size_in_bits); 353 jit = MakeJit(&page_table, new_address_space_size_in_bits);
362 LoadContext(ctx); 354 LoadContext(ctx);
363 jit_cache.emplace(key, jit); 355 jit_cache.emplace(key, jit);
364} 356}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 329b59a32..edef04376 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -61,7 +61,7 @@ public:
61 std::size_t new_address_space_size_in_bits) override; 61 std::size_t new_address_space_size_in_bits) override;
62 62
63private: 63private:
64 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table, 64 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
65 std::size_t address_space_bits) const; 65 std::size_t address_space_bits) const;
66 66
67 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; 67 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
@@ -71,10 +71,11 @@ private:
71 friend class DynarmicCallbacks64; 71 friend class DynarmicCallbacks64;
72 std::unique_ptr<DynarmicCallbacks64> cb; 72 std::unique_ptr<DynarmicCallbacks64> cb;
73 JitCacheType jit_cache; 73 JitCacheType jit_cache;
74 std::shared_ptr<Dynarmic::A64::Jit> jit;
75 74
76 std::size_t core_index; 75 std::size_t core_index;
77 DynarmicExclusiveMonitor& exclusive_monitor; 76 DynarmicExclusiveMonitor& exclusive_monitor;
77
78 std::shared_ptr<Dynarmic::A64::Jit> jit;
78}; 79};
79 80
80} // namespace Core 81} // namespace Core
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 305f56ff1..d459d6c34 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -9,6 +9,7 @@
9#include "common/file_util.h" 9#include "common/file_util.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/microprofile.h" 11#include "common/microprofile.h"
12#include "common/settings.h"
12#include "common/string_util.h" 13#include "common/string_util.h"
13#include "core/arm/exclusive_monitor.h" 14#include "core/arm/exclusive_monitor.h"
14#include "core/core.h" 15#include "core/core.h"
@@ -36,6 +37,7 @@
36#include "core/hle/service/apm/controller.h" 37#include "core/hle/service/apm/controller.h"
37#include "core/hle/service/filesystem/filesystem.h" 38#include "core/hle/service/filesystem/filesystem.h"
38#include "core/hle/service/glue/manager.h" 39#include "core/hle/service/glue/manager.h"
40#include "core/hle/service/hid/hid.h"
39#include "core/hle/service/service.h" 41#include "core/hle/service/service.h"
40#include "core/hle/service/sm/sm.h" 42#include "core/hle/service/sm/sm.h"
41#include "core/hle/service/time/time_manager.h" 43#include "core/hle/service/time/time_manager.h"
@@ -45,7 +47,6 @@
45#include "core/network/network.h" 47#include "core/network/network.h"
46#include "core/perf_stats.h" 48#include "core/perf_stats.h"
47#include "core/reporter.h" 49#include "core/reporter.h"
48#include "core/settings.h"
49#include "core/telemetry_session.h" 50#include "core/telemetry_session.h"
50#include "core/tools/freezer.h" 51#include "core/tools/freezer.h"
51#include "video_core/renderer_base.h" 52#include "video_core/renderer_base.h"
@@ -296,7 +297,7 @@ struct System::Impl {
296 exit_lock = false; 297 exit_lock = false;
297 298
298 if (gpu_core) { 299 if (gpu_core) {
299 gpu_core->WaitIdle(); 300 gpu_core->ShutDown();
300 } 301 }
301 302
302 services.reset(); 303 services.reset();
@@ -774,4 +775,12 @@ void System::ExecuteProgram(std::size_t program_index) {
774 } 775 }
775} 776}
776 777
778void System::ApplySettings() {
779 if (IsPoweredOn()) {
780 Renderer().RefreshBaseSettings();
781 }
782
783 Service::HID::ReloadInputDevices();
784}
785
777} // namespace Core 786} // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index 3a8e040c1..f1068d23f 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -388,6 +388,9 @@ public:
388 */ 388 */
389 void ExecuteProgram(std::size_t program_index); 389 void ExecuteProgram(std::size_t program_index);
390 390
391 /// Applies any changes to settings to this core instance.
392 void ApplySettings();
393
391private: 394private:
392 System(); 395 System();
393 396
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index ad116dcc0..070ed439e 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -22,6 +22,7 @@
22#include "common/file_util.h" 22#include "common/file_util.h"
23#include "common/hex_util.h" 23#include "common/hex_util.h"
24#include "common/logging/log.h" 24#include "common/logging/log.h"
25#include "common/settings.h"
25#include "common/string_util.h" 26#include "common/string_util.h"
26#include "core/crypto/aes_util.h" 27#include "core/crypto/aes_util.h"
27#include "core/crypto/key_manager.h" 28#include "core/crypto/key_manager.h"
@@ -32,7 +33,6 @@
32#include "core/file_sys/registered_cache.h" 33#include "core/file_sys/registered_cache.h"
33#include "core/hle/service/filesystem/filesystem.h" 34#include "core/hle/service/filesystem/filesystem.h"
34#include "core/loader/loader.h" 35#include "core/loader/loader.h"
35#include "core/settings.h"
36 36
37namespace Core::Crypto { 37namespace Core::Crypto {
38namespace { 38namespace {
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index b0a130345..f66759815 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -100,6 +100,14 @@ u64 NACP::GetDeviceSaveDataSize() const {
100 return raw.device_save_data_size; 100 return raw.device_save_data_size;
101} 101}
102 102
103u32 NACP::GetParentalControlFlag() const {
104 return raw.parental_control;
105}
106
107const std::array<u8, 0x20>& NACP::GetRatingAge() const {
108 return raw.rating_age;
109}
110
103std::vector<u8> NACP::GetRawBytes() const { 111std::vector<u8> NACP::GetRawBytes() const {
104 std::vector<u8> out(sizeof(RawNACP)); 112 std::vector<u8> out(sizeof(RawNACP));
105 std::memcpy(out.data(), &raw, sizeof(RawNACP)); 113 std::memcpy(out.data(), &raw, sizeof(RawNACP));
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 403c4219a..dd9837cf5 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -114,6 +114,8 @@ public:
114 std::vector<u8> GetRawBytes() const; 114 std::vector<u8> GetRawBytes() const;
115 bool GetUserAccountSwitchLock() const; 115 bool GetUserAccountSwitchLock() const;
116 u64 GetDeviceSaveDataSize() const; 116 u64 GetDeviceSaveDataSize() const;
117 u32 GetParentalControlFlag() const;
118 const std::array<u8, 0x20>& GetRatingAge() const;
117 119
118private: 120private:
119 RawNACP raw{}; 121 RawNACP raw{};
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 7c3284df8..cc9b4b637 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -10,6 +10,7 @@
10#include "common/file_util.h" 10#include "common/file_util.h"
11#include "common/hex_util.h" 11#include "common/hex_util.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/settings.h"
13#include "common/string_util.h" 14#include "common/string_util.h"
14#include "core/core.h" 15#include "core/core.h"
15#include "core/file_sys/common_funcs.h" 16#include "core/file_sys/common_funcs.h"
@@ -25,7 +26,6 @@
25#include "core/loader/loader.h" 26#include "core/loader/loader.h"
26#include "core/loader/nso.h" 27#include "core/loader/nso.h"
27#include "core/memory/cheat_engine.h" 28#include "core/memory/cheat_engine.h"
28#include "core/settings.h"
29 29
30namespace FileSys { 30namespace FileSys {
31namespace { 31namespace {
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp
index 4df3574d2..8d960d1ca 100644
--- a/src/core/frontend/applets/profile_select.cpp
+++ b/src/core/frontend/applets/profile_select.cpp
@@ -2,9 +2,9 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
5#include "core/frontend/applets/profile_select.h" 6#include "core/frontend/applets/profile_select.h"
6#include "core/hle/service/acc/profile_manager.h" 7#include "core/hle/service/acc/profile_manager.h"
7#include "core/settings.h"
8 8
9namespace Core::Frontend { 9namespace Core::Frontend {
10 10
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index 856ed33da..12c76c9ee 100644
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -1,29 +1,149 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/backend.h" 5#include <thread>
6
7#include "common/logging/log.h"
6#include "common/string_util.h" 8#include "common/string_util.h"
7#include "core/frontend/applets/software_keyboard.h" 9#include "core/frontend/applets/software_keyboard.h"
8 10
9namespace Core::Frontend { 11namespace Core::Frontend {
12
10SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; 13SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
11 14
12void DefaultSoftwareKeyboardApplet::RequestText( 15DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
13 std::function<void(std::optional<std::u16string>)> out, 16
14 SoftwareKeyboardParameters parameters) const { 17void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
15 if (parameters.initial_text.empty()) 18 bool is_inline, KeyboardInitializeParameters initialize_parameters,
16 out(u"yuzu"); 19 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
20 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
21 submit_inline_callback_) {
22 if (is_inline) {
23 LOG_WARNING(
24 Service_AM,
25 "(STUBBED) called, backend requested to initialize the inline software keyboard.");
26
27 submit_inline_callback = std::move(submit_inline_callback_);
28 } else {
29 LOG_WARNING(
30 Service_AM,
31 "(STUBBED) called, backend requested to initialize the normal software keyboard.");
32
33 submit_normal_callback = std::move(submit_normal_callback_);
34 }
35
36 parameters = std::move(initialize_parameters);
37
38 LOG_INFO(Service_AM,
39 "\nKeyboardInitializeParameters:"
40 "\nok_text={}"
41 "\nheader_text={}"
42 "\nsub_text={}"
43 "\nguide_text={}"
44 "\ninitial_text={}"
45 "\nmax_text_length={}"
46 "\nmin_text_length={}"
47 "\ninitial_cursor_position={}"
48 "\ntype={}"
49 "\npassword_mode={}"
50 "\ntext_draw_type={}"
51 "\nkey_disable_flags={}"
52 "\nuse_blur_background={}"
53 "\nenable_backspace_button={}"
54 "\nenable_return_button={}"
55 "\ndisable_cancel_button={}",
56 Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text),
57 Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text),
58 Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length,
59 parameters.min_text_length, parameters.initial_cursor_position, parameters.type,
60 parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw,
61 parameters.use_blur_background, parameters.enable_backspace_button,
62 parameters.enable_return_button, parameters.disable_cancel_button);
63}
64
65void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
66 LOG_WARNING(Service_AM,
67 "(STUBBED) called, backend requested to show the normal software keyboard.");
68
69 SubmitNormalText(u"yuzu");
70}
71
72void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
73 Service::AM::Applets::SwkbdTextCheckResult text_check_result,
74 std::u16string text_check_message) const {
75 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog.");
76}
77
78void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard(
79 InlineAppearParameters appear_parameters) const {
80 LOG_WARNING(Service_AM,
81 "(STUBBED) called, backend requested to show the inline software keyboard.");
82
83 LOG_INFO(Service_AM,
84 "\nInlineAppearParameters:"
85 "\nmax_text_length={}"
86 "\nmin_text_length={}"
87 "\nkey_top_scale_x={}"
88 "\nkey_top_scale_y={}"
89 "\nkey_top_translate_x={}"
90 "\nkey_top_translate_y={}"
91 "\ntype={}"
92 "\nkey_disable_flags={}"
93 "\nkey_top_as_floating={}"
94 "\nenable_backspace_button={}"
95 "\nenable_return_button={}"
96 "\ndisable_cancel_button={}",
97 appear_parameters.max_text_length, appear_parameters.min_text_length,
98 appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
99 appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
100 appear_parameters.type, appear_parameters.key_disable_flags.raw,
101 appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
102 appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
103
104 std::thread([this] { SubmitInlineText(u"yuzu"); }).detach();
105}
17 106
18 out(parameters.initial_text); 107void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
108 LOG_WARNING(Service_AM,
109 "(STUBBED) called, backend requested to hide the inline software keyboard.");
19} 110}
20 111
21void DefaultSoftwareKeyboardApplet::SendTextCheckDialog( 112void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const {
22 std::u16string error_message, std::function<void()> finished_check) const {
23 LOG_WARNING(Service_AM, 113 LOG_WARNING(Service_AM,
24 "(STUBBED) called - Default fallback software keyboard does not support text " 114 "(STUBBED) called, backend requested to change the inline keyboard text.");
25 "check! (error_message={})", 115
26 Common::UTF16ToUTF8(error_message)); 116 LOG_INFO(Service_AM,
27 finished_check(); 117 "\nInlineTextParameters:"
118 "\ninput_text={}"
119 "\ncursor_position={}",
120 Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
121
122 submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
123 text_parameters.input_text, text_parameters.cursor_position);
124}
125
126void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
127 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard.");
28} 128}
129
130void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
131 submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text);
132}
133
134void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
135 std::this_thread::sleep_for(std::chrono::milliseconds(500));
136
137 for (std::size_t index = 0; index < text.size(); ++index) {
138 submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
139 std::u16string(text.data(), text.data() + index + 1),
140 static_cast<s32>(index) + 1);
141
142 std::this_thread::sleep_for(std::chrono::milliseconds(250));
143 }
144
145 submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text),
146 static_cast<s32>(text.size()));
147}
148
29} // namespace Core::Frontend 149} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index f9b202664..506eb35bb 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -1,54 +1,116 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <functional> 7#include <functional>
8#include <optional> 8#include <thread>
9#include <string> 9
10#include "common/bit_field.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12 11
12#include "core/hle/service/am/applets/software_keyboard_types.h"
13
13namespace Core::Frontend { 14namespace Core::Frontend {
14struct SoftwareKeyboardParameters { 15
15 std::u16string submit_text; 16struct KeyboardInitializeParameters {
17 std::u16string ok_text;
16 std::u16string header_text; 18 std::u16string header_text;
17 std::u16string sub_text; 19 std::u16string sub_text;
18 std::u16string guide_text; 20 std::u16string guide_text;
19 std::u16string initial_text; 21 std::u16string initial_text;
20 std::size_t max_length; 22 u32 max_text_length;
21 bool password; 23 u32 min_text_length;
22 bool cursor_at_beginning; 24 s32 initial_cursor_position;
23 25 Service::AM::Applets::SwkbdType type;
24 union { 26 Service::AM::Applets::SwkbdPasswordMode password_mode;
25 u8 value; 27 Service::AM::Applets::SwkbdTextDrawType text_draw_type;
26 28 Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
27 BitField<1, 1, u8> disable_space; 29 bool use_blur_background;
28 BitField<2, 1, u8> disable_address; 30 bool enable_backspace_button;
29 BitField<3, 1, u8> disable_percent; 31 bool enable_return_button;
30 BitField<4, 1, u8> disable_slash; 32 bool disable_cancel_button;
31 BitField<6, 1, u8> disable_number; 33};
32 BitField<7, 1, u8> disable_download_code; 34
33 }; 35struct InlineAppearParameters {
36 u32 max_text_length;
37 u32 min_text_length;
38 f32 key_top_scale_x;
39 f32 key_top_scale_y;
40 f32 key_top_translate_x;
41 f32 key_top_translate_y;
42 Service::AM::Applets::SwkbdType type;
43 Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
44 bool key_top_as_floating;
45 bool enable_backspace_button;
46 bool enable_return_button;
47 bool disable_cancel_button;
48};
49
50struct InlineTextParameters {
51 std::u16string input_text;
52 s32 cursor_position;
34}; 53};
35 54
36class SoftwareKeyboardApplet { 55class SoftwareKeyboardApplet {
37public: 56public:
38 virtual ~SoftwareKeyboardApplet(); 57 virtual ~SoftwareKeyboardApplet();
39 58
40 virtual void RequestText(std::function<void(std::optional<std::u16string>)> out, 59 virtual void InitializeKeyboard(
41 SoftwareKeyboardParameters parameters) const = 0; 60 bool is_inline, KeyboardInitializeParameters initialize_parameters,
42 virtual void SendTextCheckDialog(std::u16string error_message, 61 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
43 std::function<void()> finished_check) const = 0; 62 submit_normal_callback_,
63 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
64 submit_inline_callback_) = 0;
65
66 virtual void ShowNormalKeyboard() const = 0;
67
68 virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
69 std::u16string text_check_message) const = 0;
70
71 virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0;
72
73 virtual void HideInlineKeyboard() const = 0;
74
75 virtual void InlineTextChanged(InlineTextParameters text_parameters) const = 0;
76
77 virtual void ExitKeyboard() const = 0;
44}; 78};
45 79
46class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { 80class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
47public: 81public:
48 void RequestText(std::function<void(std::optional<std::u16string>)> out, 82 ~DefaultSoftwareKeyboardApplet() override;
49 SoftwareKeyboardParameters parameters) const override; 83
50 void SendTextCheckDialog(std::u16string error_message, 84 void InitializeKeyboard(
51 std::function<void()> finished_check) const override; 85 bool is_inline, KeyboardInitializeParameters initialize_parameters,
86 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
87 submit_normal_callback_,
88 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
89 submit_inline_callback_) override;
90
91 void ShowNormalKeyboard() const override;
92
93 void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
94 std::u16string text_check_message) const override;
95
96 void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override;
97
98 void HideInlineKeyboard() const override;
99
100 void InlineTextChanged(InlineTextParameters text_parameters) const override;
101
102 void ExitKeyboard() const override;
103
104private:
105 void SubmitNormalText(std::u16string text) const;
106 void SubmitInlineText(std::u16string_view text) const;
107
108 KeyboardInitializeParameters parameters;
109
110 mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
111 submit_normal_callback;
112 mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
113 submit_inline_callback;
52}; 114};
53 115
54} // namespace Core::Frontend 116} // namespace Core::Frontend
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp
index ee7a58b1c..474de9206 100644
--- a/src/core/frontend/emu_window.cpp
+++ b/src/core/frontend/emu_window.cpp
@@ -4,9 +4,9 @@
4 4
5#include <cmath> 5#include <cmath>
6#include <mutex> 6#include <mutex>
7#include "common/settings.h"
7#include "core/frontend/emu_window.h" 8#include "core/frontend/emu_window.h"
8#include "core/frontend/input.h" 9#include "core/frontend/input.h"
9#include "core/settings.h"
10 10
11namespace Core::Frontend { 11namespace Core::Frontend {
12 12
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index b9a270a55..0832463d6 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -5,8 +5,8 @@
5#include <cmath> 5#include <cmath>
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/settings.h"
8#include "core/frontend/framebuffer_layout.h" 9#include "core/frontend/framebuffer_layout.h"
9#include "core/settings.h"
10 10
11namespace Layout { 11namespace Layout {
12 12
diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp
index ec5fe660e..9f6a90e8f 100644
--- a/src/core/frontend/input_interpreter.cpp
+++ b/src/core/frontend/input_interpreter.cpp
@@ -12,7 +12,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
12 : npad{system.ServiceManager() 12 : npad{system.ServiceManager()
13 .GetService<Service::HID::Hid>("hid") 13 .GetService<Service::HID::Hid>("hid")
14 ->GetAppletResource() 14 ->GetAppletResource()
15 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {} 15 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
16 ResetButtonStates();
17}
16 18
17InputInterpreter::~InputInterpreter() = default; 19InputInterpreter::~InputInterpreter() = default;
18 20
@@ -25,6 +27,17 @@ void InputInterpreter::PollInput() {
25 button_states[current_index] = button_state; 27 button_states[current_index] = button_state;
26} 28}
27 29
30void InputInterpreter::ResetButtonStates() {
31 previous_index = 0;
32 current_index = 0;
33
34 button_states[0] = 0xFFFFFFFF;
35
36 for (std::size_t i = 1; i < button_states.size(); ++i) {
37 button_states[i] = 0;
38 }
39}
40
28bool InputInterpreter::IsButtonPressed(HIDButton button) const { 41bool InputInterpreter::IsButtonPressed(HIDButton button) const {
29 return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0; 42 return (button_states[current_index] & (1U << static_cast<u8>(button))) != 0;
30} 43}
diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h
index 73fc47ffb..9495e3daf 100644
--- a/src/core/frontend/input_interpreter.h
+++ b/src/core/frontend/input_interpreter.h
@@ -66,6 +66,9 @@ public:
66 /// Gets a button state from HID and inserts it into the array of button states. 66 /// Gets a button state from HID and inserts it into the array of button states.
67 void PollInput(); 67 void PollInput();
68 68
69 /// Resets all the button states to their defaults.
70 void ResetButtonStates();
71
69 /** 72 /**
70 * Checks whether the button is pressed. 73 * Checks whether the button is pressed.
71 * 74 *
diff --git a/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc
new file mode 100644
index 000000000..857b512ba
--- /dev/null
+++ b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc
@@ -0,0 +1,20 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// All architectures must define NumArchitectureDeviceRegions.
6constexpr inline const auto NumArchitectureDeviceRegions = 3;
7
8constexpr inline const auto KMemoryRegionType_Uart =
9 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0);
10constexpr inline const auto KMemoryRegionType_InterruptCpuInterface =
11 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1)
12 .SetAttribute(KMemoryRegionAttr_NoUserMap);
13constexpr inline const auto KMemoryRegionType_InterruptDistributor =
14 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2)
15 .SetAttribute(KMemoryRegionAttr_NoUserMap);
16static_assert(KMemoryRegionType_Uart.GetValue() == (0x1D));
17static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() ==
18 (0x2D | KMemoryRegionAttr_NoUserMap));
19static_assert(KMemoryRegionType_InterruptDistributor.GetValue() ==
20 (0x4D | KMemoryRegionAttr_NoUserMap));
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc
new file mode 100644
index 000000000..58d6c0b16
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc
@@ -0,0 +1,52 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// All architectures must define NumBoardDeviceRegions.
6constexpr inline const auto NumBoardDeviceRegions = 6;
7// UNUSED: .Derive(NumBoardDeviceRegions, 0);
8constexpr inline const auto KMemoryRegionType_MemoryController =
9 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1)
10 .SetAttribute(KMemoryRegionAttr_NoUserMap);
11constexpr inline const auto KMemoryRegionType_MemoryController1 =
12 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2)
13 .SetAttribute(KMemoryRegionAttr_NoUserMap);
14constexpr inline const auto KMemoryRegionType_MemoryController0 =
15 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3)
16 .SetAttribute(KMemoryRegionAttr_NoUserMap);
17constexpr inline const auto KMemoryRegionType_PowerManagementController =
18 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition();
19constexpr inline const auto KMemoryRegionType_LegacyLpsDevices =
20 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 5);
21static_assert(KMemoryRegionType_MemoryController.GetValue() ==
22 (0x55 | KMemoryRegionAttr_NoUserMap));
23static_assert(KMemoryRegionType_MemoryController1.GetValue() ==
24 (0x65 | KMemoryRegionAttr_NoUserMap));
25static_assert(KMemoryRegionType_MemoryController0.GetValue() ==
26 (0x95 | KMemoryRegionAttr_NoUserMap));
27static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5));
28
29static_assert(KMemoryRegionType_LegacyLpsDevices.GetValue() == 0xC5);
30
31constexpr inline const auto NumLegacyLpsDevices = 7;
32constexpr inline const auto KMemoryRegionType_LegacyLpsExceptionVectors =
33 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 0);
34constexpr inline const auto KMemoryRegionType_LegacyLpsIram =
35 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 1);
36constexpr inline const auto KMemoryRegionType_LegacyLpsFlowController =
37 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 2);
38constexpr inline const auto KMemoryRegionType_LegacyLpsPrimaryICtlr =
39 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 3);
40constexpr inline const auto KMemoryRegionType_LegacyLpsSemaphore =
41 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 4);
42constexpr inline const auto KMemoryRegionType_LegacyLpsAtomics =
43 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 5);
44constexpr inline const auto KMemoryRegionType_LegacyLpsClkRst =
45 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 6);
46static_assert(KMemoryRegionType_LegacyLpsExceptionVectors.GetValue() == 0x3C5);
47static_assert(KMemoryRegionType_LegacyLpsIram.GetValue() == 0x5C5);
48static_assert(KMemoryRegionType_LegacyLpsFlowController.GetValue() == 0x6C5);
49static_assert(KMemoryRegionType_LegacyLpsPrimaryICtlr.GetValue() == 0x9C5);
50static_assert(KMemoryRegionType_LegacyLpsSemaphore.GetValue() == 0xAC5);
51static_assert(KMemoryRegionType_LegacyLpsAtomics.GetValue() == 0xCC5);
52static_assert(KMemoryRegionType_LegacyLpsClkRst.GetValue() == 0x11C5);
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
new file mode 100644
index 000000000..86472b5ce
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -0,0 +1,164 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <random>
6
7#include "common/common_sizes.h"
8#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
9#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
10#include "core/hle/kernel/k_trace.h"
11
12namespace Kernel::Board::Nintendo::Nx {
13
14namespace impl {
15
16constexpr const std::size_t RequiredNonSecureSystemMemorySizeVi = 0x2238 * 4 * 1024;
17constexpr const std::size_t RequiredNonSecureSystemMemorySizeNvservices = 0x710 * 4 * 1024;
18constexpr const std::size_t RequiredNonSecureSystemMemorySizeMisc = 0x80 * 4 * 1024;
19
20} // namespace impl
21
22constexpr const std::size_t RequiredNonSecureSystemMemorySize =
23 impl::RequiredNonSecureSystemMemorySizeVi + impl::RequiredNonSecureSystemMemorySizeNvservices +
24 impl::RequiredNonSecureSystemMemorySizeMisc;
25
26namespace {
27
28u32 GetMemoryModeForInit() {
29 return 0x01;
30}
31
32u32 GetMemorySizeForInit() {
33 return 0;
34}
35
36Smc::MemoryArrangement GetMemoryArrangeForInit() {
37 switch (GetMemoryModeForInit() & 0x3F) {
38 case 0x01:
39 default:
40 return Smc::MemoryArrangement_4GB;
41 case 0x02:
42 return Smc::MemoryArrangement_4GBForAppletDev;
43 case 0x03:
44 return Smc::MemoryArrangement_4GBForSystemDev;
45 case 0x11:
46 return Smc::MemoryArrangement_6GB;
47 case 0x12:
48 return Smc::MemoryArrangement_6GBForAppletDev;
49 case 0x21:
50 return Smc::MemoryArrangement_8GB;
51 }
52}
53} // namespace
54
55// Initialization.
56size_t KSystemControl::Init::GetIntendedMemorySize() {
57 switch (GetMemorySizeForInit()) {
58 case Smc::MemorySize_4GB:
59 default: // All invalid modes should go to 4GB.
60 return Common::Size_4_GB;
61 case Smc::MemorySize_6GB:
62 return Common::Size_6_GB;
63 case Smc::MemorySize_8GB:
64 return Common::Size_8_GB;
65 }
66}
67
68PAddr KSystemControl::Init::GetKernelPhysicalBaseAddress(u64 base_address) {
69 return base_address;
70}
71
72bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
73 return true;
74}
75
76std::size_t KSystemControl::Init::GetApplicationPoolSize() {
77 // Get the base pool size.
78 const size_t base_pool_size = []() -> size_t {
79 switch (GetMemoryArrangeForInit()) {
80 case Smc::MemoryArrangement_4GB:
81 default:
82 return Common::Size_3285_MB;
83 case Smc::MemoryArrangement_4GBForAppletDev:
84 return Common::Size_2048_MB;
85 case Smc::MemoryArrangement_4GBForSystemDev:
86 return Common::Size_3285_MB;
87 case Smc::MemoryArrangement_6GB:
88 return Common::Size_4916_MB;
89 case Smc::MemoryArrangement_6GBForAppletDev:
90 return Common::Size_3285_MB;
91 case Smc::MemoryArrangement_8GB:
92 return Common::Size_4916_MB;
93 }
94 }();
95
96 // Return (possibly) adjusted size.
97 return base_pool_size;
98}
99
100size_t KSystemControl::Init::GetAppletPoolSize() {
101 // Get the base pool size.
102 const size_t base_pool_size = []() -> size_t {
103 switch (GetMemoryArrangeForInit()) {
104 case Smc::MemoryArrangement_4GB:
105 default:
106 return Common::Size_507_MB;
107 case Smc::MemoryArrangement_4GBForAppletDev:
108 return Common::Size_1554_MB;
109 case Smc::MemoryArrangement_4GBForSystemDev:
110 return Common::Size_448_MB;
111 case Smc::MemoryArrangement_6GB:
112 return Common::Size_562_MB;
113 case Smc::MemoryArrangement_6GBForAppletDev:
114 return Common::Size_2193_MB;
115 case Smc::MemoryArrangement_8GB:
116 return Common::Size_2193_MB;
117 }
118 }();
119
120 // Return (possibly) adjusted size.
121 constexpr size_t ExtraSystemMemoryForAtmosphere = Common::Size_33_MB;
122 return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
123}
124
125size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() {
126 // Verify that our minimum is at least as large as Nintendo's.
127 constexpr size_t MinimumSize = RequiredNonSecureSystemMemorySize;
128 static_assert(MinimumSize >= 0x29C8000);
129
130 return MinimumSize;
131}
132
133namespace {
134template <typename F>
135u64 GenerateUniformRange(u64 min, u64 max, F f) {
136 // Handle the case where the difference is too large to represent.
137 if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
138 return f();
139 }
140
141 // Iterate until we get a value in range.
142 const u64 range_size = ((max + 1) - min);
143 const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
144 while (true) {
145 if (const u64 rnd = f(); rnd < effective_max) {
146 return min + (rnd % range_size);
147 }
148 }
149}
150
151} // Anonymous namespace
152
153u64 KSystemControl::GenerateRandomU64() {
154 static std::random_device device;
155 static std::mt19937 gen(device());
156 static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
157 return distribution(gen);
158}
159
160u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
161 return GenerateUniformRange(min, max, GenerateRandomU64);
162}
163
164} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
new file mode 100644
index 000000000..52f230ced
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
@@ -0,0 +1,28 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9namespace Kernel::Board::Nintendo::Nx {
10
11class KSystemControl {
12public:
13 class Init {
14 public:
15 // Initialization.
16 static std::size_t GetIntendedMemorySize();
17 static PAddr GetKernelPhysicalBaseAddress(u64 base_address);
18 static bool ShouldIncreaseThreadResourceLimit();
19 static std::size_t GetApplicationPoolSize();
20 static std::size_t GetAppletPoolSize();
21 static std::size_t GetMinimumNonSecureSystemPoolSize();
22 };
23
24 static u64 GenerateRandomRange(u64 min, u64 max);
25 static u64 GenerateRandomU64();
26};
27
28} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h
new file mode 100644
index 000000000..0c366b252
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h
@@ -0,0 +1,26 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9namespace Kernel::Board::Nintendo::Nx::Smc {
10
11enum MemorySize {
12 MemorySize_4GB = 0,
13 MemorySize_6GB = 1,
14 MemorySize_8GB = 2,
15};
16
17enum MemoryArrangement {
18 MemoryArrangement_4GB = 0,
19 MemoryArrangement_4GBForAppletDev = 1,
20 MemoryArrangement_4GBForSystemDev = 2,
21 MemoryArrangement_6GB = 3,
22 MemoryArrangement_6GBForAppletDev = 4,
23 MemoryArrangement_8GB = 5,
24};
25
26} // namespace Kernel::Board::Nintendo::Nx::Smc
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 161d9f782..2b363b1d9 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -75,10 +75,14 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
75 if (incoming) { 75 if (incoming) {
76 // Populate the object lists with the data in the IPC request. 76 // Populate the object lists with the data in the IPC request.
77 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { 77 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
78 copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>())); 78 const u32 copy_handle{rp.Pop<Handle>()};
79 copy_handles.push_back(copy_handle);
80 copy_objects.push_back(handle_table.GetGeneric(copy_handle));
79 } 81 }
80 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { 82 for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
81 move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>())); 83 const u32 move_handle{rp.Pop<Handle>()};
84 move_handles.push_back(move_handle);
85 move_objects.push_back(handle_table.GetGeneric(move_handle));
82 } 86 }
83 } else { 87 } else {
84 // For responses we just ignore the handles, they're empty and will be populated when 88 // For responses we just ignore the handles, they're empty and will be populated when
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 9a769781b..6fba42615 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -210,6 +210,14 @@ public:
210 /// Helper function to test whether the output buffer at buffer_index can be written 210 /// Helper function to test whether the output buffer at buffer_index can be written
211 bool CanWriteBuffer(std::size_t buffer_index = 0) const; 211 bool CanWriteBuffer(std::size_t buffer_index = 0) const;
212 212
213 Handle GetCopyHandle(std::size_t index) const {
214 return copy_handles.at(index);
215 }
216
217 Handle GetMoveHandle(std::size_t index) const {
218 return move_handles.at(index);
219 }
220
213 template <typename T> 221 template <typename T>
214 std::shared_ptr<T> GetCopyObject(std::size_t index) { 222 std::shared_ptr<T> GetCopyObject(std::size_t index) {
215 return DynamicObjectCast<T>(copy_objects.at(index)); 223 return DynamicObjectCast<T>(copy_objects.at(index));
@@ -285,6 +293,8 @@ private:
285 std::shared_ptr<Kernel::ServerSession> server_session; 293 std::shared_ptr<Kernel::ServerSession> server_session;
286 std::shared_ptr<KThread> thread; 294 std::shared_ptr<KThread> thread;
287 // TODO(yuriks): Check common usage of this and optimize size accordingly 295 // TODO(yuriks): Check common usage of this and optimize size accordingly
296 boost::container::small_vector<Handle, 8> move_handles;
297 boost::container::small_vector<Handle, 8> copy_handles;
288 boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects; 298 boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects;
289 boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects; 299 boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects;
290 boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; 300 boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp
index 24944d15b..c7549f7a2 100644
--- a/src/core/hle/kernel/k_address_space_info.cpp
+++ b/src/core/hle/kernel/k_address_space_info.cpp
@@ -5,45 +5,34 @@
5#include <array> 5#include <array>
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/common_sizes.h"
8#include "core/hle/kernel/k_address_space_info.h" 9#include "core/hle/kernel/k_address_space_info.h"
9 10
10namespace Kernel { 11namespace Kernel {
11 12
12namespace { 13namespace {
13 14
14enum : u64 {
15 Size_1_MB = 0x100000,
16 Size_2_MB = 2 * Size_1_MB,
17 Size_128_MB = 128 * Size_1_MB,
18 Size_1_GB = 0x40000000,
19 Size_2_GB = 2 * Size_1_GB,
20 Size_4_GB = 4 * Size_1_GB,
21 Size_6_GB = 6 * Size_1_GB,
22 Size_64_GB = 64 * Size_1_GB,
23 Size_512_GB = 512 * Size_1_GB,
24 Invalid = std::numeric_limits<u64>::max(),
25};
26
27// clang-format off 15// clang-format off
28constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ 16constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{
29 { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, }, 17 { .bit_width = 32, .address = Common::Size_2_MB , .size = Common::Size_1_GB - Common::Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, },
30 { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, 18 { .bit_width = 32, .address = Common::Size_1_GB , .size = Common::Size_4_GB - Common::Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
31 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, }, 19 { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, },
32 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, }, 20 { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, },
33 { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, }, 21 { .bit_width = 36, .address = Common::Size_128_MB , .size = Common::Size_2_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, },
34 { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, 22 { .bit_width = 36, .address = Common::Size_2_GB , .size = Common::Size_64_GB - Common::Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
35 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, 23 { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
36 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, }, 24 { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, },
37 { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, }, 25 { .bit_width = 39, .address = Common::Size_128_MB , .size = Common::Size_512_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, },
38 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall }, 26 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall },
39 { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, 27 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
40 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, }, 28 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, },
41 { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, }, 29 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, },
42}}; 30}};
43// clang-format on 31// clang-format on
44 32
45constexpr bool IsAllowedIndexForAddress(std::size_t index) { 33constexpr bool IsAllowedIndexForAddress(std::size_t index) {
46 return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid; 34 return index < AddressSpaceInfos.size() &&
35 AddressSpaceInfos[index].address != Common::Size_Invalid;
47} 36}
48 37
49using IndexArray = 38using IndexArray =
diff --git a/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp
new file mode 100644
index 000000000..a78551291
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp
@@ -0,0 +1,199 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/alignment.h"
6#include "core/hle/kernel/k_memory_layout.h"
7#include "core/hle/kernel/k_memory_manager.h"
8#include "core/hle/kernel/k_system_control.h"
9#include "core/hle/kernel/k_trace.h"
10
11namespace Kernel {
12
13namespace {
14
15constexpr size_t CarveoutAlignment = 0x20000;
16constexpr size_t CarveoutSizeMax = (512ULL * 1024 * 1024) - CarveoutAlignment;
17
18bool SetupPowerManagementControllerMemoryRegion(KMemoryLayout& memory_layout) {
19 // Above firmware 2.0.0, the PMC is not mappable.
20 return memory_layout.GetPhysicalMemoryRegionTree().Insert(
21 0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap) &&
22 memory_layout.GetPhysicalMemoryRegionTree().Insert(
23 0x7000E400, 0xC00,
24 KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap);
25}
26
27void InsertPoolPartitionRegionIntoBothTrees(KMemoryLayout& memory_layout, size_t start, size_t size,
28 KMemoryRegionType phys_type,
29 KMemoryRegionType virt_type, u32& cur_attr) {
30 const u32 attr = cur_attr++;
31 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(start, size,
32 static_cast<u32>(phys_type), attr));
33 const KMemoryRegion* phys = memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(
34 static_cast<u32>(phys_type), attr);
35 ASSERT(phys != nullptr);
36 ASSERT(phys->GetEndAddress() != 0);
37 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size,
38 static_cast<u32>(virt_type), attr));
39}
40
41} // namespace
42
43namespace Init {
44
45void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout) {
46 ASSERT(SetupPowerManagementControllerMemoryRegion(memory_layout));
47 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
48 0x70019000, 0x1000, KMemoryRegionType_MemoryController | KMemoryRegionAttr_NoUserMap));
49 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
50 0x7001C000, 0x1000, KMemoryRegionType_MemoryController0 | KMemoryRegionAttr_NoUserMap));
51 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
52 0x7001D000, 0x1000, KMemoryRegionType_MemoryController1 | KMemoryRegionAttr_NoUserMap));
53 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
54 0x50040000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
55 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
56 0x50041000, 0x1000,
57 KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap));
58 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
59 0x50042000, 0x1000,
60 KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap));
61 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
62 0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
63
64 // Map IRAM unconditionally, to support debug-logging-to-iram build config.
65 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
66 0x40000000, 0x40000, KMemoryRegionType_LegacyLpsIram | KMemoryRegionAttr_ShouldKernelMap));
67
68 // Above firmware 2.0.0, prevent mapping the bpmp exception vectors or the ipatch region.
69 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
70 0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
71 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
72 0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
73}
74
75void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) {
76 const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize();
77 const PAddr physical_memory_base_address =
78 KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress);
79
80 // Insert blocks into the tree.
81 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
82 physical_memory_base_address, intended_memory_size, KMemoryRegionType_Dram));
83 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
84 physical_memory_base_address, ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly));
85
86 // Insert the KTrace block at the end of Dram, if KTrace is enabled.
87 static_assert(!IsKTraceEnabled || KTraceBufferSize > 0);
88 if constexpr (IsKTraceEnabled) {
89 const PAddr ktrace_buffer_phys_addr =
90 physical_memory_base_address + intended_memory_size - KTraceBufferSize;
91 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
92 ktrace_buffer_phys_addr, KTraceBufferSize, KMemoryRegionType_KernelTraceBuffer));
93 }
94}
95
96void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout) {
97 // Start by identifying the extents of the DRAM memory region.
98 const auto dram_extents = memory_layout.GetMainMemoryPhysicalExtents();
99 ASSERT(dram_extents.GetEndAddress() != 0);
100
101 // Determine the end of the pool region.
102 const u64 pool_end = dram_extents.GetEndAddress() - KTraceBufferSize;
103
104 // Find the start of the kernel DRAM region.
105 const KMemoryRegion* kernel_dram_region =
106 memory_layout.GetPhysicalMemoryRegionTree().FindFirstDerived(
107 KMemoryRegionType_DramKernelBase);
108 ASSERT(kernel_dram_region != nullptr);
109
110 const u64 kernel_dram_start = kernel_dram_region->GetAddress();
111 ASSERT(Common::IsAligned(kernel_dram_start, CarveoutAlignment));
112
113 // Find the start of the pool partitions region.
114 const KMemoryRegion* pool_partitions_region =
115 memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(
116 KMemoryRegionType_DramPoolPartition, 0);
117 ASSERT(pool_partitions_region != nullptr);
118 const u64 pool_partitions_start = pool_partitions_region->GetAddress();
119
120 // Setup the pool partition layouts.
121 // On 5.0.0+, setup modern 4-pool-partition layout.
122
123 // Get Application and Applet pool sizes.
124 const size_t application_pool_size = KSystemControl::Init::GetApplicationPoolSize();
125 const size_t applet_pool_size = KSystemControl::Init::GetAppletPoolSize();
126 const size_t unsafe_system_pool_min_size =
127 KSystemControl::Init::GetMinimumNonSecureSystemPoolSize();
128
129 // Decide on starting addresses for our pools.
130 const u64 application_pool_start = pool_end - application_pool_size;
131 const u64 applet_pool_start = application_pool_start - applet_pool_size;
132 const u64 unsafe_system_pool_start = std::min(
133 kernel_dram_start + CarveoutSizeMax,
134 Common::AlignDown(applet_pool_start - unsafe_system_pool_min_size, CarveoutAlignment));
135 const size_t unsafe_system_pool_size = applet_pool_start - unsafe_system_pool_start;
136
137 // We want to arrange application pool depending on where the middle of dram is.
138 const u64 dram_midpoint = (dram_extents.GetAddress() + dram_extents.GetEndAddress()) / 2;
139 u32 cur_pool_attr = 0;
140 size_t total_overhead_size = 0;
141 if (dram_extents.GetEndAddress() <= dram_midpoint || dram_midpoint <= application_pool_start) {
142 InsertPoolPartitionRegionIntoBothTrees(
143 memory_layout, application_pool_start, application_pool_size,
144 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
145 cur_pool_attr);
146 total_overhead_size +=
147 KMemoryManager::CalculateManagementOverheadSize(application_pool_size);
148 } else {
149 const size_t first_application_pool_size = dram_midpoint - application_pool_start;
150 const size_t second_application_pool_size =
151 application_pool_start + application_pool_size - dram_midpoint;
152 InsertPoolPartitionRegionIntoBothTrees(
153 memory_layout, application_pool_start, first_application_pool_size,
154 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
155 cur_pool_attr);
156 InsertPoolPartitionRegionIntoBothTrees(
157 memory_layout, dram_midpoint, second_application_pool_size,
158 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
159 cur_pool_attr);
160 total_overhead_size +=
161 KMemoryManager::CalculateManagementOverheadSize(first_application_pool_size);
162 total_overhead_size +=
163 KMemoryManager::CalculateManagementOverheadSize(second_application_pool_size);
164 }
165
166 // Insert the applet pool.
167 InsertPoolPartitionRegionIntoBothTrees(memory_layout, applet_pool_start, applet_pool_size,
168 KMemoryRegionType_DramAppletPool,
169 KMemoryRegionType_VirtualDramAppletPool, cur_pool_attr);
170 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(applet_pool_size);
171
172 // Insert the nonsecure system pool.
173 InsertPoolPartitionRegionIntoBothTrees(
174 memory_layout, unsafe_system_pool_start, unsafe_system_pool_size,
175 KMemoryRegionType_DramSystemNonSecurePool, KMemoryRegionType_VirtualDramSystemNonSecurePool,
176 cur_pool_attr);
177 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(unsafe_system_pool_size);
178
179 // Insert the pool management region.
180 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(
181 (unsafe_system_pool_start - pool_partitions_start) - total_overhead_size);
182 const u64 pool_management_start = unsafe_system_pool_start - total_overhead_size;
183 const size_t pool_management_size = total_overhead_size;
184 u32 pool_management_attr = 0;
185 InsertPoolPartitionRegionIntoBothTrees(
186 memory_layout, pool_management_start, pool_management_size,
187 KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement,
188 pool_management_attr);
189
190 // Insert the system pool.
191 const u64 system_pool_size = pool_management_start - pool_partitions_start;
192 InsertPoolPartitionRegionIntoBothTrees(memory_layout, pool_partitions_start, system_pool_size,
193 KMemoryRegionType_DramSystemPool,
194 KMemoryRegionType_VirtualDramSystemPool, cur_pool_attr);
195}
196
197} // namespace Init
198
199} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp
new file mode 100644
index 000000000..fb1e2435f
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_layout.cpp
@@ -0,0 +1,166 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6
7#include "common/alignment.h"
8#include "core/hle/kernel/k_memory_layout.h"
9#include "core/hle/kernel/k_system_control.h"
10
11namespace Kernel {
12
13namespace {
14
15template <typename... Args>
16KMemoryRegion* AllocateRegion(KMemoryRegionAllocator& memory_region_allocator, Args&&... args) {
17 return memory_region_allocator.Allocate(std::forward<Args>(args)...);
18}
19
20} // namespace
21
22KMemoryRegionTree::KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_)
23 : memory_region_allocator{memory_region_allocator_} {}
24
25void KMemoryRegionTree::InsertDirectly(u64 address, u64 last_address, u32 attr, u32 type_id) {
26 this->insert(*AllocateRegion(memory_region_allocator, address, last_address, attr, type_id));
27}
28
29bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) {
30 // Locate the memory region that contains the address.
31 KMemoryRegion* found = this->FindModifiable(address);
32
33 // We require that the old attr is correct.
34 if (found->GetAttributes() != old_attr) {
35 return false;
36 }
37
38 // We further require that the region can be split from the old region.
39 const u64 inserted_region_end = address + size;
40 const u64 inserted_region_last = inserted_region_end - 1;
41 if (found->GetLastAddress() < inserted_region_last) {
42 return false;
43 }
44
45 // Further, we require that the type id is a valid transformation.
46 if (!found->CanDerive(type_id)) {
47 return false;
48 }
49
50 // Cache information from the region before we remove it.
51 const u64 old_address = found->GetAddress();
52 const u64 old_last = found->GetLastAddress();
53 const u64 old_pair = found->GetPairAddress();
54 const u32 old_type = found->GetType();
55
56 // Erase the existing region from the tree.
57 this->erase(this->iterator_to(*found));
58
59 // Insert the new region into the tree.
60 if (old_address == address) {
61 // Reuse the old object for the new region, if we can.
62 found->Reset(address, inserted_region_last, old_pair, new_attr, type_id);
63 this->insert(*found);
64 } else {
65 // If we can't re-use, adjust the old region.
66 found->Reset(old_address, address - 1, old_pair, old_attr, old_type);
67 this->insert(*found);
68
69 // Insert a new region for the split.
70 const u64 new_pair = (old_pair != std::numeric_limits<u64>::max())
71 ? old_pair + (address - old_address)
72 : old_pair;
73 this->insert(*AllocateRegion(memory_region_allocator, address, inserted_region_last,
74 new_pair, new_attr, type_id));
75 }
76
77 // If we need to insert a region after the region, do so.
78 if (old_last != inserted_region_last) {
79 const u64 after_pair = (old_pair != std::numeric_limits<u64>::max())
80 ? old_pair + (inserted_region_end - old_address)
81 : old_pair;
82 this->insert(*AllocateRegion(memory_region_allocator, inserted_region_end, old_last,
83 after_pair, old_attr, old_type));
84 }
85
86 return true;
87}
88
89VAddr KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) {
90 // We want to find the total extents of the type id.
91 const auto extents = this->GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id));
92
93 // Ensure that our alignment is correct.
94 ASSERT(Common::IsAligned(extents.GetAddress(), alignment));
95
96 const u64 first_address = extents.GetAddress();
97 const u64 last_address = extents.GetLastAddress();
98
99 const u64 first_index = first_address / alignment;
100 const u64 last_index = last_address / alignment;
101
102 while (true) {
103 const u64 candidate =
104 KSystemControl::GenerateRandomRange(first_index, last_index) * alignment;
105
106 // Ensure that the candidate doesn't overflow with the size.
107 if (!(candidate < candidate + size)) {
108 continue;
109 }
110
111 const u64 candidate_last = candidate + size - 1;
112
113 // Ensure that the candidate fits within the region.
114 if (candidate_last > last_address) {
115 continue;
116 }
117
118 // Locate the candidate region, and ensure it fits and has the correct type id.
119 if (const auto& candidate_region = *this->Find(candidate);
120 !(candidate_last <= candidate_region.GetLastAddress() &&
121 candidate_region.GetType() == type_id)) {
122 continue;
123 }
124
125 return candidate;
126 }
127}
128
129KMemoryLayout::KMemoryLayout()
130 : virtual_tree{memory_region_allocator}, physical_tree{memory_region_allocator},
131 virtual_linear_tree{memory_region_allocator}, physical_linear_tree{memory_region_allocator} {}
132
133void KMemoryLayout::InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start,
134 VAddr linear_virtual_start) {
135 // Set static differences.
136 linear_phys_to_virt_diff = linear_virtual_start - aligned_linear_phys_start;
137 linear_virt_to_phys_diff = aligned_linear_phys_start - linear_virtual_start;
138
139 // Initialize linear trees.
140 for (auto& region : GetPhysicalMemoryRegionTree()) {
141 if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
142 GetPhysicalLinearMemoryRegionTree().InsertDirectly(
143 region.GetAddress(), region.GetLastAddress(), region.GetAttributes(),
144 region.GetType());
145 }
146 }
147
148 for (auto& region : GetVirtualMemoryRegionTree()) {
149 if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
150 GetVirtualLinearMemoryRegionTree().InsertDirectly(
151 region.GetAddress(), region.GetLastAddress(), region.GetAttributes(),
152 region.GetType());
153 }
154 }
155}
156
157size_t KMemoryLayout::GetResourceRegionSizeForInit() {
158 // Calculate resource region size based on whether we allow extra threads.
159 const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
160 size_t resource_region_size =
161 KernelResourceSize + (use_extra_resources ? KernelSlabHeapAdditionalSize : 0);
162
163 return resource_region_size;
164}
165
166} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_layout.h b/src/core/hle/kernel/k_memory_layout.h
index 0821d2d8c..288642d9a 100644
--- a/src/core/hle/kernel/k_memory_layout.h
+++ b/src/core/hle/kernel/k_memory_layout.h
@@ -1,23 +1,69 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <utility>
8
9#include "common/alignment.h"
10#include "common/common_sizes.h"
7#include "common/common_types.h" 11#include "common/common_types.h"
8#include "core/device_memory.h" 12#include "core/device_memory.h"
13#include "core/hle/kernel/k_memory_region.h"
14#include "core/hle/kernel/k_memory_region_type.h"
15#include "core/hle/kernel/memory_types.h"
9 16
10namespace Kernel { 17namespace Kernel {
11 18
12constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; 19constexpr std::size_t L1BlockSize = Common::Size_1_GB;
20constexpr std::size_t L2BlockSize = Common::Size_2_MB;
21
22constexpr std::size_t GetMaximumOverheadSize(std::size_t size) {
23 return (Common::DivideUp(size, L1BlockSize) + Common::DivideUp(size, L2BlockSize)) * PageSize;
24}
25
26constexpr std::size_t MainMemorySize = Common::Size_4_GB;
27constexpr std::size_t MainMemorySizeMax = Common::Size_8_GB;
28
29constexpr std::size_t ReservedEarlyDramSize = 0x60000;
30constexpr std::size_t DramPhysicalAddress = 0x80000000;
31
32constexpr std::size_t KernelAslrAlignment = Common::Size_2_MB;
13constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; 33constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39;
14constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48; 34constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48;
35
15constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth; 36constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth;
16constexpr std::size_t KernelVirtualAddressSpaceEnd = 37constexpr std::size_t KernelVirtualAddressSpaceEnd =
17 KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment); 38 KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment);
18constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1; 39constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1ULL;
19constexpr std::size_t KernelVirtualAddressSpaceSize = 40constexpr std::size_t KernelVirtualAddressSpaceSize =
20 KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase; 41 KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase;
42constexpr std::size_t KernelVirtualAddressCodeBase = KernelVirtualAddressSpaceBase;
43constexpr std::size_t KernelVirtualAddressCodeSize = 0x62000;
44constexpr std::size_t KernelVirtualAddressCodeEnd =
45 KernelVirtualAddressCodeBase + KernelVirtualAddressCodeSize;
46
47constexpr std::size_t KernelPhysicalAddressSpaceBase = 0ULL;
48constexpr std::size_t KernelPhysicalAddressSpaceEnd =
49 KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceWidth;
50constexpr std::size_t KernelPhysicalAddressSpaceLast = KernelPhysicalAddressSpaceEnd - 1ULL;
51constexpr std::size_t KernelPhysicalAddressSpaceSize =
52 KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase;
53constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize;
54
55constexpr std::size_t KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax);
56constexpr std::size_t KernelInitialPageHeapSize = Common::Size_128_KB;
57
58constexpr std::size_t KernelSlabHeapDataSize = Common::Size_5_MB;
59constexpr std::size_t KernelSlabHeapGapsSize = Common::Size_2_MB - Common::Size_64_KB;
60constexpr std::size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSize;
61
62// NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860.
63constexpr std::size_t KernelSlabHeapAdditionalSize = 0x68000ULL;
64
65constexpr std::size_t KernelResourceSize =
66 KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;
21 67
22constexpr bool IsKernelAddressKey(VAddr key) { 68constexpr bool IsKernelAddressKey(VAddr key) {
23 return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast; 69 return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast;
@@ -27,64 +73,327 @@ constexpr bool IsKernelAddress(VAddr address) {
27 return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; 73 return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
28} 74}
29 75
30class KMemoryRegion final { 76class KMemoryLayout final {
31 friend class KMemoryLayout;
32
33public: 77public:
34 constexpr PAddr StartAddress() const { 78 KMemoryLayout();
35 return start_address; 79
80 KMemoryRegionTree& GetVirtualMemoryRegionTree() {
81 return virtual_tree;
82 }
83 const KMemoryRegionTree& GetVirtualMemoryRegionTree() const {
84 return virtual_tree;
85 }
86 KMemoryRegionTree& GetPhysicalMemoryRegionTree() {
87 return physical_tree;
88 }
89 const KMemoryRegionTree& GetPhysicalMemoryRegionTree() const {
90 return physical_tree;
91 }
92 KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() {
93 return virtual_linear_tree;
94 }
95 const KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() const {
96 return virtual_linear_tree;
97 }
98 KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() {
99 return physical_linear_tree;
100 }
101 const KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() const {
102 return physical_linear_tree;
103 }
104
105 VAddr GetLinearVirtualAddress(PAddr address) const {
106 return address + linear_phys_to_virt_diff;
107 }
108 PAddr GetLinearPhysicalAddress(VAddr address) const {
109 return address + linear_virt_to_phys_diff;
110 }
111
112 const KMemoryRegion* FindVirtual(VAddr address) const {
113 return Find(address, GetVirtualMemoryRegionTree());
114 }
115 const KMemoryRegion* FindPhysical(PAddr address) const {
116 return Find(address, GetPhysicalMemoryRegionTree());
117 }
118
119 const KMemoryRegion* FindVirtualLinear(VAddr address) const {
120 return Find(address, GetVirtualLinearMemoryRegionTree());
121 }
122 const KMemoryRegion* FindPhysicalLinear(PAddr address) const {
123 return Find(address, GetPhysicalLinearMemoryRegionTree());
124 }
125
126 VAddr GetMainStackTopAddress(s32 core_id) const {
127 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack);
128 }
129 VAddr GetIdleStackTopAddress(s32 core_id) const {
130 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack);
131 }
132 VAddr GetExceptionStackTopAddress(s32 core_id) const {
133 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack);
134 }
135
136 VAddr GetSlabRegionAddress() const {
137 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab))
138 .GetAddress();
139 }
140
141 const KMemoryRegion& GetDeviceRegion(KMemoryRegionType type) const {
142 return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type));
143 }
144 PAddr GetDevicePhysicalAddress(KMemoryRegionType type) const {
145 return GetDeviceRegion(type).GetAddress();
146 }
147 VAddr GetDeviceVirtualAddress(KMemoryRegionType type) const {
148 return GetDeviceRegion(type).GetPairAddress();
149 }
150
151 const KMemoryRegion& GetPoolManagementRegion() const {
152 return Dereference(
153 GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramPoolManagement));
154 }
155 const KMemoryRegion& GetPageTableHeapRegion() const {
156 return Dereference(
157 GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap));
158 }
159 const KMemoryRegion& GetKernelStackRegion() const {
160 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack));
161 }
162 const KMemoryRegion& GetTempRegion() const {
163 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp));
164 }
165
166 const KMemoryRegion& GetKernelTraceBufferRegion() const {
167 return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(
168 KMemoryRegionType_VirtualDramKernelTraceBuffer));
169 }
170
171 const KMemoryRegion& GetVirtualLinearRegion(VAddr address) const {
172 return Dereference(FindVirtualLinear(address));
173 }
174
175 const KMemoryRegion* GetPhysicalKernelTraceBufferRegion() const {
176 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_KernelTraceBuffer);
177 }
178 const KMemoryRegion* GetPhysicalOnMemoryBootImageRegion() const {
179 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_OnMemoryBootImage);
180 }
181 const KMemoryRegion* GetPhysicalDTBRegion() const {
182 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB);
183 }
184
185 bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address) const {
186 return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
187 KMemoryRegionType_DramUserPool);
188 }
189 bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address) const {
190 return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(),
191 KMemoryRegionType_VirtualDramUserPool);
192 }
193
194 bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address, size_t size) const {
195 return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
196 KMemoryRegionType_DramUserPool);
197 }
198 bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address, size_t size) const {
199 return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(),
200 KMemoryRegionType_VirtualDramUserPool);
201 }
202
203 bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address) const {
204 return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
205 static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
206 }
207 bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address,
208 size_t size) const {
209 return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
210 static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
211 }
212
213 std::pair<size_t, size_t> GetTotalAndKernelMemorySizes() const {
214 size_t total_size = 0, kernel_size = 0;
215 for (const auto& region : GetPhysicalMemoryRegionTree()) {
216 if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
217 total_size += region.GetSize();
218 if (!region.IsDerivedFrom(KMemoryRegionType_DramUserPool)) {
219 kernel_size += region.GetSize();
220 }
221 }
222 }
223 return std::make_pair(total_size, kernel_size);
224 }
225
226 void InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start,
227 VAddr linear_virtual_start);
228 static size_t GetResourceRegionSizeForInit();
229
230 auto GetKernelRegionExtents() const {
231 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel);
232 }
233 auto GetKernelCodeRegionExtents() const {
234 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode);
235 }
236 auto GetKernelStackRegionExtents() const {
237 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelStack);
238 }
239 auto GetKernelMiscRegionExtents() const {
240 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelMisc);
241 }
242 auto GetKernelSlabRegionExtents() const {
243 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelSlab);
244 }
245
246 auto GetLinearRegionPhysicalExtents() const {
247 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
248 KMemoryRegionAttr_LinearMapped);
249 }
250
251 auto GetLinearRegionVirtualExtents() const {
252 const auto physical = GetLinearRegionPhysicalExtents();
253 return KMemoryRegion(GetLinearVirtualAddress(physical.GetAddress()),
254 GetLinearVirtualAddress(physical.GetLastAddress()), 0,
255 KMemoryRegionType_None);
256 }
257
258 auto GetMainMemoryPhysicalExtents() const {
259 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Dram);
260 }
261 auto GetCarveoutRegionExtents() const {
262 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
263 KMemoryRegionAttr_CarveoutProtected);
264 }
265
266 auto GetKernelRegionPhysicalExtents() const {
267 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
268 KMemoryRegionType_DramKernelBase);
269 }
270 auto GetKernelCodeRegionPhysicalExtents() const {
271 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
272 KMemoryRegionType_DramKernelCode);
273 }
274 auto GetKernelSlabRegionPhysicalExtents() const {
275 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
276 KMemoryRegionType_DramKernelSlab);
277 }
278 auto GetKernelPageTableHeapRegionPhysicalExtents() const {
279 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
280 KMemoryRegionType_DramKernelPtHeap);
281 }
282 auto GetKernelInitPageTableRegionPhysicalExtents() const {
283 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
284 KMemoryRegionType_DramKernelInitPt);
285 }
286
287 auto GetKernelPoolManagementRegionPhysicalExtents() const {
288 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
289 KMemoryRegionType_DramPoolManagement);
290 }
291 auto GetKernelPoolPartitionRegionPhysicalExtents() const {
292 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
293 KMemoryRegionType_DramPoolPartition);
294 }
295 auto GetKernelSystemPoolRegionPhysicalExtents() const {
296 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
297 KMemoryRegionType_DramSystemPool);
298 }
299 auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() const {
300 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
301 KMemoryRegionType_DramSystemNonSecurePool);
302 }
303 auto GetKernelAppletPoolRegionPhysicalExtents() const {
304 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
305 KMemoryRegionType_DramAppletPool);
306 }
307 auto GetKernelApplicationPoolRegionPhysicalExtents() const {
308 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
309 KMemoryRegionType_DramApplicationPool);
36 } 310 }
37 311
38 constexpr PAddr EndAddress() const { 312 auto GetKernelTraceBufferRegionPhysicalExtents() const {
39 return end_address; 313 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
314 KMemoryRegionType_KernelTraceBuffer);
40 } 315 }
41 316
42private: 317private:
43 constexpr KMemoryRegion() = default; 318 template <typename AddressType>
44 constexpr KMemoryRegion(PAddr start_address, PAddr end_address) 319 static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address,
45 : start_address{start_address}, end_address{end_address} {} 320 const KMemoryRegionTree& tree, KMemoryRegionType type) {
321 // Check if the cached region already contains the address.
322 if (region != nullptr && region->Contains(address)) {
323 return true;
324 }
46 325
47 const PAddr start_address{}; 326 // Find the containing region, and update the cache.
48 const PAddr end_address{}; 327 if (const KMemoryRegion* found = tree.Find(address);
49}; 328 found != nullptr && found->IsDerivedFrom(type)) {
329 region = found;
330 return true;
331 } else {
332 return false;
333 }
334 }
50 335
51class KMemoryLayout final { 336 template <typename AddressType>
52public: 337 static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, size_t size,
53 constexpr const KMemoryRegion& Application() const { 338 const KMemoryRegionTree& tree, KMemoryRegionType type) {
54 return application; 339 // Get the end of the checked region.
340 const u64 last_address = address + size - 1;
341
342 // Walk the tree to verify the region is correct.
343 const KMemoryRegion* cur =
344 (region != nullptr && region->Contains(address)) ? region : tree.Find(address);
345 while (cur != nullptr && cur->IsDerivedFrom(type)) {
346 if (last_address <= cur->GetLastAddress()) {
347 region = cur;
348 return true;
349 }
350
351 cur = cur->GetNext();
352 }
353 return false;
55 } 354 }
56 355
57 constexpr const KMemoryRegion& Applet() const { 356 template <typename AddressType>
58 return applet; 357 static const KMemoryRegion* Find(AddressType address, const KMemoryRegionTree& tree) {
358 return tree.Find(address);
59 } 359 }
60 360
61 constexpr const KMemoryRegion& System() const { 361 static KMemoryRegion& Dereference(KMemoryRegion* region) {
62 return system; 362 ASSERT(region != nullptr);
363 return *region;
63 } 364 }
64 365
65 static constexpr KMemoryLayout GetDefaultLayout() { 366 static const KMemoryRegion& Dereference(const KMemoryRegion* region) {
66 constexpr std::size_t application_size{0xcd500000}; 367 ASSERT(region != nullptr);
67 constexpr std::size_t applet_size{0x1fb00000}; 368 return *region;
68 constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size}; 369 }
69 constexpr PAddr application_end_address{Core::DramMemoryMap::End}; 370
70 constexpr PAddr applet_start_address{application_start_address - applet_size}; 371 VAddr GetStackTopAddress(s32 core_id, KMemoryRegionType type) const {
71 constexpr PAddr applet_end_address{applet_start_address + applet_size}; 372 const auto& region = Dereference(
72 constexpr PAddr system_start_address{Core::DramMemoryMap::SlabHeapEnd}; 373 GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
73 constexpr PAddr system_end_address{applet_start_address}; 374 ASSERT(region.GetEndAddress() != 0);
74 return {application_start_address, application_end_address, applet_start_address, 375 return region.GetEndAddress();
75 applet_end_address, system_start_address, system_end_address};
76 } 376 }
77 377
78private: 378private:
79 constexpr KMemoryLayout(PAddr application_start_address, std::size_t application_size, 379 u64 linear_phys_to_virt_diff{};
80 PAddr applet_start_address, std::size_t applet_size, 380 u64 linear_virt_to_phys_diff{};
81 PAddr system_start_address, std::size_t system_size) 381 KMemoryRegionAllocator memory_region_allocator;
82 : application{application_start_address, application_size}, 382 KMemoryRegionTree virtual_tree;
83 applet{applet_start_address, applet_size}, system{system_start_address, system_size} {} 383 KMemoryRegionTree physical_tree;
84 384 KMemoryRegionTree virtual_linear_tree;
85 const KMemoryRegion application; 385 KMemoryRegionTree physical_linear_tree;
86 const KMemoryRegion applet;
87 const KMemoryRegion system;
88}; 386};
89 387
388namespace Init {
389
390// These should be generic, regardless of board.
391void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout);
392
393// These may be implemented in a board-specific manner.
394void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout);
395void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout);
396
397} // namespace Init
398
90} // namespace Kernel 399} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 9027602bf..aa71697b2 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -173,4 +173,16 @@ ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_page
173 return RESULT_SUCCESS; 173 return RESULT_SUCCESS;
174} 174}
175 175
176std::size_t KMemoryManager::Impl::CalculateManagementOverheadSize(std::size_t region_size) {
177 const std::size_t ref_count_size = (region_size / PageSize) * sizeof(u16);
178 const std::size_t optimize_map_size =
179 (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
180 Common::BitSize<u64>()) *
181 sizeof(u64);
182 const std::size_t manager_meta_size =
183 Common::AlignUp(optimize_map_size + ref_count_size, PageSize);
184 const std::size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(region_size);
185 return manager_meta_size + page_heap_size;
186}
187
176} // namespace Kernel 188} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index ae9f683b8..ac840b3d0 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -29,6 +29,10 @@ public:
29 29
30 Shift = 4, 30 Shift = 4,
31 Mask = (0xF << Shift), 31 Mask = (0xF << Shift),
32
33 // Aliases.
34 Unsafe = Application,
35 Secure = System,
32 }; 36 };
33 37
34 enum class Direction : u32 { 38 enum class Direction : u32 {
@@ -56,6 +60,10 @@ public:
56 static constexpr std::size_t MaxManagerCount = 10; 60 static constexpr std::size_t MaxManagerCount = 10;
57 61
58public: 62public:
63 static std::size_t CalculateManagementOverheadSize(std::size_t region_size) {
64 return Impl::CalculateManagementOverheadSize(region_size);
65 }
66
59 static constexpr u32 EncodeOption(Pool pool, Direction dir) { 67 static constexpr u32 EncodeOption(Pool pool, Direction dir) {
60 return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) | 68 return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) |
61 (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift)); 69 (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift));
@@ -86,6 +94,16 @@ private:
86 Pool pool{}; 94 Pool pool{};
87 95
88 public: 96 public:
97 static std::size_t CalculateManagementOverheadSize(std::size_t region_size);
98
99 static constexpr std::size_t CalculateOptimizedProcessOverheadSize(
100 std::size_t region_size) {
101 return (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
102 Common::BitSize<u64>()) *
103 sizeof(u64);
104 }
105
106 public:
89 Impl() = default; 107 Impl() = default;
90 108
91 std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); 109 std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address);
diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h
new file mode 100644
index 000000000..a861c04ab
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_region.h
@@ -0,0 +1,350 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/assert.h"
8#include "common/common_types.h"
9#include "common/intrusive_red_black_tree.h"
10#include "core/hle/kernel/k_memory_region_type.h"
11
12namespace Kernel {
13
14class KMemoryRegionAllocator;
15
16class KMemoryRegion final : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryRegion>,
17 NonCopyable {
18 friend class KMemoryRegionTree;
19
20public:
21 constexpr KMemoryRegion() = default;
22 constexpr KMemoryRegion(u64 address_, u64 last_address_)
23 : address{address_}, last_address{last_address_} {}
24 constexpr KMemoryRegion(u64 address_, u64 last_address_, u64 pair_address_, u32 attributes_,
25 u32 type_id_)
26 : address(address_), last_address(last_address_), pair_address(pair_address_),
27 attributes(attributes_), type_id(type_id_) {}
28 constexpr KMemoryRegion(u64 address_, u64 last_address_, u32 attributes_, u32 type_id_)
29 : KMemoryRegion(address_, last_address_, std::numeric_limits<u64>::max(), attributes_,
30 type_id_) {}
31
32 static constexpr int Compare(const KMemoryRegion& lhs, const KMemoryRegion& rhs) {
33 if (lhs.GetAddress() < rhs.GetAddress()) {
34 return -1;
35 } else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
36 return 0;
37 } else {
38 return 1;
39 }
40 }
41
42private:
43 constexpr void Reset(u64 a, u64 la, u64 p, u32 r, u32 t) {
44 address = a;
45 pair_address = p;
46 last_address = la;
47 attributes = r;
48 type_id = t;
49 }
50
51public:
52 constexpr u64 GetAddress() const {
53 return address;
54 }
55
56 constexpr u64 GetPairAddress() const {
57 return pair_address;
58 }
59
60 constexpr u64 GetLastAddress() const {
61 return last_address;
62 }
63
64 constexpr u64 GetEndAddress() const {
65 return this->GetLastAddress() + 1;
66 }
67
68 constexpr size_t GetSize() const {
69 return this->GetEndAddress() - this->GetAddress();
70 }
71
72 constexpr u32 GetAttributes() const {
73 return attributes;
74 }
75
76 constexpr u32 GetType() const {
77 return type_id;
78 }
79
80 constexpr void SetType(u32 type) {
81 ASSERT(this->CanDerive(type));
82 type_id = type;
83 }
84
85 constexpr bool Contains(u64 address) const {
86 ASSERT(this->GetEndAddress() != 0);
87 return this->GetAddress() <= address && address <= this->GetLastAddress();
88 }
89
90 constexpr bool IsDerivedFrom(u32 type) const {
91 return (this->GetType() | type) == this->GetType();
92 }
93
94 constexpr bool HasTypeAttribute(u32 attr) const {
95 return (this->GetType() | attr) == this->GetType();
96 }
97
98 constexpr bool CanDerive(u32 type) const {
99 return (this->GetType() | type) == type;
100 }
101
102 constexpr void SetPairAddress(u64 a) {
103 pair_address = a;
104 }
105
106 constexpr void SetTypeAttribute(u32 attr) {
107 type_id |= attr;
108 }
109
110private:
111 u64 address{};
112 u64 last_address{};
113 u64 pair_address{};
114 u32 attributes{};
115 u32 type_id{};
116};
117
118class KMemoryRegionTree final : NonCopyable {
119public:
120 struct DerivedRegionExtents {
121 const KMemoryRegion* first_region{};
122 const KMemoryRegion* last_region{};
123
124 constexpr DerivedRegionExtents() = default;
125
126 constexpr u64 GetAddress() const {
127 return this->first_region->GetAddress();
128 }
129
130 constexpr u64 GetLastAddress() const {
131 return this->last_region->GetLastAddress();
132 }
133
134 constexpr u64 GetEndAddress() const {
135 return this->GetLastAddress() + 1;
136 }
137
138 constexpr size_t GetSize() const {
139 return this->GetEndAddress() - this->GetAddress();
140 }
141 };
142
143private:
144 using TreeType =
145 Common::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
146
147public:
148 using value_type = TreeType::value_type;
149 using size_type = TreeType::size_type;
150 using difference_type = TreeType::difference_type;
151 using pointer = TreeType::pointer;
152 using const_pointer = TreeType::const_pointer;
153 using reference = TreeType::reference;
154 using const_reference = TreeType::const_reference;
155 using iterator = TreeType::iterator;
156 using const_iterator = TreeType::const_iterator;
157
158private:
159 TreeType m_tree{};
160 KMemoryRegionAllocator& memory_region_allocator;
161
162public:
163 explicit KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_);
164
165public:
166 KMemoryRegion* FindModifiable(u64 address) {
167 if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) {
168 return std::addressof(*it);
169 } else {
170 return nullptr;
171 }
172 }
173
174 const KMemoryRegion* Find(u64 address) const {
175 if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) {
176 return std::addressof(*it);
177 } else {
178 return nullptr;
179 }
180 }
181
182 const KMemoryRegion* FindByType(KMemoryRegionType type_id) const {
183 for (auto it = this->cbegin(); it != this->cend(); ++it) {
184 if (it->GetType() == static_cast<u32>(type_id)) {
185 return std::addressof(*it);
186 }
187 }
188 return nullptr;
189 }
190
191 const KMemoryRegion* FindByTypeAndAttribute(u32 type_id, u32 attr) const {
192 for (auto it = this->cbegin(); it != this->cend(); ++it) {
193 if (it->GetType() == type_id && it->GetAttributes() == attr) {
194 return std::addressof(*it);
195 }
196 }
197 return nullptr;
198 }
199
200 const KMemoryRegion* FindFirstDerived(KMemoryRegionType type_id) const {
201 for (auto it = this->cbegin(); it != this->cend(); it++) {
202 if (it->IsDerivedFrom(type_id)) {
203 return std::addressof(*it);
204 }
205 }
206 return nullptr;
207 }
208
209 const KMemoryRegion* FindLastDerived(KMemoryRegionType type_id) const {
210 const KMemoryRegion* region = nullptr;
211 for (auto it = this->begin(); it != this->end(); it++) {
212 if (it->IsDerivedFrom(type_id)) {
213 region = std::addressof(*it);
214 }
215 }
216 return region;
217 }
218
219 DerivedRegionExtents GetDerivedRegionExtents(KMemoryRegionType type_id) const {
220 DerivedRegionExtents extents;
221
222 ASSERT(extents.first_region == nullptr);
223 ASSERT(extents.last_region == nullptr);
224
225 for (auto it = this->cbegin(); it != this->cend(); it++) {
226 if (it->IsDerivedFrom(type_id)) {
227 if (extents.first_region == nullptr) {
228 extents.first_region = std::addressof(*it);
229 }
230 extents.last_region = std::addressof(*it);
231 }
232 }
233
234 ASSERT(extents.first_region != nullptr);
235 ASSERT(extents.last_region != nullptr);
236
237 return extents;
238 }
239
240 DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const {
241 return GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id));
242 }
243
244public:
245 void InsertDirectly(u64 address, u64 last_address, u32 attr = 0, u32 type_id = 0);
246 bool Insert(u64 address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
247
248 VAddr GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
249
250 VAddr GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id,
251 size_t guard_size) {
252 return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
253 }
254
255public:
256 // Iterator accessors.
257 iterator begin() {
258 return m_tree.begin();
259 }
260
261 const_iterator begin() const {
262 return m_tree.begin();
263 }
264
265 iterator end() {
266 return m_tree.end();
267 }
268
269 const_iterator end() const {
270 return m_tree.end();
271 }
272
273 const_iterator cbegin() const {
274 return this->begin();
275 }
276
277 const_iterator cend() const {
278 return this->end();
279 }
280
281 iterator iterator_to(reference ref) {
282 return m_tree.iterator_to(ref);
283 }
284
285 const_iterator iterator_to(const_reference ref) const {
286 return m_tree.iterator_to(ref);
287 }
288
289 // Content management.
290 bool empty() const {
291 return m_tree.empty();
292 }
293
294 reference back() {
295 return m_tree.back();
296 }
297
298 const_reference back() const {
299 return m_tree.back();
300 }
301
302 reference front() {
303 return m_tree.front();
304 }
305
306 const_reference front() const {
307 return m_tree.front();
308 }
309
310 iterator insert(reference ref) {
311 return m_tree.insert(ref);
312 }
313
314 iterator erase(iterator it) {
315 return m_tree.erase(it);
316 }
317
318 iterator find(const_reference ref) const {
319 return m_tree.find(ref);
320 }
321
322 iterator nfind(const_reference ref) const {
323 return m_tree.nfind(ref);
324 }
325};
326
327class KMemoryRegionAllocator final : NonCopyable {
328public:
329 static constexpr size_t MaxMemoryRegions = 200;
330
331 constexpr KMemoryRegionAllocator() = default;
332
333 template <typename... Args>
334 KMemoryRegion* Allocate(Args&&... args) {
335 // Ensure we stay within the bounds of our heap.
336 ASSERT(this->num_regions < MaxMemoryRegions);
337
338 // Create the new region.
339 KMemoryRegion* region = std::addressof(this->region_heap[this->num_regions++]);
340 new (region) KMemoryRegion(std::forward<Args>(args)...);
341
342 return region;
343 }
344
345private:
346 std::array<KMemoryRegion, MaxMemoryRegions> region_heap{};
347 size_t num_regions{};
348};
349
350} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_region_type.h b/src/core/hle/kernel/k_memory_region_type.h
new file mode 100644
index 000000000..a05e66677
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_region_type.h
@@ -0,0 +1,338 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/bit_util.h"
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11#define ARCH_ARM64
12#define BOARD_NINTENDO_NX
13
14namespace Kernel {
15
16enum KMemoryRegionType : u32 {
17 KMemoryRegionAttr_CarveoutProtected = 0x04000000,
18 KMemoryRegionAttr_DidKernelMap = 0x08000000,
19 KMemoryRegionAttr_ShouldKernelMap = 0x10000000,
20 KMemoryRegionAttr_UserReadOnly = 0x20000000,
21 KMemoryRegionAttr_NoUserMap = 0x40000000,
22 KMemoryRegionAttr_LinearMapped = 0x80000000,
23};
24DECLARE_ENUM_FLAG_OPERATORS(KMemoryRegionType);
25
26namespace impl {
27
28constexpr size_t BitsForDeriveSparse(size_t n) {
29 return n + 1;
30}
31
32constexpr size_t BitsForDeriveDense(size_t n) {
33 size_t low = 0, high = 1;
34 for (size_t i = 0; i < n - 1; ++i) {
35 if ((++low) == high) {
36 ++high;
37 low = 0;
38 }
39 }
40 return high + 1;
41}
42
43class KMemoryRegionTypeValue {
44public:
45 using ValueType = std::underlying_type_t<KMemoryRegionType>;
46
47 constexpr KMemoryRegionTypeValue() = default;
48
49 constexpr operator KMemoryRegionType() const {
50 return static_cast<KMemoryRegionType>(m_value);
51 }
52
53 constexpr ValueType GetValue() const {
54 return m_value;
55 }
56
57 constexpr const KMemoryRegionTypeValue& Finalize() {
58 m_finalized = true;
59 return *this;
60 }
61
62 constexpr const KMemoryRegionTypeValue& SetSparseOnly() {
63 m_sparse_only = true;
64 return *this;
65 }
66
67 constexpr const KMemoryRegionTypeValue& SetDenseOnly() {
68 m_dense_only = true;
69 return *this;
70 }
71
72 constexpr KMemoryRegionTypeValue& SetAttribute(u32 attr) {
73 m_value |= attr;
74 return *this;
75 }
76
77 constexpr KMemoryRegionTypeValue DeriveInitial(
78 size_t i, size_t next = Common::BitSize<ValueType>()) const {
79 KMemoryRegionTypeValue new_type = *this;
80 new_type.m_value = (ValueType{1} << i);
81 new_type.m_next_bit = next;
82 return new_type;
83 }
84
85 constexpr KMemoryRegionTypeValue DeriveAttribute(u32 attr) const {
86 KMemoryRegionTypeValue new_type = *this;
87 new_type.m_value |= attr;
88 return new_type;
89 }
90
91 constexpr KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const {
92 KMemoryRegionTypeValue new_type = *this;
93 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
94 new_type.m_next_bit += adv;
95 return new_type;
96 }
97
98 constexpr KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const {
99 KMemoryRegionTypeValue new_type = *this;
100 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
101 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs + 1 + i));
102 new_type.m_next_bit += ofs + n + 1;
103 return new_type;
104 }
105
106 constexpr KMemoryRegionTypeValue Derive(size_t n, size_t i) const {
107 size_t low = 0, high = 1;
108 for (size_t j = 0; j < i; ++j) {
109 if ((++low) == high) {
110 ++high;
111 low = 0;
112 }
113 }
114
115 KMemoryRegionTypeValue new_type = *this;
116 new_type.m_value |= (ValueType{1} << (m_next_bit + low));
117 new_type.m_value |= (ValueType{1} << (m_next_bit + high));
118 new_type.m_next_bit += BitsForDeriveDense(n);
119 return new_type;
120 }
121
122 constexpr KMemoryRegionTypeValue Advance(size_t n) const {
123 KMemoryRegionTypeValue new_type = *this;
124 new_type.m_next_bit += n;
125 return new_type;
126 }
127
128 constexpr bool IsAncestorOf(ValueType v) const {
129 return (m_value | v) == v;
130 }
131
132private:
133 constexpr KMemoryRegionTypeValue(ValueType v) : m_value(v) {}
134
135private:
136 ValueType m_value{};
137 size_t m_next_bit{};
138 bool m_finalized{};
139 bool m_sparse_only{};
140 bool m_dense_only{};
141};
142
143} // namespace impl
144
145constexpr auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
146constexpr auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
147constexpr auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
148static_assert(KMemoryRegionType_Kernel.GetValue() == 0x1);
149static_assert(KMemoryRegionType_Dram.GetValue() == 0x2);
150
151constexpr auto KMemoryRegionType_DramKernelBase =
152 KMemoryRegionType_Dram.DeriveSparse(0, 3, 0)
153 .SetAttribute(KMemoryRegionAttr_NoUserMap)
154 .SetAttribute(KMemoryRegionAttr_CarveoutProtected);
155constexpr auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
156constexpr auto KMemoryRegionType_DramHeapBase =
157 KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr_LinearMapped);
158static_assert(KMemoryRegionType_DramKernelBase.GetValue() ==
159 (0xE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
160static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16));
161static_assert(KMemoryRegionType_DramHeapBase.GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped));
162
163constexpr auto KMemoryRegionType_DramKernelCode =
164 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0);
165constexpr auto KMemoryRegionType_DramKernelSlab =
166 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1);
167constexpr auto KMemoryRegionType_DramKernelPtHeap =
168 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute(
169 KMemoryRegionAttr_LinearMapped);
170constexpr auto KMemoryRegionType_DramKernelInitPt =
171 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute(
172 KMemoryRegionAttr_LinearMapped);
173static_assert(KMemoryRegionType_DramKernelCode.GetValue() ==
174 (0xCE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
175static_assert(KMemoryRegionType_DramKernelSlab.GetValue() ==
176 (0x14E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
177static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() ==
178 (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap |
179 KMemoryRegionAttr_LinearMapped));
180static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() ==
181 (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap |
182 KMemoryRegionAttr_LinearMapped));
183
184constexpr auto KMemoryRegionType_DramReservedEarly =
185 KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
186static_assert(KMemoryRegionType_DramReservedEarly.GetValue() ==
187 (0x16 | KMemoryRegionAttr_NoUserMap));
188
189constexpr auto KMemoryRegionType_KernelTraceBuffer =
190 KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 0)
191 .SetAttribute(KMemoryRegionAttr_LinearMapped)
192 .SetAttribute(KMemoryRegionAttr_UserReadOnly);
193constexpr auto KMemoryRegionType_OnMemoryBootImage =
194 KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1);
195constexpr auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2);
196static_assert(KMemoryRegionType_KernelTraceBuffer.GetValue() ==
197 (0xD6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_UserReadOnly));
198static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156);
199static_assert(KMemoryRegionType_DTB.GetValue() == 0x256);
200
201constexpr auto KMemoryRegionType_DramPoolPartition =
202 KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
203static_assert(KMemoryRegionType_DramPoolPartition.GetValue() ==
204 (0x26 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
205
206constexpr auto KMemoryRegionType_DramPoolManagement =
207 KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition().SetAttribute(
208 KMemoryRegionAttr_CarveoutProtected);
209constexpr auto KMemoryRegionType_DramUserPool =
210 KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition();
211static_assert(KMemoryRegionType_DramPoolManagement.GetValue() ==
212 (0x166 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap |
213 KMemoryRegionAttr_CarveoutProtected));
214static_assert(KMemoryRegionType_DramUserPool.GetValue() ==
215 (0x1A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
216
217constexpr auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0);
218constexpr auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1);
219constexpr auto KMemoryRegionType_DramSystemNonSecurePool =
220 KMemoryRegionType_DramUserPool.Derive(4, 2);
221constexpr auto KMemoryRegionType_DramSystemPool =
222 KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
223static_assert(KMemoryRegionType_DramApplicationPool.GetValue() ==
224 (0x7A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
225static_assert(KMemoryRegionType_DramAppletPool.GetValue() ==
226 (0xBA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
227static_assert(KMemoryRegionType_DramSystemNonSecurePool.GetValue() ==
228 (0xDA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
229static_assert(KMemoryRegionType_DramSystemPool.GetValue() ==
230 (0x13A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap |
231 KMemoryRegionAttr_CarveoutProtected));
232
233constexpr auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0);
234constexpr auto KMemoryRegionType_VirtualDramKernelPtHeap =
235 KMemoryRegionType_Dram.DeriveSparse(1, 3, 1);
236constexpr auto KMemoryRegionType_VirtualDramKernelTraceBuffer =
237 KMemoryRegionType_Dram.DeriveSparse(1, 3, 2);
238static_assert(KMemoryRegionType_VirtualDramHeapBase.GetValue() == 0x1A);
239static_assert(KMemoryRegionType_VirtualDramKernelPtHeap.GetValue() == 0x2A);
240static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A);
241
242constexpr auto KMemoryRegionType_VirtualDramKernelInitPt =
243 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
244constexpr auto KMemoryRegionType_VirtualDramPoolManagement =
245 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
246constexpr auto KMemoryRegionType_VirtualDramUserPool =
247 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
248static_assert(KMemoryRegionType_VirtualDramKernelInitPt.GetValue() == 0x19A);
249static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A);
250static_assert(KMemoryRegionType_VirtualDramUserPool.GetValue() == 0x31A);
251
252// NOTE: For unknown reason, the pools are derived out-of-order here. It's worth eventually trying
253// to understand why Nintendo made this choice.
254// UNUSED: .Derive(6, 0);
255// UNUSED: .Derive(6, 1);
256constexpr auto KMemoryRegionType_VirtualDramAppletPool =
257 KMemoryRegionType_VirtualDramUserPool.Derive(6, 2);
258constexpr auto KMemoryRegionType_VirtualDramApplicationPool =
259 KMemoryRegionType_VirtualDramUserPool.Derive(6, 3);
260constexpr auto KMemoryRegionType_VirtualDramSystemNonSecurePool =
261 KMemoryRegionType_VirtualDramUserPool.Derive(6, 4);
262constexpr auto KMemoryRegionType_VirtualDramSystemPool =
263 KMemoryRegionType_VirtualDramUserPool.Derive(6, 5);
264static_assert(KMemoryRegionType_VirtualDramAppletPool.GetValue() == 0x1B1A);
265static_assert(KMemoryRegionType_VirtualDramApplicationPool.GetValue() == 0x271A);
266static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A);
267static_assert(KMemoryRegionType_VirtualDramSystemPool.GetValue() == 0x331A);
268
269constexpr auto KMemoryRegionType_ArchDeviceBase =
270 KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly();
271constexpr auto KMemoryRegionType_BoardDeviceBase =
272 KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly();
273static_assert(KMemoryRegionType_ArchDeviceBase.GetValue() == 0x5);
274static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5);
275
276#if defined(ARCH_ARM64)
277#include "core/hle/kernel/arch/arm64/k_memory_region_device_types.inc"
278#elif defined(ARCH_ARM)
279#error "Unimplemented"
280#else
281// Default to no architecture devices.
282constexpr auto NumArchitectureDeviceRegions = 0;
283#endif
284static_assert(NumArchitectureDeviceRegions >= 0);
285
286#if defined(BOARD_NINTENDO_NX)
287#include "core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc"
288#else
289// Default to no board devices.
290constexpr auto NumBoardDeviceRegions = 0;
291#endif
292static_assert(NumBoardDeviceRegions >= 0);
293
294constexpr auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0);
295constexpr auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1);
296constexpr auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2);
297constexpr auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3);
298static_assert(KMemoryRegionType_KernelCode.GetValue() == 0x19);
299static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29);
300static_assert(KMemoryRegionType_KernelMisc.GetValue() == 0x49);
301static_assert(KMemoryRegionType_KernelSlab.GetValue() == 0x89);
302
303constexpr auto KMemoryRegionType_KernelMiscDerivedBase =
304 KMemoryRegionType_KernelMisc.DeriveTransition();
305static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149);
306
307// UNUSED: .Derive(7, 0);
308constexpr auto KMemoryRegionType_KernelMiscMainStack =
309 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
310constexpr auto KMemoryRegionType_KernelMiscMappedDevice =
311 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
312constexpr auto KMemoryRegionType_KernelMiscExceptionStack =
313 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
314constexpr auto KMemoryRegionType_KernelMiscUnknownDebug =
315 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
316// UNUSED: .Derive(7, 5);
317constexpr auto KMemoryRegionType_KernelMiscIdleStack =
318 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
319static_assert(KMemoryRegionType_KernelMiscMainStack.GetValue() == 0xB49);
320static_assert(KMemoryRegionType_KernelMiscMappedDevice.GetValue() == 0xD49);
321static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x1349);
322static_assert(KMemoryRegionType_KernelMiscUnknownDebug.GetValue() == 0x1549);
323static_assert(KMemoryRegionType_KernelMiscIdleStack.GetValue() == 0x2349);
324
325constexpr auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
326static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
327
328constexpr KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) {
329 if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) {
330 return KMemoryRegionType_VirtualDramKernelTraceBuffer;
331 } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
332 return KMemoryRegionType_VirtualDramKernelPtHeap;
333 } else {
334 return KMemoryRegionType_Dram;
335 }
336}
337
338} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index d7a4a38e6..d05b34ea3 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -2,21 +2,16 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include "common/assert.h" 5#include "common/assert.h"
9#include "core/core.h"
10#include "core/core_timing.h" 6#include "core/core_timing.h"
11#include "core/core_timing_util.h"
12#include "core/hle/kernel/k_resource_limit.h" 7#include "core/hle/kernel/k_resource_limit.h"
13#include "core/hle/kernel/svc_results.h" 8#include "core/hle/kernel/svc_results.h"
14 9
15namespace Kernel { 10namespace Kernel {
16constexpr s64 DefaultTimeout = 10000000000; // 10 seconds 11constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
17 12
18KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) 13KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_)
19 : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} 14 : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {}
20KResourceLimit::~KResourceLimit() = default; 15KResourceLimit::~KResourceLimit() = default;
21 16
22s64 KResourceLimit::GetLimitValue(LimitableResource which) const { 17s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
@@ -83,7 +78,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
83} 78}
84 79
85bool KResourceLimit::Reserve(LimitableResource which, s64 value) { 80bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
86 return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout); 81 return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout);
87} 82}
88 83
89bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { 84bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
@@ -114,7 +109,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
114 } 109 }
115 110
116 if (current_hints[index] + value <= limit_values[index] && 111 if (current_hints[index] + value <= limit_values[index] &&
117 (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) { 112 (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) {
118 waiter_count++; 113 waiter_count++;
119 cond_var.Wait(&lock, timeout); 114 cond_var.Wait(&lock, timeout);
120 waiter_count--; 115 waiter_count--;
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 58ae456f1..4542317d0 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -2,9 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include <array> 7#include <array>
@@ -15,8 +12,8 @@
15 12
16union ResultCode; 13union ResultCode;
17 14
18namespace Core { 15namespace Core::Timing {
19class System; 16class CoreTiming;
20} 17}
21 18
22namespace Kernel { 19namespace Kernel {
@@ -37,7 +34,7 @@ constexpr bool IsValidResourceType(LimitableResource type) {
37 34
38class KResourceLimit final : public Object { 35class KResourceLimit final : public Object {
39public: 36public:
40 explicit KResourceLimit(KernelCore& kernel, Core::System& system); 37 explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_);
41 ~KResourceLimit(); 38 ~KResourceLimit();
42 39
43 s64 GetLimitValue(LimitableResource which) const; 40 s64 GetLimitValue(LimitableResource which) const;
@@ -75,7 +72,6 @@ private:
75 mutable KLightLock lock; 72 mutable KLightLock lock;
76 s32 waiter_count{}; 73 s32 waiter_count{};
77 KLightConditionVariable cond_var; 74 KLightConditionVariable cond_var;
78 KernelCore& kernel; 75 const Core::Timing::CoreTiming& core_timing;
79 Core::System& system;
80}; 76};
81} // namespace Kernel 77} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index e7de48476..d1df97305 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -62,7 +62,7 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul
62} 62}
63 63
64u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { 64u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
65 std::scoped_lock lock{guard}; 65 KScopedSpinLock lk{guard};
66 if (KThread* prev_highest_thread = state.highest_priority_thread; 66 if (KThread* prev_highest_thread = state.highest_priority_thread;
67 prev_highest_thread != highest_thread) { 67 prev_highest_thread != highest_thread) {
68 if (prev_highest_thread != nullptr) { 68 if (prev_highest_thread != nullptr) {
@@ -637,11 +637,11 @@ void KScheduler::RescheduleCurrentCore() {
637 if (phys_core.IsInterrupted()) { 637 if (phys_core.IsInterrupted()) {
638 phys_core.ClearInterrupt(); 638 phys_core.ClearInterrupt();
639 } 639 }
640 guard.lock(); 640 guard.Lock();
641 if (state.needs_scheduling.load()) { 641 if (state.needs_scheduling.load()) {
642 Schedule(); 642 Schedule();
643 } else { 643 } else {
644 guard.unlock(); 644 guard.Unlock();
645 } 645 }
646} 646}
647 647
@@ -669,7 +669,7 @@ void KScheduler::Unload(KThread* thread) {
669 } else { 669 } else {
670 prev_thread = nullptr; 670 prev_thread = nullptr;
671 } 671 }
672 thread->context_guard.unlock(); 672 thread->context_guard.Unlock();
673 } 673 }
674} 674}
675 675
@@ -713,7 +713,7 @@ void KScheduler::ScheduleImpl() {
713 713
714 // If we're not actually switching thread, there's nothing to do. 714 // If we're not actually switching thread, there's nothing to do.
715 if (next_thread == current_thread.load()) { 715 if (next_thread == current_thread.load()) {
716 guard.unlock(); 716 guard.Unlock();
717 return; 717 return;
718 } 718 }
719 719
@@ -732,7 +732,7 @@ void KScheduler::ScheduleImpl() {
732 } else { 732 } else {
733 old_context = &idle_thread->GetHostContext(); 733 old_context = &idle_thread->GetHostContext();
734 } 734 }
735 guard.unlock(); 735 guard.Unlock();
736 736
737 Common::Fiber::YieldTo(*old_context, *switch_fiber); 737 Common::Fiber::YieldTo(*old_context, *switch_fiber);
738 /// When a thread wakes up, the scheduler may have changed to other in another core. 738 /// When a thread wakes up, the scheduler may have changed to other in another core.
@@ -748,24 +748,24 @@ void KScheduler::OnSwitch(void* this_scheduler) {
748void KScheduler::SwitchToCurrent() { 748void KScheduler::SwitchToCurrent() {
749 while (true) { 749 while (true) {
750 { 750 {
751 std::scoped_lock lock{guard}; 751 KScopedSpinLock lk{guard};
752 current_thread.store(state.highest_priority_thread); 752 current_thread.store(state.highest_priority_thread);
753 state.needs_scheduling.store(false); 753 state.needs_scheduling.store(false);
754 } 754 }
755 const auto is_switch_pending = [this] { 755 const auto is_switch_pending = [this] {
756 std::scoped_lock lock{guard}; 756 KScopedSpinLock lk{guard};
757 return state.needs_scheduling.load(); 757 return state.needs_scheduling.load();
758 }; 758 };
759 do { 759 do {
760 auto next_thread = current_thread.load(); 760 auto next_thread = current_thread.load();
761 if (next_thread != nullptr) { 761 if (next_thread != nullptr) {
762 next_thread->context_guard.lock(); 762 next_thread->context_guard.Lock();
763 if (next_thread->GetRawState() != ThreadState::Runnable) { 763 if (next_thread->GetRawState() != ThreadState::Runnable) {
764 next_thread->context_guard.unlock(); 764 next_thread->context_guard.Unlock();
765 break; 765 break;
766 } 766 }
767 if (next_thread->GetActiveCore() != core_id) { 767 if (next_thread->GetActiveCore() != core_id) {
768 next_thread->context_guard.unlock(); 768 next_thread->context_guard.Unlock();
769 break; 769 break;
770 } 770 }
771 } 771 }
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index f595b9a5c..8e32865aa 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -2,19 +2,16 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include <atomic> 7#include <atomic>
11 8
12#include "common/common_types.h" 9#include "common/common_types.h"
13#include "common/spin_lock.h"
14#include "core/hle/kernel/global_scheduler_context.h" 10#include "core/hle/kernel/global_scheduler_context.h"
15#include "core/hle/kernel/k_priority_queue.h" 11#include "core/hle/kernel/k_priority_queue.h"
16#include "core/hle/kernel/k_scheduler_lock.h" 12#include "core/hle/kernel/k_scheduler_lock.h"
17#include "core/hle/kernel/k_scoped_lock.h" 13#include "core/hle/kernel/k_scoped_lock.h"
14#include "core/hle/kernel/k_spin_lock.h"
18 15
19namespace Common { 16namespace Common {
20class Fiber; 17class Fiber;
@@ -195,12 +192,12 @@ private:
195 u64 last_context_switch_time{}; 192 u64 last_context_switch_time{};
196 const s32 core_id; 193 const s32 core_id;
197 194
198 Common::SpinLock guard{}; 195 KSpinLock guard{};
199}; 196};
200 197
201class KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> { 198class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> {
202public: 199public:
203 explicit KScopedSchedulerLock(KernelCore& kernel); 200 explicit KScopedSchedulerLock(KernelCore & kernel);
204 ~KScopedSchedulerLock(); 201 ~KScopedSchedulerLock();
205}; 202};
206 203
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h
index 169455d18..47e315555 100644
--- a/src/core/hle/kernel/k_scheduler_lock.h
+++ b/src/core/hle/kernel/k_scheduler_lock.h
@@ -2,14 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include "common/assert.h" 7#include "common/assert.h"
11#include "common/spin_lock.h"
12#include "core/hardware_properties.h" 8#include "core/hardware_properties.h"
9#include "core/hle/kernel/k_spin_lock.h"
13#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
14#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
15 12
@@ -34,7 +31,7 @@ public:
34 } else { 31 } else {
35 // Otherwise, we want to disable scheduling and acquire the spinlock. 32 // Otherwise, we want to disable scheduling and acquire the spinlock.
36 SchedulerType::DisableScheduling(kernel); 33 SchedulerType::DisableScheduling(kernel);
37 spin_lock.lock(); 34 spin_lock.Lock();
38 35
39 // For debug, ensure that our state is valid. 36 // For debug, ensure that our state is valid.
40 ASSERT(lock_count == 0); 37 ASSERT(lock_count == 0);
@@ -58,7 +55,7 @@ public:
58 55
59 // Note that we no longer hold the lock, and unlock the spinlock. 56 // Note that we no longer hold the lock, and unlock the spinlock.
60 owner_thread = nullptr; 57 owner_thread = nullptr;
61 spin_lock.unlock(); 58 spin_lock.Unlock();
62 59
63 // Enable scheduling, and perform a rescheduling operation. 60 // Enable scheduling, and perform a rescheduling operation.
64 SchedulerType::EnableScheduling(kernel, cores_needing_scheduling); 61 SchedulerType::EnableScheduling(kernel, cores_needing_scheduling);
@@ -67,7 +64,7 @@ public:
67 64
68private: 65private:
69 KernelCore& kernel; 66 KernelCore& kernel;
70 Common::SpinLock spin_lock{}; 67 KAlignedSpinLock spin_lock{};
71 s32 lock_count{}; 68 s32 lock_count{};
72 KThread* owner_thread{}; 69 KThread* owner_thread{};
73}; 70};
diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h
index d7cc557b2..72c3b0252 100644
--- a/src/core/hle/kernel/k_scoped_lock.h
+++ b/src/core/hle/kernel/k_scoped_lock.h
@@ -20,19 +20,22 @@ concept KLockable = !std::is_reference_v<T> && requires(T & t) {
20}; 20};
21 21
22template <typename T> 22template <typename T>
23requires KLockable<T> class KScopedLock { 23requires KLockable<T> class [[nodiscard]] KScopedLock {
24public: 24public:
25 explicit KScopedLock(T* l) : lock_ptr(l) { 25 explicit KScopedLock(T * l) : lock_ptr(l) {
26 this->lock_ptr->Lock(); 26 this->lock_ptr->Lock();
27 } 27 }
28 explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) { /* ... */ 28 explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {}
29 } 29
30 ~KScopedLock() { 30 ~KScopedLock() {
31 this->lock_ptr->Unlock(); 31 this->lock_ptr->Unlock();
32 } 32 }
33 33
34 KScopedLock(const KScopedLock&) = delete; 34 KScopedLock(const KScopedLock&) = delete;
35 KScopedLock(KScopedLock&&) = delete; 35 KScopedLock& operator=(const KScopedLock&) = delete;
36
37 KScopedLock(KScopedLock &&) = delete;
38 KScopedLock& operator=(KScopedLock&&) = delete;
36 39
37private: 40private:
38 T* lock_ptr; 41 T* lock_ptr;
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
index f8189e107..ebecf0c77 100644
--- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
+++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
@@ -15,9 +15,9 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18class KScopedSchedulerLockAndSleep { 18class [[nodiscard]] KScopedSchedulerLockAndSleep {
19public: 19public:
20 explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, KThread* t, s64 timeout) 20 explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout)
21 : kernel(kernel), thread(t), timeout_tick(timeout) { 21 : kernel(kernel), thread(t), timeout_tick(timeout) {
22 // Lock the scheduler. 22 // Lock the scheduler.
23 kernel.GlobalSchedulerContext().scheduler_lock.Lock(); 23 kernel.GlobalSchedulerContext().scheduler_lock.Lock();
diff --git a/src/core/hle/kernel/k_spin_lock.h b/src/core/hle/kernel/k_spin_lock.h
index 12c4b2e88..4d87d006a 100644
--- a/src/core/hle/kernel/k_spin_lock.h
+++ b/src/core/hle/kernel/k_spin_lock.h
@@ -28,6 +28,12 @@ private:
28 std::atomic_flag lck = ATOMIC_FLAG_INIT; 28 std::atomic_flag lck = ATOMIC_FLAG_INIT;
29}; 29};
30 30
31// TODO(bunnei): Alias for now, in case we want to implement these accurately in the future.
32using KAlignedSpinLock = KSpinLock;
33using KNotAlignedSpinLock = KSpinLock;
34
31using KScopedSpinLock = KScopedLock<KSpinLock>; 35using KScopedSpinLock = KScopedLock<KSpinLock>;
36using KScopedAlignedSpinLock = KScopedLock<KAlignedSpinLock>;
37using KScopedNotAlignedSpinLock = KScopedLock<KNotAlignedSpinLock>;
32 38
33} // namespace Kernel 39} // namespace Kernel
diff --git a/src/core/hle/kernel/k_system_control.cpp b/src/core/hle/kernel/k_system_control.cpp
deleted file mode 100644
index aa1682f69..000000000
--- a/src/core/hle/kernel/k_system_control.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <random>
6
7#include "core/hle/kernel/k_system_control.h"
8
9namespace Kernel {
10
11namespace {
12template <typename F>
13u64 GenerateUniformRange(u64 min, u64 max, F f) {
14 // Handle the case where the difference is too large to represent.
15 if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
16 return f();
17 }
18
19 // Iterate until we get a value in range.
20 const u64 range_size = ((max + 1) - min);
21 const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
22 while (true) {
23 if (const u64 rnd = f(); rnd < effective_max) {
24 return min + (rnd % range_size);
25 }
26 }
27}
28
29} // Anonymous namespace
30
31u64 KSystemControl::GenerateRandomU64() {
32 static std::random_device device;
33 static std::mt19937 gen(device());
34 static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
35 return distribution(gen);
36}
37
38u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
39 return GenerateUniformRange(min, max, GenerateRandomU64);
40}
41
42} // namespace Kernel
diff --git a/src/core/hle/kernel/k_system_control.h b/src/core/hle/kernel/k_system_control.h
index 1d5b64ffa..d755082c2 100644
--- a/src/core/hle/kernel/k_system_control.h
+++ b/src/core/hle/kernel/k_system_control.h
@@ -6,14 +6,18 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9namespace Kernel { 9#define BOARD_NINTENDO_NX
10
11#ifdef BOARD_NINTENDO_NX
10 12
11class KSystemControl { 13#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
12public:
13 KSystemControl() = default;
14 14
15 static u64 GenerateRandomRange(u64 min, u64 max); 15namespace Kernel {
16 static u64 GenerateRandomU64(); 16
17}; 17using Kernel::Board::Nintendo::Nx::KSystemControl;
18 18
19} // namespace Kernel 19} // namespace Kernel
20
21#else
22#error "Unknown board for KSystemControl"
23#endif
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 1c19b23dc..b442dfe57 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -14,10 +14,10 @@
14 14
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "common/intrusive_red_black_tree.h" 16#include "common/intrusive_red_black_tree.h"
17#include "common/spin_lock.h"
18#include "core/arm/arm_interface.h" 17#include "core/arm/arm_interface.h"
19#include "core/hle/kernel/k_affinity_mask.h" 18#include "core/hle/kernel/k_affinity_mask.h"
20#include "core/hle/kernel/k_light_lock.h" 19#include "core/hle/kernel/k_light_lock.h"
20#include "core/hle/kernel/k_spin_lock.h"
21#include "core/hle/kernel/k_synchronization_object.h" 21#include "core/hle/kernel/k_synchronization_object.h"
22#include "core/hle/kernel/object.h" 22#include "core/hle/kernel/object.h"
23#include "core/hle/kernel/svc_common.h" 23#include "core/hle/kernel/svc_common.h"
@@ -402,7 +402,7 @@ public:
402 return wait_cancelled; 402 return wait_cancelled;
403 } 403 }
404 404
405 [[nodiscard]] void ClearWaitCancelled() { 405 void ClearWaitCancelled() {
406 wait_cancelled = false; 406 wait_cancelled = false;
407 } 407 }
408 408
@@ -732,7 +732,7 @@ private:
732 s8 priority_inheritance_count{}; 732 s8 priority_inheritance_count{};
733 bool resource_limit_release_hint{}; 733 bool resource_limit_release_hint{};
734 StackParameters stack_parameters{}; 734 StackParameters stack_parameters{};
735 Common::SpinLock context_guard{}; 735 KSpinLock context_guard{};
736 736
737 // For emulation 737 // For emulation
738 std::shared_ptr<Common::Fiber> host_context{}; 738 std::shared_ptr<Common::Fiber> host_context{};
diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h
new file mode 100644
index 000000000..91ebf9ab2
--- /dev/null
+++ b/src/core/hle/kernel/k_trace.h
@@ -0,0 +1,12 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7namespace Kernel {
8
9constexpr bool IsKTraceEnabled = false;
10constexpr std::size_t KTraceBufferSize = IsKTraceEnabled ? 16 * 1024 * 1024 : 0;
11
12} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 5b6c7792e..5c4f45ab4 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -12,6 +12,7 @@
12#include <utility> 12#include <utility>
13 13
14#include "common/assert.h" 14#include "common/assert.h"
15#include "common/common_sizes.h"
15#include "common/logging/log.h" 16#include "common/logging/log.h"
16#include "common/microprofile.h" 17#include "common/microprofile.h"
17#include "common/thread.h" 18#include "common/thread.h"
@@ -66,8 +67,13 @@ struct KernelCore::Impl {
66 is_phantom_mode_for_singlecore = false; 67 is_phantom_mode_for_singlecore = false;
67 68
68 InitializePhysicalCores(); 69 InitializePhysicalCores();
69 InitializeSystemResourceLimit(kernel, system); 70
70 InitializeMemoryLayout(); 71 // Derive the initial memory layout from the emulated board
72 KMemoryLayout memory_layout;
73 DeriveInitialMemoryLayout(memory_layout);
74 InitializeMemoryLayout(memory_layout);
75 InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout);
76 InitializeSlabHeaps();
71 InitializeSchedulers(); 77 InitializeSchedulers();
72 InitializeSuspendThreads(); 78 InitializeSuspendThreads();
73 InitializePreemption(kernel); 79 InitializePreemption(kernel);
@@ -136,27 +142,33 @@ struct KernelCore::Impl {
136 } 142 }
137 143
138 // Creates the default system resource limit 144 // Creates the default system resource limit
139 void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { 145 void InitializeSystemResourceLimit(KernelCore& kernel,
140 system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); 146 const Core::Timing::CoreTiming& core_timing,
147 const KMemoryLayout& memory_layout) {
148 system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing);
149 const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
141 150
142 // If setting the default system values fails, then something seriously wrong has occurred. 151 // If setting the default system values fails, then something seriously wrong has occurred.
143 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) 152 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
144 .IsSuccess()); 153 .IsSuccess());
145 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); 154 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
146 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); 155 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
147 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) 156 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
148 .IsSuccess()); 157 .IsSuccess());
149 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess()); 158 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
159 system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
150 160
151 // Derived from recent software updates. The kernel reserves 27MB
152 constexpr u64 kernel_size{0x1b00000};
153 if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
154 UNREACHABLE();
155 }
156 // Reserve secure applet memory, introduced in firmware 5.0.0 161 // Reserve secure applet memory, introduced in firmware 5.0.0
157 constexpr u64 secure_applet_memory_size{0x400000}; 162 constexpr u64 secure_applet_memory_size{Common::Size_4_MB};
158 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 163 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
159 secure_applet_memory_size)); 164 secure_applet_memory_size));
165
166 // This memory seems to be reserved on hardware, but is not reserved/used by yuzu.
167 // Likely Horizon OS reserved memory
168 // TODO(ameerj): Derive the memory rather than hardcode it.
169 constexpr u64 unknown_reserved_memory{0x2f896000};
170 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
171 unknown_reserved_memory));
160 } 172 }
161 173
162 void InitializePreemption(KernelCore& kernel) { 174 void InitializePreemption(KernelCore& kernel) {
@@ -268,51 +280,319 @@ struct KernelCore::Impl {
268 return schedulers[thread_id]->GetCurrentThread(); 280 return schedulers[thread_id]->GetCurrentThread();
269 } 281 }
270 282
271 void InitializeMemoryLayout() { 283 void DeriveInitialMemoryLayout(KMemoryLayout& memory_layout) {
272 // Initialize memory layout 284 // Insert the root region for the virtual memory tree, from which all other regions will
273 constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()}; 285 // derive.
286 memory_layout.GetVirtualMemoryRegionTree().InsertDirectly(
287 KernelVirtualAddressSpaceBase,
288 KernelVirtualAddressSpaceBase + KernelVirtualAddressSpaceSize - 1);
289
290 // Insert the root region for the physical memory tree, from which all other regions will
291 // derive.
292 memory_layout.GetPhysicalMemoryRegionTree().InsertDirectly(
293 KernelPhysicalAddressSpaceBase,
294 KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1);
295
296 // Save start and end for ease of use.
297 const VAddr code_start_virt_addr = KernelVirtualAddressCodeBase;
298 const VAddr code_end_virt_addr = KernelVirtualAddressCodeEnd;
299
300 // Setup the containing kernel region.
301 constexpr size_t KernelRegionSize = Common::Size_1_GB;
302 constexpr size_t KernelRegionAlign = Common::Size_1_GB;
303 constexpr VAddr kernel_region_start =
304 Common::AlignDown(code_start_virt_addr, KernelRegionAlign);
305 size_t kernel_region_size = KernelRegionSize;
306 if (!(kernel_region_start + KernelRegionSize - 1 <= KernelVirtualAddressSpaceLast)) {
307 kernel_region_size = KernelVirtualAddressSpaceEnd - kernel_region_start;
308 }
309 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
310 kernel_region_start, kernel_region_size, KMemoryRegionType_Kernel));
311
312 // Setup the code region.
313 constexpr size_t CodeRegionAlign = PageSize;
314 constexpr VAddr code_region_start =
315 Common::AlignDown(code_start_virt_addr, CodeRegionAlign);
316 constexpr VAddr code_region_end = Common::AlignUp(code_end_virt_addr, CodeRegionAlign);
317 constexpr size_t code_region_size = code_region_end - code_region_start;
318 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
319 code_region_start, code_region_size, KMemoryRegionType_KernelCode));
320
321 // Setup board-specific device physical regions.
322 Init::SetupDevicePhysicalMemoryRegions(memory_layout);
323
324 // Determine the amount of space needed for the misc region.
325 size_t misc_region_needed_size;
326 {
327 // Each core has a one page stack for all three stack types (Main, Idle, Exception).
328 misc_region_needed_size = Core::Hardware::NUM_CPU_CORES * (3 * (PageSize + PageSize));
329
330 // Account for each auto-map device.
331 for (const auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
332 if (region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
333 // Check that the region is valid.
334 ASSERT(region.GetEndAddress() != 0);
335
336 // Account for the region.
337 misc_region_needed_size +=
338 PageSize + (Common::AlignUp(region.GetLastAddress(), PageSize) -
339 Common::AlignDown(region.GetAddress(), PageSize));
340 }
341 }
342
343 // Multiply the needed size by three, to account for the need for guard space.
344 misc_region_needed_size *= 3;
345 }
346
347 // Decide on the actual size for the misc region.
348 constexpr size_t MiscRegionAlign = KernelAslrAlignment;
349 constexpr size_t MiscRegionMinimumSize = Common::Size_32_MB;
350 const size_t misc_region_size = Common::AlignUp(
351 std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign);
352 ASSERT(misc_region_size > 0);
353
354 // Setup the misc region.
355 const VAddr misc_region_start =
356 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
357 misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel);
358 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
359 misc_region_start, misc_region_size, KMemoryRegionType_KernelMisc));
360
361 // Setup the stack region.
362 constexpr size_t StackRegionSize = Common::Size_14_MB;
363 constexpr size_t StackRegionAlign = KernelAslrAlignment;
364 const VAddr stack_region_start =
365 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
366 StackRegionSize, StackRegionAlign, KMemoryRegionType_Kernel);
367 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
368 stack_region_start, StackRegionSize, KMemoryRegionType_KernelStack));
369
370 // Determine the size of the resource region.
371 const size_t resource_region_size = memory_layout.GetResourceRegionSizeForInit();
372
373 // Determine the size of the slab region.
374 const size_t slab_region_size = Common::AlignUp(KernelSlabHeapSize, PageSize);
375 ASSERT(slab_region_size <= resource_region_size);
376
377 // Setup the slab region.
378 const PAddr code_start_phys_addr = KernelPhysicalAddressCodeBase;
379 const PAddr code_end_phys_addr = code_start_phys_addr + code_region_size;
380 const PAddr slab_start_phys_addr = code_end_phys_addr;
381 const PAddr slab_end_phys_addr = slab_start_phys_addr + slab_region_size;
382 constexpr size_t SlabRegionAlign = KernelAslrAlignment;
383 const size_t slab_region_needed_size =
384 Common::AlignUp(code_end_phys_addr + slab_region_size, SlabRegionAlign) -
385 Common::AlignDown(code_end_phys_addr, SlabRegionAlign);
386 const VAddr slab_region_start =
387 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
388 slab_region_needed_size, SlabRegionAlign, KMemoryRegionType_Kernel) +
389 (code_end_phys_addr % SlabRegionAlign);
390 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
391 slab_region_start, slab_region_size, KMemoryRegionType_KernelSlab));
392
393 // Setup the temp region.
394 constexpr size_t TempRegionSize = Common::Size_128_MB;
395 constexpr size_t TempRegionAlign = KernelAslrAlignment;
396 const VAddr temp_region_start =
397 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
398 TempRegionSize, TempRegionAlign, KMemoryRegionType_Kernel);
399 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(temp_region_start, TempRegionSize,
400 KMemoryRegionType_KernelTemp));
401
402 // Automatically map in devices that have auto-map attributes.
403 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
404 // We only care about kernel regions.
405 if (!region.IsDerivedFrom(KMemoryRegionType_Kernel)) {
406 continue;
407 }
408
409 // Check whether we should map the region.
410 if (!region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
411 continue;
412 }
413
414 // If this region has already been mapped, no need to consider it.
415 if (region.HasTypeAttribute(KMemoryRegionAttr_DidKernelMap)) {
416 continue;
417 }
418
419 // Check that the region is valid.
420 ASSERT(region.GetEndAddress() != 0);
421
422 // Set the attribute to note we've mapped this region.
423 region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap);
424
425 // Create a virtual pair region and insert it into the tree.
426 const PAddr map_phys_addr = Common::AlignDown(region.GetAddress(), PageSize);
427 const size_t map_size =
428 Common::AlignUp(region.GetEndAddress(), PageSize) - map_phys_addr;
429 const VAddr map_virt_addr =
430 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
431 map_size, PageSize, KMemoryRegionType_KernelMisc, PageSize);
432 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
433 map_virt_addr, map_size, KMemoryRegionType_KernelMiscMappedDevice));
434 region.SetPairAddress(map_virt_addr + region.GetAddress() - map_phys_addr);
435 }
436
437 Init::SetupDramPhysicalMemoryRegions(memory_layout);
438
439 // Insert a physical region for the kernel code region.
440 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
441 code_start_phys_addr, code_region_size, KMemoryRegionType_DramKernelCode));
442
443 // Insert a physical region for the kernel slab region.
444 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
445 slab_start_phys_addr, slab_region_size, KMemoryRegionType_DramKernelSlab));
446
447 // Determine size available for kernel page table heaps, requiring > 8 MB.
448 const PAddr resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
449 const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr;
450 ASSERT(page_table_heap_size / Common::Size_4_MB > 2);
451
452 // Insert a physical region for the kernel page table heap region
453 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
454 slab_end_phys_addr, page_table_heap_size, KMemoryRegionType_DramKernelPtHeap));
455
456 // All DRAM regions that we haven't tagged by this point will be mapped under the linear
457 // mapping. Tag them.
458 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
459 if (region.GetType() == KMemoryRegionType_Dram) {
460 // Check that the region is valid.
461 ASSERT(region.GetEndAddress() != 0);
462
463 // Set the linear map attribute.
464 region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped);
465 }
466 }
467
468 // Get the linear region extents.
469 const auto linear_extents =
470 memory_layout.GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
471 KMemoryRegionAttr_LinearMapped);
472 ASSERT(linear_extents.GetEndAddress() != 0);
473
474 // Setup the linear mapping region.
475 constexpr size_t LinearRegionAlign = Common::Size_1_GB;
476 const PAddr aligned_linear_phys_start =
477 Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
478 const size_t linear_region_size =
479 Common::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) -
480 aligned_linear_phys_start;
481 const VAddr linear_region_start =
482 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
483 linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign);
484
485 const u64 linear_region_phys_to_virt_diff = linear_region_start - aligned_linear_phys_start;
486
487 // Map and create regions for all the linearly-mapped data.
488 {
489 PAddr cur_phys_addr = 0;
490 u64 cur_size = 0;
491 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
492 if (!region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
493 continue;
494 }
495
496 ASSERT(region.GetEndAddress() != 0);
497
498 if (cur_size == 0) {
499 cur_phys_addr = region.GetAddress();
500 cur_size = region.GetSize();
501 } else if (cur_phys_addr + cur_size == region.GetAddress()) {
502 cur_size += region.GetSize();
503 } else {
504 cur_phys_addr = region.GetAddress();
505 cur_size = region.GetSize();
506 }
507
508 const VAddr region_virt_addr =
509 region.GetAddress() + linear_region_phys_to_virt_diff;
510 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
511 region_virt_addr, region.GetSize(),
512 GetTypeForVirtualLinearMapping(region.GetType())));
513 region.SetPairAddress(region_virt_addr);
514
515 KMemoryRegion* virt_region =
516 memory_layout.GetVirtualMemoryRegionTree().FindModifiable(region_virt_addr);
517 ASSERT(virt_region != nullptr);
518 virt_region->SetPairAddress(region.GetAddress());
519 }
520 }
521
522 // Insert regions for the initial page table region.
523 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
524 resource_end_phys_addr, KernelPageTableHeapSize, KMemoryRegionType_DramKernelInitPt));
525 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
526 resource_end_phys_addr + linear_region_phys_to_virt_diff, KernelPageTableHeapSize,
527 KMemoryRegionType_VirtualDramKernelInitPt));
528
529 // All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to
530 // some pool partition. Tag them.
531 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
532 if (region.GetType() == (KMemoryRegionType_Dram | KMemoryRegionAttr_LinearMapped)) {
533 region.SetType(KMemoryRegionType_DramPoolPartition);
534 }
535 }
536
537 // Setup all other memory regions needed to arrange the pool partitions.
538 Init::SetupPoolPartitionMemoryRegions(memory_layout);
539
540 // Cache all linear regions in their own trees for faster access, later.
541 memory_layout.InitializeLinearMemoryRegionTrees(aligned_linear_phys_start,
542 linear_region_start);
543 }
544
545 void InitializeMemoryLayout(const KMemoryLayout& memory_layout) {
546 const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
547 const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
548 const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
549
550 // Initialize memory managers
551 memory_manager = std::make_unique<KMemoryManager>();
552 memory_manager->InitializeManager(KMemoryManager::Pool::Application,
553 application_pool.GetAddress(),
554 application_pool.GetEndAddress());
555 memory_manager->InitializeManager(KMemoryManager::Pool::Applet, applet_pool.GetAddress(),
556 applet_pool.GetEndAddress());
557 memory_manager->InitializeManager(KMemoryManager::Pool::System, system_pool.GetAddress(),
558 system_pool.GetEndAddress());
559
560 // Setup memory regions for emulated processes
561 // TODO(bunnei): These should not be hardcoded regions initialized within the kernel
274 constexpr std::size_t hid_size{0x40000}; 562 constexpr std::size_t hid_size{0x40000};
275 constexpr std::size_t font_size{0x1100000}; 563 constexpr std::size_t font_size{0x1100000};
276 constexpr std::size_t irs_size{0x8000}; 564 constexpr std::size_t irs_size{0x8000};
277 constexpr std::size_t time_size{0x1000}; 565 constexpr std::size_t time_size{0x1000};
278 constexpr PAddr hid_addr{layout.System().StartAddress()};
279 constexpr PAddr font_pa{layout.System().StartAddress() + hid_size};
280 constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size};
281 constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
282 566
283 // Initialize memory manager 567 const PAddr hid_phys_addr{system_pool.GetAddress()};
284 memory_manager = std::make_unique<KMemoryManager>(); 568 const PAddr font_phys_addr{system_pool.GetAddress() + hid_size};
285 memory_manager->InitializeManager(KMemoryManager::Pool::Application, 569 const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size};
286 layout.Application().StartAddress(), 570 const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size};
287 layout.Application().EndAddress());
288 memory_manager->InitializeManager(KMemoryManager::Pool::Applet,
289 layout.Applet().StartAddress(),
290 layout.Applet().EndAddress());
291 memory_manager->InitializeManager(KMemoryManager::Pool::System,
292 layout.System().StartAddress(),
293 layout.System().EndAddress());
294 571
295 hid_shared_mem = Kernel::KSharedMemory::Create( 572 hid_shared_mem = Kernel::KSharedMemory::Create(
296 system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize}, 573 system.Kernel(), system.DeviceMemory(), nullptr, {hid_phys_addr, hid_size / PageSize},
297 KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size, 574 KMemoryPermission::None, KMemoryPermission::Read, hid_phys_addr, hid_size,
298 "HID:SharedMemory"); 575 "HID:SharedMemory");
299 font_shared_mem = Kernel::KSharedMemory::Create( 576 font_shared_mem = Kernel::KSharedMemory::Create(
300 system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize}, 577 system.Kernel(), system.DeviceMemory(), nullptr, {font_phys_addr, font_size / PageSize},
301 KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size, 578 KMemoryPermission::None, KMemoryPermission::Read, font_phys_addr, font_size,
302 "Font:SharedMemory"); 579 "Font:SharedMemory");
303 irs_shared_mem = Kernel::KSharedMemory::Create( 580 irs_shared_mem = Kernel::KSharedMemory::Create(
304 system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize}, 581 system.Kernel(), system.DeviceMemory(), nullptr, {irs_phys_addr, irs_size / PageSize},
305 KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size, 582 KMemoryPermission::None, KMemoryPermission::Read, irs_phys_addr, irs_size,
306 "IRS:SharedMemory"); 583 "IRS:SharedMemory");
307 time_shared_mem = Kernel::KSharedMemory::Create( 584 time_shared_mem = Kernel::KSharedMemory::Create(
308 system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize}, 585 system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
309 KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size, 586 KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
310 "Time:SharedMemory"); 587 "Time:SharedMemory");
588 }
311 589
590 void InitializeSlabHeaps() {
312 // Allocate slab heaps 591 // Allocate slab heaps
313 user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); 592 user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
314 593
315 constexpr u64 user_slab_heap_size{0x1ef000}; 594 // TODO(ameerj): This should be derived, not hardcoded within the kernel
595 constexpr u64 user_slab_heap_size{0x3de000};
316 // Reserve slab heaps 596 // Reserve slab heaps
317 ASSERT( 597 ASSERT(
318 system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); 598 system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 56906f2da..a500e63bc 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 9d5956ead..e35deb8e2 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -10,6 +10,7 @@
10#include "common/alignment.h" 10#include "common/alignment.h"
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/settings.h"
13#include "core/core.h" 14#include "core/core.h"
14#include "core/device_memory.h" 15#include "core/device_memory.h"
15#include "core/file_sys/program_metadata.h" 16#include "core/file_sys/program_metadata.h"
@@ -26,7 +27,6 @@
26#include "core/hle/kernel/svc_results.h" 27#include "core/hle/kernel/svc_results.h"
27#include "core/hle/lock.h" 28#include "core/hle/lock.h"
28#include "core/memory.h" 29#include "core/memory.h"
29#include "core/settings.h"
30 30
31namespace Kernel { 31namespace Kernel {
32namespace { 32namespace {
@@ -120,9 +120,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
120 std::shared_ptr<Process> process = std::make_shared<Process>(system); 120 std::shared_ptr<Process> process = std::make_shared<Process>(system);
121 process->name = std::move(name); 121 process->name = std::move(name);
122 122
123 // TODO: This is inaccurate 123 process->resource_limit = kernel.GetSystemResourceLimit();
124 // The process should hold a reference to the kernel-wide resource limit.
125 process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
126 process->status = ProcessStatus::Created; 124 process->status = ProcessStatus::Created;
127 process->program_id = 0; 125 process->program_id = 0;
128 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() 126 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -160,17 +158,13 @@ void Process::DecrementThreadCount() {
160} 158}
161 159
162u64 Process::GetTotalPhysicalMemoryAvailable() const { 160u64 Process::GetTotalPhysicalMemoryAvailable() const {
163 // TODO: This is expected to always return the application memory pool size after accurately
164 // reserving kernel resources. The current workaround uses a process-local resource limit of
165 // application memory pool size, which is inaccurate.
166 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + 161 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
167 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 162 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
168 main_thread_stack_size}; 163 main_thread_stack_size};
169 164 ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
170 if (capacity < memory_usage_capacity) { 165 if (capacity < memory_usage_capacity) {
171 return capacity; 166 return capacity;
172 } 167 }
173
174 return memory_usage_capacity; 168 return memory_usage_capacity;
175} 169}
176 170
@@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
272 system_resource_size = metadata.GetSystemResourceSize(); 266 system_resource_size = metadata.GetSystemResourceSize();
273 image_size = code_size; 267 image_size = code_size;
274 268
275 // Set initial resource limits
276 resource_limit->SetLimitValue(
277 LimitableResource::PhysicalMemory,
278 kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
279 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, 269 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
280 code_size + system_resource_size); 270 code_size + system_resource_size);
281 if (!memory_reservation.Succeeded()) { 271 if (!memory_reservation.Succeeded()) {
@@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
324 UNREACHABLE(); 314 UNREACHABLE();
325 } 315 }
326 316
327 // Set initial resource limits
328 resource_limit->SetLimitValue(
329 LimitableResource::PhysicalMemory,
330 kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
331
332 resource_limit->SetLimitValue(LimitableResource::Threads, 608);
333 resource_limit->SetLimitValue(LimitableResource::Events, 700);
334 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
335 resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
336
337 // Create TLS region 317 // Create TLS region
338 tls_region_address = CreateTLSRegion(); 318 tls_region_address = CreateTLSRegion();
339 memory_reservation.Commit(); 319 memory_reservation.Commit();
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp
index 3fc326eab..1006ee50c 100644
--- a/src/core/hle/kernel/process_capability.cpp
+++ b/src/core/hle/kernel/process_capability.cpp
@@ -281,11 +281,6 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags)
281 continue; 281 continue;
282 } 282 }
283 283
284 if (svc_number >= svc_capabilities.size()) {
285 LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number);
286 return ResultOutOfRange;
287 }
288
289 svc_capabilities[svc_number] = true; 284 svc_capabilities[svc_number] = true;
290 } 285 }
291 286
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h
index 73ad197fa..b7a9b2e45 100644
--- a/src/core/hle/kernel/process_capability.h
+++ b/src/core/hle/kernel/process_capability.h
@@ -68,7 +68,7 @@ enum class ProgramType {
68class ProcessCapabilities { 68class ProcessCapabilities {
69public: 69public:
70 using InterruptCapabilities = std::bitset<1024>; 70 using InterruptCapabilities = std::bitset<1024>;
71 using SyscallCapabilities = std::bitset<128>; 71 using SyscallCapabilities = std::bitset<192>;
72 72
73 ProcessCapabilities() = default; 73 ProcessCapabilities() = default;
74 ProcessCapabilities(const ProcessCapabilities&) = delete; 74 ProcessCapabilities(const ProcessCapabilities&) = delete;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 326d3b9ec..bebb86154 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2156,7 +2156,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
2156 LOG_DEBUG(Kernel_SVC, "called"); 2156 LOG_DEBUG(Kernel_SVC, "called");
2157 2157
2158 auto& kernel = system.Kernel(); 2158 auto& kernel = system.Kernel();
2159 auto resource_limit = std::make_shared<KResourceLimit>(kernel, system); 2159 auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming());
2160 2160
2161 auto* const current_process = kernel.CurrentProcess(); 2161 auto* const current_process = kernel.CurrentProcess();
2162 ASSERT(current_process != nullptr); 2162 ASSERT(current_process != nullptr);
@@ -2455,6 +2455,74 @@ static const FunctionDef SVC_Table_32[] = {
2455 {0x79, nullptr, "Unknown"}, 2455 {0x79, nullptr, "Unknown"},
2456 {0x7A, nullptr, "Unknown"}, 2456 {0x7A, nullptr, "Unknown"},
2457 {0x7B, nullptr, "TerminateProcess32"}, 2457 {0x7B, nullptr, "TerminateProcess32"},
2458 {0x7C, nullptr, "GetProcessInfo32"},
2459 {0x7D, nullptr, "CreateResourceLimit32"},
2460 {0x7E, nullptr, "SetResourceLimitLimitValue32"},
2461 {0x7F, nullptr, "CallSecureMonitor32"},
2462 {0x80, nullptr, "Unknown"},
2463 {0x81, nullptr, "Unknown"},
2464 {0x82, nullptr, "Unknown"},
2465 {0x83, nullptr, "Unknown"},
2466 {0x84, nullptr, "Unknown"},
2467 {0x85, nullptr, "Unknown"},
2468 {0x86, nullptr, "Unknown"},
2469 {0x87, nullptr, "Unknown"},
2470 {0x88, nullptr, "Unknown"},
2471 {0x89, nullptr, "Unknown"},
2472 {0x8A, nullptr, "Unknown"},
2473 {0x8B, nullptr, "Unknown"},
2474 {0x8C, nullptr, "Unknown"},
2475 {0x8D, nullptr, "Unknown"},
2476 {0x8E, nullptr, "Unknown"},
2477 {0x8F, nullptr, "Unknown"},
2478 {0x90, nullptr, "Unknown"},
2479 {0x91, nullptr, "Unknown"},
2480 {0x92, nullptr, "Unknown"},
2481 {0x93, nullptr, "Unknown"},
2482 {0x94, nullptr, "Unknown"},
2483 {0x95, nullptr, "Unknown"},
2484 {0x96, nullptr, "Unknown"},
2485 {0x97, nullptr, "Unknown"},
2486 {0x98, nullptr, "Unknown"},
2487 {0x99, nullptr, "Unknown"},
2488 {0x9A, nullptr, "Unknown"},
2489 {0x9B, nullptr, "Unknown"},
2490 {0x9C, nullptr, "Unknown"},
2491 {0x9D, nullptr, "Unknown"},
2492 {0x9E, nullptr, "Unknown"},
2493 {0x9F, nullptr, "Unknown"},
2494 {0xA0, nullptr, "Unknown"},
2495 {0xA1, nullptr, "Unknown"},
2496 {0xA2, nullptr, "Unknown"},
2497 {0xA3, nullptr, "Unknown"},
2498 {0xA4, nullptr, "Unknown"},
2499 {0xA5, nullptr, "Unknown"},
2500 {0xA6, nullptr, "Unknown"},
2501 {0xA7, nullptr, "Unknown"},
2502 {0xA8, nullptr, "Unknown"},
2503 {0xA9, nullptr, "Unknown"},
2504 {0xAA, nullptr, "Unknown"},
2505 {0xAB, nullptr, "Unknown"},
2506 {0xAC, nullptr, "Unknown"},
2507 {0xAD, nullptr, "Unknown"},
2508 {0xAE, nullptr, "Unknown"},
2509 {0xAF, nullptr, "Unknown"},
2510 {0xB0, nullptr, "Unknown"},
2511 {0xB1, nullptr, "Unknown"},
2512 {0xB2, nullptr, "Unknown"},
2513 {0xB3, nullptr, "Unknown"},
2514 {0xB4, nullptr, "Unknown"},
2515 {0xB5, nullptr, "Unknown"},
2516 {0xB6, nullptr, "Unknown"},
2517 {0xB7, nullptr, "Unknown"},
2518 {0xB8, nullptr, "Unknown"},
2519 {0xB9, nullptr, "Unknown"},
2520 {0xBA, nullptr, "Unknown"},
2521 {0xBB, nullptr, "Unknown"},
2522 {0xBC, nullptr, "Unknown"},
2523 {0xBD, nullptr, "Unknown"},
2524 {0xBE, nullptr, "Unknown"},
2525 {0xBF, nullptr, "Unknown"},
2458}; 2526};
2459 2527
2460static const FunctionDef SVC_Table_64[] = { 2528static const FunctionDef SVC_Table_64[] = {
@@ -2586,6 +2654,70 @@ static const FunctionDef SVC_Table_64[] = {
2586 {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"}, 2654 {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"},
2587 {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"}, 2655 {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
2588 {0x7F, nullptr, "CallSecureMonitor"}, 2656 {0x7F, nullptr, "CallSecureMonitor"},
2657 {0x80, nullptr, "Unknown"},
2658 {0x81, nullptr, "Unknown"},
2659 {0x82, nullptr, "Unknown"},
2660 {0x83, nullptr, "Unknown"},
2661 {0x84, nullptr, "Unknown"},
2662 {0x85, nullptr, "Unknown"},
2663 {0x86, nullptr, "Unknown"},
2664 {0x87, nullptr, "Unknown"},
2665 {0x88, nullptr, "Unknown"},
2666 {0x89, nullptr, "Unknown"},
2667 {0x8A, nullptr, "Unknown"},
2668 {0x8B, nullptr, "Unknown"},
2669 {0x8C, nullptr, "Unknown"},
2670 {0x8D, nullptr, "Unknown"},
2671 {0x8E, nullptr, "Unknown"},
2672 {0x8F, nullptr, "Unknown"},
2673 {0x90, nullptr, "Unknown"},
2674 {0x91, nullptr, "Unknown"},
2675 {0x92, nullptr, "Unknown"},
2676 {0x93, nullptr, "Unknown"},
2677 {0x94, nullptr, "Unknown"},
2678 {0x95, nullptr, "Unknown"},
2679 {0x96, nullptr, "Unknown"},
2680 {0x97, nullptr, "Unknown"},
2681 {0x98, nullptr, "Unknown"},
2682 {0x99, nullptr, "Unknown"},
2683 {0x9A, nullptr, "Unknown"},
2684 {0x9B, nullptr, "Unknown"},
2685 {0x9C, nullptr, "Unknown"},
2686 {0x9D, nullptr, "Unknown"},
2687 {0x9E, nullptr, "Unknown"},
2688 {0x9F, nullptr, "Unknown"},
2689 {0xA0, nullptr, "Unknown"},
2690 {0xA1, nullptr, "Unknown"},
2691 {0xA2, nullptr, "Unknown"},
2692 {0xA3, nullptr, "Unknown"},
2693 {0xA4, nullptr, "Unknown"},
2694 {0xA5, nullptr, "Unknown"},
2695 {0xA6, nullptr, "Unknown"},
2696 {0xA7, nullptr, "Unknown"},
2697 {0xA8, nullptr, "Unknown"},
2698 {0xA9, nullptr, "Unknown"},
2699 {0xAA, nullptr, "Unknown"},
2700 {0xAB, nullptr, "Unknown"},
2701 {0xAC, nullptr, "Unknown"},
2702 {0xAD, nullptr, "Unknown"},
2703 {0xAE, nullptr, "Unknown"},
2704 {0xAF, nullptr, "Unknown"},
2705 {0xB0, nullptr, "Unknown"},
2706 {0xB1, nullptr, "Unknown"},
2707 {0xB2, nullptr, "Unknown"},
2708 {0xB3, nullptr, "Unknown"},
2709 {0xB4, nullptr, "Unknown"},
2710 {0xB5, nullptr, "Unknown"},
2711 {0xB6, nullptr, "Unknown"},
2712 {0xB7, nullptr, "Unknown"},
2713 {0xB8, nullptr, "Unknown"},
2714 {0xB9, nullptr, "Unknown"},
2715 {0xBA, nullptr, "Unknown"},
2716 {0xBB, nullptr, "Unknown"},
2717 {0xBC, nullptr, "Unknown"},
2718 {0xBD, nullptr, "Unknown"},
2719 {0xBE, nullptr, "Unknown"},
2720 {0xBF, nullptr, "Unknown"},
2589}; 2721};
2590 2722
2591static const FunctionDef* GetSVCInfo32(u32 func_num) { 2723static const FunctionDef* GetSVCInfo32(u32 func_num) {
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 615e20a54..52535ecc0 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -610,12 +610,17 @@ public:
610 explicit DAUTH_O(Core::System& system_, Common::UUID) : ServiceFramework{system_, "dauth:o"} { 610 explicit DAUTH_O(Core::System& system_, Common::UUID) : ServiceFramework{system_, "dauth:o"} {
611 // clang-format off 611 // clang-format off
612 static const FunctionInfo functions[] = { 612 static const FunctionInfo functions[] = {
613 {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, // [5.0.0-5.1.0] GeneratePostData 613 {0, nullptr, "EnsureAuthenticationTokenCacheAsync"},
614 {1, nullptr, "LoadAuthenticationTokenCache"}, // 6.0.0+ 614 {1, nullptr, "LoadAuthenticationTokenCache"},
615 {2, nullptr, "InvalidateAuthenticationTokenCache"}, // 6.0.0+ 615 {2, nullptr, "InvalidateAuthenticationTokenCache"},
616 {10, nullptr, "EnsureEdgeTokenCacheAsync"}, // 6.0.0+ 616 {10, nullptr, "EnsureEdgeTokenCacheAsync"},
617 {11, nullptr, "LoadEdgeTokenCache"}, // 6.0.0+ 617 {11, nullptr, "LoadEdgeTokenCache"},
618 {12, nullptr, "InvalidateEdgeTokenCache"}, // 6.0.0+ 618 {12, nullptr, "InvalidateEdgeTokenCache"},
619 {20, nullptr, "EnsureApplicationAuthenticationCacheAsync"},
620 {21, nullptr, "LoadApplicationAuthenticationTokenCache"},
621 {22, nullptr, "LoadApplicationNetworkServiceClientConfigCache"},
622 {23, nullptr, "IsApplicationAuthenticationCacheAvailable"},
623 {24, nullptr, "InvalidateApplicationAuthenticationCache"},
619 }; 624 };
620 // clang-format on 625 // clang-format on
621 626
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 49b22583e..bb6118abf 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -17,28 +17,30 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
17 {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, 17 {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
18 {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, 18 {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"},
19 {5, &ACC_SU::GetProfile, "GetProfile"}, 19 {5, &ACC_SU::GetProfile, "GetProfile"},
20 {6, nullptr, "GetProfileDigest"}, // 3.0.0+ 20 {6, nullptr, "GetProfileDigest"},
21 {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, 21 {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
22 {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, 22 {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
23 {60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 23 {60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
24 {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ 24 {99, nullptr, "DebugActivateOpenContextRetention"},
25 {100, nullptr, "GetUserRegistrationNotifier"}, 25 {100, nullptr, "GetUserRegistrationNotifier"},
26 {101, nullptr, "GetUserStateChangeNotifier"}, 26 {101, nullptr, "GetUserStateChangeNotifier"},
27 {102, nullptr, "GetBaasAccountManagerForSystemService"}, 27 {102, nullptr, "GetBaasAccountManagerForSystemService"},
28 {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, 28 {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
29 {104, nullptr, "GetProfileUpdateNotifier"}, 29 {104, nullptr, "GetProfileUpdateNotifier"},
30 {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ 30 {105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
31 {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ 31 {106, nullptr, "GetProfileSyncNotifier"},
32 {110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"}, 32 {110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"},
33 {111, nullptr, "ClearSaveDataThumbnail"}, 33 {111, nullptr, "ClearSaveDataThumbnail"},
34 {112, nullptr, "LoadSaveDataThumbnail"}, 34 {112, nullptr, "LoadSaveDataThumbnail"},
35 {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ 35 {113, nullptr, "GetSaveDataThumbnailExistence"},
36 {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ 36 {120, nullptr, "ListOpenUsersInApplication"},
37 {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ 37 {130, nullptr, "ActivateOpenContextRetention"},
38 {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ 38 {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"},
39 {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ 39 {150, nullptr, "AuthenticateApplicationAsync"},
40 {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 40 {151, nullptr, "Unknown151"},
41 {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ 41 {152, nullptr, "Unknown152"},
42 {190, nullptr, "GetUserLastOpenedApplication"},
43 {191, nullptr, "ActivateOpenContextHolder"},
42 {200, nullptr, "BeginUserRegistration"}, 44 {200, nullptr, "BeginUserRegistration"},
43 {201, nullptr, "CompleteUserRegistration"}, 45 {201, nullptr, "CompleteUserRegistration"},
44 {202, nullptr, "CancelUserRegistration"}, 46 {202, nullptr, "CancelUserRegistration"},
@@ -46,15 +48,15 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
46 {204, nullptr, "SetUserPosition"}, 48 {204, nullptr, "SetUserPosition"},
47 {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"}, 49 {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"},
48 {206, nullptr, "CompleteUserRegistrationForcibly"}, 50 {206, nullptr, "CompleteUserRegistrationForcibly"},
49 {210, nullptr, "CreateFloatingRegistrationRequest"}, // 3.0.0+ 51 {210, nullptr, "CreateFloatingRegistrationRequest"},
50 {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ 52 {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"},
51 {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ 53 {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"},
52 {230, nullptr, "AuthenticateServiceAsync"}, 54 {230, nullptr, "AuthenticateServiceAsync"},
53 {250, nullptr, "GetBaasAccountAdministrator"}, 55 {250, nullptr, "GetBaasAccountAdministrator"},
54 {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, 56 {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
55 {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, // 3.0.0+ 57 {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
56 {299, nullptr, "SuspendBackgroundDaemon"}, 58 {299, nullptr, "SuspendBackgroundDaemon"},
57 {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ 59 {997, nullptr, "DebugInvalidateTokenCacheForUser"},
58 {998, nullptr, "DebugSetUserStateClose"}, 60 {998, nullptr, "DebugSetUserStateClose"},
59 {999, nullptr, "DebugSetUserStateOpen"}, 61 {999, nullptr, "DebugSetUserStateOpen"},
60 }; 62 };
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index 951081cd0..71982ad5a 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -17,29 +17,31 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
17 {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, 17 {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
18 {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, 18 {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"},
19 {5, &ACC_U1::GetProfile, "GetProfile"}, 19 {5, &ACC_U1::GetProfile, "GetProfile"},
20 {6, nullptr, "GetProfileDigest"}, // 3.0.0+ 20 {6, nullptr, "GetProfileDigest"},
21 {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, 21 {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
22 {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, 22 {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
23 {60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 23 {60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
24 {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ 24 {99, nullptr, "DebugActivateOpenContextRetention"},
25 {100, nullptr, "GetUserRegistrationNotifier"}, 25 {100, nullptr, "GetUserRegistrationNotifier"},
26 {101, nullptr, "GetUserStateChangeNotifier"}, 26 {101, nullptr, "GetUserStateChangeNotifier"},
27 {102, nullptr, "GetBaasAccountManagerForSystemService"}, 27 {102, nullptr, "GetBaasAccountManagerForSystemService"},
28 {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, 28 {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
29 {104, nullptr, "GetProfileUpdateNotifier"}, 29 {104, nullptr, "GetProfileUpdateNotifier"},
30 {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ 30 {105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
31 {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ 31 {106, nullptr, "GetProfileSyncNotifier"},
32 {110, &ACC_U1::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"}, 32 {110, &ACC_U1::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
33 {111, nullptr, "ClearSaveDataThumbnail"}, 33 {111, nullptr, "ClearSaveDataThumbnail"},
34 {112, nullptr, "LoadSaveDataThumbnail"}, 34 {112, nullptr, "LoadSaveDataThumbnail"},
35 {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ 35 {113, nullptr, "GetSaveDataThumbnailExistence"},
36 {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ 36 {120, nullptr, "ListOpenUsersInApplication"},
37 {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ 37 {130, nullptr, "ActivateOpenContextRetention"},
38 {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ 38 {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"},
39 {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ 39 {150, nullptr, "AuthenticateApplicationAsync"},
40 {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 40 {151, nullptr, "Unknown151"},
41 {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ 41 {152, nullptr, "Unknown152"},
42 {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ 42 {190, nullptr, "GetUserLastOpenedApplication"},
43 {191, nullptr, "ActivateOpenContextHolder"},
44 {997, nullptr, "DebugInvalidateTokenCacheForUser"},
43 {998, nullptr, "DebugSetUserStateClose"}, 45 {998, nullptr, "DebugSetUserStateClose"},
44 {999, nullptr, "DebugSetUserStateOpen"}, 46 {999, nullptr, "DebugSetUserStateOpen"},
45 }; 47 };
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 50b2c58e2..de83d82a4 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -8,8 +8,8 @@
8#include <fmt/format.h> 8#include <fmt/format.h>
9 9
10#include "common/file_util.h" 10#include "common/file_util.h"
11#include "common/settings.h"
11#include "core/hle/service/acc/profile_manager.h" 12#include "core/hle/service/acc/profile_manager.h"
12#include "core/settings.h"
13 13
14namespace Service::Account { 14namespace Service::Account {
15 15
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 8e1fe9438..c59054468 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -7,6 +7,7 @@
7#include <cinttypes> 7#include <cinttypes>
8#include <cstring> 8#include <cstring>
9#include "audio_core/audio_renderer.h" 9#include "audio_core/audio_renderer.h"
10#include "common/settings.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/file_sys/control_metadata.h" 12#include "core/file_sys/control_metadata.h"
12#include "core/file_sys/patch_manager.h" 13#include "core/file_sys/patch_manager.h"
@@ -41,7 +42,6 @@
41#include "core/hle/service/set/set.h" 42#include "core/hle/service/set/set.h"
42#include "core/hle/service/sm/sm.h" 43#include "core/hle/service/sm/sm.h"
43#include "core/hle/service/vi/vi.h" 44#include "core/hle/service/vi/vi.h"
44#include "core/settings.h"
45 45
46namespace Service::AM { 46namespace Service::AM {
47 47
@@ -231,6 +231,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
231 {10, nullptr, "PerformSystemButtonPressing"}, 231 {10, nullptr, "PerformSystemButtonPressing"},
232 {20, nullptr, "InvalidateTransitionLayer"}, 232 {20, nullptr, "InvalidateTransitionLayer"},
233 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, 233 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
234 {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
234 {40, nullptr, "GetAppletResourceUsageInfo"}, 235 {40, nullptr, "GetAppletResourceUsageInfo"},
235 {100, nullptr, "SetCpuBoostModeForApplet"}, 236 {100, nullptr, "SetCpuBoostModeForApplet"},
236 {101, nullptr, "CancelCpuBoostModeForApplet"}, 237 {101, nullptr, "CancelCpuBoostModeForApplet"},
@@ -242,6 +243,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
242 {130, nullptr, "FriendInvitationSetApplicationParameter"}, 243 {130, nullptr, "FriendInvitationSetApplicationParameter"},
243 {131, nullptr, "FriendInvitationClearApplicationParameter"}, 244 {131, nullptr, "FriendInvitationClearApplicationParameter"},
244 {132, nullptr, "FriendInvitationPushApplicationParameter"}, 245 {132, nullptr, "FriendInvitationPushApplicationParameter"},
246 {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
245 }; 247 };
246 // clang-format on 248 // clang-format on
247 249
@@ -295,8 +297,9 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
295 {80, nullptr, "SetWirelessPriorityMode"}, 297 {80, nullptr, "SetWirelessPriorityMode"},
296 {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, 298 {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
297 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, 299 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
298 {100, nullptr, "SetAlbumImageTakenNotificationEnabled"}, 300 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
299 {110, nullptr, "SetApplicationAlbumUserData"}, 301 {110, nullptr, "SetApplicationAlbumUserData"},
302 {120, nullptr, "SaveCurrentScreenshot"},
300 {1000, nullptr, "GetDebugStorageChannel"}, 303 {1000, nullptr, "GetDebugStorageChannel"},
301 }; 304 };
302 // clang-format on 305 // clang-format on
@@ -560,6 +563,21 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
560 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); 563 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
561} 564}
562 565
566void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) {
567 IPC::RequestParser rp{ctx};
568
569 // This service call sets an internal flag whether a notification is shown when an image is
570 // captured. Currently we do not support capturing images via the capture button, so this can be
571 // stubbed for now.
572 const bool album_image_taken_notification_enabled = rp.Pop<bool>();
573
574 LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
575 album_image_taken_notification_enabled);
576
577 IPC::ResponseBuilder rb{ctx, 2};
578 rb.Push(RESULT_SUCCESS);
579}
580
563AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { 581AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
564 on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived"); 582 on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived");
565 on_new_message->Initialize(); 583 on_new_message->Initialize();
@@ -630,6 +648,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
630 {11, nullptr, "ReleaseSleepLock"}, 648 {11, nullptr, "ReleaseSleepLock"},
631 {12, nullptr, "ReleaseSleepLockTransiently"}, 649 {12, nullptr, "ReleaseSleepLockTransiently"},
632 {13, nullptr, "GetAcquiredSleepLockEvent"}, 650 {13, nullptr, "GetAcquiredSleepLockEvent"},
651 {14, nullptr, "GetWakeupCount"},
633 {20, nullptr, "PushToGeneralChannel"}, 652 {20, nullptr, "PushToGeneralChannel"},
634 {30, nullptr, "GetHomeButtonReaderLockAccessor"}, 653 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
635 {31, nullptr, "GetReaderLockAccessorEx"}, 654 {31, nullptr, "GetReaderLockAccessorEx"},
@@ -641,6 +660,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
641 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, 660 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
642 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, 661 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
643 {55, nullptr, "IsInControllerFirmwareUpdateSection"}, 662 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
663 {59, nullptr, "SetVrPositionForDebug"},
644 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, 664 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
645 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, 665 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
646 {62, nullptr, "GetHdcpAuthenticationState"}, 666 {62, nullptr, "GetHdcpAuthenticationState"},
@@ -649,14 +669,21 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
649 {65, nullptr, "GetApplicationIdByContentActionName"}, 669 {65, nullptr, "GetApplicationIdByContentActionName"},
650 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, 670 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
651 {67, nullptr, "CancelCpuBoostMode"}, 671 {67, nullptr, "CancelCpuBoostMode"},
672 {68, nullptr, "GetBuiltInDisplayType"},
652 {80, nullptr, "PerformSystemButtonPressingIfInFocus"}, 673 {80, nullptr, "PerformSystemButtonPressingIfInFocus"},
653 {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, 674 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
654 {91, nullptr, "GetCurrentPerformanceConfiguration"}, 675 {91, nullptr, "GetCurrentPerformanceConfiguration"},
655 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, 676 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
677 {110, nullptr, "OpenMyGpuErrorHandler"},
656 {200, nullptr, "GetOperationModeSystemInfo"}, 678 {200, nullptr, "GetOperationModeSystemInfo"},
657 {300, nullptr, "GetSettingsPlatformRegion"}, 679 {300, nullptr, "GetSettingsPlatformRegion"},
658 {400, nullptr, "ActivateMigrationService"}, 680 {400, nullptr, "ActivateMigrationService"},
659 {401, nullptr, "DeactivateMigrationService"}, 681 {401, nullptr, "DeactivateMigrationService"},
682 {500, nullptr, "DisableSleepTillShutdown"},
683 {501, nullptr, "SuppressDisablingSleepTemporarily"},
684 {502, nullptr, "IsSleepEnabled"},
685 {503, nullptr, "IsDisablingSleepSuppressed"},
686 {900, nullptr, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
660 }; 687 };
661 // clang-format on 688 // clang-format on
662 689
@@ -944,7 +971,7 @@ private:
944 971
945 auto storage = applet->GetBroker().PopNormalDataToGame(); 972 auto storage = applet->GetBroker().PopNormalDataToGame();
946 if (storage == nullptr) { 973 if (storage == nullptr) {
947 LOG_ERROR(Service_AM, 974 LOG_DEBUG(Service_AM,
948 "storage is a nullptr. There is no data in the current normal channel"); 975 "storage is a nullptr. There is no data in the current normal channel");
949 IPC::ResponseBuilder rb{ctx, 2}; 976 IPC::ResponseBuilder rb{ctx, 2};
950 rb.Push(ERR_NO_DATA_IN_CHANNEL); 977 rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -975,7 +1002,7 @@ private:
975 1002
976 auto storage = applet->GetBroker().PopInteractiveDataToGame(); 1003 auto storage = applet->GetBroker().PopInteractiveDataToGame();
977 if (storage == nullptr) { 1004 if (storage == nullptr) {
978 LOG_ERROR(Service_AM, 1005 LOG_DEBUG(Service_AM,
979 "storage is a nullptr. There is no data in the current interactive channel"); 1006 "storage is a nullptr. There is no data in the current interactive channel");
980 IPC::ResponseBuilder rb{ctx, 2}; 1007 IPC::ResponseBuilder rb{ctx, 2};
981 rb.Push(ERR_NO_DATA_IN_CHANNEL); 1008 rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -1098,7 +1125,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
1098 {2, nullptr, "AreAnyLibraryAppletsLeft"}, 1125 {2, nullptr, "AreAnyLibraryAppletsLeft"},
1099 {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, 1126 {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
1100 {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, 1127 {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
1101 {12, nullptr, "CreateHandleStorage"}, 1128 {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
1102 }; 1129 };
1103 RegisterHandlers(functions); 1130 RegisterHandlers(functions);
1104} 1131}
@@ -1107,14 +1134,15 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
1107 1134
1108void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { 1135void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
1109 IPC::RequestParser rp{ctx}; 1136 IPC::RequestParser rp{ctx};
1137
1110 const auto applet_id = rp.PopRaw<Applets::AppletId>(); 1138 const auto applet_id = rp.PopRaw<Applets::AppletId>();
1111 const auto applet_mode = rp.PopRaw<u32>(); 1139 const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
1112 1140
1113 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, 1141 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
1114 applet_mode); 1142 applet_mode);
1115 1143
1116 const auto& applet_manager{system.GetAppletManager()}; 1144 const auto& applet_manager{system.GetAppletManager()};
1117 const auto applet = applet_manager.GetApplet(applet_id); 1145 const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
1118 1146
1119 if (applet == nullptr) { 1147 if (applet == nullptr) {
1120 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); 1148 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
@@ -1132,9 +1160,18 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
1132 1160
1133void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { 1161void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
1134 IPC::RequestParser rp{ctx}; 1162 IPC::RequestParser rp{ctx};
1135 const u64 size{rp.Pop<u64>()}; 1163
1164 const s64 size{rp.Pop<s64>()};
1165
1136 LOG_DEBUG(Service_AM, "called, size={}", size); 1166 LOG_DEBUG(Service_AM, "called, size={}", size);
1137 1167
1168 if (size <= 0) {
1169 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1170 IPC::ResponseBuilder rb{ctx, 2};
1171 rb.Push(RESULT_UNKNOWN);
1172 return;
1173 }
1174
1138 std::vector<u8> buffer(size); 1175 std::vector<u8> buffer(size);
1139 1176
1140 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1177 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -1143,18 +1180,65 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
1143} 1180}
1144 1181
1145void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { 1182void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
1146 LOG_DEBUG(Service_AM, "called"); 1183 IPC::RequestParser rp{ctx};
1184
1185 struct Parameters {
1186 u8 permissions;
1187 s64 size;
1188 };
1189
1190 const auto parameters{rp.PopRaw<Parameters>()};
1191 const auto handle{ctx.GetCopyHandle(0)};
1192
1193 LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
1194 parameters.size, handle);
1195
1196 if (parameters.size <= 0) {
1197 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1198 IPC::ResponseBuilder rb{ctx, 2};
1199 rb.Push(RESULT_UNKNOWN);
1200 return;
1201 }
1202
1203 auto transfer_mem =
1204 system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
1205
1206 if (transfer_mem == nullptr) {
1207 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
1208 IPC::ResponseBuilder rb{ctx, 2};
1209 rb.Push(RESULT_UNKNOWN);
1210 return;
1211 }
1212
1213 const u8* const mem_begin = transfer_mem->GetPointer();
1214 const u8* const mem_end = mem_begin + transfer_mem->GetSize();
1215 std::vector<u8> memory{mem_begin, mem_end};
1216
1217 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1218 rb.Push(RESULT_SUCCESS);
1219 rb.PushIpcInterface<IStorage>(system, std::move(memory));
1220}
1147 1221
1222void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) {
1148 IPC::RequestParser rp{ctx}; 1223 IPC::RequestParser rp{ctx};
1149 1224
1150 rp.SetCurrentOffset(3); 1225 const s64 size{rp.Pop<s64>()};
1151 const auto handle{rp.Pop<Kernel::Handle>()}; 1226 const auto handle{ctx.GetCopyHandle(0)};
1227
1228 LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
1229
1230 if (size <= 0) {
1231 LOG_ERROR(Service_AM, "size is less than or equal to 0");
1232 IPC::ResponseBuilder rb{ctx, 2};
1233 rb.Push(RESULT_UNKNOWN);
1234 return;
1235 }
1152 1236
1153 auto transfer_mem = 1237 auto transfer_mem =
1154 system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); 1238 system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
1155 1239
1156 if (transfer_mem == nullptr) { 1240 if (transfer_mem == nullptr) {
1157 LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle); 1241 LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
1158 IPC::ResponseBuilder rb{ctx, 2}; 1242 IPC::ResponseBuilder rb{ctx, 2};
1159 rb.Push(RESULT_UNKNOWN); 1243 rb.Push(RESULT_UNKNOWN);
1160 return; 1244 return;
@@ -1188,11 +1272,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1188 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, 1272 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
1189 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, 1273 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
1190 {27, nullptr, "CreateCacheStorage"}, 1274 {27, nullptr, "CreateCacheStorage"},
1275 {28, nullptr, "GetSaveDataSizeMax"},
1276 {29, nullptr, "GetCacheStorageMax"},
1191 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, 1277 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
1192 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, 1278 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
1193 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, 1279 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
1194 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, 1280 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
1195 {34, nullptr, "SelectApplicationLicense"}, 1281 {34, nullptr, "SelectApplicationLicense"},
1282 {35, nullptr, "GetDeviceSaveDataSizeMax"},
1196 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, 1283 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
1197 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, 1284 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
1198 {60, nullptr, "SetMediaPlaybackStateForApplication"}, 1285 {60, nullptr, "SetMediaPlaybackStateForApplication"},
@@ -1216,6 +1303,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1216 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, 1303 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
1217 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, 1304 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
1218 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, 1305 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
1306 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
1219 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, 1307 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
1220 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, 1308 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
1221 {150, nullptr, "GetNotificationStorageChannelEvent"}, 1309 {150, nullptr, "GetNotificationStorageChannelEvent"},
@@ -1224,6 +1312,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1224 {170, nullptr, "SetHdcpAuthenticationActivated"}, 1312 {170, nullptr, "SetHdcpAuthenticationActivated"},
1225 {180, nullptr, "GetLaunchRequiredVersion"}, 1313 {180, nullptr, "GetLaunchRequiredVersion"},
1226 {181, nullptr, "UpgradeLaunchRequiredVersion"}, 1314 {181, nullptr, "UpgradeLaunchRequiredVersion"},
1315 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
1316 {200, nullptr, "GetLastApplicationExitReason"},
1227 {500, nullptr, "StartContinuousRecordingFlushForDebug"}, 1317 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
1228 {1000, nullptr, "CreateMovieMaker"}, 1318 {1000, nullptr, "CreateMovieMaker"},
1229 {1001, nullptr, "PrepareForJit"}, 1319 {1001, nullptr, "PrepareForJit"},
@@ -1690,9 +1780,12 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
1690 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, 1780 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
1691 {30, nullptr, "GetHomeButtonWriterLockAccessor"}, 1781 {30, nullptr, "GetHomeButtonWriterLockAccessor"},
1692 {31, nullptr, "GetWriterLockAccessorEx"}, 1782 {31, nullptr, "GetWriterLockAccessorEx"},
1783 {40, nullptr, "IsSleepEnabled"},
1784 {41, nullptr, "IsRebootEnabled"},
1693 {100, nullptr, "PopRequestLaunchApplicationForDebug"}, 1785 {100, nullptr, "PopRequestLaunchApplicationForDebug"},
1694 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, 1786 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
1695 {200, nullptr, "LaunchDevMenu"}, 1787 {200, nullptr, "LaunchDevMenu"},
1788 {1000, nullptr, "SetLastApplicationExitReason"},
1696 }; 1789 };
1697 // clang-format on 1790 // clang-format on
1698 1791
@@ -1736,6 +1829,7 @@ IGlobalStateController::IGlobalStateController(Core::System& system_)
1736 {13, nullptr, "UpdateDefaultDisplayResolution"}, 1829 {13, nullptr, "UpdateDefaultDisplayResolution"},
1737 {14, nullptr, "ShouldSleepOnBoot"}, 1830 {14, nullptr, "ShouldSleepOnBoot"},
1738 {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, 1831 {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
1832 {30, nullptr, "OpenCradleFirmwareUpdater"},
1739 }; 1833 };
1740 // clang-format on 1834 // clang-format on
1741 1835
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 6911f0d6e..aefbdf0d5 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -146,6 +146,7 @@ private:
146 void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx); 146 void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx);
147 void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); 147 void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx);
148 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); 148 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx);
149 void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx);
149 150
150 enum class ScreenshotPermission : u32 { 151 enum class ScreenshotPermission : u32 {
151 Inherit = 0, 152 Inherit = 0,
@@ -253,6 +254,7 @@ private:
253 void CreateLibraryApplet(Kernel::HLERequestContext& ctx); 254 void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
254 void CreateStorage(Kernel::HLERequestContext& ctx); 255 void CreateStorage(Kernel::HLERequestContext& ctx);
255 void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); 256 void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx);
257 void CreateHandleStorage(Kernel::HLERequestContext& ctx);
256}; 258};
257 259
258class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { 260class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index e2f3b7563..5ddad851a 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -241,31 +241,31 @@ void AppletManager::ClearAll() {
241 frontend = {}; 241 frontend = {};
242} 242}
243 243
244std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { 244std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
245 switch (id) { 245 switch (id) {
246 case AppletId::Auth: 246 case AppletId::Auth:
247 return std::make_shared<Auth>(system, *frontend.parental_controls); 247 return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
248 case AppletId::Controller: 248 case AppletId::Controller:
249 return std::make_shared<Controller>(system, *frontend.controller); 249 return std::make_shared<Controller>(system, mode, *frontend.controller);
250 case AppletId::Error: 250 case AppletId::Error:
251 return std::make_shared<Error>(system, *frontend.error); 251 return std::make_shared<Error>(system, mode, *frontend.error);
252 case AppletId::ProfileSelect: 252 case AppletId::ProfileSelect:
253 return std::make_shared<ProfileSelect>(system, *frontend.profile_select); 253 return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
254 case AppletId::SoftwareKeyboard: 254 case AppletId::SoftwareKeyboard:
255 return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard); 255 return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
256 case AppletId::Web: 256 case AppletId::Web:
257 case AppletId::Shop: 257 case AppletId::Shop:
258 case AppletId::OfflineWeb: 258 case AppletId::OfflineWeb:
259 case AppletId::LoginShare: 259 case AppletId::LoginShare:
260 case AppletId::WebAuth: 260 case AppletId::WebAuth:
261 return std::make_shared<WebBrowser>(system, *frontend.web_browser); 261 return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
262 case AppletId::PhotoViewer: 262 case AppletId::PhotoViewer:
263 return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer); 263 return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
264 default: 264 default:
265 UNIMPLEMENTED_MSG( 265 UNIMPLEMENTED_MSG(
266 "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", 266 "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
267 static_cast<u8>(id)); 267 static_cast<u8>(id));
268 return std::make_shared<StubApplet>(system, id); 268 return std::make_shared<StubApplet>(system, id, mode);
269 } 269 }
270} 270}
271 271
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index b9a006317..26b482015 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -62,6 +62,14 @@ enum class AppletId : u32 {
62 MyPage = 0x1A, 62 MyPage = 0x1A,
63}; 63};
64 64
65enum class LibraryAppletMode : u32 {
66 AllForeground = 0,
67 Background = 1,
68 NoUI = 2,
69 BackgroundIndirectDisplay = 3,
70 AllForegroundInitiallyHidden = 4,
71};
72
65class AppletDataBroker final { 73class AppletDataBroker final {
66public: 74public:
67 explicit AppletDataBroker(Kernel::KernelCore& kernel_); 75 explicit AppletDataBroker(Kernel::KernelCore& kernel_);
@@ -200,7 +208,7 @@ public:
200 void SetDefaultAppletsIfMissing(); 208 void SetDefaultAppletsIfMissing();
201 void ClearAll(); 209 void ClearAll();
202 210
203 std::shared_ptr<Applet> GetApplet(AppletId id) const; 211 std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
204 212
205private: 213private:
206 AppletFrontendSet frontend; 214 AppletFrontendSet frontend;
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp
index c2bfe698f..a33f05f97 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -45,8 +45,9 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
45 }; 45 };
46} 46}
47 47
48Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) 48Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
49 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} 49 const Core::Frontend::ControllerApplet& frontend_)
50 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
50 51
51Controller::~Controller() = default; 52Controller::~Controller() = default;
52 53
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h
index d4c9da7b1..07cb92bf9 100644
--- a/src/core/hle/service/am/applets/controller.h
+++ b/src/core/hle/service/am/applets/controller.h
@@ -106,7 +106,8 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
106 106
107class Controller final : public Applet { 107class Controller final : public Applet {
108public: 108public:
109 explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_); 109 explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_,
110 const Core::Frontend::ControllerApplet& frontend_);
110 ~Controller() override; 111 ~Controller() override;
111 112
112 void Initialize() override; 113 void Initialize() override;
@@ -119,6 +120,7 @@ public:
119 void ConfigurationComplete(); 120 void ConfigurationComplete();
120 121
121private: 122private:
123 LibraryAppletMode applet_mode;
122 const Core::Frontend::ControllerApplet& frontend; 124 const Core::Frontend::ControllerApplet& frontend;
123 Core::System& system; 125 Core::System& system;
124 126
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index 0c8b632e8..a9f0a9c95 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -86,8 +86,9 @@ ResultCode Decode64BitError(u64 error) {
86 86
87} // Anonymous namespace 87} // Anonymous namespace
88 88
89Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_) 89Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
90 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} 90 const Core::Frontend::ErrorApplet& frontend_)
91 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
91 92
92Error::~Error() = default; 93Error::~Error() = default;
93 94
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
index a105cdb0c..a3e520cd4 100644
--- a/src/core/hle/service/am/applets/error.h
+++ b/src/core/hle/service/am/applets/error.h
@@ -25,7 +25,8 @@ enum class ErrorAppletMode : u8 {
25 25
26class Error final : public Applet { 26class Error final : public Applet {
27public: 27public:
28 explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_); 28 explicit Error(Core::System& system_, LibraryAppletMode applet_mode_,
29 const Core::Frontend::ErrorApplet& frontend_);
29 ~Error() override; 30 ~Error() override;
30 31
31 void Initialize() override; 32 void Initialize() override;
@@ -40,6 +41,7 @@ public:
40private: 41private:
41 union ErrorArguments; 42 union ErrorArguments;
42 43
44 LibraryAppletMode applet_mode;
43 const Core::Frontend::ErrorApplet& frontend; 45 const Core::Frontend::ErrorApplet& frontend;
44 ResultCode error_code = RESULT_SUCCESS; 46 ResultCode error_code = RESULT_SUCCESS;
45 ErrorAppletMode mode = ErrorAppletMode::ShowError; 47 ErrorAppletMode mode = ErrorAppletMode::ShowError;
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 4d1df5cbe..71016cce7 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -37,8 +37,9 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
37 } 37 }
38} 38}
39 39
40Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_) 40Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
41 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} 41 Core::Frontend::ParentalControlsApplet& frontend_)
42 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
42 43
43Auth::~Auth() = default; 44Auth::~Auth() = default;
44 45
@@ -152,8 +153,9 @@ void Auth::AuthFinished(bool is_successful) {
152 broker.SignalStateChanged(); 153 broker.SignalStateChanged();
153} 154}
154 155
155PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_) 156PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
156 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} 157 const Core::Frontend::PhotoViewerApplet& frontend_)
158 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
157 159
158PhotoViewer::~PhotoViewer() = default; 160PhotoViewer::~PhotoViewer() = default;
159 161
@@ -202,8 +204,8 @@ void PhotoViewer::ViewFinished() {
202 broker.SignalStateChanged(); 204 broker.SignalStateChanged();
203} 205}
204 206
205StubApplet::StubApplet(Core::System& system_, AppletId id_) 207StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
206 : Applet{system_.Kernel()}, id{id_}, system{system_} {} 208 : Applet{system_.Kernel()}, id{id_}, applet_mode{applet_mode_}, system{system_} {}
207 209
208StubApplet::~StubApplet() = default; 210StubApplet::~StubApplet() = default;
209 211
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
index ba76ae3d3..d9e6d4384 100644
--- a/src/core/hle/service/am/applets/general_backend.h
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -20,7 +20,8 @@ enum class AuthAppletType : u32 {
20 20
21class Auth final : public Applet { 21class Auth final : public Applet {
22public: 22public:
23 explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_); 23 explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
24 Core::Frontend::ParentalControlsApplet& frontend_);
24 ~Auth() override; 25 ~Auth() override;
25 26
26 void Initialize() override; 27 void Initialize() override;
@@ -32,6 +33,7 @@ public:
32 void AuthFinished(bool is_successful = true); 33 void AuthFinished(bool is_successful = true);
33 34
34private: 35private:
36 LibraryAppletMode applet_mode;
35 Core::Frontend::ParentalControlsApplet& frontend; 37 Core::Frontend::ParentalControlsApplet& frontend;
36 Core::System& system; 38 Core::System& system;
37 bool complete = false; 39 bool complete = false;
@@ -50,7 +52,8 @@ enum class PhotoViewerAppletMode : u8 {
50 52
51class PhotoViewer final : public Applet { 53class PhotoViewer final : public Applet {
52public: 54public:
53 explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_); 55 explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
56 const Core::Frontend::PhotoViewerApplet& frontend_);
54 ~PhotoViewer() override; 57 ~PhotoViewer() override;
55 58
56 void Initialize() override; 59 void Initialize() override;
@@ -62,6 +65,7 @@ public:
62 void ViewFinished(); 65 void ViewFinished();
63 66
64private: 67private:
68 LibraryAppletMode applet_mode;
65 const Core::Frontend::PhotoViewerApplet& frontend; 69 const Core::Frontend::PhotoViewerApplet& frontend;
66 bool complete = false; 70 bool complete = false;
67 PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; 71 PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
@@ -70,7 +74,7 @@ private:
70 74
71class StubApplet final : public Applet { 75class StubApplet final : public Applet {
72public: 76public:
73 explicit StubApplet(Core::System& system_, AppletId id_); 77 explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
74 ~StubApplet() override; 78 ~StubApplet() override;
75 79
76 void Initialize() override; 80 void Initialize() override;
@@ -82,6 +86,7 @@ public:
82 86
83private: 87private:
84 AppletId id; 88 AppletId id;
89 LibraryAppletMode applet_mode;
85 Core::System& system; 90 Core::System& system;
86}; 91};
87 92
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 77fba16c7..ab8b6fcc5 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,9 +15,9 @@ namespace Service::AM::Applets {
15 15
16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; 16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
17 17
18ProfileSelect::ProfileSelect(Core::System& system_, 18ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
19 const Core::Frontend::ProfileSelectApplet& frontend_) 19 const Core::Frontend::ProfileSelectApplet& frontend_)
20 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} 20 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
21 21
22ProfileSelect::~ProfileSelect() = default; 22ProfileSelect::~ProfileSelect() = default;
23 23
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 648d33a24..90f054030 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
33 33
34class ProfileSelect final : public Applet { 34class ProfileSelect final : public Applet {
35public: 35public:
36 explicit ProfileSelect(Core::System& system_, 36 explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
37 const Core::Frontend::ProfileSelectApplet& frontend_); 37 const Core::Frontend::ProfileSelectApplet& frontend_);
38 ~ProfileSelect() override; 38 ~ProfileSelect() override;
39 39
@@ -47,6 +47,7 @@ public:
47 void SelectionComplete(std::optional<Common::UUID> uuid); 47 void SelectionComplete(std::optional<Common::UUID> uuid);
48 48
49private: 49private:
50 LibraryAppletMode applet_mode;
50 const Core::Frontend::ProfileSelectApplet& frontend; 51 const Core::Frontend::ProfileSelectApplet& frontend;
51 52
52 UserSelectionConfig config; 53 UserSelectionConfig config;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 79b209c6b..c3a05de9c 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -1,93 +1,80 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include "common/assert.h"
7#include "common/string_util.h" 5#include "common/string_util.h"
8#include "core/core.h" 6#include "core/core.h"
9#include "core/frontend/applets/software_keyboard.h" 7#include "core/frontend/applets/software_keyboard.h"
10#include "core/hle/result.h"
11#include "core/hle/service/am/am.h" 8#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/software_keyboard.h" 9#include "core/hle/service/am/applets/software_keyboard.h"
13 10
14namespace Service::AM::Applets { 11namespace Service::AM::Applets {
15 12
16namespace { 13namespace {
17enum class Request : u32 { 14
18 Finalize = 0x4, 15// The maximum number of UTF-16 characters that can be input into the swkbd text field.
19 SetUserWordInfo = 0x6, 16constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500;
20 SetCustomizeDic = 0x7, 17
21 Calc = 0xa, 18constexpr std::size_t REPLY_BASE_SIZE = sizeof(SwkbdState) + sizeof(SwkbdReplyType);
22 SetCustomizedDictionaries = 0xb, 19constexpr std::size_t REPLY_UTF8_SIZE = 0x7D4;
23 UnsetCustomizedDictionaries = 0xc, 20constexpr std::size_t REPLY_UTF16_SIZE = 0x3EC;
24 UnknownD = 0xd, 21
25 UnknownE = 0xe, 22constexpr const char* GetTextCheckResultName(SwkbdTextCheckResult text_check_result) {
26}; 23 switch (text_check_result) {
27constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8; 24 case SwkbdTextCheckResult::Success:
28constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; 25 return "Success";
29constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; 26 case SwkbdTextCheckResult::Failure:
30constexpr std::size_t DEFAULT_MAX_LENGTH = 500; 27 return "Failure";
31constexpr bool INTERACTIVE_STATUS_OK = false; 28 case SwkbdTextCheckResult::Confirm:
29 return "Confirm";
30 case SwkbdTextCheckResult::Silent:
31 return "Silent";
32 default:
33 UNIMPLEMENTED_MSG("Unknown TextCheckResult={}", text_check_result);
34 return "Unknown";
35 }
36}
37
38void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply_type) {
39 std::memcpy(reply.data(), &state, sizeof(SwkbdState));
40 std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType));
41}
42
32} // Anonymous namespace 43} // Anonymous namespace
33static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( 44
34 KeyboardConfig config, std::u16string initial_text) { 45SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
35 Core::Frontend::SoftwareKeyboardParameters params{}; 46 Core::Frontend::SoftwareKeyboardApplet& frontend_)
36 47 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {}
37 params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
38 config.submit_text.data(), config.submit_text.size());
39 params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
40 config.header_text.data(), config.header_text.size());
41 params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(),
42 config.sub_text.size());
43 params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(),
44 config.guide_text.size());
45 params.initial_text = std::move(initial_text);
46 params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit;
47 params.password = static_cast<bool>(config.is_password);
48 params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position);
49 params.value = static_cast<u8>(config.keyset_disable_bitmask);
50
51 return params;
52}
53
54SoftwareKeyboard::SoftwareKeyboard(Core::System& system_,
55 const Core::Frontend::SoftwareKeyboardApplet& frontend_)
56 : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
57 48
58SoftwareKeyboard::~SoftwareKeyboard() = default; 49SoftwareKeyboard::~SoftwareKeyboard() = default;
59 50
60void SoftwareKeyboard::Initialize() { 51void SoftwareKeyboard::Initialize() {
61 complete = false;
62 is_inline = false;
63 initial_text.clear();
64 final_data.clear();
65
66 Applet::Initialize(); 52 Applet::Initialize();
67 53
68 const auto keyboard_config_storage = broker.PopNormalDataToApplet(); 54 LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
69 ASSERT(keyboard_config_storage != nullptr); 55 applet_mode);
70 const auto& keyboard_config = keyboard_config_storage->GetData();
71
72 if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
73 is_inline = true;
74 return;
75 }
76
77 ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
78 std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
79 56
80 const auto work_buffer_storage = broker.PopNormalDataToApplet(); 57 LOG_DEBUG(Service_AM,
81 ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; }); 58 "Initializing Applet with common_args: arg_version={}, lib_version={}, "
82 const auto& work_buffer = work_buffer_storage->GetData(); 59 "play_startup_sound={}, size={}, system_tick={}, theme_color={}",
60 common_args.arguments_version, common_args.library_version,
61 common_args.play_startup_sound, common_args.size, common_args.system_tick,
62 common_args.theme_color);
83 63
84 if (config.initial_string_size == 0) 64 swkbd_applet_version = SwkbdAppletVersion{common_args.library_version};
85 return;
86 65
87 std::vector<char16_t> string(config.initial_string_size); 66 switch (applet_mode) {
88 std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset, 67 case LibraryAppletMode::AllForeground:
89 string.size() * 2); 68 InitializeForeground();
90 initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); 69 break;
70 case LibraryAppletMode::Background:
71 case LibraryAppletMode::BackgroundIndirectDisplay:
72 InitializeBackground(applet_mode);
73 break;
74 default:
75 UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode);
76 break;
77 }
91} 78}
92 79
93bool SoftwareKeyboard::TransactionComplete() const { 80bool SoftwareKeyboard::TransactionComplete() const {
@@ -95,106 +82,996 @@ bool SoftwareKeyboard::TransactionComplete() const {
95} 82}
96 83
97ResultCode SoftwareKeyboard::GetStatus() const { 84ResultCode SoftwareKeyboard::GetStatus() const {
98 return RESULT_SUCCESS; 85 return status;
99} 86}
100 87
101void SoftwareKeyboard::ExecuteInteractive() { 88void SoftwareKeyboard::ExecuteInteractive() {
102 if (complete) 89 if (complete) {
103 return; 90 return;
91 }
104 92
105 const auto storage = broker.PopInteractiveDataToApplet(); 93 if (is_background) {
106 ASSERT(storage != nullptr); 94 ProcessInlineKeyboardRequest();
107 const auto data = storage->GetData();
108 if (!is_inline) {
109 const auto status = static_cast<bool>(data[0]);
110 if (status == INTERACTIVE_STATUS_OK) {
111 complete = true;
112 } else {
113 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
114 std::memcpy(string.data(), data.data() + 4, string.size() * 2);
115 frontend.SendTextCheckDialog(
116 Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
117 [this] { broker.SignalStateChanged(); });
118 }
119 } else { 95 } else {
120 Request request{}; 96 ProcessTextCheck();
121 std::memcpy(&request, data.data(), sizeof(Request)); 97 }
98}
99
100void SoftwareKeyboard::Execute() {
101 if (complete) {
102 return;
103 }
104
105 if (is_background) {
106 return;
107 }
108
109 ShowNormalKeyboard();
110}
122 111
123 switch (request) { 112void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) {
124 case Request::Finalize: 113 if (complete) {
125 complete = true; 114 return;
126 broker.SignalStateChanged(); 115 }
116
117 if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) {
118 SubmitForTextCheck(submitted_text);
119 } else {
120 SubmitNormalOutputAndExit(result, submitted_text);
121 }
122}
123
124void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
125 s32 cursor_position) {
126 if (complete) {
127 return;
128 }
129
130 current_text = std::move(submitted_text);
131 current_cursor_position = cursor_position;
132
133 if (inline_use_utf8) {
134 switch (reply_type) {
135 case SwkbdReplyType::ChangedString:
136 reply_type = SwkbdReplyType::ChangedStringUtf8;
127 break; 137 break;
128 case Request::Calc: { 138 case SwkbdReplyType::MovedCursor:
129 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1})); 139 reply_type = SwkbdReplyType::MovedCursorUtf8;
130 broker.SignalStateChanged(); 140 break;
141 case SwkbdReplyType::DecidedEnter:
142 reply_type = SwkbdReplyType::DecidedEnterUtf8;
143 break;
144 default:
131 break; 145 break;
132 } 146 }
147 }
148
149 if (use_changed_string_v2) {
150 switch (reply_type) {
151 case SwkbdReplyType::ChangedString:
152 reply_type = SwkbdReplyType::ChangedStringV2;
153 break;
154 case SwkbdReplyType::ChangedStringUtf8:
155 reply_type = SwkbdReplyType::ChangedStringUtf8V2;
156 break;
133 default: 157 default:
134 UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
135 break; 158 break;
136 } 159 }
137 } 160 }
161
162 if (use_moved_cursor_v2) {
163 switch (reply_type) {
164 case SwkbdReplyType::MovedCursor:
165 reply_type = SwkbdReplyType::MovedCursorV2;
166 break;
167 case SwkbdReplyType::MovedCursorUtf8:
168 reply_type = SwkbdReplyType::MovedCursorUtf8V2;
169 break;
170 default:
171 break;
172 }
173 }
174
175 SendReply(reply_type);
138} 176}
139 177
140void SoftwareKeyboard::Execute() { 178void SoftwareKeyboard::InitializeForeground() {
141 if (complete) { 179 LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet.");
142 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); 180
143 broker.SignalStateChanged(); 181 is_background = false;
182
183 const auto swkbd_config_storage = broker.PopNormalDataToApplet();
184 ASSERT(swkbd_config_storage != nullptr);
185
186 const auto& swkbd_config_data = swkbd_config_storage->GetData();
187 ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon));
188
189 std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon));
190
191 switch (swkbd_applet_version) {
192 case SwkbdAppletVersion::Version5:
193 case SwkbdAppletVersion::Version65542:
194 ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld));
195 std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
196 sizeof(SwkbdConfigOld));
197 break;
198 case SwkbdAppletVersion::Version196615:
199 case SwkbdAppletVersion::Version262152:
200 case SwkbdAppletVersion::Version327689:
201 ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2));
202 std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
203 sizeof(SwkbdConfigOld2));
204 break;
205 case SwkbdAppletVersion::Version393227:
206 case SwkbdAppletVersion::Version524301:
207 ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
208 std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
209 sizeof(SwkbdConfigNew));
210 break;
211 default:
212 UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version,
213 swkbd_config_data.size());
214 ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
215 std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
216 sizeof(SwkbdConfigNew));
217 break;
218 }
219
220 const auto work_buffer_storage = broker.PopNormalDataToApplet();
221 ASSERT(work_buffer_storage != nullptr);
222
223 if (swkbd_config_common.initial_string_length == 0) {
224 InitializeFrontendKeyboard();
144 return; 225 return;
145 } 226 }
146 227
147 const auto parameters = ConvertToFrontendParameters(config, initial_text); 228 const auto& work_buffer = work_buffer_storage->GetData();
148 if (!is_inline) { 229
149 frontend.RequestText( 230 std::vector<char16_t> initial_string(swkbd_config_common.initial_string_length);
150 [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters); 231
232 std::memcpy(initial_string.data(),
233 work_buffer.data() + swkbd_config_common.initial_string_offset,
234 swkbd_config_common.initial_string_length * sizeof(char16_t));
235
236 initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(initial_string.data(),
237 initial_string.size());
238
239 LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text));
240
241 InitializeFrontendKeyboard();
242}
243
244void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) {
245 LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet.");
246
247 is_background = true;
248
249 const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet();
250 ASSERT(swkbd_inline_initialize_arg_storage != nullptr);
251
252 const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData();
253 ASSERT(swkbd_inline_initialize_arg.size() == sizeof(SwkbdInitializeArg));
254
255 std::memcpy(&swkbd_initialize_arg, swkbd_inline_initialize_arg.data(),
256 swkbd_inline_initialize_arg.size());
257
258 if (swkbd_initialize_arg.library_applet_mode_flag) {
259 ASSERT(applet_mode == LibraryAppletMode::Background);
260 } else {
261 ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay);
262 }
263}
264
265void SoftwareKeyboard::ProcessTextCheck() {
266 const auto text_check_storage = broker.PopInteractiveDataToApplet();
267 ASSERT(text_check_storage != nullptr);
268
269 const auto& text_check_data = text_check_storage->GetData();
270 ASSERT(text_check_data.size() == sizeof(SwkbdTextCheck));
271
272 SwkbdTextCheck swkbd_text_check;
273
274 std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck));
275
276 std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer(
277 swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size());
278
279 LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}",
280 GetTextCheckResultName(swkbd_text_check.text_check_result),
281 Common::UTF16ToUTF8(text_check_message));
282
283 switch (swkbd_text_check.text_check_result) {
284 case SwkbdTextCheckResult::Success:
285 SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text);
286 break;
287 case SwkbdTextCheckResult::Failure:
288 ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message);
289 break;
290 case SwkbdTextCheckResult::Confirm:
291 ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message);
292 break;
293 case SwkbdTextCheckResult::Silent:
294 default:
295 break;
151 } 296 }
152} 297}
153 298
154void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { 299void SoftwareKeyboard::ProcessInlineKeyboardRequest() {
155 std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE); 300 const auto request_data_storage = broker.PopInteractiveDataToApplet();
301 ASSERT(request_data_storage != nullptr);
302
303 const auto& request_data = request_data_storage->GetData();
304 ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand));
156 305
157 if (text.has_value()) { 306 SwkbdRequestCommand request_command;
158 std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
159 307
160 if (config.utf_8) { 308 std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand));
161 const u64 size = text->size() + sizeof(u64);
162 const auto new_text = Common::UTF16ToUTF8(*text);
163 309
164 std::memcpy(output_sub.data(), &size, sizeof(u64)); 310 switch (request_command) {
165 std::memcpy(output_sub.data() + 8, new_text.data(), 311 case SwkbdRequestCommand::Finalize:
166 std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8)); 312 RequestFinalize(request_data);
313 break;
314 case SwkbdRequestCommand::SetUserWordInfo:
315 RequestSetUserWordInfo(request_data);
316 break;
317 case SwkbdRequestCommand::SetCustomizeDic:
318 RequestSetCustomizeDic(request_data);
319 break;
320 case SwkbdRequestCommand::Calc:
321 RequestCalc(request_data);
322 break;
323 case SwkbdRequestCommand::SetCustomizedDictionaries:
324 RequestSetCustomizedDictionaries(request_data);
325 break;
326 case SwkbdRequestCommand::UnsetCustomizedDictionaries:
327 RequestUnsetCustomizedDictionaries(request_data);
328 break;
329 case SwkbdRequestCommand::SetChangedStringV2Flag:
330 RequestSetChangedStringV2Flag(request_data);
331 break;
332 case SwkbdRequestCommand::SetMovedCursorV2Flag:
333 RequestSetMovedCursorV2Flag(request_data);
334 break;
335 default:
336 UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command);
337 break;
338 }
339}
167 340
168 output_main[0] = INTERACTIVE_STATUS_OK; 341void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
169 std::memcpy(output_main.data() + 4, new_text.data(), 342 std::u16string submitted_text) {
170 std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); 343 std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE);
171 } else {
172 const u64 size = text->size() * 2 + sizeof(u64);
173 std::memcpy(output_sub.data(), &size, sizeof(u64));
174 std::memcpy(output_sub.data() + 8, text->data(),
175 std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8));
176 344
177 output_main[0] = INTERACTIVE_STATUS_OK; 345 if (swkbd_config_common.use_utf8) {
178 std::memcpy(output_main.data() + 4, text->data(), 346 std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text);
179 std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
180 }
181 347
182 complete = !config.text_check; 348 LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result,
183 final_data = output_main; 349 utf8_submitted_text);
184 350
185 if (complete) { 351 std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
186 broker.PushNormalDataFromApplet( 352 std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(),
187 std::make_shared<IStorage>(system, std::move(output_main))); 353 utf8_submitted_text.size());
188 broker.SignalStateChanged();
189 } else {
190 broker.PushInteractiveDataFromApplet(
191 std::make_shared<IStorage>(system, std::move(output_sub)));
192 }
193 } else { 354 } else {
194 output_main[0] = 1; 355 LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result,
195 complete = true; 356 Common::UTF16ToUTF8(submitted_text));
196 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main))); 357
197 broker.SignalStateChanged(); 358 std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
359 std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(),
360 submitted_text.size() * sizeof(char16_t));
361 }
362
363 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
364
365 ExitKeyboard();
366}
367
368void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
369 current_text = std::move(submitted_text);
370
371 std::vector<u8> out_data(sizeof(u64) + STRING_BUFFER_SIZE);
372
373 if (swkbd_config_common.use_utf8) {
374 std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text);
375 const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size();
376
377 LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size,
378 utf8_submitted_text);
379
380 std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
381 std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(),
382 utf8_submitted_text.size());
383 } else {
384 const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t);
385
386 LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size,
387 Common::UTF16ToUTF8(current_text));
388
389 std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
390 std::memcpy(out_data.data() + sizeof(u64), current_text.data(),
391 current_text.size() * sizeof(char16_t));
392 }
393
394 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
395}
396
397void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) {
398 switch (reply_type) {
399 case SwkbdReplyType::FinishedInitialize:
400 ReplyFinishedInitialize();
401 break;
402 case SwkbdReplyType::Default:
403 ReplyDefault();
404 break;
405 case SwkbdReplyType::ChangedString:
406 ReplyChangedString();
407 break;
408 case SwkbdReplyType::MovedCursor:
409 ReplyMovedCursor();
410 break;
411 case SwkbdReplyType::MovedTab:
412 ReplyMovedTab();
413 break;
414 case SwkbdReplyType::DecidedEnter:
415 ReplyDecidedEnter();
416 break;
417 case SwkbdReplyType::DecidedCancel:
418 ReplyDecidedCancel();
419 break;
420 case SwkbdReplyType::ChangedStringUtf8:
421 ReplyChangedStringUtf8();
422 break;
423 case SwkbdReplyType::MovedCursorUtf8:
424 ReplyMovedCursorUtf8();
425 break;
426 case SwkbdReplyType::DecidedEnterUtf8:
427 ReplyDecidedEnterUtf8();
428 break;
429 case SwkbdReplyType::UnsetCustomizeDic:
430 ReplyUnsetCustomizeDic();
431 break;
432 case SwkbdReplyType::ReleasedUserWordInfo:
433 ReplyReleasedUserWordInfo();
434 break;
435 case SwkbdReplyType::UnsetCustomizedDictionaries:
436 ReplyUnsetCustomizedDictionaries();
437 break;
438 case SwkbdReplyType::ChangedStringV2:
439 ReplyChangedStringV2();
440 break;
441 case SwkbdReplyType::MovedCursorV2:
442 ReplyMovedCursorV2();
443 break;
444 case SwkbdReplyType::ChangedStringUtf8V2:
445 ReplyChangedStringUtf8V2();
446 break;
447 case SwkbdReplyType::MovedCursorUtf8V2:
448 ReplyMovedCursorUtf8V2();
449 break;
450 default:
451 UNIMPLEMENTED_MSG("Unknown SwkbdReplyType={}", reply_type);
452 ReplyDefault();
453 break;
454 }
455}
456
457void SoftwareKeyboard::ChangeState(SwkbdState state) {
458 swkbd_state = state;
459
460 ReplyDefault();
461}
462
463void SoftwareKeyboard::InitializeFrontendKeyboard() {
464 if (is_background) {
465 const auto& appear_arg = swkbd_calc_arg.appear_arg;
466
467 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
468 appear_arg.ok_text.data(), appear_arg.ok_text.size());
469
470 const u32 max_text_length =
471 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
472 ? appear_arg.max_text_length
473 : DEFAULT_MAX_TEXT_LENGTH;
474
475 const u32 min_text_length =
476 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
477
478 const s32 initial_cursor_position =
479 current_cursor_position > 0 ? current_cursor_position : 0;
480
481 const auto text_draw_type =
482 max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
483
484 Core::Frontend::KeyboardInitializeParameters initialize_parameters{
485 .ok_text{ok_text},
486 .header_text{},
487 .sub_text{},
488 .guide_text{},
489 .initial_text{current_text},
490 .max_text_length{max_text_length},
491 .min_text_length{min_text_length},
492 .initial_cursor_position{initial_cursor_position},
493 .type{appear_arg.type},
494 .password_mode{SwkbdPasswordMode::Disabled},
495 .text_draw_type{text_draw_type},
496 .key_disable_flags{appear_arg.key_disable_flags},
497 .use_blur_background{false},
498 .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
499 .enable_return_button{appear_arg.enable_return_button},
500 .disable_cancel_button{appear_arg.disable_cancel_button},
501 };
502
503 frontend.InitializeKeyboard(
504 true, std::move(initialize_parameters), {},
505 [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) {
506 SubmitTextInline(reply_type, submitted_text, cursor_position);
507 });
508 } else {
509 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
510 swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size());
511
512 std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
513 swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size());
514
515 std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
516 swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size());
517
518 std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
519 swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size());
520
521 const u32 max_text_length =
522 swkbd_config_common.max_text_length > 0 &&
523 swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
524 ? swkbd_config_common.max_text_length
525 : DEFAULT_MAX_TEXT_LENGTH;
526
527 const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length
528 ? swkbd_config_common.min_text_length
529 : 0;
530
531 const s32 initial_cursor_position = [this] {
532 switch (swkbd_config_common.initial_cursor_position) {
533 case SwkbdInitialCursorPosition::Start:
534 default:
535 return 0;
536 case SwkbdInitialCursorPosition::End:
537 return static_cast<s32>(initial_text.size());
538 }
539 }();
540
541 const auto text_draw_type = [this, max_text_length] {
542 switch (swkbd_config_common.text_draw_type) {
543 case SwkbdTextDrawType::Line:
544 default:
545 return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
546 case SwkbdTextDrawType::Box:
547 case SwkbdTextDrawType::DownloadCode:
548 return swkbd_config_common.text_draw_type;
549 }
550 }();
551
552 const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box
553 ? swkbd_config_common.enable_return_button
554 : false;
555
556 const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227
557 ? swkbd_config_new.disable_cancel_button
558 : false;
559
560 Core::Frontend::KeyboardInitializeParameters initialize_parameters{
561 .ok_text{ok_text},
562 .header_text{header_text},
563 .sub_text{sub_text},
564 .guide_text{guide_text},
565 .initial_text{initial_text},
566 .max_text_length{max_text_length},
567 .min_text_length{min_text_length},
568 .initial_cursor_position{initial_cursor_position},
569 .type{swkbd_config_common.type},
570 .password_mode{swkbd_config_common.password_mode},
571 .text_draw_type{text_draw_type},
572 .key_disable_flags{swkbd_config_common.key_disable_flags},
573 .use_blur_background{swkbd_config_common.use_blur_background},
574 .enable_backspace_button{true},
575 .enable_return_button{enable_return_button},
576 .disable_cancel_button{disable_cancel_button},
577 };
578
579 frontend.InitializeKeyboard(false, std::move(initialize_parameters),
580 [this](SwkbdResult result, std::u16string submitted_text) {
581 SubmitTextNormal(result, submitted_text);
582 },
583 {});
584 }
585}
586
587void SoftwareKeyboard::ShowNormalKeyboard() {
588 frontend.ShowNormalKeyboard();
589}
590
591void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
592 std::u16string text_check_message) {
593 frontend.ShowTextCheckDialog(text_check_result, text_check_message);
594}
595
596void SoftwareKeyboard::ShowInlineKeyboard() {
597 if (swkbd_state != SwkbdState::InitializedIsHidden) {
598 return;
599 }
600
601 ChangeState(SwkbdState::InitializedIsAppearing);
602
603 const auto& appear_arg = swkbd_calc_arg.appear_arg;
604
605 const u32 max_text_length =
606 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
607 ? appear_arg.max_text_length
608 : DEFAULT_MAX_TEXT_LENGTH;
609
610 const u32 min_text_length =
611 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
612
613 Core::Frontend::InlineAppearParameters appear_parameters{
614 .max_text_length{max_text_length},
615 .min_text_length{min_text_length},
616 .key_top_scale_x{swkbd_calc_arg.key_top_scale_x},
617 .key_top_scale_y{swkbd_calc_arg.key_top_scale_y},
618 .key_top_translate_x{swkbd_calc_arg.key_top_translate_x},
619 .key_top_translate_y{swkbd_calc_arg.key_top_translate_y},
620 .type{appear_arg.type},
621 .key_disable_flags{appear_arg.key_disable_flags},
622 .key_top_as_floating{swkbd_calc_arg.key_top_as_floating},
623 .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
624 .enable_return_button{appear_arg.enable_return_button},
625 .disable_cancel_button{appear_arg.disable_cancel_button},
626 };
627
628 frontend.ShowInlineKeyboard(std::move(appear_parameters));
629
630 ChangeState(SwkbdState::InitializedIsShown);
631}
632
633void SoftwareKeyboard::HideInlineKeyboard() {
634 if (swkbd_state != SwkbdState::InitializedIsShown) {
635 return;
636 }
637
638 ChangeState(SwkbdState::InitializedIsDisappearing);
639
640 frontend.HideInlineKeyboard();
641
642 ChangeState(SwkbdState::InitializedIsHidden);
643}
644
645void SoftwareKeyboard::InlineTextChanged() {
646 Core::Frontend::InlineTextParameters text_parameters{
647 .input_text{current_text},
648 .cursor_position{current_cursor_position},
649 };
650
651 frontend.InlineTextChanged(std::move(text_parameters));
652}
653
654void SoftwareKeyboard::ExitKeyboard() {
655 complete = true;
656 status = RESULT_SUCCESS;
657
658 frontend.ExitKeyboard();
659
660 broker.SignalStateChanged();
661}
662
663// Inline Software Keyboard Requests
664
665void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) {
666 LOG_DEBUG(Service_AM, "Processing Request: Finalize");
667
668 ChangeState(SwkbdState::NotInitialized);
669
670 ExitKeyboard();
671}
672
673void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) {
674 LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented.");
675}
676
677void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) {
678 LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented.");
679}
680
681void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) {
682 LOG_DEBUG(Service_AM, "Processing Request: Calc");
683
684 ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg));
685
686 std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand),
687 sizeof(SwkbdCalcArg));
688
689 if (swkbd_calc_arg.flags.set_input_text) {
690 current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
691 swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size());
692 }
693
694 if (swkbd_calc_arg.flags.set_cursor_position) {
695 current_cursor_position = swkbd_calc_arg.cursor_position;
696 }
697
698 if (swkbd_calc_arg.flags.set_utf8_mode) {
699 inline_use_utf8 = swkbd_calc_arg.utf8_mode;
700 }
701
702 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
703 swkbd_calc_arg.flags.unset_customize_dic) {
704 ReplyUnsetCustomizeDic();
198 } 705 }
706
707 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
708 swkbd_calc_arg.flags.unset_user_word_info) {
709 ReplyReleasedUserWordInfo();
710 }
711
712 if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) {
713 InitializeFrontendKeyboard();
714
715 ChangeState(SwkbdState::InitializedIsHidden);
716
717 ReplyFinishedInitialize();
718 }
719
720 if (!swkbd_calc_arg.flags.set_initialize_arg &&
721 (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) {
722 InlineTextChanged();
723 }
724
725 if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) {
726 ShowInlineKeyboard();
727 return;
728 }
729
730 if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) {
731 HideInlineKeyboard();
732 return;
733 }
734}
735
736void SoftwareKeyboard::RequestSetCustomizedDictionaries(const std::vector<u8>& request_data) {
737 LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented.");
738}
739
740void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data) {
741 LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries");
742
743 ReplyUnsetCustomizedDictionaries();
744}
745
746void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector<u8>& request_data) {
747 LOG_DEBUG(Service_AM, "Processing Request: SetChangedStringV2Flag");
748
749 ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
750
751 std::memcpy(&use_changed_string_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
752}
753
754void SoftwareKeyboard::RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data) {
755 LOG_DEBUG(Service_AM, "Processing Request: SetMovedCursorV2Flag");
756
757 ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
758
759 std::memcpy(&use_moved_cursor_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
760}
761
762// Inline Software Keyboard Replies
763
764void SoftwareKeyboard::ReplyFinishedInitialize() {
765 LOG_DEBUG(Service_AM, "Sending Reply: FinishedInitialize");
766
767 std::vector<u8> reply(REPLY_BASE_SIZE + 1);
768
769 SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
770
771 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
772}
773
774void SoftwareKeyboard::ReplyDefault() {
775 LOG_DEBUG(Service_AM, "Sending Reply: Default");
776
777 std::vector<u8> reply(REPLY_BASE_SIZE);
778
779 SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
780
781 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
782}
783
784void SoftwareKeyboard::ReplyChangedString() {
785 LOG_DEBUG(Service_AM, "Sending Reply: ChangedString");
786
787 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg));
788
789 SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString);
790
791 const SwkbdChangedStringArg changed_string_arg{
792 .text_length{static_cast<u32>(current_text.size())},
793 .dictionary_start_cursor_position{-1},
794 .dictionary_end_cursor_position{-1},
795 .cursor_position{current_cursor_position},
796 };
797
798 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
799 current_text.size() * sizeof(char16_t));
800 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
801 sizeof(SwkbdChangedStringArg));
802
803 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
804}
805
806void SoftwareKeyboard::ReplyMovedCursor() {
807 LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor");
808
809 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg));
810
811 SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor);
812
813 const SwkbdMovedCursorArg moved_cursor_arg{
814 .text_length{static_cast<u32>(current_text.size())},
815 .cursor_position{current_cursor_position},
816 };
817
818 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
819 current_text.size() * sizeof(char16_t));
820 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
821 sizeof(SwkbdMovedCursorArg));
822
823 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
824}
825
826void SoftwareKeyboard::ReplyMovedTab() {
827 LOG_DEBUG(Service_AM, "Sending Reply: MovedTab");
828
829 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg));
830
831 SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab);
832
833 const SwkbdMovedTabArg moved_tab_arg{
834 .text_length{static_cast<u32>(current_text.size())},
835 .cursor_position{current_cursor_position},
836 };
837
838 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
839 current_text.size() * sizeof(char16_t));
840 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg,
841 sizeof(SwkbdMovedTabArg));
842
843 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
844}
845
846void SoftwareKeyboard::ReplyDecidedEnter() {
847 LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter");
848
849 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg));
850
851 SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter);
852
853 const SwkbdDecidedEnterArg decided_enter_arg{
854 .text_length{static_cast<u32>(current_text.size())},
855 };
856
857 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
858 current_text.size() * sizeof(char16_t));
859 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg,
860 sizeof(SwkbdDecidedEnterArg));
861
862 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
863
864 HideInlineKeyboard();
865}
866
867void SoftwareKeyboard::ReplyDecidedCancel() {
868 LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel");
869
870 std::vector<u8> reply(REPLY_BASE_SIZE);
871
872 SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
873
874 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
875
876 HideInlineKeyboard();
877}
878
879void SoftwareKeyboard::ReplyChangedStringUtf8() {
880 LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8");
881
882 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg));
883
884 SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8);
885
886 std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
887
888 const SwkbdChangedStringArg changed_string_arg{
889 .text_length{static_cast<u32>(current_text.size())},
890 .dictionary_start_cursor_position{-1},
891 .dictionary_end_cursor_position{-1},
892 .cursor_position{current_cursor_position},
893 };
894
895 std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
896 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
897 sizeof(SwkbdChangedStringArg));
898
899 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
199} 900}
901
902void SoftwareKeyboard::ReplyMovedCursorUtf8() {
903 LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8");
904
905 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg));
906
907 SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8);
908
909 std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
910
911 const SwkbdMovedCursorArg moved_cursor_arg{
912 .text_length{static_cast<u32>(current_text.size())},
913 .cursor_position{current_cursor_position},
914 };
915
916 std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
917 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
918 sizeof(SwkbdMovedCursorArg));
919
920 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
921}
922
923void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
924 LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8");
925
926 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdDecidedEnterArg));
927
928 SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnterUtf8);
929
930 std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
931
932 const SwkbdDecidedEnterArg decided_enter_arg{
933 .text_length{static_cast<u32>(current_text.size())},
934 };
935
936 std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
937 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg,
938 sizeof(SwkbdDecidedEnterArg));
939
940 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
941
942 HideInlineKeyboard();
943}
944
945void SoftwareKeyboard::ReplyUnsetCustomizeDic() {
946 LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic");
947
948 std::vector<u8> reply(REPLY_BASE_SIZE);
949
950 SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
951
952 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
953}
954
955void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
956 LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo");
957
958 std::vector<u8> reply(REPLY_BASE_SIZE);
959
960 SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
961
962 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
963}
964
965void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
966 LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries");
967
968 std::vector<u8> reply(REPLY_BASE_SIZE);
969
970 SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
971
972 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
973}
974
975void SoftwareKeyboard::ReplyChangedStringV2() {
976 LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2");
977
978 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg) + 1);
979
980 SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringV2);
981
982 const SwkbdChangedStringArg changed_string_arg{
983 .text_length{static_cast<u32>(current_text.size())},
984 .dictionary_start_cursor_position{-1},
985 .dictionary_end_cursor_position{-1},
986 .cursor_position{current_cursor_position},
987 };
988
989 constexpr u8 flag = 0;
990
991 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
992 current_text.size() * sizeof(char16_t));
993 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
994 sizeof(SwkbdChangedStringArg));
995 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg),
996 &flag, 1);
997
998 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
999}
1000
1001void SoftwareKeyboard::ReplyMovedCursorV2() {
1002 LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2");
1003
1004 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
1005
1006 SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorV2);
1007
1008 const SwkbdMovedCursorArg moved_cursor_arg{
1009 .text_length{static_cast<u32>(current_text.size())},
1010 .cursor_position{current_cursor_position},
1011 };
1012
1013 constexpr u8 flag = 0;
1014
1015 std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
1016 current_text.size() * sizeof(char16_t));
1017 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
1018 sizeof(SwkbdMovedCursorArg));
1019 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg),
1020 &flag, 1);
1021
1022 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
1023}
1024
1025void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
1026 LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2");
1027
1028 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg) + 1);
1029
1030 SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8V2);
1031
1032 std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
1033
1034 const SwkbdChangedStringArg changed_string_arg{
1035 .text_length{static_cast<u32>(current_text.size())},
1036 .dictionary_start_cursor_position{-1},
1037 .dictionary_end_cursor_position{-1},
1038 .cursor_position{current_cursor_position},
1039 };
1040
1041 constexpr u8 flag = 0;
1042
1043 std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
1044 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
1045 sizeof(SwkbdChangedStringArg));
1046 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg),
1047 &flag, 1);
1048
1049 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
1050}
1051
1052void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
1053 LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2");
1054
1055 std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
1056
1057 SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8V2);
1058
1059 std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
1060
1061 const SwkbdMovedCursorArg moved_cursor_arg{
1062 .text_length{static_cast<u32>(current_text.size())},
1063 .cursor_position{current_cursor_position},
1064 };
1065
1066 constexpr u8 flag = 0;
1067
1068 std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
1069 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
1070 sizeof(SwkbdMovedCursorArg));
1071 std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg),
1072 &flag, 1);
1073
1074 broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
1075}
1076
200} // namespace Service::AM::Applets 1077} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index 1d260fef8..85aeb4eb1 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -1,20 +1,14 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <string>
9#include <vector>
10
11#include "common/common_funcs.h" 7#include "common/common_funcs.h"
12#include "common/common_types.h" 8#include "common/common_types.h"
13#include "common/swap.h" 9#include "core/hle/result.h"
14#include "core/hle/service/am/am.h"
15#include "core/hle/service/am/applets/applets.h" 10#include "core/hle/service/am/applets/applets.h"
16 11#include "core/hle/service/am/applets/software_keyboard_types.h"
17union ResultCode;
18 12
19namespace Core { 13namespace Core {
20class System; 14class System;
@@ -22,45 +16,10 @@ class System;
22 16
23namespace Service::AM::Applets { 17namespace Service::AM::Applets {
24 18
25enum class KeysetDisable : u32 {
26 Space = 0x02,
27 Address = 0x04,
28 Percent = 0x08,
29 Slashes = 0x10,
30 Numbers = 0x40,
31 DownloadCode = 0x80,
32};
33
34struct KeyboardConfig {
35 INSERT_PADDING_BYTES(4);
36 std::array<char16_t, 9> submit_text;
37 u16_le left_symbol_key;
38 u16_le right_symbol_key;
39 INSERT_PADDING_BYTES(1);
40 KeysetDisable keyset_disable_bitmask;
41 u32_le initial_cursor_position;
42 std::array<char16_t, 65> header_text;
43 std::array<char16_t, 129> sub_text;
44 std::array<char16_t, 257> guide_text;
45 u32_le length_limit;
46 INSERT_PADDING_BYTES(4);
47 u32_le is_password;
48 INSERT_PADDING_BYTES(5);
49 bool utf_8;
50 bool draw_background;
51 u32_le initial_string_offset;
52 u32_le initial_string_size;
53 u32_le user_dictionary_offset;
54 u32_le user_dictionary_size;
55 bool text_check;
56 u64_le text_check_callback;
57};
58static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size.");
59
60class SoftwareKeyboard final : public Applet { 19class SoftwareKeyboard final : public Applet {
61public: 20public:
62 explicit SoftwareKeyboard(Core::System& system_, 21 explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
63 const Core::Frontend::SoftwareKeyboardApplet& frontend_); 22 Core::Frontend::SoftwareKeyboardApplet& frontend_);
64 ~SoftwareKeyboard() override; 23 ~SoftwareKeyboard() override;
65 24
66 void Initialize() override; 25 void Initialize() override;
@@ -70,17 +29,139 @@ public:
70 void ExecuteInteractive() override; 29 void ExecuteInteractive() override;
71 void Execute() override; 30 void Execute() override;
72 31
73 void WriteText(std::optional<std::u16string> text); 32 /**
33 * Submits the input text to the application.
34 * If text checking is enabled, the application will verify the input text.
35 * If use_utf8 is enabled, the input text will be converted to UTF-8 prior to being submitted.
36 * This should only be used by the normal software keyboard.
37 *
38 * @param result SwkbdResult enum
39 * @param submitted_text UTF-16 encoded string
40 */
41 void SubmitTextNormal(SwkbdResult result, std::u16string submitted_text);
42
43 /**
44 * Submits the input text to the application.
45 * If utf8_mode is enabled, the input text will be converted to UTF-8 prior to being submitted.
46 * This should only be used by the inline software keyboard.
47 *
48 * @param reply_type SwkbdReplyType enum
49 * @param submitted_text UTF-16 encoded string
50 * @param cursor_position The current position of the text cursor
51 */
52 void SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
53 s32 cursor_position);
74 54
75private: 55private:
76 const Core::Frontend::SoftwareKeyboardApplet& frontend; 56 /// Initializes the normal software keyboard.
57 void InitializeForeground();
77 58
78 KeyboardConfig config; 59 /// Initializes the inline software keyboard.
79 std::u16string initial_text; 60 void InitializeBackground(LibraryAppletMode applet_mode);
80 bool complete = false; 61
81 bool is_inline = false; 62 /// Processes the text check sent by the application.
82 std::vector<u8> final_data; 63 void ProcessTextCheck();
64
65 /// Processes the inline software keyboard request command sent by the application.
66 void ProcessInlineKeyboardRequest();
67
68 /// Submits the input text and exits the applet.
69 void SubmitNormalOutputAndExit(SwkbdResult result, std::u16string submitted_text);
70
71 /// Submits the input text for text checking.
72 void SubmitForTextCheck(std::u16string submitted_text);
73
74 /// Sends a reply to the application after processing a request command.
75 void SendReply(SwkbdReplyType reply_type);
76
77 /// Changes the inline keyboard state.
78 void ChangeState(SwkbdState state);
79
80 /**
81 * Signals the frontend to initialize the software keyboard with common parameters.
82 * This initializes either the normal software keyboard or the inline software keyboard
83 * depending on the state of is_background.
84 * Note that this does not cause the keyboard to appear.
85 * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear.
86 */
87 void InitializeFrontendKeyboard();
88
89 /// Signals the frontend to show the normal software keyboard.
90 void ShowNormalKeyboard();
91
92 /// Signals the frontend to show the text check dialog.
93 void ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
94 std::u16string text_check_message);
95
96 /// Signals the frontend to show the inline software keyboard.
97 void ShowInlineKeyboard();
98
99 /// Signals the frontend to hide the inline software keyboard.
100 void HideInlineKeyboard();
101
102 /// Signals the frontend that the current inline keyboard text has changed.
103 void InlineTextChanged();
104
105 /// Signals both the frontend and application that the software keyboard is exiting.
106 void ExitKeyboard();
107
108 // Inline Software Keyboard Requests
109
110 void RequestFinalize(const std::vector<u8>& request_data);
111 void RequestSetUserWordInfo(const std::vector<u8>& request_data);
112 void RequestSetCustomizeDic(const std::vector<u8>& request_data);
113 void RequestCalc(const std::vector<u8>& request_data);
114 void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data);
115 void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data);
116 void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data);
117 void RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data);
118
119 // Inline Software Keyboard Replies
120
121 void ReplyFinishedInitialize();
122 void ReplyDefault();
123 void ReplyChangedString();
124 void ReplyMovedCursor();
125 void ReplyMovedTab();
126 void ReplyDecidedEnter();
127 void ReplyDecidedCancel();
128 void ReplyChangedStringUtf8();
129 void ReplyMovedCursorUtf8();
130 void ReplyDecidedEnterUtf8();
131 void ReplyUnsetCustomizeDic();
132 void ReplyReleasedUserWordInfo();
133 void ReplyUnsetCustomizedDictionaries();
134 void ReplyChangedStringV2();
135 void ReplyMovedCursorV2();
136 void ReplyChangedStringUtf8V2();
137 void ReplyMovedCursorUtf8V2();
138
139 LibraryAppletMode applet_mode;
140 Core::Frontend::SoftwareKeyboardApplet& frontend;
83 Core::System& system; 141 Core::System& system;
142
143 SwkbdAppletVersion swkbd_applet_version;
144
145 SwkbdConfigCommon swkbd_config_common;
146 SwkbdConfigOld swkbd_config_old;
147 SwkbdConfigOld2 swkbd_config_old2;
148 SwkbdConfigNew swkbd_config_new;
149 std::u16string initial_text;
150
151 SwkbdState swkbd_state{SwkbdState::NotInitialized};
152 SwkbdInitializeArg swkbd_initialize_arg;
153 SwkbdCalcArg swkbd_calc_arg;
154 bool use_changed_string_v2{false};
155 bool use_moved_cursor_v2{false};
156 bool inline_use_utf8{false};
157 s32 current_cursor_position{};
158
159 std::u16string current_text;
160
161 bool is_background{false};
162
163 bool complete{false};
164 ResultCode status{RESULT_SUCCESS};
84}; 165};
85 166
86} // namespace Service::AM::Applets 167} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard_types.h b/src/core/hle/service/am/applets/software_keyboard_types.h
new file mode 100644
index 000000000..21aa8e800
--- /dev/null
+++ b/src/core/hle/service/am/applets/software_keyboard_types.h
@@ -0,0 +1,295 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/swap.h"
13
14namespace Service::AM::Applets {
15
16constexpr std::size_t MAX_OK_TEXT_LENGTH = 8;
17constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64;
18constexpr std::size_t MAX_SUB_TEXT_LENGTH = 128;
19constexpr std::size_t MAX_GUIDE_TEXT_LENGTH = 256;
20constexpr std::size_t STRING_BUFFER_SIZE = 0x7D4;
21
22enum class SwkbdAppletVersion : u32_le {
23 Version5 = 0x5, // 1.0.0
24 Version65542 = 0x10006, // 2.0.0 - 2.3.0
25 Version196615 = 0x30007, // 3.0.0 - 3.0.2
26 Version262152 = 0x40008, // 4.0.0 - 4.1.0
27 Version327689 = 0x50009, // 5.0.0 - 5.1.0
28 Version393227 = 0x6000B, // 6.0.0 - 7.0.1
29 Version524301 = 0x8000D, // 8.0.0+
30};
31
32enum class SwkbdType : u32 {
33 Normal,
34 NumberPad,
35 Qwerty,
36 Unknown3,
37 Latin,
38 SimplifiedChinese,
39 TraditionalChinese,
40 Korean,
41};
42
43enum class SwkbdInitialCursorPosition : u32 {
44 Start,
45 End,
46};
47
48enum class SwkbdPasswordMode : u32 {
49 Disabled,
50 Enabled,
51};
52
53enum class SwkbdTextDrawType : u32 {
54 Line,
55 Box,
56 DownloadCode,
57};
58
59enum class SwkbdResult : u32 {
60 Ok,
61 Cancel,
62};
63
64enum class SwkbdTextCheckResult : u32 {
65 Success,
66 Failure,
67 Confirm,
68 Silent,
69};
70
71enum class SwkbdState : u32 {
72 NotInitialized = 0x0,
73 InitializedIsHidden = 0x1,
74 InitializedIsAppearing = 0x2,
75 InitializedIsShown = 0x3,
76 InitializedIsDisappearing = 0x4,
77};
78
79enum class SwkbdRequestCommand : u32 {
80 Finalize = 0x4,
81 SetUserWordInfo = 0x6,
82 SetCustomizeDic = 0x7,
83 Calc = 0xA,
84 SetCustomizedDictionaries = 0xB,
85 UnsetCustomizedDictionaries = 0xC,
86 SetChangedStringV2Flag = 0xD,
87 SetMovedCursorV2Flag = 0xE,
88};
89
90enum class SwkbdReplyType : u32 {
91 FinishedInitialize = 0x0,
92 Default = 0x1,
93 ChangedString = 0x2,
94 MovedCursor = 0x3,
95 MovedTab = 0x4,
96 DecidedEnter = 0x5,
97 DecidedCancel = 0x6,
98 ChangedStringUtf8 = 0x7,
99 MovedCursorUtf8 = 0x8,
100 DecidedEnterUtf8 = 0x9,
101 UnsetCustomizeDic = 0xA,
102 ReleasedUserWordInfo = 0xB,
103 UnsetCustomizedDictionaries = 0xC,
104 ChangedStringV2 = 0xD,
105 MovedCursorV2 = 0xE,
106 ChangedStringUtf8V2 = 0xF,
107 MovedCursorUtf8V2 = 0x10,
108};
109
110struct SwkbdKeyDisableFlags {
111 union {
112 u32 raw{};
113
114 BitField<1, 1, u32> space;
115 BitField<2, 1, u32> at;
116 BitField<3, 1, u32> percent;
117 BitField<4, 1, u32> slash;
118 BitField<5, 1, u32> backslash;
119 BitField<6, 1, u32> numbers;
120 BitField<7, 1, u32> download_code;
121 BitField<8, 1, u32> username;
122 };
123};
124static_assert(sizeof(SwkbdKeyDisableFlags) == 0x4, "SwkbdKeyDisableFlags has incorrect size.");
125
126struct SwkbdConfigCommon {
127 SwkbdType type{};
128 std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
129 char16_t left_optional_symbol_key{};
130 char16_t right_optional_symbol_key{};
131 bool use_prediction{};
132 INSERT_PADDING_BYTES(1);
133 SwkbdKeyDisableFlags key_disable_flags{};
134 SwkbdInitialCursorPosition initial_cursor_position{};
135 std::array<char16_t, MAX_HEADER_TEXT_LENGTH + 1> header_text{};
136 std::array<char16_t, MAX_SUB_TEXT_LENGTH + 1> sub_text{};
137 std::array<char16_t, MAX_GUIDE_TEXT_LENGTH + 1> guide_text{};
138 u32 max_text_length{};
139 u32 min_text_length{};
140 SwkbdPasswordMode password_mode{};
141 SwkbdTextDrawType text_draw_type{};
142 bool enable_return_button{};
143 bool use_utf8{};
144 bool use_blur_background{};
145 INSERT_PADDING_BYTES(1);
146 u32 initial_string_offset{};
147 u32 initial_string_length{};
148 u32 user_dictionary_offset{};
149 u32 user_dictionary_entries{};
150 bool use_text_check{};
151 INSERT_PADDING_BYTES(3);
152};
153static_assert(sizeof(SwkbdConfigCommon) == 0x3D4, "SwkbdConfigCommon has incorrect size.");
154
155#pragma pack(push, 4)
156// SwkbdAppletVersion 0x5, 0x10006
157struct SwkbdConfigOld {
158 INSERT_PADDING_WORDS(1);
159 VAddr text_check_callback{};
160};
161static_assert(sizeof(SwkbdConfigOld) == 0x3E0 - sizeof(SwkbdConfigCommon),
162 "SwkbdConfigOld has incorrect size.");
163
164// SwkbdAppletVersion 0x30007, 0x40008, 0x50009
165struct SwkbdConfigOld2 {
166 INSERT_PADDING_WORDS(1);
167 VAddr text_check_callback{};
168 std::array<u32, 8> text_grouping{};
169};
170static_assert(sizeof(SwkbdConfigOld2) == 0x400 - sizeof(SwkbdConfigCommon),
171 "SwkbdConfigOld2 has incorrect size.");
172
173// SwkbdAppletVersion 0x6000B, 0x8000D
174struct SwkbdConfigNew {
175 std::array<u32, 8> text_grouping{};
176 std::array<u64, 24> customized_dictionary_set_entries{};
177 u8 total_customized_dictionary_set_entries{};
178 bool disable_cancel_button{};
179 INSERT_PADDING_BYTES(18);
180};
181static_assert(sizeof(SwkbdConfigNew) == 0x4C8 - sizeof(SwkbdConfigCommon),
182 "SwkbdConfigNew has incorrect size.");
183#pragma pack(pop)
184
185struct SwkbdTextCheck {
186 SwkbdTextCheckResult text_check_result{};
187 std::array<char16_t, STRING_BUFFER_SIZE / 2> text_check_message{};
188};
189static_assert(sizeof(SwkbdTextCheck) == 0x7D8, "SwkbdTextCheck has incorrect size.");
190
191struct SwkbdCalcArgFlags {
192 union {
193 u64 raw{};
194
195 BitField<0, 1, u64> set_initialize_arg;
196 BitField<1, 1, u64> set_volume;
197 BitField<2, 1, u64> appear;
198 BitField<3, 1, u64> set_input_text;
199 BitField<4, 1, u64> set_cursor_position;
200 BitField<5, 1, u64> set_utf8_mode;
201 BitField<6, 1, u64> unset_customize_dic;
202 BitField<7, 1, u64> disappear;
203 BitField<8, 1, u64> unknown;
204 BitField<9, 1, u64> set_key_top_translate_scale;
205 BitField<10, 1, u64> unset_user_word_info;
206 BitField<11, 1, u64> set_disable_hardware_keyboard;
207 };
208};
209static_assert(sizeof(SwkbdCalcArgFlags) == 0x8, "SwkbdCalcArgFlags has incorrect size.");
210
211struct SwkbdInitializeArg {
212 u32 unknown{};
213 bool library_applet_mode_flag{};
214 bool is_above_hos_500{};
215 INSERT_PADDING_BYTES(2);
216};
217static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size.");
218
219struct SwkbdAppearArg {
220 SwkbdType type{};
221 std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
222 char16_t left_optional_symbol_key{};
223 char16_t right_optional_symbol_key{};
224 bool use_prediction{};
225 bool disable_cancel_button{};
226 SwkbdKeyDisableFlags key_disable_flags{};
227 u32 max_text_length{};
228 u32 min_text_length{};
229 bool enable_return_button{};
230 INSERT_PADDING_BYTES(3);
231 u32 flags{};
232 INSERT_PADDING_WORDS(6);
233};
234static_assert(sizeof(SwkbdAppearArg) == 0x48, "SwkbdAppearArg has incorrect size.");
235
236struct SwkbdCalcArg {
237 u32 unknown{};
238 u16 calc_arg_size{};
239 INSERT_PADDING_BYTES(2);
240 SwkbdCalcArgFlags flags{};
241 SwkbdInitializeArg initialize_arg{};
242 f32 volume{};
243 s32 cursor_position{};
244 SwkbdAppearArg appear_arg{};
245 std::array<char16_t, 0x1FA> input_text{};
246 bool utf8_mode{};
247 INSERT_PADDING_BYTES(1);
248 bool enable_backspace_button{};
249 INSERT_PADDING_BYTES(3);
250 bool key_top_as_floating{};
251 bool footer_scalable{};
252 bool alpha_enabled_in_input_mode{};
253 u8 input_mode_fade_type{};
254 bool disable_touch{};
255 bool disable_hardware_keyboard{};
256 INSERT_PADDING_BYTES(8);
257 f32 key_top_scale_x{};
258 f32 key_top_scale_y{};
259 f32 key_top_translate_x{};
260 f32 key_top_translate_y{};
261 f32 key_top_bg_alpha{};
262 f32 footer_bg_alpha{};
263 f32 balloon_scale{};
264 INSERT_PADDING_WORDS(4);
265 u8 se_group{};
266 INSERT_PADDING_BYTES(3);
267};
268static_assert(sizeof(SwkbdCalcArg) == 0x4A0, "SwkbdCalcArg has incorrect size.");
269
270struct SwkbdChangedStringArg {
271 u32 text_length{};
272 s32 dictionary_start_cursor_position{};
273 s32 dictionary_end_cursor_position{};
274 s32 cursor_position{};
275};
276static_assert(sizeof(SwkbdChangedStringArg) == 0x10, "SwkbdChangedStringArg has incorrect size.");
277
278struct SwkbdMovedCursorArg {
279 u32 text_length{};
280 s32 cursor_position{};
281};
282static_assert(sizeof(SwkbdMovedCursorArg) == 0x8, "SwkbdMovedCursorArg has incorrect size.");
283
284struct SwkbdMovedTabArg {
285 u32 text_length{};
286 s32 cursor_position{};
287};
288static_assert(sizeof(SwkbdMovedTabArg) == 0x8, "SwkbdMovedTabArg has incorrect size.");
289
290struct SwkbdDecidedEnterArg {
291 u32 text_length{};
292};
293static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size.");
294
295} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 2ab420789..b28b849bc 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -208,8 +208,9 @@ void ExtractSharedFonts(Core::System& system) {
208 208
209} // namespace 209} // namespace
210 210
211WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) 211WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
212 : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} 212 const Core::Frontend::WebBrowserApplet& frontend_)
213 : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend(frontend_), system{system_} {}
213 214
214WebBrowser::~WebBrowser() = default; 215WebBrowser::~WebBrowser() = default;
215 216
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 04c274754..5eafbae7b 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -25,7 +25,8 @@ namespace Service::AM::Applets {
25 25
26class WebBrowser final : public Applet { 26class WebBrowser final : public Applet {
27public: 27public:
28 WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_); 28 WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
29 const Core::Frontend::WebBrowserApplet& frontend_);
29 30
30 ~WebBrowser() override; 31 ~WebBrowser() override;
31 32
@@ -63,6 +64,7 @@ private:
63 void ExecuteWifi(); 64 void ExecuteWifi();
64 void ExecuteLobby(); 65 void ExecuteLobby();
65 66
67 LibraryAppletMode applet_mode;
66 const Core::Frontend::WebBrowserApplet& frontend; 68 const Core::Frontend::WebBrowserApplet& frontend;
67 69
68 bool complete{false}; 70 bool complete{false};
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 8d657c0bf..75867e349 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/settings.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/file_sys/common_funcs.h" 12#include "core/file_sys/common_funcs.h"
12#include "core/file_sys/content_archive.h" 13#include "core/file_sys/content_archive.h"
@@ -21,7 +22,6 @@
21#include "core/hle/kernel/process.h" 22#include "core/hle/kernel/process.h"
22#include "core/hle/service/aoc/aoc_u.h" 23#include "core/hle/service/aoc/aoc_u.h"
23#include "core/loader/loader.h" 24#include "core/loader/loader.h"
24#include "core/settings.h"
25 25
26namespace Service::AOC { 26namespace Service::AOC {
27 27
@@ -118,8 +118,10 @@ AOC_U::AOC_U(Core::System& system_)
118 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, 118 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
119 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, 119 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
120 {9, nullptr, "GetAddOnContentLostErrorCode"}, 120 {9, nullptr, "GetAddOnContentLostErrorCode"},
121 {10, nullptr, "GetAddOnContentListChangedEventWithProcessId"},
121 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"}, 122 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"},
122 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, 123 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"},
124 {110, nullptr, "CreateContentsServiceManager"},
123 }; 125 };
124 // clang-format on 126 // clang-format on
125 127
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
index 03636642b..00c174bb0 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/controller.cpp
@@ -7,9 +7,9 @@
7#include <utility> 7#include <utility>
8 8
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/settings.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/hle/service/apm/controller.h" 12#include "core/hle/service/apm/controller.h"
12#include "core/settings.h"
13 13
14namespace Service::APM { 14namespace Service::APM {
15 15
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp
index 79c3aa920..10acaad19 100644
--- a/src/core/hle/service/audio/audin_a.cpp
+++ b/src/core/hle/service/audio/audin_a.cpp
@@ -9,10 +9,10 @@ namespace Service::Audio {
9AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { 9AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioIns"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioIns"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioInsProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioInsProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 }; 16 };
17 // clang-format on 17 // clang-format on
18 18
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 26a6deddf..ecd05e4a6 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -15,19 +15,19 @@ public:
15 // clang-format off 15 // clang-format off
16 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
17 {0, nullptr, "GetAudioInState"}, 17 {0, nullptr, "GetAudioInState"},
18 {1, nullptr, "StartAudioIn"}, 18 {1, nullptr, "Start"},
19 {2, nullptr, "StopAudioIn"}, 19 {2, nullptr, "Stop"},
20 {3, nullptr, "AppendAudioInBuffer"}, 20 {3, nullptr, "AppendAudioInBuffer"},
21 {4, nullptr, "RegisterBufferEvent"}, 21 {4, nullptr, "RegisterBufferEvent"},
22 {5, nullptr, "GetReleasedAudioInBuffer"}, 22 {5, nullptr, "GetReleasedAudioInBuffer"},
23 {6, nullptr, "ContainsAudioInBuffer"}, 23 {6, nullptr, "ContainsAudioInBuffer"},
24 {7, nullptr, "AppendAudioInBufferWithUserEvent"}, 24 {7, nullptr, "AppendUacInBuffer"},
25 {8, nullptr, "AppendAudioInBufferAuto"}, 25 {8, nullptr, "AppendAudioInBufferAuto"},
26 {9, nullptr, "GetReleasedAudioInBufferAuto"}, 26 {9, nullptr, "GetReleasedAudioInBuffersAuto"},
27 {10, nullptr, "AppendAudioInBufferWithUserEventAuto"}, 27 {10, nullptr, "AppendUacInBufferAuto"},
28 {11, nullptr, "GetAudioInBufferCount"}, 28 {11, nullptr, "GetAudioInBufferCount"},
29 {12, nullptr, "SetAudioInDeviceGain"}, 29 {12, nullptr, "SetDeviceGain"},
30 {13, nullptr, "GetAudioInDeviceGain"}, 30 {13, nullptr, "GetDeviceGain"},
31 {14, nullptr, "FlushAudioInBuffers"}, 31 {14, nullptr, "FlushAudioInBuffers"},
32 }; 32 };
33 // clang-format on 33 // clang-format on
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp
index 19825fd5d..3ee522b50 100644
--- a/src/core/hle/service/audio/audout_a.cpp
+++ b/src/core/hle/service/audio/audout_a.cpp
@@ -9,12 +9,12 @@ namespace Service::Audio {
9AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { 9AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioOuts"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioOuts"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioOutsProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioOutsProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 {4, nullptr, "GetAudioOutsProcessRecordVolume"}, 16 {4, nullptr, "GetProcessRecordVolume"},
17 {5, nullptr, "SetAudioOutsProcessRecordVolume"}, 17 {5, nullptr, "SetProcessRecordVolume"},
18 }; 18 };
19 // clang-format on 19 // clang-format on
20 20
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 5ed9cb20e..5f51fca9a 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -49,11 +49,11 @@ public:
49 // clang-format off 49 // clang-format off
50 static const FunctionInfo functions[] = { 50 static const FunctionInfo functions[] = {
51 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, 51 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
52 {1, &IAudioOut::StartAudioOut, "StartAudioOut"}, 52 {1, &IAudioOut::StartAudioOut, "Start"},
53 {2, &IAudioOut::StopAudioOut, "StopAudioOut"}, 53 {2, &IAudioOut::StopAudioOut, "Stop"},
54 {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"}, 54 {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
55 {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"}, 55 {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
56 {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"}, 56 {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffers"},
57 {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"}, 57 {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
58 {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"}, 58 {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
59 {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"}, 59 {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp
index c5ab7cad4..70fc17ae2 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/audrec_a.cpp
@@ -9,8 +9,8 @@ namespace Service::Audio {
9AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { 9AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendFinalOutputRecorders"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeFinalOutputRecorders"}, 13 {1, nullptr, "RequestResume"},
14 }; 14 };
15 // clang-format on 15 // clang-format on
16 16
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index eb5c63c62..74a65ccff 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -13,16 +13,17 @@ public:
13 // clang-format off 13 // clang-format off
14 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
15 {0, nullptr, "GetFinalOutputRecorderState"}, 15 {0, nullptr, "GetFinalOutputRecorderState"},
16 {1, nullptr, "StartFinalOutputRecorder"}, 16 {1, nullptr, "Start"},
17 {2, nullptr, "StopFinalOutputRecorder"}, 17 {2, nullptr, "Stop"},
18 {3, nullptr, "AppendFinalOutputRecorderBuffer"}, 18 {3, nullptr, "AppendFinalOutputRecorderBuffer"},
19 {4, nullptr, "RegisterBufferEvent"}, 19 {4, nullptr, "RegisterBufferEvent"},
20 {5, nullptr, "GetReleasedFinalOutputRecorderBuffer"}, 20 {5, nullptr, "GetReleasedFinalOutputRecorderBuffers"},
21 {6, nullptr, "ContainsFinalOutputRecorderBuffer"}, 21 {6, nullptr, "ContainsFinalOutputRecorderBuffer"},
22 {7, nullptr, "GetFinalOutputRecorderBufferEndTime"}, 22 {7, nullptr, "GetFinalOutputRecorderBufferEndTime"},
23 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"}, 23 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
24 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"}, 24 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
25 {10, nullptr, "FlushFinalOutputRecorderBuffers"}, 25 {10, nullptr, "FlushFinalOutputRecorderBuffers"},
26 {11, nullptr, "AttachWorkBuffer"},
26 }; 27 };
27 // clang-format on 28 // clang-format on
28 29
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp
index 5e9f866f0..cf8c34a15 100644
--- a/src/core/hle/service/audio/audren_a.cpp
+++ b/src/core/hle/service/audio/audren_a.cpp
@@ -9,14 +9,14 @@ namespace Service::Audio {
9AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { 9AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioRenderers"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioRenderers"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioRenderersProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioRenderersProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 {4, nullptr, "RegisterAppletResourceUserId"}, 16 {4, nullptr, "RegisterAppletResourceUserId"},
17 {5, nullptr, "UnregisterAppletResourceUserId"}, 17 {5, nullptr, "UnregisterAppletResourceUserId"},
18 {6, nullptr, "GetAudioRenderersProcessRecordVolume"}, 18 {6, nullptr, "GetProcessRecordVolume"},
19 {7, nullptr, "SetAudioRenderersProcessRecordVolume"}, 19 {7, nullptr, "SetProcessRecordVolume"},
20 }; 20 };
21 // clang-format on 21 // clang-format on
22 22
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index b2b2ffc5a..572be8e00 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -332,9 +332,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"}
332 // clang-format off 332 // clang-format off
333 static const FunctionInfo functions[] = { 333 static const FunctionInfo functions[] = {
334 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, 334 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
335 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, 335 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetWorkBufferSize"},
336 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, 336 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
337 {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"}, 337 {3, &AudRenU::OpenAudioRendererForManualExecution, "OpenAudioRendererForManualExecution"},
338 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, 338 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
339 }; 339 };
340 // clang-format on 340 // clang-format on
@@ -665,7 +665,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) {
665 rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); 665 rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1'));
666} 666}
667 667
668void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) { 668void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) {
669 LOG_DEBUG(Service_Audio, "called"); 669 LOG_DEBUG(Service_Audio, "called");
670 670
671 OpenAudioRendererImpl(ctx); 671 OpenAudioRendererImpl(ctx);
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index d693dc406..37e8b4716 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -25,7 +25,7 @@ private:
25 void OpenAudioRenderer(Kernel::HLERequestContext& ctx); 25 void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
26 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); 26 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
27 void GetAudioDeviceService(Kernel::HLERequestContext& ctx); 27 void GetAudioDeviceService(Kernel::HLERequestContext& ctx);
28 void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx); 28 void OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx);
29 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); 29 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
30 30
31 void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); 31 void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp
index 94afec1b6..42961d908 100644
--- a/src/core/hle/service/audio/codecctl.cpp
+++ b/src/core/hle/service/audio/codecctl.cpp
@@ -8,19 +8,19 @@ namespace Service::Audio {
8 8
9CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { 9CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} {
10 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
11 {0, nullptr, "InitializeCodecController"}, 11 {0, nullptr, "Initialize"},
12 {1, nullptr, "FinalizeCodecController"}, 12 {1, nullptr, "Finalize"},
13 {2, nullptr, "SleepCodecController"}, 13 {2, nullptr, "Sleep"},
14 {3, nullptr, "WakeCodecController"}, 14 {3, nullptr, "Wake"},
15 {4, nullptr, "SetCodecVolume"}, 15 {4, nullptr, "SetVolume"},
16 {5, nullptr, "GetCodecVolumeMax"}, 16 {5, nullptr, "GetVolumeMax"},
17 {6, nullptr, "GetCodecVolumeMin"}, 17 {6, nullptr, "GetVolumeMin"},
18 {7, nullptr, "SetCodecActiveTarget"}, 18 {7, nullptr, "SetActiveTarget"},
19 {8, nullptr, "GetCodecActiveTarget"}, 19 {8, nullptr, "GetActiveTarget"},
20 {9, nullptr, "BindCodecHeadphoneMicJackInterrupt"}, 20 {9, nullptr, "BindHeadphoneMicJackInterrupt"},
21 {10, nullptr, "IsCodecHeadphoneMicJackInserted"}, 21 {10, nullptr, "IsHeadphoneMicJackInserted"},
22 {11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"}, 22 {11, nullptr, "ClearHeadphoneMicJackInterrupt"},
23 {12, nullptr, "IsCodecDeviceRequested"}, 23 {12, nullptr, "IsRequested"},
24 }; 24 };
25 RegisterHandlers(functions); 25 RegisterHandlers(functions);
26} 26}
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index ea3414fd2..19c578b3a 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -297,6 +297,10 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
297 {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, 297 {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
298 {2, nullptr, "OpenOpusDecoderForMultiStream"}, 298 {2, nullptr, "OpenOpusDecoderForMultiStream"},
299 {3, nullptr, "GetWorkBufferSizeForMultiStream"}, 299 {3, nullptr, "GetWorkBufferSizeForMultiStream"},
300 {4, nullptr, "OpenHardwareOpusDecoderEx"},
301 {5, nullptr, "GetWorkBufferSizeEx"},
302 {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"},
303 {7, nullptr, "GetWorkBufferSizeForMultiStreamEx"},
300 }; 304 };
301 RegisterHandlers(functions); 305 RegisterHandlers(functions);
302} 306}
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index e43f3f47f..78c047bd2 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -9,6 +9,7 @@
9#include "common/hex_util.h" 9#include "common/hex_util.h"
10#include "common/logging/backend.h" 10#include "common/logging/backend.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h"
12#include "core/core.h" 13#include "core/core.h"
13#include "core/file_sys/vfs.h" 14#include "core/file_sys/vfs.h"
14#include "core/file_sys/vfs_libzip.h" 15#include "core/file_sys/vfs_libzip.h"
@@ -16,7 +17,6 @@
16#include "core/frontend/applets/error.h" 17#include "core/frontend/applets/error.h"
17#include "core/hle/service/am/applets/applets.h" 18#include "core/hle/service/am/applets/applets.h"
18#include "core/hle/service/bcat/backend/boxcat.h" 19#include "core/hle/service/bcat/backend/boxcat.h"
19#include "core/settings.h"
20 20
21namespace Service::BCAT { 21namespace Service::BCAT {
22namespace { 22namespace {
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index 503109fdd..c7dd04a6e 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -7,6 +7,7 @@
7#include "backend/boxcat.h" 7#include "backend/boxcat.h"
8#include "common/hex_util.h" 8#include "common/hex_util.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/settings.h"
10#include "common/string_util.h" 11#include "common/string_util.h"
11#include "core/core.h" 12#include "core/core.h"
12#include "core/file_sys/vfs.h" 13#include "core/file_sys/vfs.h"
@@ -18,7 +19,6 @@
18#include "core/hle/service/bcat/bcat.h" 19#include "core/hle/service/bcat/bcat.h"
19#include "core/hle/service/bcat/module.h" 20#include "core/hle/service/bcat/module.h"
20#include "core/hle/service/filesystem/filesystem.h" 21#include "core/hle/service/filesystem/filesystem.h"
21#include "core/settings.h"
22 22
23namespace Service::BCAT { 23namespace Service::BCAT {
24 24
@@ -155,10 +155,12 @@ public:
155 {30210, nullptr, "SetDeliveryTaskTimer"}, 155 {30210, nullptr, "SetDeliveryTaskTimer"},
156 {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, 156 {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"},
157 {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, 157 {90100, nullptr, "EnumerateBackgroundDeliveryTask"},
158 {90101, nullptr, "Unknown90101"},
158 {90200, nullptr, "GetDeliveryList"}, 159 {90200, nullptr, "GetDeliveryList"},
159 {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"}, 160 {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"},
160 {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"}, 161 {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"},
161 {90300, nullptr, "GetPushNotificationLog"}, 162 {90300, nullptr, "GetPushNotificationLog"},
163 {90301, nullptr, "Unknown90301"},
162 }; 164 };
163 // clang-format on 165 // clang-format on
164 RegisterHandlers(functions); 166 RegisterHandlers(functions);
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp
index e4630320e..78e01d8d8 100644
--- a/src/core/hle/service/bpc/bpc.cpp
+++ b/src/core/hle/service/bpc/bpc.cpp
@@ -29,8 +29,8 @@ public:
29 {11, nullptr, "CreateWakeupTimerEx"}, 29 {11, nullptr, "CreateWakeupTimerEx"},
30 {12, nullptr, "GetLastEnabledWakeupTimerType"}, 30 {12, nullptr, "GetLastEnabledWakeupTimerType"},
31 {13, nullptr, "CleanAllWakeupTimers"}, 31 {13, nullptr, "CleanAllWakeupTimers"},
32 {14, nullptr, "Unknown"}, 32 {14, nullptr, "GetPowerButton"},
33 {15, nullptr, "Unknown2"}, 33 {15, nullptr, "SetEnableWakeupTimer"},
34 }; 34 };
35 // clang-format on 35 // clang-format on
36 36
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 17a2ac899..af3a5842d 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -156,6 +156,25 @@ public:
156 {97, nullptr, "RegisterBleHidEvent"}, 156 {97, nullptr, "RegisterBleHidEvent"},
157 {98, nullptr, "SetBleScanParameter"}, 157 {98, nullptr, "SetBleScanParameter"},
158 {99, nullptr, "MoveToSecondaryPiconet"}, 158 {99, nullptr, "MoveToSecondaryPiconet"},
159 {100, nullptr, "IsBluetoothEnabled"},
160 {128, nullptr, "AcquireAudioEvent"},
161 {129, nullptr, "GetAudioEventInfo"},
162 {130, nullptr, "OpenAudioConnection"},
163 {131, nullptr, "CloseAudioConnection"},
164 {132, nullptr, "OpenAudioOut"},
165 {133, nullptr, "CloseAudioOut"},
166 {134, nullptr, "AcquireAudioOutStateChangedEvent"},
167 {135, nullptr, "StartAudioOut"},
168 {136, nullptr, "StopAudioOut"},
169 {137, nullptr, "GetAudioOutState"},
170 {138, nullptr, "GetAudioOutFeedingCodec"},
171 {139, nullptr, "GetAudioOutFeedingParameter"},
172 {140, nullptr, "AcquireAudioOutBufferAvailableEvent"},
173 {141, nullptr, "SendAudioData"},
174 {142, nullptr, "AcquireAudioControlInputStateChangedEvent"},
175 {143, nullptr, "GetAudioControlInputState"},
176 {144, nullptr, "AcquireAudioConnectionStateChangedEvent"},
177 {145, nullptr, "GetConnectedAudioDevice"},
159 {256, nullptr, "IsManufacturingMode"}, 178 {256, nullptr, "IsManufacturingMode"},
160 {257, nullptr, "EmulateBluetoothCrash"}, 179 {257, nullptr, "EmulateBluetoothCrash"},
161 {258, nullptr, "GetBleChannelMap"}, 180 {258, nullptr, "GetBleChannelMap"},
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 9cf2ee92a..d1ebc2388 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -223,6 +223,7 @@ public:
223 {10, nullptr, "GetGattClientDisconnectionReason"}, 223 {10, nullptr, "GetGattClientDisconnectionReason"},
224 {11, nullptr, "GetBleConnectionParameter"}, 224 {11, nullptr, "GetBleConnectionParameter"},
225 {12, nullptr, "GetBleConnectionParameterRequest"}, 225 {12, nullptr, "GetBleConnectionParameterRequest"},
226 {13, nullptr, "Unknown13"},
226 }; 227 };
227 // clang-format on 228 // clang-format on
228 229
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 1fe4f0e14..6220e9f77 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -49,6 +49,7 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
49 {16, nullptr, "GetAlbumMountResult"}, 49 {16, nullptr, "GetAlbumMountResult"},
50 {17, nullptr, "GetAlbumUsage16"}, 50 {17, nullptr, "GetAlbumUsage16"},
51 {18, nullptr, "Unknown18"}, 51 {18, nullptr, "Unknown18"},
52 {19, nullptr, "Unknown19"},
52 {100, nullptr, "GetAlbumFileCountEx0"}, 53 {100, nullptr, "GetAlbumFileCountEx0"},
53 {101, nullptr, "GetAlbumFileListEx0"}, 54 {101, nullptr, "GetAlbumFileListEx0"},
54 {202, nullptr, "SaveEditedScreenShot"}, 55 {202, nullptr, "SaveEditedScreenShot"},
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp
index 842316a2e..10b8d54b1 100644
--- a/src/core/hle/service/caps/caps_u.cpp
+++ b/src/core/hle/service/caps/caps_u.cpp
@@ -43,6 +43,7 @@ CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} {
43 {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, 43 {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
44 {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"}, 44 {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"},
45 {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, 45 {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
46 {144, nullptr, "GetAllAlbumFileList3AaeAruid"},
46 {60002, nullptr, "OpenAccessorSessionForApplication"}, 47 {60002, nullptr, "OpenAccessorSessionForApplication"},
47 }; 48 };
48 // clang-format on 49 // clang-format on
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp
index 4924c61c3..c767926a4 100644
--- a/src/core/hle/service/erpt/erpt.cpp
+++ b/src/core/hle/service/erpt/erpt.cpp
@@ -16,7 +16,7 @@ public:
16 // clang-format off 16 // clang-format off
17 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
18 {0, nullptr, "SubmitContext"}, 18 {0, nullptr, "SubmitContext"},
19 {1, nullptr, "CreateReport"}, 19 {1, nullptr, "CreateReportV0"},
20 {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, 20 {2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
21 {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, 21 {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
22 {4, nullptr, "UpdatePowerOnTime"}, 22 {4, nullptr, "UpdatePowerOnTime"},
@@ -26,6 +26,11 @@ public:
26 {8, nullptr, "ClearApplicationLaunchTime"}, 26 {8, nullptr, "ClearApplicationLaunchTime"},
27 {9, nullptr, "SubmitAttachment"}, 27 {9, nullptr, "SubmitAttachment"},
28 {10, nullptr, "CreateReportWithAttachments"}, 28 {10, nullptr, "CreateReportWithAttachments"},
29 {11, nullptr, "CreateReport"},
30 {20, nullptr, "RegisterRunningApplet"},
31 {21, nullptr, "UnregisterRunningApplet"},
32 {22, nullptr, "UpdateAppletSuspendedDuration"},
33 {30, nullptr, "InvalidateForcedShutdownDetection"},
29 }; 34 };
30 // clang-format on 35 // clang-format on
31 36
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index b15c737e1..72ad273b2 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -6,6 +6,7 @@
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "common/settings.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/file_sys/bis_factory.h" 11#include "core/file_sys/bis_factory.h"
11#include "core/file_sys/card_image.h" 12#include "core/file_sys/card_image.h"
@@ -26,7 +27,6 @@
26#include "core/hle/service/filesystem/fsp_pr.h" 27#include "core/hle/service/filesystem/fsp_pr.h"
27#include "core/hle/service/filesystem/fsp_srv.h" 28#include "core/hle/service/filesystem/fsp_srv.h"
28#include "core/loader/loader.h" 29#include "core/loader/loader.h"
29#include "core/settings.h"
30 30
31namespace Service::FileSystem { 31namespace Service::FileSystem {
32 32
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 9cc260515..a0215c4d7 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -118,9 +118,13 @@ public:
118 explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) 118 explicit IFile(Core::System& system_, FileSys::VirtualFile backend_)
119 : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { 119 : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) {
120 static const FunctionInfo functions[] = { 120 static const FunctionInfo functions[] = {
121 {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, 121 {0, &IFile::Read, "Read"},
122 {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, 122 {1, &IFile::Write, "Write"},
123 {4, &IFile::GetSize, "GetSize"}, {5, nullptr, "OperateRange"}, 123 {2, &IFile::Flush, "Flush"},
124 {3, &IFile::SetSize, "SetSize"},
125 {4, &IFile::GetSize, "GetSize"},
126 {5, nullptr, "OperateRange"},
127 {6, nullptr, "OperateRangeWithBuffer"},
124 }; 128 };
125 RegisterHandlers(functions); 129 RegisterHandlers(functions);
126 } 130 }
@@ -708,7 +712,10 @@ FSP_SRV::FSP_SRV(Core::System& system_)
708 {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"}, 712 {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"},
709 {85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"}, 713 {85, nullptr, "OpenSaveDataTransferManagerForSaveDataRepair"},
710 {86, nullptr, "OpenSaveDataMover"}, 714 {86, nullptr, "OpenSaveDataMover"},
715 {87, nullptr, "OpenSaveDataTransferManagerForRepair"},
711 {100, nullptr, "OpenImageDirectoryFileSystem"}, 716 {100, nullptr, "OpenImageDirectoryFileSystem"},
717 {101, nullptr, "OpenBaseFileSystem"},
718 {102, nullptr, "FormatBaseFileSystem"},
712 {110, nullptr, "OpenContentStorageFileSystem"}, 719 {110, nullptr, "OpenContentStorageFileSystem"},
713 {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, 720 {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
714 {130, nullptr, "OpenCustomStorageFileSystem"}, 721 {130, nullptr, "OpenCustomStorageFileSystem"},
@@ -764,10 +771,12 @@ FSP_SRV::FSP_SRV(Core::System& system_)
764 {1008, nullptr, "OpenRegisteredUpdatePartition"}, 771 {1008, nullptr, "OpenRegisteredUpdatePartition"},
765 {1009, nullptr, "GetAndClearMemoryReportInfo"}, 772 {1009, nullptr, "GetAndClearMemoryReportInfo"},
766 {1010, nullptr, "SetDataStorageRedirectTarget"}, 773 {1010, nullptr, "SetDataStorageRedirectTarget"},
767 {1011, &FSP_SRV::GetAccessLogVersionInfo, "GetAccessLogVersionInfo"}, 774 {1011, &FSP_SRV::GetProgramIndexForAccessLog, "GetProgramIndexForAccessLog"},
768 {1012, nullptr, "GetFsStackUsage"}, 775 {1012, nullptr, "GetFsStackUsage"},
769 {1013, nullptr, "UnsetSaveDataRootPath"}, 776 {1013, nullptr, "UnsetSaveDataRootPath"},
770 {1014, nullptr, "OutputMultiProgramTagAccessLog"}, 777 {1014, nullptr, "OutputMultiProgramTagAccessLog"},
778 {1016, nullptr, "FlushAccessLogOnSdCard"},
779 {1017, nullptr, "OutputApplicationInfoAccessLog"},
771 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, 780 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
772 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, 781 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
773 {1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"}, 782 {1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"},
@@ -1051,7 +1060,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
1051 rb.Push(RESULT_SUCCESS); 1060 rb.Push(RESULT_SUCCESS);
1052} 1061}
1053 1062
1054void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) { 1063void FSP_SRV::GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx) {
1055 LOG_DEBUG(Service_FS, "called"); 1064 LOG_DEBUG(Service_FS, "called");
1056 1065
1057 IPC::ResponseBuilder rb{ctx, 4}; 1066 IPC::ResponseBuilder rb{ctx, 4};
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 8ed933279..b01b924eb 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -53,7 +53,7 @@ private:
53 void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 53 void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
54 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 54 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
55 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); 55 void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
56 void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); 56 void GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx);
57 void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); 57 void OpenMultiCommitManager(Kernel::HLERequestContext& ctx);
58 58
59 FileSystemController& fsc; 59 FileSystemController& fsc;
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 0a6621ef2..a35979053 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -38,7 +38,7 @@ public:
38 {10600, nullptr, "DeclareOpenOnlinePlaySession"}, 38 {10600, nullptr, "DeclareOpenOnlinePlaySession"},
39 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"}, 39 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"},
40 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"}, 40 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
41 {10700, nullptr, "GetPlayHistoryRegistrationKey"}, 41 {10700, &IFriendService::GetPlayHistoryRegistrationKey, "GetPlayHistoryRegistrationKey"},
42 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, 42 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
43 {10702, nullptr, "AddPlayHistory"}, 43 {10702, nullptr, "AddPlayHistory"},
44 {11000, nullptr, "GetProfileImageUrl"}, 44 {11000, nullptr, "GetProfileImageUrl"},
@@ -153,6 +153,18 @@ private:
153 rb.Push(RESULT_SUCCESS); 153 rb.Push(RESULT_SUCCESS);
154 } 154 }
155 155
156 void GetPlayHistoryRegistrationKey(Kernel::HLERequestContext& ctx) {
157 IPC::RequestParser rp{ctx};
158 const auto local_play = rp.Pop<bool>();
159 const auto uuid = rp.PopRaw<Common::UUID>();
160
161 LOG_WARNING(Service_Friend, "(STUBBED) called local_play={} uuid={}", local_play,
162 uuid.Format());
163
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(RESULT_SUCCESS);
166 }
167
156 void GetFriendList(Kernel::HLERequestContext& ctx) { 168 void GetFriendList(Kernel::HLERequestContext& ctx) {
157 IPC::RequestParser rp{ctx}; 169 IPC::RequestParser rp{ctx};
158 const auto friend_offset = rp.Pop<u32>(); 170 const auto friend_offset = rp.Pop<u32>();
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index fc77e7286..322125135 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -41,6 +41,12 @@ ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
41 {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, 41 {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
42 {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, 42 {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
43 {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, 43 {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
44 {4, nullptr, "GetApplicationInstanceUnregistrationNotifier"},
45 {5, nullptr, "ListApplicationInstanceId"},
46 {6, nullptr, "GetMicroApplicationInstanceId"},
47 {7, nullptr, "GetApplicationCertificate"},
48 {9998, nullptr, "GetPreomiaApplicationLaunchProperty"},
49 {9999, nullptr, "GetPreomiaApplicationControlProperty"},
44 }; 50 };
45 // clang-format on 51 // clang-format on
46 52
@@ -243,7 +249,8 @@ ARP_W::ARP_W(Core::System& system_, ARPManager& manager_)
243 // clang-format off 249 // clang-format off
244 static const FunctionInfo functions[] = { 250 static const FunctionInfo functions[] = {
245 {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, 251 {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
246 {1, &ARP_W::DeleteProperties, "DeleteProperties"}, 252 {1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "},
253 {2, nullptr, "AcquireUpdater"},
247 }; 254 };
248 // clang-format on 255 // clang-format on
249 256
@@ -270,7 +277,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
270 rb.PushIpcInterface(registrar); 277 rb.PushIpcInterface(registrar);
271} 278}
272 279
273void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { 280void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) {
274 IPC::RequestParser rp{ctx}; 281 IPC::RequestParser rp{ctx};
275 const auto process_id = rp.PopRaw<u64>(); 282 const auto process_id = rp.PopRaw<u64>();
276 283
diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h
index 34b412e26..0df3c5e1f 100644
--- a/src/core/hle/service/glue/arp.h
+++ b/src/core/hle/service/glue/arp.h
@@ -32,7 +32,7 @@ public:
32 32
33private: 33private:
34 void AcquireRegistrar(Kernel::HLERequestContext& ctx); 34 void AcquireRegistrar(Kernel::HLERequestContext& ctx);
35 void DeleteProperties(Kernel::HLERequestContext& ctx); 35 void UnregisterApplicationInstance(Kernel::HLERequestContext& ctx);
36 36
37 ARPManager& manager; 37 ARPManager& manager;
38 std::shared_ptr<IRegistrar> registrar; 38 std::shared_ptr<IRegistrar> registrar;
diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp
index a478b68e1..daecfff15 100644
--- a/src/core/hle/service/glue/bgtc.cpp
+++ b/src/core/hle/service/glue/bgtc.cpp
@@ -2,6 +2,9 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h"
6#include "core/core.h"
7#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/glue/bgtc.h" 8#include "core/hle/service/glue/bgtc.h"
6 9
7namespace Service::Glue { 10namespace Service::Glue {
@@ -9,6 +12,26 @@ namespace Service::Glue {
9BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { 12BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} {
10 // clang-format off 13 // clang-format off
11 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
15 {100, &BGTC_T::OpenTaskService, "OpenTaskService"},
16 };
17 // clang-format on
18
19 RegisterHandlers(functions);
20}
21
22BGTC_T::~BGTC_T() = default;
23
24void BGTC_T::OpenTaskService(Kernel::HLERequestContext& ctx) {
25 LOG_DEBUG(Service_BGTC, "called");
26
27 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
28 rb.Push(RESULT_SUCCESS);
29 rb.PushIpcInterface<ITaskService>(system);
30}
31
32ITaskService::ITaskService(Core::System& system_) : ServiceFramework{system_, "ITaskService"} {
33 // clang-format off
34 static const FunctionInfo functions[] = {
12 {1, nullptr, "NotifyTaskStarting"}, 35 {1, nullptr, "NotifyTaskStarting"},
13 {2, nullptr, "NotifyTaskFinished"}, 36 {2, nullptr, "NotifyTaskFinished"},
14 {3, nullptr, "GetTriggerEvent"}, 37 {3, nullptr, "GetTriggerEvent"},
@@ -20,16 +43,18 @@ BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} {
20 {13, nullptr, "UnscheduleTask"}, 43 {13, nullptr, "UnscheduleTask"},
21 {14, nullptr, "GetScheduleEvent"}, 44 {14, nullptr, "GetScheduleEvent"},
22 {15, nullptr, "SchedulePeriodicTask"}, 45 {15, nullptr, "SchedulePeriodicTask"},
46 {16, nullptr, "Unknown16"},
23 {101, nullptr, "GetOperationMode"}, 47 {101, nullptr, "GetOperationMode"},
24 {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, 48 {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"},
25 {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, 49 {103, nullptr, "WillStayHalfAwakeInsteadSleep"},
50 {200, nullptr, "Unknown200"},
26 }; 51 };
27 // clang-format on 52 // clang-format on
28 53
29 RegisterHandlers(functions); 54 RegisterHandlers(functions);
30} 55}
31 56
32BGTC_T::~BGTC_T() = default; 57ITaskService::~ITaskService() = default;
33 58
34BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} { 59BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} {
35 // clang-format off 60 // clang-format off
diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h
index 906116ba6..4c0142fd5 100644
--- a/src/core/hle/service/glue/bgtc.h
+++ b/src/core/hle/service/glue/bgtc.h
@@ -16,6 +16,14 @@ class BGTC_T final : public ServiceFramework<BGTC_T> {
16public: 16public:
17 explicit BGTC_T(Core::System& system_); 17 explicit BGTC_T(Core::System& system_);
18 ~BGTC_T() override; 18 ~BGTC_T() override;
19
20 void OpenTaskService(Kernel::HLERequestContext& ctx);
21};
22
23class ITaskService final : public ServiceFramework<ITaskService> {
24public:
25 explicit ITaskService(Core::System& system_);
26 ~ITaskService() override;
19}; 27};
20 28
21class BGTC_SC final : public ServiceFramework<BGTC_SC> { 29class BGTC_SC final : public ServiceFramework<BGTC_SC> {
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index ad251ed4a..a460f2f79 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -4,9 +4,9 @@
4 4
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/settings.h"
7#include "core/core_timing.h" 8#include "core/core_timing.h"
8#include "core/hle/service/hid/controllers/debug_pad.h" 9#include "core/hle/service/hid/controllers/debug_pad.h"
9#include "core/settings.h"
10 10
11namespace Service::HID { 11namespace Service::HID {
12 12
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 555b29d76..0593d7d39 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -8,10 +8,10 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/settings.h"
11#include "common/swap.h" 12#include "common/swap.h"
12#include "core/frontend/input.h" 13#include "core/frontend/input.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 14#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/settings.h"
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_DebugPad final : public ControllerBase { 17class Controller_DebugPad final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 93c43a203..155808f6a 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,10 +5,10 @@
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h"
8#include "core/core_timing.h" 9#include "core/core_timing.h"
9#include "core/frontend/emu_window.h" 10#include "core/frontend/emu_window.h"
10#include "core/hle/service/hid/controllers/gesture.h" 11#include "core/hle/service/hid/controllers/gesture.h"
11#include "core/settings.h"
12 12
13namespace Service::HID { 13namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index c4a59147d..18b76038f 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -4,9 +4,9 @@
4 4
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/settings.h"
7#include "core/core_timing.h" 8#include "core/core_timing.h"
8#include "core/hle/service/hid/controllers/keyboard.h" 9#include "core/hle/service/hid/controllers/keyboard.h"
9#include "core/settings.h"
10 10
11namespace Service::HID { 11namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index b5b281752..e72948591 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -8,10 +8,10 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/settings.h"
11#include "common/swap.h" 12#include "common/swap.h"
12#include "core/frontend/input.h" 13#include "core/frontend/input.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 14#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/settings.h"
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Keyboard final : public ControllerBase { 17class Controller_Keyboard final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 3b432a36e..0ec0c2b94 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -7,10 +7,10 @@
7#include <array> 7#include <array>
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/settings.h"
10#include "common/swap.h" 11#include "common/swap.h"
11#include "core/frontend/input.h" 12#include "core/frontend/input.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 13#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/settings.h"
14 14
15namespace Service::HID { 15namespace Service::HID {
16class Controller_Mouse final : public ControllerBase { 16class Controller_Mouse final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 70b9f3824..783386fcf 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -9,6 +9,7 @@
9#include "common/bit_field.h" 9#include "common/bit_field.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h"
12#include "core/core.h" 13#include "core/core.h"
13#include "core/core_timing.h" 14#include "core/core_timing.h"
14#include "core/frontend/input.h" 15#include "core/frontend/input.h"
@@ -17,7 +18,6 @@
17#include "core/hle/kernel/k_writable_event.h" 18#include "core/hle/kernel/k_writable_event.h"
18#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
19#include "core/hle/service/hid/controllers/npad.h" 20#include "core/hle/service/hid/controllers/npad.h"
20#include "core/settings.h"
21 21
22namespace Service::HID { 22namespace Service::HID {
23constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 23constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -413,12 +413,16 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
413 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); 413 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
414 } 414 }
415 415
416 if (controller_type == NPadControllerType::JoyLeft || 416 if (controller_type == NPadControllerType::JoyLeft) {
417 controller_type == NPadControllerType::JoyRight) {
418 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); 417 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
419 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); 418 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
420 } 419 }
421 420
421 if (controller_type == NPadControllerType::JoyRight) {
422 pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
423 pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
424 }
425
422 if (controller_type == NPadControllerType::GameCube) { 426 if (controller_type == NPadControllerType::GameCube) {
423 trigger_entry.l_analog = static_cast<s32>( 427 trigger_entry.l_analog = static_cast<s32>(
424 button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0); 428 button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
@@ -1134,6 +1138,10 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot
1134 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; 1138 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
1135} 1139}
1136 1140
1141void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
1142 analog_stick_use_center_clamp = use_center_clamp;
1143}
1144
1137void Controller_NPad::ClearAllConnectedControllers() { 1145void Controller_NPad::ClearAllConnectedControllers() {
1138 for (auto& controller : connected_controllers) { 1146 for (auto& controller : connected_controllers) {
1139 if (controller.is_connected && controller.type != NPadControllerType::None) { 1147 if (controller.is_connected && controller.type != NPadControllerType::None) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index bc2e6779d..14d0ac067 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,10 +8,10 @@
8#include <atomic> 8#include <atomic>
9#include "common/bit_field.h" 9#include "common/bit_field.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/settings.h"
11#include "core/frontend/input.h" 12#include "core/frontend/input.h"
12#include "core/hle/kernel/object.h" 13#include "core/hle/kernel/object.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 14#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/settings.h"
15 15
16namespace Kernel { 16namespace Kernel {
17class KEvent; 17class KEvent;
@@ -219,6 +219,7 @@ public:
219 LedPattern GetLedPattern(u32 npad_id); 219 LedPattern GetLedPattern(u32 npad_id);
220 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; 220 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
221 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); 221 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
222 void SetAnalogStickUseCenterClamp(bool use_center_clamp);
222 void ClearAllConnectedControllers(); 223 void ClearAllConnectedControllers();
223 void DisconnectAllConnectedControllers(); 224 void DisconnectAllConnectedControllers();
224 void ConnectAllDisconnectedControllers(); 225 void ConnectAllDisconnectedControllers();
@@ -577,6 +578,7 @@ private:
577 std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; 578 std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
578 std::array<ControllerHolder, 10> connected_controllers{}; 579 std::array<ControllerHolder, 10> connected_controllers{};
579 std::array<bool, 10> unintended_home_button_input_protection{}; 580 std::array<bool, 10> unintended_home_button_input_protection{};
581 bool analog_stick_use_center_clamp{};
580 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; 582 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
581 bool sixaxis_sensors_enabled{true}; 583 bool sixaxis_sensors_enabled{true};
582 f32 sixaxis_fusion_parameter1{}; 584 f32 sixaxis_fusion_parameter1{};
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index be60492a4..b5f8077be 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -6,11 +6,11 @@
6#include <cstring> 6#include <cstring>
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/settings.h"
9#include "core/core_timing.h" 10#include "core/core_timing.h"
10#include "core/frontend/emu_window.h" 11#include "core/frontend/emu_window.h"
11#include "core/frontend/input.h" 12#include "core/frontend/input.h"
12#include "core/hle/service/hid/controllers/touchscreen.h" 13#include "core/hle/service/hid/controllers/touchscreen.h"
13#include "core/settings.h"
14 14
15namespace Service::HID { 15namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; 16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ba27bbb05..4c1c0ac68 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -5,6 +5,7 @@
5#include <array> 5#include <array>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h"
8#include "core/core.h" 9#include "core/core.h"
9#include "core/core_timing.h" 10#include "core/core_timing.h"
10#include "core/core_timing_util.h" 11#include "core/core_timing_util.h"
@@ -23,7 +24,6 @@
23#include "core/hle/service/hid/irs.h" 24#include "core/hle/service/hid/irs.h"
24#include "core/hle/service/hid/xcd.h" 25#include "core/hle/service/hid/xcd.h"
25#include "core/hle/service/service.h" 26#include "core/hle/service/service.h"
26#include "core/settings.h"
27 27
28#include "core/hle/service/hid/controllers/controller_base.h" 28#include "core/hle/service/hid/controllers/controller_base.h"
29#include "core/hle/service/hid/controllers/debug_pad.h" 29#include "core/hle/service/hid/controllers/debug_pad.h"
@@ -263,7 +263,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
263 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, 263 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
264 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, 264 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
265 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 265 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
266 {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, 266 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
267 {135, nullptr, "SetNpadCaptureButtonAssignment"}, 267 {135, nullptr, "SetNpadCaptureButtonAssignment"},
268 {136, nullptr, "ClearNpadCaptureButtonAssignment"}, 268 {136, nullptr, "ClearNpadCaptureButtonAssignment"},
269 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, 269 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
@@ -278,6 +278,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, 278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, 279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, 280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
281 {212, nullptr, "SendVibrationValueInBool"},
281 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, 282 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
282 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, 283 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
283 {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, 284 {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
@@ -1087,6 +1088,27 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
1087 rb.Push(RESULT_SUCCESS); 1088 rb.Push(RESULT_SUCCESS);
1088} 1089}
1089 1090
1091void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1092 IPC::RequestParser rp{ctx};
1093 struct Parameters {
1094 bool analog_stick_use_center_clamp;
1095 u64 applet_resource_user_id;
1096 };
1097 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1098
1099 const auto parameters{rp.PopRaw<Parameters>()};
1100
1101 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1102 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
1103
1104 LOG_WARNING(Service_HID,
1105 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
1106 parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
1107
1108 IPC::ResponseBuilder rb{ctx, 2};
1109 rb.Push(RESULT_SUCCESS);
1110}
1111
1090void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 1112void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1091 IPC::RequestParser rp{ctx}; 1113 IPC::RequestParser rp{ctx};
1092 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; 1114 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
@@ -1553,6 +1575,7 @@ public:
1553 {11, nullptr, "SetTouchScreenAutoPilotState"}, 1575 {11, nullptr, "SetTouchScreenAutoPilotState"},
1554 {12, nullptr, "UnsetTouchScreenAutoPilotState"}, 1576 {12, nullptr, "UnsetTouchScreenAutoPilotState"},
1555 {13, nullptr, "GetTouchScreenConfiguration"}, 1577 {13, nullptr, "GetTouchScreenConfiguration"},
1578 {14, nullptr, "ProcessTouchScreenAutoTune"},
1556 {20, nullptr, "DeactivateMouse"}, 1579 {20, nullptr, "DeactivateMouse"},
1557 {21, nullptr, "SetMouseAutoPilotState"}, 1580 {21, nullptr, "SetMouseAutoPilotState"},
1558 {22, nullptr, "UnsetMouseAutoPilotState"}, 1581 {22, nullptr, "UnsetMouseAutoPilotState"},
@@ -1562,6 +1585,7 @@ public:
1562 {50, nullptr, "DeactivateXpad"}, 1585 {50, nullptr, "DeactivateXpad"},
1563 {51, nullptr, "SetXpadAutoPilotState"}, 1586 {51, nullptr, "SetXpadAutoPilotState"},
1564 {52, nullptr, "UnsetXpadAutoPilotState"}, 1587 {52, nullptr, "UnsetXpadAutoPilotState"},
1588 {53, nullptr, "DeactivateJoyXpad"},
1565 {60, nullptr, "ClearNpadSystemCommonPolicy"}, 1589 {60, nullptr, "ClearNpadSystemCommonPolicy"},
1566 {61, nullptr, "DeactivateNpad"}, 1590 {61, nullptr, "DeactivateNpad"},
1567 {62, nullptr, "ForceDisconnectNpad"}, 1591 {62, nullptr, "ForceDisconnectNpad"},
@@ -1632,6 +1656,11 @@ public:
1632 {244, nullptr, "RequestKuinaFirmwareVersion"}, 1656 {244, nullptr, "RequestKuinaFirmwareVersion"},
1633 {245, nullptr, "GetKuinaFirmwareVersion"}, 1657 {245, nullptr, "GetKuinaFirmwareVersion"},
1634 {246, nullptr, "GetVidPid"}, 1658 {246, nullptr, "GetVidPid"},
1659 {247, nullptr, "GetAnalogStickCalibrationValue"},
1660 {248, nullptr, "GetUniquePadIdsFull"},
1661 {249, nullptr, "ConnectUniquePad"},
1662 {250, nullptr, "IsVirtual"},
1663 {251, nullptr, "GetAnalogStickModuleParam"},
1635 {301, nullptr, "GetAbstractedPadHandles"}, 1664 {301, nullptr, "GetAbstractedPadHandles"},
1636 {302, nullptr, "GetAbstractedPadState"}, 1665 {302, nullptr, "GetAbstractedPadState"},
1637 {303, nullptr, "GetAbstractedPadsState"}, 1666 {303, nullptr, "GetAbstractedPadsState"},
@@ -1652,12 +1681,16 @@ public:
1652 {401, nullptr, "DisableRailDeviceFiltering"}, 1681 {401, nullptr, "DisableRailDeviceFiltering"},
1653 {402, nullptr, "EnableWiredPairing"}, 1682 {402, nullptr, "EnableWiredPairing"},
1654 {403, nullptr, "EnableShipmentModeAutoClear"}, 1683 {403, nullptr, "EnableShipmentModeAutoClear"},
1684 {404, nullptr, "SetRailEnabled"},
1655 {500, nullptr, "SetFactoryInt"}, 1685 {500, nullptr, "SetFactoryInt"},
1656 {501, nullptr, "IsFactoryBootEnabled"}, 1686 {501, nullptr, "IsFactoryBootEnabled"},
1657 {550, nullptr, "SetAnalogStickModelDataTemporarily"}, 1687 {550, nullptr, "SetAnalogStickModelDataTemporarily"},
1658 {551, nullptr, "GetAnalogStickModelData"}, 1688 {551, nullptr, "GetAnalogStickModelData"},
1659 {552, nullptr, "ResetAnalogStickModelData"}, 1689 {552, nullptr, "ResetAnalogStickModelData"},
1660 {600, nullptr, "ConvertPadState"}, 1690 {600, nullptr, "ConvertPadState"},
1691 {650, nullptr, "AddButtonPlayData"},
1692 {651, nullptr, "StartButtonPlayData"},
1693 {652, nullptr, "StopButtonPlayData"},
1661 {2000, nullptr, "DeactivateDigitizer"}, 1694 {2000, nullptr, "DeactivateDigitizer"},
1662 {2001, nullptr, "SetDigitizerAutoPilotState"}, 1695 {2001, nullptr, "SetDigitizerAutoPilotState"},
1663 {2002, nullptr, "UnsetDigitizerAutoPilotState"}, 1696 {2002, nullptr, "UnsetDigitizerAutoPilotState"},
@@ -1689,6 +1722,8 @@ public:
1689 {215, nullptr, "IsNfcActivated"}, 1722 {215, nullptr, "IsNfcActivated"},
1690 {230, nullptr, "AcquireIrSensorEventHandle"}, 1723 {230, nullptr, "AcquireIrSensorEventHandle"},
1691 {231, nullptr, "ActivateIrSensor"}, 1724 {231, nullptr, "ActivateIrSensor"},
1725 {232, nullptr, "GetIrSensorState"},
1726 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
1692 {301, nullptr, "ActivateNpadSystem"}, 1727 {301, nullptr, "ActivateNpadSystem"},
1693 {303, nullptr, "ApplyNpadSystemCommonPolicy"}, 1728 {303, nullptr, "ApplyNpadSystemCommonPolicy"},
1694 {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, 1729 {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
@@ -1703,9 +1738,16 @@ public:
1703 {313, nullptr, "GetNpadCaptureButtonAssignment"}, 1738 {313, nullptr, "GetNpadCaptureButtonAssignment"},
1704 {314, nullptr, "GetAppletFooterUiType"}, 1739 {314, nullptr, "GetAppletFooterUiType"},
1705 {315, nullptr, "GetAppletDetailedUiType"}, 1740 {315, nullptr, "GetAppletDetailedUiType"},
1741 {316, nullptr, "GetNpadInterfaceType"},
1742 {317, nullptr, "GetNpadLeftRightInterfaceType"},
1743 {318, nullptr, "HasBattery"},
1744 {319, nullptr, "HasLeftRightBattery"},
1706 {321, nullptr, "GetUniquePadsFromNpad"}, 1745 {321, nullptr, "GetUniquePadsFromNpad"},
1707 {322, nullptr, "GetIrSensorState"}, 1746 {322, nullptr, "GetIrSensorState"},
1708 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, 1747 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
1748 {324, nullptr, "GetUniquePadButtonSet"},
1749 {325, nullptr, "GetUniquePadColor"},
1750 {326, nullptr, "GetUniquePadAppletDetailedUiType"},
1709 {500, nullptr, "SetAppletResourceUserId"}, 1751 {500, nullptr, "SetAppletResourceUserId"},
1710 {501, nullptr, "RegisterAppletResourceUserId"}, 1752 {501, nullptr, "RegisterAppletResourceUserId"},
1711 {502, nullptr, "UnregisterAppletResourceUserId"}, 1753 {502, nullptr, "UnregisterAppletResourceUserId"},
@@ -1716,10 +1758,13 @@ public:
1716 {511, nullptr, "GetVibrationMasterVolume"}, 1758 {511, nullptr, "GetVibrationMasterVolume"},
1717 {512, nullptr, "BeginPermitVibrationSession"}, 1759 {512, nullptr, "BeginPermitVibrationSession"},
1718 {513, nullptr, "EndPermitVibrationSession"}, 1760 {513, nullptr, "EndPermitVibrationSession"},
1761 {514, nullptr, "Unknown514"},
1719 {520, nullptr, "EnableHandheldHids"}, 1762 {520, nullptr, "EnableHandheldHids"},
1720 {521, nullptr, "DisableHandheldHids"}, 1763 {521, nullptr, "DisableHandheldHids"},
1721 {522, nullptr, "SetJoyConRailEnabled"}, 1764 {522, nullptr, "SetJoyConRailEnabled"},
1722 {523, nullptr, "IsJoyConRailEnabled"}, 1765 {523, nullptr, "IsJoyConRailEnabled"},
1766 {524, nullptr, "IsHandheldHidsEnabled"},
1767 {525, nullptr, "IsJoyConAttachedOnAllRail"},
1723 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"}, 1768 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
1724 {541, nullptr, "GetPlayReportControllerUsages"}, 1769 {541, nullptr, "GetPlayReportControllerUsages"},
1725 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"}, 1770 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
@@ -1795,6 +1840,65 @@ public:
1795 {1154, nullptr, "IsFirmwareAvailableForNotification"}, 1840 {1154, nullptr, "IsFirmwareAvailableForNotification"},
1796 {1155, nullptr, "SetForceHandheldStyleVibration"}, 1841 {1155, nullptr, "SetForceHandheldStyleVibration"},
1797 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, 1842 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
1843 {1157, nullptr, "CancelConnectionTrigger"},
1844 {1200, nullptr, "IsButtonConfigSupported"},
1845 {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
1846 {1202, nullptr, "DeleteButtonConfig"},
1847 {1203, nullptr, "DeleteButtonConfigEmbedded"},
1848 {1204, nullptr, "SetButtonConfigEnabled"},
1849 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
1850 {1206, nullptr, "IsButtonConfigEnabled"},
1851 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
1852 {1208, nullptr, "SetButtonConfigEmbedded"},
1853 {1209, nullptr, "SetButtonConfigFull"},
1854 {1210, nullptr, "SetButtonConfigLeft"},
1855 {1211, nullptr, "SetButtonConfigRight"},
1856 {1212, nullptr, "GetButtonConfigEmbedded"},
1857 {1213, nullptr, "GetButtonConfigFull"},
1858 {1214, nullptr, "GetButtonConfigLeft"},
1859 {1215, nullptr, "GetButtonConfigRight"},
1860 {1250, nullptr, "IsCustomButtonConfigSupported"},
1861 {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
1862 {1252, nullptr, "IsDefaultButtonConfigFull"},
1863 {1253, nullptr, "IsDefaultButtonConfigLeft"},
1864 {1254, nullptr, "IsDefaultButtonConfigRight"},
1865 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
1866 {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
1867 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
1868 {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
1869 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
1870 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
1871 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
1872 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
1873 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
1874 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
1875 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
1876 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
1877 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
1878 {1268, nullptr, "DeleteButtonConfigStorageFull"},
1879 {1269, nullptr, "DeleteButtonConfigStorageLeft"},
1880 {1270, nullptr, "DeleteButtonConfigStorageRight"},
1881 {1271, nullptr, "IsUsingCustomButtonConfig"},
1882 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
1883 {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
1884 {1274, nullptr, "SetDefaultButtonConfig"},
1885 {1275, nullptr, "SetAllDefaultButtonConfig"},
1886 {1276, nullptr, "SetHidButtonConfigEmbedded"},
1887 {1277, nullptr, "SetHidButtonConfigFull"},
1888 {1278, nullptr, "SetHidButtonConfigLeft"},
1889 {1279, nullptr, "SetHidButtonConfigRight"},
1890 {1280, nullptr, "GetHidButtonConfigEmbedded"},
1891 {1281, nullptr, "GetHidButtonConfigFull"},
1892 {1282, nullptr, "GetHidButtonConfigLeft"},
1893 {1283, nullptr, "GetHidButtonConfigRight"},
1894 {1284, nullptr, "GetButtonConfigStorageEmbedded"},
1895 {1285, nullptr, "GetButtonConfigStorageFull"},
1896 {1286, nullptr, "GetButtonConfigStorageLeft"},
1897 {1287, nullptr, "GetButtonConfigStorageRight"},
1898 {1288, nullptr, "SetButtonConfigStorageEmbedded"},
1899 {1289, nullptr, "SetButtonConfigStorageFull"},
1900 {1290, nullptr, "DeleteButtonConfigStorageRight"},
1901 {1291, nullptr, "DeleteButtonConfigStorageRight"},
1798 }; 1902 };
1799 // clang-format on 1903 // clang-format on
1800 1904
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 36ed228c8..c2bdd39a3 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -129,6 +129,7 @@ private:
129 void SwapNpadAssignment(Kernel::HLERequestContext& ctx); 129 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
130 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); 130 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
131 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); 131 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
132 void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx);
132 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); 133 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
133 void SendVibrationValue(Kernel::HLERequestContext& ctx); 134 void SendVibrationValue(Kernel::HLERequestContext& ctx);
134 void GetActualVibrationValue(Kernel::HLERequestContext& ctx); 135 void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp
index 43a8840d0..b1efa3d05 100644
--- a/src/core/hle/service/hid/xcd.cpp
+++ b/src/core/hle/service/hid/xcd.cpp
@@ -28,6 +28,8 @@ XCD_SYS::XCD_SYS(Core::System& system_) : ServiceFramework{system_, "xcd:sys"} {
28 {20, nullptr, "StartMifareWrite"}, 28 {20, nullptr, "StartMifareWrite"},
29 {101, nullptr, "GetAwakeTriggerReasonForLeftRail"}, 29 {101, nullptr, "GetAwakeTriggerReasonForLeftRail"},
30 {102, nullptr, "GetAwakeTriggerReasonForRightRail"}, 30 {102, nullptr, "GetAwakeTriggerReasonForRightRail"},
31 {103, nullptr, "GetAwakeTriggerBatteryLevelTransitionForLeftRail"},
32 {104, nullptr, "GetAwakeTriggerBatteryLevelTransitionForRightRail"},
31 }; 33 };
32 // clang-format on 34 // clang-format on
33 35
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index d111c1357..c8bc60ad1 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -118,9 +118,9 @@ public:
118 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} { 118 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} {
119 // clang-format off 119 // clang-format off
120 static const FunctionInfo functions[] = { 120 static const FunctionInfo functions[] = {
121 {0, nullptr, "AddProcessToDebugLaunchQueue"}, 121 {0, nullptr, "SetProgramArgument"},
122 {1, nullptr, "ClearDebugLaunchQueue"}, 122 {1, nullptr, "FlushArguments"},
123 {2, nullptr, "GetNsoInfos"}, 123 {2, nullptr, "GetProcessModuleInfo"},
124 }; 124 };
125 // clang-format on 125 // clang-format on
126 126
@@ -135,8 +135,8 @@ public:
135 static const FunctionInfo functions[] = { 135 static const FunctionInfo functions[] = {
136 {0, nullptr, "CreateProcess"}, 136 {0, nullptr, "CreateProcess"},
137 {1, nullptr, "GetProgramInfo"}, 137 {1, nullptr, "GetProgramInfo"},
138 {2, nullptr, "RegisterTitle"}, 138 {2, nullptr, "PinProgram"},
139 {3, nullptr, "UnregisterTitle"}, 139 {3, nullptr, "UnpinProgram"},
140 {4, nullptr, "SetEnabledProgramVerification"}, 140 {4, nullptr, "SetEnabledProgramVerification"},
141 }; 141 };
142 // clang-format on 142 // clang-format on
@@ -150,8 +150,8 @@ public:
150 explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} { 150 explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} {
151 // clang-format off 151 // clang-format off
152 static const FunctionInfo functions[] = { 152 static const FunctionInfo functions[] = {
153 {0, nullptr, "AddProcessToLaunchQueue"}, 153 {0, nullptr, "SetProgramArgument"},
154 {1, nullptr, "ClearLaunchQueue"}, 154 {1, nullptr, "FlushArguments"},
155 }; 155 };
156 // clang-format on 156 // clang-format on
157 157
@@ -164,19 +164,19 @@ public:
164 explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { 164 explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} {
165 // clang-format off 165 // clang-format off
166 static const FunctionInfo functions[] = { 166 static const FunctionInfo functions[] = {
167 {0, &RelocatableObject::LoadNro, "LoadNro"}, 167 {0, &RelocatableObject::LoadModule, "LoadModule"},
168 {1, &RelocatableObject::UnloadNro, "UnloadNro"}, 168 {1, &RelocatableObject::UnloadModule, "UnloadModule"},
169 {2, &RelocatableObject::LoadNrr, "LoadNrr"}, 169 {2, &RelocatableObject::RegisterModuleInfo, "RegisterModuleInfo"},
170 {3, &RelocatableObject::UnloadNrr, "UnloadNrr"}, 170 {3, &RelocatableObject::UnregisterModuleInfo, "UnregisterModuleInfo"},
171 {4, &RelocatableObject::Initialize, "Initialize"}, 171 {4, &RelocatableObject::Initialize, "Initialize"},
172 {10, nullptr, "LoadNrrEx"}, 172 {10, nullptr, "RegisterModuleInfo2"},
173 }; 173 };
174 // clang-format on 174 // clang-format on
175 175
176 RegisterHandlers(functions); 176 RegisterHandlers(functions);
177 } 177 }
178 178
179 void LoadNrr(Kernel::HLERequestContext& ctx) { 179 void RegisterModuleInfo(Kernel::HLERequestContext& ctx) {
180 struct Parameters { 180 struct Parameters {
181 u64_le process_id; 181 u64_le process_id;
182 u64_le nrr_address; 182 u64_le nrr_address;
@@ -273,7 +273,7 @@ public:
273 rb.Push(RESULT_SUCCESS); 273 rb.Push(RESULT_SUCCESS);
274 } 274 }
275 275
276 void UnloadNrr(Kernel::HLERequestContext& ctx) { 276 void UnregisterModuleInfo(Kernel::HLERequestContext& ctx) {
277 IPC::RequestParser rp{ctx}; 277 IPC::RequestParser rp{ctx};
278 const auto pid = rp.Pop<u64>(); 278 const auto pid = rp.Pop<u64>();
279 const auto nrr_address = rp.Pop<VAddr>(); 279 const auto nrr_address = rp.Pop<VAddr>();
@@ -408,7 +408,7 @@ public:
408 data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); 408 data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite);
409 } 409 }
410 410
411 void LoadNro(Kernel::HLERequestContext& ctx) { 411 void LoadModule(Kernel::HLERequestContext& ctx) {
412 struct Parameters { 412 struct Parameters {
413 u64_le process_id; 413 u64_le process_id;
414 u64_le image_address; 414 u64_le image_address;
@@ -546,7 +546,7 @@ public:
546 return RESULT_SUCCESS; 546 return RESULT_SUCCESS;
547 } 547 }
548 548
549 void UnloadNro(Kernel::HLERequestContext& ctx) { 549 void UnloadModule(Kernel::HLERequestContext& ctx) {
550 if (!initialized) { 550 if (!initialized) {
551 LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); 551 LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
552 IPC::ResponseBuilder rb{ctx, 2}; 552 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 6ab35de47..44a5d5789 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -5,12 +5,12 @@
5#include <memory> 5#include <memory>
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h"
8#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/hle_ipc.h" 10#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/nfc/nfc.h" 11#include "core/hle/service/nfc/nfc.h"
11#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
12#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
13#include "core/settings.h"
14 14
15namespace Service::NFC { 15namespace Service::NFC {
16 16
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index afb3342d6..9f110df8e 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
5#include "core/core.h" 6#include "core/core.h"
6#include "core/hle/ipc_helpers.h" 7#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h" 8#include "core/hle/kernel/k_event.h"
@@ -10,7 +11,6 @@
10#include "core/hle/service/nifm/nifm.h" 11#include "core/hle/service/nifm/nifm.h"
11#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
12#include "core/network/network.h" 13#include "core/network/network.h"
13#include "core/settings.h"
14 14
15namespace Service::NIFM { 15namespace Service::NIFM {
16 16
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index f3be0b878..fee360ab9 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -125,51 +125,51 @@ public:
125 {39, nullptr, "PrepareShutdown"}, 125 {39, nullptr, "PrepareShutdown"},
126 {40, nullptr, "ListApplyDeltaTask"}, 126 {40, nullptr, "ListApplyDeltaTask"},
127 {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"}, 127 {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
128 {42, nullptr, "Unknown42"}, 128 {42, nullptr, "CreateApplyDeltaTaskFromDownloadTask"},
129 {43, nullptr, "Unknown43"}, 129 {43, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
130 {44, nullptr, "Unknown44"}, 130 {44, nullptr, "GetApplyDeltaTaskRequiredStorage"},
131 {45, nullptr, "Unknown45"}, 131 {45, nullptr, "CalculateNetworkInstallTaskContentsSize"},
132 {46, nullptr, "Unknown46"}, 132 {46, nullptr, "PrepareShutdownForSystemUpdate"},
133 {47, nullptr, "Unknown47"}, 133 {47, nullptr, "FindMaxRequiredApplicationVersionOfTask"},
134 {48, nullptr, "Unknown48"}, 134 {48, nullptr, "CommitNetworkInstallTaskPartially"},
135 {49, nullptr, "Unknown49"}, 135 {49, nullptr, "ListNetworkInstallTaskCommittedContentMeta"},
136 {50, nullptr, "Unknown50"}, 136 {50, nullptr, "ListNetworkInstallTaskNotCommittedContentMeta"},
137 {51, nullptr, "Unknown51"}, 137 {51, nullptr, "FindMaxRequiredSystemVersionOfTask"},
138 {52, nullptr, "Unknown52"}, 138 {52, nullptr, "GetNetworkInstallTaskErrorContext"},
139 {53, nullptr, "Unknown53"}, 139 {53, nullptr, "CreateLocalCommunicationReceiveApplicationTask"},
140 {54, nullptr, "Unknown54"}, 140 {54, nullptr, "DestroyLocalCommunicationReceiveApplicationTask"},
141 {55, nullptr, "Unknown55"}, 141 {55, nullptr, "ListLocalCommunicationReceiveApplicationTask"},
142 {56, nullptr, "Unknown56"}, 142 {56, nullptr, "RequestLocalCommunicationReceiveApplicationTaskRun"},
143 {57, nullptr, "Unknown57"}, 143 {57, nullptr, "GetLocalCommunicationReceiveApplicationTaskInfo"},
144 {58, nullptr, "Unknown58"}, 144 {58, nullptr, "CommitLocalCommunicationReceiveApplicationTask"},
145 {59, nullptr, "Unknown59"}, 145 {59, nullptr, "ListLocalCommunicationReceiveApplicationTaskContentMeta"},
146 {60, nullptr, "Unknown60"}, 146 {60, nullptr, "CreateLocalCommunicationSendApplicationTask"},
147 {61, nullptr, "Unknown61"}, 147 {61, nullptr, "RequestLocalCommunicationSendApplicationTaskRun"},
148 {62, nullptr, "Unknown62"}, 148 {62, nullptr, "GetLocalCommunicationReceiveApplicationTaskErrorContext"},
149 {63, nullptr, "Unknown63"}, 149 {63, nullptr, "GetLocalCommunicationSendApplicationTaskInfo"},
150 {64, nullptr, "Unknown64"}, 150 {64, nullptr, "DestroyLocalCommunicationSendApplicationTask"},
151 {65, nullptr, "Unknown65"}, 151 {65, nullptr, "GetLocalCommunicationSendApplicationTaskErrorContext"},
152 {66, nullptr, "Unknown66"}, 152 {66, nullptr, "CalculateLocalCommunicationReceiveApplicationTaskRequiredSize"},
153 {67, nullptr, "Unknown67"}, 153 {67, nullptr, "ListApplicationLocalCommunicationReceiveApplicationTask"},
154 {68, nullptr, "Unknown68"}, 154 {68, nullptr, "ListApplicationLocalCommunicationSendApplicationTask"},
155 {69, nullptr, "Unknown69"}, 155 {69, nullptr, "CreateLocalCommunicationReceiveSystemUpdateTask"},
156 {70, nullptr, "Unknown70"}, 156 {70, nullptr, "DestroyLocalCommunicationReceiveSystemUpdateTask"},
157 {71, nullptr, "Unknown71"}, 157 {71, nullptr, "ListLocalCommunicationReceiveSystemUpdateTask"},
158 {72, nullptr, "Unknown72"}, 158 {72, nullptr, "RequestLocalCommunicationReceiveSystemUpdateTaskRun"},
159 {73, nullptr, "Unknown73"}, 159 {73, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskInfo"},
160 {74, nullptr, "Unknown74"}, 160 {74, nullptr, "CommitLocalCommunicationReceiveSystemUpdateTask"},
161 {75, nullptr, "Unknown75"}, 161 {75, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskErrorContext"},
162 {76, nullptr, "Unknown76"}, 162 {76, nullptr, "CreateLocalCommunicationSendSystemUpdateTask"},
163 {77, nullptr, "Unknown77"}, 163 {77, nullptr, "RequestLocalCommunicationSendSystemUpdateTaskRun"},
164 {78, nullptr, "Unknown78"}, 164 {78, nullptr, "GetLocalCommunicationSendSystemUpdateTaskInfo"},
165 {79, nullptr, "Unknown79"}, 165 {79, nullptr, "DestroyLocalCommunicationSendSystemUpdateTask"},
166 {80, nullptr, "Unknown80"}, 166 {80, nullptr, "GetLocalCommunicationSendSystemUpdateTaskErrorContext"},
167 {81, nullptr, "Unknown81"}, 167 {81, nullptr, "ListLocalCommunicationSendSystemUpdateTask"},
168 {82, nullptr, "Unknown82"}, 168 {82, nullptr, "GetReceivedSystemDataPath"},
169 {83, nullptr, "Unknown83"}, 169 {83, nullptr, "CalculateApplyDeltaTaskOccupiedSize"},
170 {84, nullptr, "Unknown84"}, 170 {84, nullptr, "Unknown84"},
171 {85, nullptr, "Unknown85"}, 171 {85, nullptr, "ListNetworkInstallTaskContentMetaFromInstallMeta"},
172 {86, nullptr, "Unknown86"}, 172 {86, nullptr, "ListNetworkInstallTaskOccupiedSize"},
173 {87, nullptr, "Unknown87"}, 173 {87, nullptr, "Unknown87"},
174 {88, nullptr, "Unknown88"}, 174 {88, nullptr, "Unknown88"},
175 {89, nullptr, "Unknown89"}, 175 {89, nullptr, "Unknown89"},
@@ -202,6 +202,17 @@ public:
202 {116, nullptr, "Unknown116"}, 202 {116, nullptr, "Unknown116"},
203 {117, nullptr, "Unknown117"}, 203 {117, nullptr, "Unknown117"},
204 {118, nullptr, "Unknown118"}, 204 {118, nullptr, "Unknown118"},
205 {119, nullptr, "Unknown119"},
206 {120, nullptr, "Unknown120"},
207 {121, nullptr, "Unknown121"},
208 {122, nullptr, "Unknown122"},
209 {123, nullptr, "Unknown123"},
210 {124, nullptr, "Unknown124"},
211 {125, nullptr, "Unknown125"},
212 {126, nullptr, "Unknown126"},
213 {127, nullptr, "Unknown127"},
214 {128, nullptr, "Unknown128"},
215 {129, nullptr, "Unknown129"},
205 }; 216 };
206 // clang-format on 217 // clang-format on
207 218
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp
index f7a58f659..e4c703da4 100644
--- a/src/core/hle/service/npns/npns.cpp
+++ b/src/core/hle/service/npns/npns.cpp
@@ -49,6 +49,8 @@ public:
49 {151, nullptr, "GetStateWithHandover"}, 49 {151, nullptr, "GetStateWithHandover"},
50 {152, nullptr, "GetStateChangeEventWithHandover"}, 50 {152, nullptr, "GetStateChangeEventWithHandover"},
51 {153, nullptr, "GetDropEventWithHandover"}, 51 {153, nullptr, "GetDropEventWithHandover"},
52 {154, nullptr, "CreateTokenAsync"},
53 {155, nullptr, "CreateTokenAsyncWithApplicationId"},
52 {161, nullptr, "GetRequestChangeStateCancelEvent"}, 54 {161, nullptr, "GetRequestChangeStateCancelEvent"},
53 {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"}, 55 {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"},
54 {201, nullptr, "RequestChangeStateForceTimed"}, 56 {201, nullptr, "RequestChangeStateForceTimed"},
@@ -84,6 +86,7 @@ public:
84 {151, nullptr, "GetStateWithHandover"}, 86 {151, nullptr, "GetStateWithHandover"},
85 {152, nullptr, "GetStateChangeEventWithHandover"}, 87 {152, nullptr, "GetStateChangeEventWithHandover"},
86 {153, nullptr, "GetDropEventWithHandover"}, 88 {153, nullptr, "GetDropEventWithHandover"},
89 {154, nullptr, "CreateTokenAsync"},
87 }; 90 };
88 // clang-format on 91 // clang-format on
89 92
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 6ccf8995c..e373609a1 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/settings.h"
6#include "core/core.h" 7#include "core/core.h"
7#include "core/file_sys/control_metadata.h" 8#include "core/file_sys/control_metadata.h"
8#include "core/file_sys/patch_manager.h" 9#include "core/file_sys/patch_manager.h"
@@ -14,7 +15,6 @@
14#include "core/hle/service/ns/ns.h" 15#include "core/hle/service/ns/ns.h"
15#include "core/hle/service/ns/pl_u.h" 16#include "core/hle/service/ns/pl_u.h"
16#include "core/hle/service/set/set.h" 17#include "core/hle/service/set/set.h"
17#include "core/settings.h"
18 18
19namespace Service::NS { 19namespace Service::NS {
20 20
@@ -55,6 +55,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
55 {26, nullptr, "BeginInstallApplication"}, 55 {26, nullptr, "BeginInstallApplication"},
56 {27, nullptr, "DeleteApplicationRecord"}, 56 {27, nullptr, "DeleteApplicationRecord"},
57 {30, nullptr, "RequestApplicationUpdateInfo"}, 57 {30, nullptr, "RequestApplicationUpdateInfo"},
58 {31, nullptr, "Unknown31"},
58 {32, nullptr, "CancelApplicationDownload"}, 59 {32, nullptr, "CancelApplicationDownload"},
59 {33, nullptr, "ResumeApplicationDownload"}, 60 {33, nullptr, "ResumeApplicationDownload"},
60 {35, nullptr, "UpdateVersionList"}, 61 {35, nullptr, "UpdateVersionList"},
@@ -182,6 +183,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
182 {913, nullptr, "ListAllApplicationRecord"}, 183 {913, nullptr, "ListAllApplicationRecord"},
183 {914, nullptr, "HideApplicationRecord"}, 184 {914, nullptr, "HideApplicationRecord"},
184 {915, nullptr, "ShowApplicationRecord"}, 185 {915, nullptr, "ShowApplicationRecord"},
186 {916, nullptr, "IsApplicationAutoDeleteDisabled"},
185 {1000, nullptr, "RequestVerifyApplicationDeprecated"}, 187 {1000, nullptr, "RequestVerifyApplicationDeprecated"},
186 {1001, nullptr, "CorruptApplicationForDebug"}, 188 {1001, nullptr, "CorruptApplicationForDebug"},
187 {1002, nullptr, "RequestVerifyAddOnContentsRights"}, 189 {1002, nullptr, "RequestVerifyAddOnContentsRights"},
@@ -201,6 +203,8 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
201 {1310, nullptr, "RequestMoveApplicationEntity"}, 203 {1310, nullptr, "RequestMoveApplicationEntity"},
202 {1311, nullptr, "EstimateSizeToMove"}, 204 {1311, nullptr, "EstimateSizeToMove"},
203 {1312, nullptr, "HasMovableEntity"}, 205 {1312, nullptr, "HasMovableEntity"},
206 {1313, nullptr, "CleanupOrphanContents"},
207 {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
204 {1400, nullptr, "PrepareShutdown"}, 208 {1400, nullptr, "PrepareShutdown"},
205 {1500, nullptr, "FormatSdCard"}, 209 {1500, nullptr, "FormatSdCard"},
206 {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, 210 {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
@@ -215,6 +219,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
215 {1702, nullptr, "GetApplicationDownloadTaskStatus"}, 219 {1702, nullptr, "GetApplicationDownloadTaskStatus"},
216 {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, 220 {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
217 {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, 221 {1704, nullptr, "GetApplicationViewWithPromotionInfo"},
222 {1705, nullptr, "IsPatchAutoDeletableApplication"},
218 {1800, nullptr, "IsNotificationSetupCompleted"}, 223 {1800, nullptr, "IsNotificationSetupCompleted"},
219 {1801, nullptr, "GetLastNotificationInfoCount"}, 224 {1801, nullptr, "GetLastNotificationInfoCount"},
220 {1802, nullptr, "ListLastNotificationInfo"}, 225 {1802, nullptr, "ListLastNotificationInfo"},
@@ -269,6 +274,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
269 {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, 274 {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
270 {2352, nullptr, "RequestResolveNoDownloadRightsError"}, 275 {2352, nullptr, "RequestResolveNoDownloadRightsError"},
271 {2353, nullptr, "GetApplicationDownloadTaskInfo"}, 276 {2353, nullptr, "GetApplicationDownloadTaskInfo"},
277 {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
278 {2355, nullptr, "Unknown2355"},
279 {2356, nullptr, "Unknown2356"},
272 {2400, nullptr, "GetPromotionInfo"}, 280 {2400, nullptr, "GetPromotionInfo"},
273 {2401, nullptr, "CountPromotionInfo"}, 281 {2401, nullptr, "CountPromotionInfo"},
274 {2402, nullptr, "ListPromotionInfo"}, 282 {2402, nullptr, "ListPromotionInfo"},
@@ -282,6 +290,21 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
282 {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, 290 {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
283 {2516, nullptr, "EnsureApplicationCertificate"}, 291 {2516, nullptr, "EnsureApplicationCertificate"},
284 {2800, nullptr, "GetApplicationIdOfPreomia"}, 292 {2800, nullptr, "GetApplicationIdOfPreomia"},
293 {3000, nullptr, "RegisterDeviceLockKey"},
294 {3001, nullptr, "UnregisterDeviceLockKey"},
295 {3002, nullptr, "VerifyDeviceLockKey"},
296 {3003, nullptr, "HideApplicationIcon"},
297 {3004, nullptr, "ShowApplicationIcon"},
298 {3005, nullptr, "HideApplicationTitle"},
299 {3006, nullptr, "ShowApplicationTitle"},
300 {3007, nullptr, "EnableGameCard"},
301 {3008, nullptr, "DisableGameCard"},
302 {3009, nullptr, "EnableLocalContentShare"},
303 {3010, nullptr, "DisableLocalContentShare"},
304 {3011, nullptr, "IsApplicationIconHidden"},
305 {3012, nullptr, "IsApplicationTitleHidden"},
306 {3013, nullptr, "IsGameCardEnabled"},
307 {3014, nullptr, "IsLocalContentShareEnabled"},
285 {9999, nullptr, "GetApplicationCertificate"}, 308 {9999, nullptr, "GetApplicationCertificate"},
286 }; 309 };
287 // clang-format on 310 // clang-format on
@@ -441,7 +464,11 @@ IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_
441 {800, nullptr, "RequestVersionList"}, 464 {800, nullptr, "RequestVersionList"},
442 {801, nullptr, "ListVersionList"}, 465 {801, nullptr, "ListVersionList"},
443 {802, nullptr, "RequestVersionListData"}, 466 {802, nullptr, "RequestVersionListData"},
467 {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
468 {901, nullptr, "ListDefaultAutoUpdatePolicy"},
469 {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
444 {1000, nullptr, "PerformAutoUpdate"}, 470 {1000, nullptr, "PerformAutoUpdate"},
471 {1001, nullptr, "ListAutoUpdateSchedule"},
445 }; 472 };
446 // clang-format on 473 // clang-format on
447 474
@@ -547,6 +574,9 @@ IFactoryResetInterface::~IFactoryResetInterface() = default;
547NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { 574NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
548 // clang-format off 575 // clang-format off
549 static const FunctionInfo functions[] = { 576 static const FunctionInfo functions[] = {
577 {7988, nullptr, "GetDynamicRightsInterface"},
578 {7989, nullptr, "GetReadOnlyApplicationControlDataInterface"},
579 {7991, nullptr, "GetReadOnlyApplicationRecordInterface"},
550 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, 580 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
551 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, 581 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
552 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, 582 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
@@ -575,18 +605,22 @@ public:
575 {0, nullptr, "LaunchProgram"}, 605 {0, nullptr, "LaunchProgram"},
576 {1, nullptr, "TerminateProcess"}, 606 {1, nullptr, "TerminateProcess"},
577 {2, nullptr, "TerminateProgram"}, 607 {2, nullptr, "TerminateProgram"},
578 {4, nullptr, "GetShellEventHandle"}, 608 {4, nullptr, "GetShellEvent"},
579 {5, nullptr, "GetShellEventInfo"}, 609 {5, nullptr, "GetShellEventInfo"},
580 {6, nullptr, "TerminateApplication"}, 610 {6, nullptr, "TerminateApplication"},
581 {7, nullptr, "PrepareLaunchProgramFromHost"}, 611 {7, nullptr, "PrepareLaunchProgramFromHost"},
582 {8, nullptr, "LaunchApplication"}, 612 {8, nullptr, "LaunchApplicationFromHost"},
583 {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, 613 {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
584 {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, 614 {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
585 {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, 615 {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
586 {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActive"}, 616 {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
587 {13, nullptr, "CreateApplicationResourceForDevelop"}, 617 {13, nullptr, "CreateApplicationResourceForDevelop"},
588 {14, nullptr, "IsPreomiaForDevelop"}, 618 {14, nullptr, "IsPreomiaForDevelop"},
589 {15, nullptr, "GetApplicationProgramIdFromHost"}, 619 {15, nullptr, "GetApplicationProgramIdFromHost"},
620 {16, nullptr, "RefreshCachedDebugValues"},
621 {17, nullptr, "PrepareLaunchApplicationFromHost"},
622 {18, nullptr, "GetLaunchEvent"},
623 {19, nullptr, "GetLaunchResult"},
590 }; 624 };
591 // clang-format on 625 // clang-format on
592 626
@@ -699,6 +733,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system
699 std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); 733 std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager);
700 std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); 734 std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager);
701 std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); 735 std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager);
736 std::make_shared<NS>("ns:ro", system)->InstallAsService(service_manager);
702 737
703 std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); 738 std::make_shared<NS_DEV>(system)->InstallAsService(service_manager);
704 std::make_shared<NS_SU>(system)->InstallAsService(service_manager); 739 std::make_shared<NS_SU>(system)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index fcd15d81f..da139fdc4 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -154,6 +154,10 @@ PL_U::PL_U(Core::System& system_)
154 {100, nullptr, "RequestApplicationFunctionAuthorization"}, 154 {100, nullptr, "RequestApplicationFunctionAuthorization"},
155 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, 155 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
156 {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, 156 {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
157 {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"},
158 {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"},
159 {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"},
160 {106, nullptr, "GetFunctionBlackListVersion"},
157 {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, 161 {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
158 {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, 162 {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
159 }; 163 };
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 933d42f3f..2edd803f3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -248,7 +248,13 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<
248 IoctlZbcSetTable params{}; 248 IoctlZbcSetTable params{};
249 std::memcpy(&params, input.data(), input.size()); 249 std::memcpy(&params, input.data(), input.size());
250 // TODO(ogniK): What does this even actually do? 250 // TODO(ogniK): What does this even actually do?
251 std::memcpy(output.data(), &params, output.size()); 251
252 // Prevent null pointer being passed as arg 1
253 if (output.empty()) {
254 LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy");
255 } else {
256 std::memcpy(output.data(), &params, output.size());
257 }
252 return NvResult::Success; 258 return NvResult::Success;
253} 259}
254 260
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 4898dc27a..c2f152190 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -23,17 +23,22 @@ namespace {
23template <typename T> 23template <typename T>
24std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, 24std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count,
25 std::size_t offset) { 25 std::size_t offset) {
26 std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); 26 if (!dst.empty()) {
27 offset += count * sizeof(T); 27 std::memcpy(dst.data(), input.data() + offset, count * sizeof(T));
28 return offset; 28 }
29 return 0;
29} 30}
30 31
31// Write vectors will write data to the output buffer 32// Write vectors will write data to the output buffer
32template <typename T> 33template <typename T>
33std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { 34std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) {
34 std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T)); 35 if (src.empty()) {
35 offset += src.size() * sizeof(T); 36 return 0;
36 return offset; 37 } else {
38 std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T));
39 offset += src.size() * sizeof(T);
40 return offset;
41 }
37} 42}
38} // Anonymous namespace 43} // Anonymous namespace
39 44
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index ac2906e5b..539b02bc4 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "common/scope_exit.h" 11#include "common/scope_exit.h"
12#include "common/settings.h"
12#include "common/thread.h" 13#include "common/thread.h"
13#include "core/core.h" 14#include "core/core.h"
14#include "core/core_timing.h" 15#include "core/core_timing.h"
@@ -23,7 +24,6 @@
23#include "core/hle/service/vi/display/vi_display.h" 24#include "core/hle/service/vi/display/vi_display.h"
24#include "core/hle/service/vi/layer/vi_layer.h" 25#include "core/hle/service/vi/layer/vi_layer.h"
25#include "core/perf_stats.h" 26#include "core/perf_stats.h"
26#include "core/settings.h"
27#include "video_core/renderer_base.h" 27#include "video_core/renderer_base.h"
28 28
29namespace Service::NVFlinger { 29namespace Service::NVFlinger {
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index e2ac71fa1..b066c3417 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -26,6 +26,7 @@ public:
26 {22, nullptr, "DeleteSaveDataBackupAsync"}, 26 {22, nullptr, "DeleteSaveDataBackupAsync"},
27 {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, 27 {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
28 {26, nullptr, "DownloadSaveDataBackupAsync"}, 28 {26, nullptr, "DownloadSaveDataBackupAsync"},
29 {27, nullptr, "UploadSaveDataBackupAsync"},
29 {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"}, 30 {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
30 {9013, nullptr, "GetSaveDataBackupSettingForDebug"}, 31 {9013, nullptr, "GetSaveDataBackupSettingForDebug"},
31 {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"}, 32 {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp
index f6686fc4d..9bc851591 100644
--- a/src/core/hle/service/pcie/pcie.cpp
+++ b/src/core/hle/service/pcie/pcie.cpp
@@ -37,7 +37,7 @@ public:
37 {19, nullptr, "SetIrqEnable"}, 37 {19, nullptr, "SetIrqEnable"},
38 {20, nullptr, "SetAspmEnable"}, 38 {20, nullptr, "SetAspmEnable"},
39 {21, nullptr, "SetResetUponResumeEnable"}, 39 {21, nullptr, "SetResetUponResumeEnable"},
40 {22, nullptr, "Unknown22"}, 40 {22, nullptr, "ResetFunction"},
41 {23, nullptr, "Unknown23"}, 41 {23, nullptr, "Unknown23"},
42 }; 42 };
43 // clang-format on 43 // clang-format on
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp
index f9089bf2f..dc59702f1 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -3,16 +3,30 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/core.h"
7#include "core/file_sys/control_metadata.h"
8#include "core/file_sys/patch_manager.h"
6#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/process.h"
7#include "core/hle/service/pctl/module.h" 11#include "core/hle/service/pctl/module.h"
8#include "core/hle/service/pctl/pctl.h" 12#include "core/hle/service/pctl/pctl.h"
9 13
10namespace Service::PCTL { 14namespace Service::PCTL {
11 15
16namespace Error {
17
18constexpr ResultCode ResultNoFreeCommunication{ErrorModule::PCTL, 101};
19constexpr ResultCode ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
20constexpr ResultCode ResultNoCapability{ErrorModule::PCTL, 131};
21constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
22
23} // namespace Error
24
12class IParentalControlService final : public ServiceFramework<IParentalControlService> { 25class IParentalControlService final : public ServiceFramework<IParentalControlService> {
13public: 26public:
14 explicit IParentalControlService(Core::System& system_) 27 explicit IParentalControlService(Core::System& system_, Capability capability)
15 : ServiceFramework{system_, "IParentalControlService"} { 28 : ServiceFramework{system_, "IParentalControlService"}, system(system_),
29 capability(capability) {
16 // clang-format off 30 // clang-format off
17 static const FunctionInfo functions[] = { 31 static const FunctionInfo functions[] = {
18 {1, &IParentalControlService::Initialize, "Initialize"}, 32 {1, &IParentalControlService::Initialize, "Initialize"},
@@ -28,13 +42,13 @@ public:
28 {1010, nullptr, "IsRestrictedSystemSettingsEntered"}, 42 {1010, nullptr, "IsRestrictedSystemSettingsEntered"},
29 {1011, nullptr, "RevertRestrictedSystemSettingsEntered"}, 43 {1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
30 {1012, nullptr, "GetRestrictedFeatures"}, 44 {1012, nullptr, "GetRestrictedFeatures"},
31 {1013, nullptr, "ConfirmStereoVisionPermission"}, 45 {1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"},
32 {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, 46 {1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
33 {1015, nullptr, "ConfirmPlayableApplicationVideo"}, 47 {1015, nullptr, "ConfirmPlayableApplicationVideo"},
34 {1016, nullptr, "ConfirmShowNewsPermission"}, 48 {1016, nullptr, "ConfirmShowNewsPermission"},
35 {1017, nullptr, "EndFreeCommunication"}, 49 {1017, nullptr, "EndFreeCommunication"},
36 {1018, nullptr, "IsFreeCommunicationAvailable"}, 50 {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
37 {1031, nullptr, "IsRestrictionEnabled"}, 51 {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
38 {1032, nullptr, "GetSafetyLevel"}, 52 {1032, nullptr, "GetSafetyLevel"},
39 {1033, nullptr, "SetSafetyLevel"}, 53 {1033, nullptr, "SetSafetyLevel"},
40 {1034, nullptr, "GetSafetyLevelSettings"}, 54 {1034, nullptr, "GetSafetyLevelSettings"},
@@ -50,6 +64,7 @@ public:
50 {1046, nullptr, "DisableFeaturesForReset"}, 64 {1046, nullptr, "DisableFeaturesForReset"},
51 {1047, nullptr, "NotifyApplicationDownloadStarted"}, 65 {1047, nullptr, "NotifyApplicationDownloadStarted"},
52 {1048, nullptr, "NotifyNetworkProfileCreated"}, 66 {1048, nullptr, "NotifyNetworkProfileCreated"},
67 {1049, nullptr, "ResetFreeCommunicationApplicationList"},
53 {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"}, 68 {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"},
54 {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"}, 69 {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"},
55 {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"}, 70 {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"},
@@ -69,6 +84,8 @@ public:
69 {1421, nullptr, "GetAccountNickname"}, 84 {1421, nullptr, "GetAccountNickname"},
70 {1424, nullptr, "GetAccountState"}, 85 {1424, nullptr, "GetAccountState"},
71 {1425, nullptr, "RequestPostEvents"}, 86 {1425, nullptr, "RequestPostEvents"},
87 {1426, nullptr, "GetPostEventInterval"},
88 {1427, nullptr, "SetPostEventInterval"},
72 {1432, nullptr, "GetSynchronizationEvent"}, 89 {1432, nullptr, "GetSynchronizationEvent"},
73 {1451, nullptr, "StartPlayTimer"}, 90 {1451, nullptr, "StartPlayTimer"},
74 {1452, nullptr, "StopPlayTimer"}, 91 {1452, nullptr, "StopPlayTimer"},
@@ -119,62 +136,235 @@ public:
119 } 136 }
120 137
121private: 138private:
139 bool CheckFreeCommunicationPermissionImpl() const {
140 if (states.temporary_unlocked) {
141 return true;
142 }
143 if ((states.application_info.parental_control_flag & 1) == 0) {
144 return true;
145 }
146 if (pin_code[0] == '\0') {
147 return true;
148 }
149 if (!settings.is_free_communication_default_on) {
150 return true;
151 }
152 // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here
153 // but as we don't have multiproceses support yet, we can just assume our application is
154 // valid for the time being
155 return true;
156 }
157
158 bool ConfirmStereoVisionPermissionImpl() const {
159 if (states.temporary_unlocked) {
160 return true;
161 }
162 if (pin_code[0] == '\0') {
163 return true;
164 }
165 if (!settings.is_stero_vision_restricted) {
166 return false;
167 }
168 return true;
169 }
170
171 void SetStereoVisionRestrictionImpl(bool is_restricted) {
172 if (settings.disabled) {
173 return;
174 }
175
176 if (pin_code[0] == '\0') {
177 return;
178 }
179 settings.is_stero_vision_restricted = is_restricted;
180 }
181
122 void Initialize(Kernel::HLERequestContext& ctx) { 182 void Initialize(Kernel::HLERequestContext& ctx) {
123 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 183 LOG_DEBUG(Service_PCTL, "called");
184 IPC::ResponseBuilder rb{ctx, 2};
185
186 if (False(capability & (Capability::Application | Capability::System))) {
187 LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability);
188 return;
189 }
190
191 // TODO(ogniK): Recovery flag initialization for pctl:r
192
193 const auto tid = system.CurrentProcess()->GetTitleID();
194 if (tid != 0) {
195 const FileSys::PatchManager pm{tid, system.GetFileSystemController(),
196 system.GetContentProvider()};
197 const auto control = pm.GetControlMetadata();
198 if (control.first) {
199 states.tid_from_event = 0;
200 states.launch_time_valid = false;
201 states.is_suspended = false;
202 states.free_communication = false;
203 states.stereo_vision = false;
204 states.application_info = ApplicationInfo{
205 .tid = tid,
206 .age_rating = control.first->GetRatingAge(),
207 .parental_control_flag = control.first->GetParentalControlFlag(),
208 .capability = capability,
209 };
210
211 if (False(capability & (Capability::System | Capability::Recovery))) {
212 // TODO(ogniK): Signal application launch event
213 }
214 }
215 }
124 216
125 IPC::ResponseBuilder rb{ctx, 2, 0, 0};
126 rb.Push(RESULT_SUCCESS); 217 rb.Push(RESULT_SUCCESS);
127 } 218 }
128 219
129 void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { 220 void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) {
130 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 221 LOG_DEBUG(Service_PCTL, "called");
222
223 IPC::ResponseBuilder rb{ctx, 2};
224 if (!CheckFreeCommunicationPermissionImpl()) {
225 rb.Push(Error::ResultNoFreeCommunication);
226 } else {
227 rb.Push(RESULT_SUCCESS);
228 }
229
230 states.free_communication = true;
231 }
232
233 void ConfirmStereoVisionPermission(Kernel::HLERequestContext& ctx) {
234 LOG_DEBUG(Service_PCTL, "called");
235 states.stereo_vision = true;
131 236
132 IPC::ResponseBuilder rb{ctx, 2}; 237 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(RESULT_SUCCESS); 238 rb.Push(RESULT_SUCCESS);
134 } 239 }
135 240
136 void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { 241 void IsFreeCommunicationAvailable(Kernel::HLERequestContext& ctx) {
137 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 242 LOG_WARNING(Service_PCTL, "(STUBBED) called");
138 243
139 IPC::ResponseBuilder rb{ctx, 2}; 244 IPC::ResponseBuilder rb{ctx, 2};
245 if (!CheckFreeCommunicationPermissionImpl()) {
246 rb.Push(Error::ResultNoFreeCommunication);
247 } else {
248 rb.Push(RESULT_SUCCESS);
249 }
250 }
251
252 void IsRestrictionEnabled(Kernel::HLERequestContext& ctx) {
253 LOG_DEBUG(Service_PCTL, "called");
254
255 IPC::ResponseBuilder rb{ctx, 3};
256 if (False(capability & (Capability::Status | Capability::Recovery))) {
257 LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!");
258 rb.Push(Error::ResultNoCapability);
259 rb.Push(false);
260 return;
261 }
262
263 rb.Push(pin_code[0] != '\0');
264 }
265
266 void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) {
267 LOG_DEBUG(Service_PCTL, "called");
268
269 IPC::ResponseBuilder rb{ctx, 2};
270
271 if (False(capability & Capability::StereoVision)) {
272 LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
273 rb.Push(Error::ResultNoCapability);
274 return;
275 }
276
277 if (pin_code[0] == '\0') {
278 rb.Push(Error::ResultNoRestrictionEnabled);
279 return;
280 }
281
140 rb.Push(RESULT_SUCCESS); 282 rb.Push(RESULT_SUCCESS);
141 } 283 }
142 284
143 void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { 285 void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) {
144 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 286 LOG_DEBUG(Service_PCTL, "called");
145 287
146 IPC::ResponseBuilder rb{ctx, 3}; 288 IPC::ResponseBuilder rb{ctx, 3};
147 rb.Push(RESULT_SUCCESS); 289 if (!ConfirmStereoVisionPermissionImpl()) {
148 rb.Push(true); 290 rb.Push(Error::ResultStereoVisionRestricted);
291 rb.Push(false);
292 } else {
293 rb.Push(RESULT_SUCCESS);
294 rb.Push(true);
295 }
149 } 296 }
150 297
151 void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { 298 void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
152 IPC::RequestParser rp{ctx}; 299 IPC::RequestParser rp{ctx};
153 const auto can_use = rp.Pop<bool>(); 300 const auto can_use = rp.Pop<bool>();
154 LOG_WARNING(Service_PCTL, "(STUBBED) called, can_use={}", can_use); 301 LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use);
155
156 can_use_stereo_vision = can_use;
157 302
158 IPC::ResponseBuilder rb{ctx, 2}; 303 IPC::ResponseBuilder rb{ctx, 2};
304 if (False(capability & Capability::StereoVision)) {
305 LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
306 rb.Push(Error::ResultNoCapability);
307 return;
308 }
309
310 SetStereoVisionRestrictionImpl(can_use);
159 rb.Push(RESULT_SUCCESS); 311 rb.Push(RESULT_SUCCESS);
160 } 312 }
161 313
162 void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { 314 void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
163 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 315 LOG_DEBUG(Service_PCTL, "called");
164 316
165 IPC::ResponseBuilder rb{ctx, 3}; 317 IPC::ResponseBuilder rb{ctx, 3};
318 if (False(capability & Capability::StereoVision)) {
319 LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
320 rb.Push(Error::ResultNoCapability);
321 rb.Push(false);
322 return;
323 }
324
166 rb.Push(RESULT_SUCCESS); 325 rb.Push(RESULT_SUCCESS);
167 rb.Push(can_use_stereo_vision); 326 rb.Push(settings.is_stero_vision_restricted);
168 } 327 }
169 328
170 void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { 329 void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) {
171 LOG_WARNING(Service_PCTL, "(STUBBED) called"); 330 LOG_DEBUG(Service_PCTL, "called");
331
332 states.stereo_vision = false;
172 333
173 IPC::ResponseBuilder rb{ctx, 2}; 334 IPC::ResponseBuilder rb{ctx, 2};
174 rb.Push(RESULT_SUCCESS); 335 rb.Push(RESULT_SUCCESS);
175 } 336 }
176 337
338 struct ApplicationInfo {
339 u64 tid{};
340 std::array<u8, 32> age_rating{};
341 u32 parental_control_flag{};
342 Capability capability{};
343 };
344
345 struct States {
346 u64 current_tid{};
347 ApplicationInfo application_info{};
348 u64 tid_from_event{};
349 bool launch_time_valid{};
350 bool is_suspended{};
351 bool temporary_unlocked{};
352 bool free_communication{};
353 bool stereo_vision{};
354 };
355
356 struct ParentalControlSettings {
357 bool is_stero_vision_restricted{};
358 bool is_free_communication_default_on{};
359 bool disabled{};
360 };
361
362 States states{};
363 ParentalControlSettings settings{};
364 std::array<char, 8> pin_code{};
177 bool can_use_stereo_vision = true; 365 bool can_use_stereo_vision = true;
366 Core::System& system;
367 Capability capability{};
178}; 368};
179 369
180void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { 370void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
@@ -182,7 +372,9 @@ void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
182 372
183 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 373 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
184 rb.Push(RESULT_SUCCESS); 374 rb.Push(RESULT_SUCCESS);
185 rb.PushIpcInterface<IParentalControlService>(system); 375 // TODO(ogniK): Get TID from process
376
377 rb.PushIpcInterface<IParentalControlService>(system, capability);
186} 378}
187 379
188void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { 380void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
@@ -190,21 +382,28 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext
190 382
191 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 383 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
192 rb.Push(RESULT_SUCCESS); 384 rb.Push(RESULT_SUCCESS);
193 rb.PushIpcInterface<IParentalControlService>(system); 385 rb.PushIpcInterface<IParentalControlService>(system, capability);
194} 386}
195 387
196Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, 388Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
197 const char* name) 389 const char* name, Capability capability)
198 : ServiceFramework{system_, name}, module{std::move(module_)} {} 390 : ServiceFramework{system_, name}, module{std::move(module_)}, capability(capability) {}
199 391
200Module::Interface::~Interface() = default; 392Module::Interface::~Interface() = default;
201 393
202void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 394void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
203 auto module = std::make_shared<Module>(); 395 auto module = std::make_shared<Module>();
204 std::make_shared<PCTL>(system, module, "pctl")->InstallAsService(service_manager); 396 std::make_shared<PCTL>(system, module, "pctl",
205 std::make_shared<PCTL>(system, module, "pctl:a")->InstallAsService(service_manager); 397 Capability::Application | Capability::SnsPost | Capability::Status |
206 std::make_shared<PCTL>(system, module, "pctl:r")->InstallAsService(service_manager); 398 Capability::StereoVision)
207 std::make_shared<PCTL>(system, module, "pctl:s")->InstallAsService(service_manager); 399 ->InstallAsService(service_manager);
400 // TODO(ogniK): Implement remaining capabilities
401 std::make_shared<PCTL>(system, module, "pctl:a", Capability::None)
402 ->InstallAsService(service_manager);
403 std::make_shared<PCTL>(system, module, "pctl:r", Capability::None)
404 ->InstallAsService(service_manager);
405 std::make_shared<PCTL>(system, module, "pctl:s", Capability::None)
406 ->InstallAsService(service_manager);
208} 407}
209 408
210} // namespace Service::PCTL 409} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h
index 4c7e09a3b..032481b00 100644
--- a/src/core/hle/service/pctl/module.h
+++ b/src/core/hle/service/pctl/module.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_funcs.h"
7#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
8 9
9namespace Core { 10namespace Core {
@@ -12,12 +13,23 @@ class System;
12 13
13namespace Service::PCTL { 14namespace Service::PCTL {
14 15
16enum class Capability : u32 {
17 None = 0,
18 Application = 1 << 0,
19 SnsPost = 1 << 1,
20 Recovery = 1 << 6,
21 Status = 1 << 8,
22 StereoVision = 1 << 9,
23 System = 1 << 15,
24};
25DECLARE_ENUM_FLAG_OPERATORS(Capability);
26
15class Module final { 27class Module final {
16public: 28public:
17 class Interface : public ServiceFramework<Interface> { 29 class Interface : public ServiceFramework<Interface> {
18 public: 30 public:
19 explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, 31 explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
20 const char* name); 32 Capability capability);
21 ~Interface() override; 33 ~Interface() override;
22 34
23 void CreateService(Kernel::HLERequestContext& ctx); 35 void CreateService(Kernel::HLERequestContext& ctx);
@@ -25,6 +37,9 @@ public:
25 37
26 protected: 38 protected:
27 std::shared_ptr<Module> module; 39 std::shared_ptr<Module> module;
40
41 private:
42 Capability capability{};
28 }; 43 };
29}; 44};
30 45
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index 16dd34f90..e4d155c86 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -6,8 +6,9 @@
6 6
7namespace Service::PCTL { 7namespace Service::PCTL {
8 8
9PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name) 9PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
10 : Interface{system_, std::move(module_), name} { 10 Capability capability)
11 : Interface{system_, std::move(module_), name, capability} {
11 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
12 {0, &PCTL::CreateService, "CreateService"}, 13 {0, &PCTL::CreateService, "CreateService"},
13 {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, 14 {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"},
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index 275d23007..fd0a1e486 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -14,7 +14,8 @@ namespace Service::PCTL {
14 14
15class PCTL final : public Module::Interface { 15class PCTL final : public Module::Interface {
16public: 16public:
17 explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name); 17 explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
18 Capability capability);
18 ~PCTL() override; 19 ~PCTL() override;
19}; 20};
20 21
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 1da56bc27..41a502d8d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -6,6 +6,7 @@
6#include <fmt/format.h> 6#include <fmt/format.h>
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/settings.h"
9#include "common/string_util.h" 10#include "common/string_util.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/hle/ipc.h" 12#include "core/hle/ipc.h"
@@ -146,6 +147,11 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
146 system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, 147 system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name,
147 service_name); 148 service_name);
148 UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); 149 UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf));
150 if (Settings::values.use_auto_stub) {
151 LOG_WARNING(Service, "Using auto stub fallback!");
152 IPC::ResponseBuilder rb{ctx, 2};
153 rb.Push(RESULT_SUCCESS);
154 }
149} 155}
150 156
151void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { 157void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index d953b4303..bc7dc776f 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -6,9 +6,9 @@
6#include <array> 6#include <array>
7#include <chrono> 7#include <chrono>
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/settings.h"
9#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
10#include "core/hle/service/set/set.h" 11#include "core/hle/service/set/set.h"
11#include "core/settings.h"
12 12
13namespace Service::Set { 13namespace Service::Set {
14namespace { 14namespace {
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index b58b2c8c5..5909fdd85 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -261,6 +261,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
261 {155, nullptr, "SetAccountOnlineStorageSettings"}, 261 {155, nullptr, "SetAccountOnlineStorageSettings"},
262 {156, nullptr, "GetPctlReadyFlag"}, 262 {156, nullptr, "GetPctlReadyFlag"},
263 {157, nullptr, "SetPctlReadyFlag"}, 263 {157, nullptr, "SetPctlReadyFlag"},
264 {158, nullptr, "GetAnalogStickUserCalibrationL"},
265 {159, nullptr, "SetAnalogStickUserCalibrationL"},
266 {160, nullptr, "GetAnalogStickUserCalibrationR"},
267 {161, nullptr, "SetAnalogStickUserCalibrationR"},
264 {162, nullptr, "GetPtmBatteryVersion"}, 268 {162, nullptr, "GetPtmBatteryVersion"},
265 {163, nullptr, "SetPtmBatteryVersion"}, 269 {163, nullptr, "SetPtmBatteryVersion"},
266 {164, nullptr, "GetUsb30HostEnableFlag"}, 270 {164, nullptr, "GetUsb30HostEnableFlag"},
@@ -302,6 +306,8 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
302 {200, nullptr, "SetButtonConfigRegisteredSettings"}, 306 {200, nullptr, "SetButtonConfigRegisteredSettings"},
303 {201, nullptr, "GetFieldTestingFlag"}, 307 {201, nullptr, "GetFieldTestingFlag"},
304 {202, nullptr, "SetFieldTestingFlag"}, 308 {202, nullptr, "SetFieldTestingFlag"},
309 {203, nullptr, "GetPanelCrcMode"},
310 {204, nullptr, "SetPanelCrcMode"},
305 }; 311 };
306 // clang-format on 312 // clang-format on
307 313
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 2b91a89d1..94608d529 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -190,10 +190,11 @@ SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_)
190 : ServiceFramework{system_, "sm:", 4}, 190 : ServiceFramework{system_, "sm:", 4},
191 service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { 191 service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} {
192 static const FunctionInfo functions[] = { 192 static const FunctionInfo functions[] = {
193 {0x00000000, &SM::Initialize, "Initialize"}, 193 {0, &SM::Initialize, "Initialize"},
194 {0x00000001, &SM::GetService, "GetService"}, 194 {1, &SM::GetService, "GetService"},
195 {0x00000002, &SM::RegisterService, "RegisterService"}, 195 {2, &SM::RegisterService, "RegisterService"},
196 {0x00000003, &SM::UnregisterService, "UnregisterService"}, 196 {3, &SM::UnregisterService, "UnregisterService"},
197 {4, nullptr, "DetachClient"},
197 }; 198 };
198 RegisterHandlers(functions); 199 RegisterHandlers(functions);
199} 200}
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp
index 05681ca2d..899a64c2f 100644
--- a/src/core/hle/service/sockets/ethc.cpp
+++ b/src/core/hle/service/sockets/ethc.cpp
@@ -15,6 +15,7 @@ ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} {
15 {3, nullptr, "GetMediaList"}, 15 {3, nullptr, "GetMediaList"},
16 {4, nullptr, "SetMediaType"}, 16 {4, nullptr, "SetMediaType"},
17 {5, nullptr, "GetMediaType"}, 17 {5, nullptr, "GetMediaType"},
18 {6, nullptr, "Unknown6"},
18 }; 19 };
19 // clang-format on 20 // clang-format on
20 21
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index 51c3739bb..1159debc5 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -9,6 +9,7 @@ namespace Service::Sockets {
9NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { 9NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {5, nullptr, "GetSettingUrl"},
12 {10, nullptr, "GetSettingName"}, 13 {10, nullptr, "GetSettingName"},
13 {11, nullptr, "GetEnvironmentIdentifier"}, 14 {11, nullptr, "GetEnvironmentIdentifier"},
14 {12, nullptr, "GetDeviceId"}, 15 {12, nullptr, "GetDeviceId"},
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 3a6329f56..5c71f423c 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -9,8 +9,8 @@ namespace Service::Sockets {
9 9
10SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} { 10SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} {
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "SetDnsAddressesPrivate"}, 12 {0, nullptr, "SetDnsAddressesPrivateRequest"},
13 {1, nullptr, "GetDnsAddressPrivate"}, 13 {1, nullptr, "GetDnsAddressPrivateRequest"},
14 {2, nullptr, "GetHostByNameRequest"}, 14 {2, nullptr, "GetHostByNameRequest"},
15 {3, nullptr, "GetHostByAddrRequest"}, 15 {3, nullptr, "GetHostByAddrRequest"},
16 {4, nullptr, "GetHostStringErrorRequest"}, 16 {4, nullptr, "GetHostStringErrorRequest"},
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 6903dd534..b1552c3f0 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -9,11 +9,11 @@
9#include <functional> 9#include <functional>
10#include <vector> 10#include <vector>
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h"
12#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
13#include "core/hle/service/spl/csrng.h" 14#include "core/hle/service/spl/csrng.h"
14#include "core/hle/service/spl/module.h" 15#include "core/hle/service/spl/module.h"
15#include "core/hle/service/spl/spl.h" 16#include "core/hle/service/spl/spl.h"
16#include "core/settings.h"
17 17
18namespace Service::SPL { 18namespace Service::SPL {
19 19
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp
index 4e212610f..fff3f3c42 100644
--- a/src/core/hle/service/spl/spl.cpp
+++ b/src/core/hle/service/spl/spl.cpp
@@ -60,6 +60,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
60 {4, nullptr, "GenerateAesKey"}, 60 {4, nullptr, "GenerateAesKey"},
61 {5, nullptr, "SetConfig"}, 61 {5, nullptr, "SetConfig"},
62 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, 62 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
63 {9, nullptr, "ImportLotusKey"},
64 {10, nullptr, "DecryptLotusMessage"},
63 {11, nullptr, "IsDevelopment"}, 65 {11, nullptr, "IsDevelopment"},
64 {12, nullptr, "GenerateSpecificAesKey"}, 66 {12, nullptr, "GenerateSpecificAesKey"},
65 {14, nullptr, "DecryptAesKey"}, 67 {14, nullptr, "DecryptAesKey"},
@@ -123,6 +125,7 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
123 {14, nullptr, "DecryptAesKey"}, 125 {14, nullptr, "DecryptAesKey"},
124 {15, nullptr, "CryptAesCtr"}, 126 {15, nullptr, "CryptAesCtr"},
125 {16, nullptr, "ComputeCmac"}, 127 {16, nullptr, "ComputeCmac"},
128 {17, nullptr, "ImportEsKey"},
126 {18, nullptr, "UnwrapTitleKey"}, 129 {18, nullptr, "UnwrapTitleKey"},
127 {20, nullptr, "PrepareEsCommonKey"}, 130 {20, nullptr, "PrepareEsCommonKey"},
128 {21, nullptr, "AllocateAesKeyslot"}, 131 {21, nullptr, "AllocateAesKeyslot"},
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index b78892223..a9cfe3eb0 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -12,6 +12,12 @@
12 12
13namespace Service::Time::Clock { 13namespace Service::Time::Clock {
14 14
15enum class TimeType : u8 {
16 UserSystemClock,
17 NetworkSystemClock,
18 LocalSystemClock,
19};
20
15/// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint 21/// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint
16struct SteadyClockTimePoint { 22struct SteadyClockTimePoint {
17 s64 time_point; 23 s64 time_point;
@@ -84,7 +90,7 @@ struct ClockSnapshot {
84 SteadyClockTimePoint steady_clock_time_point; 90 SteadyClockTimePoint steady_clock_time_point;
85 TimeZone::LocationName location_name; 91 TimeZone::LocationName location_name;
86 u8 is_automatic_correction_enabled; 92 u8 is_automatic_correction_enabled;
87 u8 type; 93 TimeType type;
88 INSERT_PADDING_BYTES_NOINIT(0x2); 94 INSERT_PADDING_BYTES_NOINIT(0x2);
89 95
90 static ResultCode GetCurrentTime(s64& current_time, 96 static ResultCode GetCurrentTime(s64& current_time,
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 78543688f..63e0247de 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -122,14 +122,16 @@ private:
122 122
123ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( 123ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
124 Kernel::KThread* thread, Clock::SystemClockContext user_context, 124 Kernel::KThread* thread, Clock::SystemClockContext user_context,
125 Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { 125 Clock::SystemClockContext network_context, Clock::TimeType type,
126 Clock::ClockSnapshot& clock_snapshot) {
126 127
127 auto& time_manager{system.GetTimeManager()}; 128 auto& time_manager{system.GetTimeManager()};
128 129
130 clock_snapshot.steady_clock_time_point =
131 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system);
129 clock_snapshot.is_automatic_correction_enabled = 132 clock_snapshot.is_automatic_correction_enabled =
130 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); 133 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
131 clock_snapshot.user_context = user_context; 134 clock_snapshot.type = type;
132 clock_snapshot.network_context = network_context;
133 135
134 if (const ResultCode result{ 136 if (const ResultCode result{
135 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName( 137 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName(
@@ -138,12 +140,11 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
138 return result; 140 return result;
139 } 141 }
140 142
141 const auto current_time_point{ 143 clock_snapshot.user_context = user_context;
142 time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
143 clock_snapshot.steady_clock_time_point = current_time_point;
144 144
145 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( 145 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime(
146 clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)}; 146 clock_snapshot.user_time, clock_snapshot.steady_clock_time_point,
147 clock_snapshot.user_context)};
147 result != RESULT_SUCCESS) { 148 result != RESULT_SUCCESS) {
148 return result; 149 return result;
149 } 150 }
@@ -157,9 +158,12 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
157 } 158 }
158 159
159 clock_snapshot.user_calendar_time = userCalendarInfo.time; 160 clock_snapshot.user_calendar_time = userCalendarInfo.time;
160 clock_snapshot.user_calendar_additional_time = userCalendarInfo.additiona_info; 161 clock_snapshot.user_calendar_additional_time = userCalendarInfo.additional_info;
162
163 clock_snapshot.network_context = network_context;
161 164
162 if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time, current_time_point, 165 if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time,
166 clock_snapshot.steady_clock_time_point,
163 clock_snapshot.network_context) != RESULT_SUCCESS) { 167 clock_snapshot.network_context) != RESULT_SUCCESS) {
164 clock_snapshot.network_time = 0; 168 clock_snapshot.network_time = 0;
165 } 169 }
@@ -173,8 +177,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
173 } 177 }
174 178
175 clock_snapshot.network_calendar_time = networkCalendarInfo.time; 179 clock_snapshot.network_calendar_time = networkCalendarInfo.time;
176 clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additiona_info; 180 clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additional_info;
177 clock_snapshot.type = type;
178 181
179 return RESULT_SUCCESS; 182 return RESULT_SUCCESS;
180} 183}
@@ -257,9 +260,10 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe
257} 260}
258 261
259void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { 262void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
260 LOG_DEBUG(Service_Time, "called");
261 IPC::RequestParser rp{ctx}; 263 IPC::RequestParser rp{ctx};
262 const auto type{rp.PopRaw<u8>()}; 264 const auto type{rp.PopEnum<Clock::TimeType>()};
265
266 LOG_DEBUG(Service_Time, "called, type={}", type);
263 267
264 Clock::SystemClockContext user_context{}; 268 Clock::SystemClockContext user_context{};
265 if (const ResultCode result{ 269 if (const ResultCode result{
@@ -270,6 +274,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
270 rb.Push(result); 274 rb.Push(result);
271 return; 275 return;
272 } 276 }
277
273 Clock::SystemClockContext network_context{}; 278 Clock::SystemClockContext network_context{};
274 if (const ResultCode result{ 279 if (const ResultCode result{
275 system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( 280 system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
@@ -295,14 +300,16 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
295} 300}
296 301
297void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) { 302void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
298 LOG_DEBUG(Service_Time, "called");
299 IPC::RequestParser rp{ctx}; 303 IPC::RequestParser rp{ctx};
300 const auto type{rp.PopRaw<u8>()}; 304 const auto type{rp.PopEnum<Clock::TimeType>()};
305
301 rp.AlignWithPadding(); 306 rp.AlignWithPadding();
302 307
303 const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()}; 308 const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
304 const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()}; 309 const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
305 310
311 LOG_DEBUG(Service_Time, "called, type={}", type);
312
306 Clock::ClockSnapshot clock_snapshot{}; 313 Clock::ClockSnapshot clock_snapshot{};
307 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal( 314 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal(
308 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)}; 315 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
@@ -321,9 +328,14 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
321 Kernel::HLERequestContext& ctx) { 328 Kernel::HLERequestContext& ctx) {
322 LOG_DEBUG(Service_Time, "called"); 329 LOG_DEBUG(Service_Time, "called");
323 330
324 IPC::RequestParser rp{ctx}; 331 Clock::ClockSnapshot snapshot_a;
325 const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>(); 332 Clock::ClockSnapshot snapshot_b;
326 const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>(); 333
334 const auto snapshot_a_data = ctx.ReadBuffer(0);
335 const auto snapshot_b_data = ctx.ReadBuffer(1);
336
337 std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot));
338 std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot));
327 339
328 auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset - 340 auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset -
329 snapshot_a.user_context.offset)}; 341 snapshot_a.user_context.offset)};
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 4154c7ee9..ce9c479c6 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -40,7 +40,7 @@ public:
40 private: 40 private:
41 ResultCode GetClockSnapshotFromSystemClockContextInternal( 41 ResultCode GetClockSnapshotFromSystemClockContextInternal(
42 Kernel::KThread* thread, Clock::SystemClockContext user_context, 42 Kernel::KThread* thread, Clock::SystemClockContext user_context,
43 Clock::SystemClockContext network_context, u8 type, 43 Clock::SystemClockContext network_context, Clock::TimeType type,
44 Clock::ClockSnapshot& cloc_snapshot); 44 Clock::ClockSnapshot& cloc_snapshot);
45 45
46 protected: 46 protected:
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 1f7309f6b..f89c5aaad 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -5,12 +5,12 @@
5#include <chrono> 5#include <chrono>
6#include <ctime> 6#include <ctime>
7 7
8#include "common/settings.h"
8#include "common/time_zone.h" 9#include "common/time_zone.h"
9#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h" 10#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
10#include "core/hle/service/time/local_system_clock_context_writer.h" 11#include "core/hle/service/time/local_system_clock_context_writer.h"
11#include "core/hle/service/time/network_system_clock_context_writer.h" 12#include "core/hle/service/time/network_system_clock_context_writer.h"
12#include "core/hle/service/time/time_manager.h" 13#include "core/hle/service/time/time_manager.h"
13#include "core/settings.h"
14 14
15namespace Service::Time { 15namespace Service::Time {
16 16
@@ -44,7 +44,11 @@ struct TimeManager::Impl final {
44 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; 44 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
45 SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); 45 SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
46 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); 46 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
47 SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); 47
48 Clock::SystemClockContext clock_context{};
49 standard_local_system_clock_core.GetClockContext(system, clock_context);
50
51 SetupStandardNetworkSystemClock(clock_context, standard_network_clock_accuracy);
48 SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); 52 SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
49 SetupEphemeralNetworkSystemClock(); 53 SetupEphemeralNetworkSystemClock();
50 } 54 }
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index 4177d0a41..3c8e71a3c 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -5,6 +5,7 @@
5#include <sstream> 5#include <sstream>
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h"
8#include "common/time_zone.h" 9#include "common/time_zone.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/file_sys/content_archive.h" 11#include "core/file_sys/content_archive.h"
@@ -15,7 +16,6 @@
15#include "core/hle/service/filesystem/filesystem.h" 16#include "core/hle/service/filesystem/filesystem.h"
16#include "core/hle/service/time/time_manager.h" 17#include "core/hle/service/time/time_manager.h"
17#include "core/hle/service/time/time_zone_content_manager.h" 18#include "core/hle/service/time/time_zone_content_manager.h"
18#include "core/settings.h"
19 19
20namespace Service::Time::TimeZone { 20namespace Service::Time::TimeZone {
21 21
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
index bdf0439f2..3032ca193 100644
--- a/src/core/hle/service/time/time_zone_manager.cpp
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -818,7 +818,7 @@ static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
818static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) { 818static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) {
819 CalendarTimeInternal calendar_time{}; 819 CalendarTimeInternal calendar_time{};
820 const ResultCode result{ 820 const ResultCode result{
821 ToCalendarTimeInternal(rules, time, calendar_time, calendar.additiona_info)}; 821 ToCalendarTimeInternal(rules, time, calendar_time, calendar.additional_info)};
822 calendar.time.year = static_cast<s16>(calendar_time.year); 822 calendar.time.year = static_cast<s16>(calendar_time.year);
823 823
824 // Internal impl. uses 0-indexed month 824 // Internal impl. uses 0-indexed month
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index 25cecbc83..3117627cf 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -20,6 +20,7 @@ ITimeZoneService ::ITimeZoneService(Core::System& system_,
20 {3, nullptr, "LoadLocationNameList"}, 20 {3, nullptr, "LoadLocationNameList"},
21 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, 21 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
22 {5, nullptr, "GetTimeZoneRuleVersion"}, 22 {5, nullptr, "GetTimeZoneRuleVersion"},
23 {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
23 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, 24 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
24 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 25 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
25 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, 26 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
diff --git a/src/core/hle/service/time/time_zone_types.h b/src/core/hle/service/time/time_zone_types.h
index 4a57e036d..d39103253 100644
--- a/src/core/hle/service/time/time_zone_types.h
+++ b/src/core/hle/service/time/time_zone_types.h
@@ -66,8 +66,8 @@ struct CalendarTime {
66static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size"); 66static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size");
67 67
68struct CalendarInfo { 68struct CalendarInfo {
69 CalendarTime time{}; 69 CalendarTime time;
70 CalendarAdditionalInfo additiona_info{}; 70 CalendarAdditionalInfo additional_info;
71}; 71};
72static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size"); 72static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size");
73 73
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
index 579de83e4..b3b230a8c 100644
--- a/src/core/hle/service/usb/usb.cpp
+++ b/src/core/hle/service/usb/usb.cpp
@@ -69,15 +69,15 @@ public:
69 : ServiceFramework{system_, "IClientEpSession"} { 69 : ServiceFramework{system_, "IClientEpSession"} {
70 // clang-format off 70 // clang-format off
71 static const FunctionInfo functions[] = { 71 static const FunctionInfo functions[] = {
72 {0, nullptr, "Open"}, 72 {0, nullptr, "ReOpen"},
73 {1, nullptr, "Close"}, 73 {1, nullptr, "Close"},
74 {2, nullptr, "Unknown2"}, 74 {2, nullptr, "GetCompletionEvent"},
75 {3, nullptr, "Populate"}, 75 {3, nullptr, "PopulateRing"},
76 {4, nullptr, "PostBufferAsync"}, 76 {4, nullptr, "PostBufferAsync"},
77 {5, nullptr, "GetXferReport"}, 77 {5, nullptr, "GetXferReport"},
78 {6, nullptr, "PostBufferMultiAsync"}, 78 {6, nullptr, "PostBufferMultiAsync"},
79 {7, nullptr, "Unknown7"}, 79 {7, nullptr, "CreateSmmuSpace"},
80 {8, nullptr, "Unknown8"}, 80 {8, nullptr, "ShareReportRing"},
81 }; 81 };
82 // clang-format on 82 // clang-format on
83 83
@@ -91,7 +91,7 @@ public:
91 : ServiceFramework{system_, "IClientIfSession"} { 91 : ServiceFramework{system_, "IClientIfSession"} {
92 // clang-format off 92 // clang-format off
93 static const FunctionInfo functions[] = { 93 static const FunctionInfo functions[] = {
94 {0, nullptr, "Unknown0"}, 94 {0, nullptr, "GetStateChangeEvent"},
95 {1, nullptr, "SetInterface"}, 95 {1, nullptr, "SetInterface"},
96 {2, nullptr, "GetInterface"}, 96 {2, nullptr, "GetInterface"},
97 {3, nullptr, "GetAlternateInterface"}, 97 {3, nullptr, "GetAlternateInterface"},
@@ -176,15 +176,15 @@ public:
176 : ServiceFramework{system_, "IPdCradleSession"} { 176 : ServiceFramework{system_, "IPdCradleSession"} {
177 // clang-format off 177 // clang-format off
178 static const FunctionInfo functions[] = { 178 static const FunctionInfo functions[] = {
179 {0, nullptr, "VdmUserWrite"}, 179 {0, nullptr, "SetCradleVdo"},
180 {1, nullptr, "VdmUserRead"}, 180 {1, nullptr, "GetCradleVdo"},
181 {2, nullptr, "Vdm20Init"}, 181 {2, nullptr, "ResetCradleUsbHub"},
182 {3, nullptr, "GetFwType"}, 182 {3, nullptr, "GetHostPdcFirmwareType"},
183 {4, nullptr, "GetFwRevision"}, 183 {4, nullptr, "GetHostPdcFirmwareRevision"},
184 {5, nullptr, "GetManufacturerId"}, 184 {5, nullptr, "GetHostPdcManufactureId"},
185 {6, nullptr, "GetDeviceId"}, 185 {6, nullptr, "GetHostPdcDeviceId"},
186 {7, nullptr, "Unknown7"}, 186 {7, nullptr, "AwakeCradle"},
187 {8, nullptr, "Unknown8"}, 187 {8, nullptr, "SleepCradle"},
188 }; 188 };
189 // clang-format on 189 // clang-format on
190 190
@@ -219,12 +219,12 @@ public:
219 explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { 219 explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} {
220 // clang-format off 220 // clang-format off
221 static const FunctionInfo functions[] = { 221 static const FunctionInfo functions[] = {
222 {0, nullptr, "Unknown0"}, 222 {0, nullptr, "GetPowerEvent"},
223 {1, nullptr, "Unknown1"}, 223 {1, nullptr, "GetPowerState"},
224 {2, nullptr, "Unknown2"}, 224 {2, nullptr, "GetDataEvent"},
225 {3, nullptr, "Unknown3"}, 225 {3, nullptr, "GetDataRole"},
226 {4, nullptr, "Unknown4"}, 226 {4, nullptr, "SetDiagData"},
227 {5, nullptr, "Unknown5"}, 227 {5, nullptr, "GetDiagData"},
228 }; 228 };
229 // clang-format on 229 // clang-format on
230 230
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 7423287ea..348360b51 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -15,6 +15,7 @@
15#include "common/common_funcs.h" 15#include "common/common_funcs.h"
16#include "common/logging/log.h" 16#include "common/logging/log.h"
17#include "common/math_util.h" 17#include "common/math_util.h"
18#include "common/settings.h"
18#include "common/swap.h" 19#include "common/swap.h"
19#include "core/core_timing.h" 20#include "core/core_timing.h"
20#include "core/hle/ipc_helpers.h" 21#include "core/hle/ipc_helpers.h"
@@ -30,7 +31,6 @@
30#include "core/hle/service/vi/vi_m.h" 31#include "core/hle/service/vi/vi_m.h"
31#include "core/hle/service/vi/vi_s.h" 32#include "core/hle/service/vi/vi_s.h"
32#include "core/hle/service/vi/vi_u.h" 33#include "core/hle/service/vi/vi_u.h"
33#include "core/settings.h"
34 34
35namespace Service::VI { 35namespace Service::VI {
36 36
@@ -695,6 +695,7 @@ public:
695 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, 695 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
696 {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, 696 {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
697 {2209, nullptr, "SetLayerAlpha"}, 697 {2209, nullptr, "SetLayerAlpha"},
698 {2210, nullptr, "SetLayerPositionAndSize"},
698 {2312, nullptr, "CreateStrayLayer"}, 699 {2312, nullptr, "CreateStrayLayer"},
699 {2400, nullptr, "OpenIndirectLayer"}, 700 {2400, nullptr, "OpenIndirectLayer"},
700 {2401, nullptr, "CloseIndirectLayer"}, 701 {2401, nullptr, "CloseIndirectLayer"},
@@ -718,6 +719,7 @@ public:
718 {3215, nullptr, "SetDisplayGamma"}, 719 {3215, nullptr, "SetDisplayGamma"},
719 {3216, nullptr, "GetDisplayCmuLuma"}, 720 {3216, nullptr, "GetDisplayCmuLuma"},
720 {3217, nullptr, "SetDisplayCmuLuma"}, 721 {3217, nullptr, "SetDisplayCmuLuma"},
722 {3218, nullptr, "SetDisplayCrcMode"},
721 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, 723 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
722 {8225, nullptr, "GetSharedBufferMemoryHandleId"}, 724 {8225, nullptr, "GetSharedBufferMemoryHandleId"},
723 {8250, nullptr, "OpenSharedLayer"}, 725 {8250, nullptr, "OpenSharedLayer"},
@@ -729,6 +731,7 @@ public:
729 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, 731 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"},
730 {8257, nullptr, "FillSharedFrameBufferColor"}, 732 {8257, nullptr, "FillSharedFrameBufferColor"},
731 {8258, nullptr, "CancelSharedFrameBuffer"}, 733 {8258, nullptr, "CancelSharedFrameBuffer"},
734 {9000, nullptr, "GetDp2hdmiController"},
732 }; 735 };
733 RegisterHandlers(functions); 736 RegisterHandlers(functions);
734 } 737 }
@@ -808,10 +811,15 @@ public:
808 {2402, nullptr, "GetDisplayHotplugState"}, 811 {2402, nullptr, "GetDisplayHotplugState"},
809 {2501, nullptr, "GetCompositorErrorInfo"}, 812 {2501, nullptr, "GetCompositorErrorInfo"},
810 {2601, nullptr, "GetDisplayErrorEvent"}, 813 {2601, nullptr, "GetDisplayErrorEvent"},
814 {2701, nullptr, "GetDisplayFatalErrorEvent"},
811 {4201, nullptr, "SetDisplayAlpha"}, 815 {4201, nullptr, "SetDisplayAlpha"},
812 {4203, nullptr, "SetDisplayLayerStack"}, 816 {4203, nullptr, "SetDisplayLayerStack"},
813 {4205, nullptr, "SetDisplayPowerState"}, 817 {4205, nullptr, "SetDisplayPowerState"},
814 {4206, nullptr, "SetDefaultDisplay"}, 818 {4206, nullptr, "SetDefaultDisplay"},
819 {4207, nullptr, "ResetDisplayPanel"},
820 {4208, nullptr, "SetDisplayFatalErrorEnabled"},
821 {4209, nullptr, "IsDisplayPanelOn"},
822 {4300, nullptr, "GetInternalPanelId"},
815 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, 823 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
816 {6001, nullptr, "RemoveFromLayerStack"}, 824 {6001, nullptr, "RemoveFromLayerStack"},
817 {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, 825 {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp
index ddbf04069..44957e01d 100644
--- a/src/core/hle/service/wlan/wlan.cpp
+++ b/src/core/hle/service/wlan/wlan.cpp
@@ -46,6 +46,13 @@ public:
46 {28, nullptr, "Unknown28"}, 46 {28, nullptr, "Unknown28"},
47 {29, nullptr, "Unknown29"}, 47 {29, nullptr, "Unknown29"},
48 {30, nullptr, "Unknown30"}, 48 {30, nullptr, "Unknown30"},
49 {31, nullptr, "Unknown31"},
50 {32, nullptr, "Unknown32"},
51 {33, nullptr, "Unknown33"},
52 {34, nullptr, "Unknown34"},
53 {35, nullptr, "Unknown35"},
54 {36, nullptr, "Unknown36"},
55 {37, nullptr, "Unknown37"},
49 }; 56 };
50 // clang-format on 57 // clang-format on
51 58
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 14618cb40..0115ed0c4 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -9,6 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/file_util.h" 10#include "common/file_util.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h"
12#include "common/swap.h" 13#include "common/swap.h"
13#include "core/core.h" 14#include "core/core.h"
14#include "core/file_sys/control_metadata.h" 15#include "core/file_sys/control_metadata.h"
@@ -22,7 +23,6 @@
22#include "core/loader/nro.h" 23#include "core/loader/nro.h"
23#include "core/loader/nso.h" 24#include "core/loader/nso.h"
24#include "core/memory.h" 25#include "core/memory.h"
25#include "core/settings.h"
26 26
27namespace Loader { 27namespace Loader {
28 28
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index cbd048695..0c83dd666 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -11,6 +11,7 @@
11#include "common/hex_util.h" 11#include "common/hex_util.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/lz4_compression.h" 13#include "common/lz4_compression.h"
14#include "common/settings.h"
14#include "common/swap.h" 15#include "common/swap.h"
15#include "core/core.h" 16#include "core/core.h"
16#include "core/file_sys/patch_manager.h" 17#include "core/file_sys/patch_manager.h"
@@ -20,7 +21,6 @@
20#include "core/hle/kernel/process.h" 21#include "core/hle/kernel/process.h"
21#include "core/loader/nso.h" 22#include "core/loader/nso.h"
22#include "core/memory.h" 23#include "core/memory.h"
23#include "core/settings.h"
24 24
25namespace Loader { 25namespace Loader {
26namespace { 26namespace {
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index b93396a80..c92337079 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -13,8 +13,8 @@
13#include <fmt/format.h> 13#include <fmt/format.h>
14#include "common/file_util.h" 14#include "common/file_util.h"
15#include "common/math_util.h" 15#include "common/math_util.h"
16#include "common/settings.h"
16#include "core/perf_stats.h" 17#include "core/perf_stats.h"
17#include "core/settings.h"
18 18
19using namespace std::chrono_literals; 19using namespace std::chrono_literals;
20using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; 20using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 74fb32814..311d4dda8 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -14,6 +14,7 @@
14#include "common/file_util.h" 14#include "common/file_util.h"
15#include "common/hex_util.h" 15#include "common/hex_util.h"
16#include "common/scm_rev.h" 16#include "common/scm_rev.h"
17#include "common/settings.h"
17#include "core/arm/arm_interface.h" 18#include "core/arm/arm_interface.h"
18#include "core/core.h" 19#include "core/core.h"
19#include "core/hle/kernel/hle_ipc.h" 20#include "core/hle/kernel/hle_ipc.h"
@@ -22,7 +23,6 @@
22#include "core/hle/result.h" 23#include "core/hle/result.h"
23#include "core/memory.h" 24#include "core/memory.h"
24#include "core/reporter.h" 25#include "core/reporter.h"
25#include "core/settings.h"
26 26
27namespace { 27namespace {
28 28
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index d11b15f38..6dcff5400 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -12,10 +12,10 @@
12#include "common/file_util.h" 12#include "common/file_util.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14 14
15#include "common/settings.h"
15#include "core/file_sys/control_metadata.h" 16#include "core/file_sys/control_metadata.h"
16#include "core/file_sys/patch_manager.h" 17#include "core/file_sys/patch_manager.h"
17#include "core/loader/loader.h" 18#include "core/loader/loader.h"
18#include "core/settings.h"
19#include "core/telemetry_session.h" 19#include "core/telemetry_session.h"
20 20
21#ifdef ENABLE_WEB_SERVICE 21#ifdef ENABLE_WEB_SERVICE
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 38ab31898..c3cfe7efc 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -9,8 +9,6 @@ add_library(input_common STATIC
9 motion_from_button.h 9 motion_from_button.h
10 motion_input.cpp 10 motion_input.cpp
11 motion_input.h 11 motion_input.h
12 settings.cpp
13 settings.h
14 touch_from_button.cpp 12 touch_from_button.cpp
15 touch_from_button.h 13 touch_from_button.h
16 gcadapter/gc_adapter.cpp 14 gcadapter/gc_adapter.cpp
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 770893687..f8ec179d0 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -7,7 +7,7 @@
7#include <cmath> 7#include <cmath>
8#include <thread> 8#include <thread>
9#include "common/math_util.h" 9#include "common/math_util.h"
10#include "core/settings.h" 10#include "common/settings.h"
11#include "input_common/analog_from_button.h" 11#include "input_common/analog_from_button.h"
12 12
13namespace InputCommon { 13namespace InputCommon {
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index d80195c82..ec3167bea 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -16,8 +16,8 @@
16 16
17#include "common/logging/log.h" 17#include "common/logging/log.h"
18#include "common/param_package.h" 18#include "common/param_package.h"
19#include "common/settings_input.h"
19#include "input_common/gcadapter/gc_adapter.h" 20#include "input_common/gcadapter/gc_adapter.h"
20#include "input_common/settings.h"
21 21
22namespace GCAdapter { 22namespace GCAdapter {
23 23
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index 329e416c7..fff1c6b45 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/settings.h" 5#include "common/settings.h"
6#include "input_common/mouse/mouse_input.h" 6#include "input_common/mouse/mouse_input.h"
7 7
8namespace MouseInput { 8namespace MouseInput {
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 0e1db54fb..d96104a4e 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -5,8 +5,8 @@
5#include <mutex> 5#include <mutex>
6#include <utility> 6#include <utility>
7 7
8#include "common/settings.h"
8#include "common/threadsafe_queue.h" 9#include "common/threadsafe_queue.h"
9#include "core/settings.h"
10#include "input_common/mouse/mouse_input.h" 10#include "input_common/mouse/mouse_input.h"
11#include "input_common/mouse/mouse_poller.h" 11#include "input_common/mouse/mouse_poller.h"
12 12
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index f67de37e3..9418e78fa 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -20,11 +20,11 @@
20#include <SDL.h> 20#include <SDL.h>
21#include "common/logging/log.h" 21#include "common/logging/log.h"
22#include "common/param_package.h" 22#include "common/param_package.h"
23#include "common/settings_input.h"
23#include "common/threadsafe_queue.h" 24#include "common/threadsafe_queue.h"
24#include "core/frontend/input.h" 25#include "core/frontend/input.h"
25#include "input_common/motion_input.h" 26#include "input_common/motion_input.h"
26#include "input_common/sdl/sdl_impl.h" 27#include "input_common/sdl/sdl_impl.h"
27#include "input_common/settings.h"
28 28
29namespace InputCommon::SDL { 29namespace InputCommon::SDL {
30 30
@@ -761,7 +761,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
761 for (const auto& joystick : value) { 761 for (const auto& joystick : value) {
762 if (auto* const controller = joystick->GetSDLGameController()) { 762 if (auto* const controller = joystick->GetSDLGameController()) {
763 std::string name = 763 std::string name =
764 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); 764 fmt::format("{} {}", GetControllerName(controller), joystick->GetPort());
765 devices.emplace_back(Common::ParamPackage{ 765 devices.emplace_back(Common::ParamPackage{
766 {"class", "sdl"}, 766 {"class", "sdl"},
767 {"display", std::move(name)}, 767 {"display", std::move(name)},
@@ -782,6 +782,17 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
782 return devices; 782 return devices;
783} 783}
784 784
785std::string SDLState::GetControllerName(SDL_GameController* controller) const {
786 switch (SDL_GameControllerGetType(controller)) {
787 case SDL_CONTROLLER_TYPE_XBOX360:
788 return "XBox 360 Controller";
789 case SDL_CONTROLLER_TYPE_XBOXONE:
790 return "XBox One Controller";
791 default:
792 return SDL_GameControllerName(controller);
793 }
794}
795
785namespace { 796namespace {
786Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, 797Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
787 float value = 0.1f) { 798 float value = 0.1f) {
@@ -930,16 +941,19 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa
930 return {}; 941 return {};
931 } 942 }
932 943
944 const bool invert =
945 SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
946
933 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. 947 // This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
934 // We will add those afterwards 948 // We will add those afterwards
935 // This list also excludes Screenshot since theres not really a mapping for that 949 // This list also excludes Screenshot since theres not really a mapping for that
936 using ButtonBindings = 950 using ButtonBindings =
937 std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; 951 std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>;
938 static constexpr ButtonBindings switch_to_sdl_button{{ 952 const ButtonBindings switch_to_sdl_button{{
939 {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, 953 {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A},
940 {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, 954 {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B},
941 {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, 955 {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X},
942 {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, 956 {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y},
943 {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, 957 {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
944 {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, 958 {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
945 {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, 959 {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index 08044b00d..8b7363f56 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -14,6 +14,7 @@
14#include "input_common/sdl/sdl.h" 14#include "input_common/sdl/sdl.h"
15 15
16union SDL_Event; 16union SDL_Event;
17using SDL_GameController = struct _SDL_GameController;
17using SDL_Joystick = struct _SDL_Joystick; 18using SDL_Joystick = struct _SDL_Joystick;
18using SDL_JoystickID = s32; 19using SDL_JoystickID = s32;
19 20
@@ -64,6 +65,9 @@ private:
64 /// Needs to be called before SDL_QuitSubSystem. 65 /// Needs to be called before SDL_QuitSubSystem.
65 void CloseJoysticks(); 66 void CloseJoysticks();
66 67
68 /// Returns a custom name for specific controllers because the default name is not correct
69 std::string GetControllerName(SDL_GameController* controller) const;
70
67 // Set to true if SDL supports game controller subsystem 71 // Set to true if SDL supports game controller subsystem
68 bool has_gamecontroller = false; 72 bool has_gamecontroller = false;
69 73
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp
index ffbe4f2ed..e94ba197b 100644
--- a/src/input_common/touch_from_button.cpp
+++ b/src/input_common/touch_from_button.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
5#include "core/frontend/framebuffer_layout.h" 6#include "core/frontend/framebuffer_layout.h"
6#include "core/settings.h"
7#include "input_common/touch_from_button.h" 7#include "input_common/touch_from_button.h"
8 8
9namespace InputCommon { 9namespace InputCommon {
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index df73f9ff7..8a38a380d 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -9,7 +9,7 @@
9#include <thread> 9#include <thread>
10#include <boost/asio.hpp> 10#include <boost/asio.hpp>
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "core/settings.h" 12#include "common/settings.h"
13#include "input_common/udp/client.h" 13#include "input_common/udp/client.h"
14#include "input_common/udp/protocol.h" 14#include "input_common/udp/protocol.h"
15 15
@@ -27,11 +27,9 @@ class Socket {
27public: 27public:
28 using clock = std::chrono::system_clock; 28 using clock = std::chrono::system_clock;
29 29
30 explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, 30 explicit Socket(const std::string& host, u16 port, SocketCallback callback_)
31 SocketCallback callback_)
32 : callback(std::move(callback_)), timer(io_service), 31 : callback(std::move(callback_)), timer(io_service),
33 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()), 32 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) {
34 pad_index(pad_index_) {
35 boost::system::error_code ec{}; 33 boost::system::error_code ec{};
36 auto ipv4 = boost::asio::ip::make_address_v4(host, ec); 34 auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
37 if (ec.value() != boost::system::errc::success) { 35 if (ec.value() != boost::system::errc::success) {
@@ -99,15 +97,15 @@ private:
99 void HandleSend(const boost::system::error_code&) { 97 void HandleSend(const boost::system::error_code&) {
100 boost::system::error_code _ignored{}; 98 boost::system::error_code _ignored{};
101 // Send a request for getting port info for the pad 99 // Send a request for getting port info for the pad
102 const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; 100 const Request::PortInfo port_info{4, {0, 1, 2, 3}};
103 const auto port_message = Request::Create(port_info, client_id); 101 const auto port_message = Request::Create(port_info, client_id);
104 std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); 102 std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
105 socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); 103 socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
106 104
107 // Send a request for getting pad data for the pad 105 // Send a request for getting pad data for the pad
108 const Request::PadData pad_data{ 106 const Request::PadData pad_data{
109 Request::PadData::Flags::Id, 107 Request::PadData::Flags::AllPorts,
110 static_cast<u8>(pad_index), 108 0,
111 EMPTY_MAC_ADDRESS, 109 EMPTY_MAC_ADDRESS,
112 }; 110 };
113 const auto pad_message = Request::Create(pad_data, client_id); 111 const auto pad_message = Request::Create(pad_data, client_id);
@@ -122,7 +120,6 @@ private:
122 udp::socket socket; 120 udp::socket socket;
123 121
124 const u32 client_id; 122 const u32 client_id;
125 std::size_t pad_index{};
126 123
127 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); 124 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
128 static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); 125 static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
@@ -150,34 +147,32 @@ Client::~Client() {
150 Reset(); 147 Reset();
151} 148}
152 149
153Client::ClientData::ClientData() = default; 150Client::ClientConnection::ClientConnection() = default;
154 151
155Client::ClientData::~ClientData() = default; 152Client::ClientConnection::~ClientConnection() = default;
156 153
157std::vector<Common::ParamPackage> Client::GetInputDevices() const { 154std::vector<Common::ParamPackage> Client::GetInputDevices() const {
158 std::vector<Common::ParamPackage> devices; 155 std::vector<Common::ParamPackage> devices;
159 for (std::size_t client = 0; client < clients.size(); client++) { 156 for (std::size_t pad = 0; pad < pads.size(); pad++) {
160 if (!DeviceConnected(client)) { 157 if (!DeviceConnected(pad)) {
161 continue; 158 continue;
162 } 159 }
163 std::string name = fmt::format("UDP Controller {}", client); 160 std::string name = fmt::format("UDP Controller {}", pad);
164 devices.emplace_back(Common::ParamPackage{ 161 devices.emplace_back(Common::ParamPackage{
165 {"class", "cemuhookudp"}, 162 {"class", "cemuhookudp"},
166 {"display", std::move(name)}, 163 {"display", std::move(name)},
167 {"port", std::to_string(client)}, 164 {"port", std::to_string(pad)},
168 }); 165 });
169 } 166 }
170 return devices; 167 return devices;
171} 168}
172 169
173bool Client::DeviceConnected(std::size_t client) const { 170bool Client::DeviceConnected(std::size_t pad) const {
174 // Use last timestamp to detect if the socket has stopped sending data 171 // Use last timestamp to detect if the socket has stopped sending data
175 const auto now = std::chrono::steady_clock::now(); 172 const auto now = std::chrono::steady_clock::now();
176 const auto time_difference = 173 const auto time_difference = static_cast<u64>(
177 static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>( 174 std::chrono::duration_cast<std::chrono::milliseconds>(now - pads[pad].last_update).count());
178 now - clients[client].last_motion_update) 175 return time_difference < 1000 && pads[pad].connected;
179 .count());
180 return time_difference < 1000 && clients[client].active == 1;
181} 176}
182 177
183void Client::ReloadSockets() { 178void Client::ReloadSockets() {
@@ -202,25 +197,21 @@ void Client::ReloadSockets() {
202 continue; 197 continue;
203 } 198 }
204 199
205 for (std::size_t pad = 0; pad < 4; ++pad) { 200 const std::size_t client_number = GetClientNumber(udp_input_address, udp_input_port);
206 const std::size_t client_number = 201 if (client_number != MAX_UDP_CLIENTS) {
207 GetClientNumber(udp_input_address, udp_input_port, pad); 202 LOG_ERROR(Input, "Duplicated UDP servers found");
208 if (client_number != MAX_UDP_CLIENTS) { 203 continue;
209 LOG_ERROR(Input, "Duplicated UDP servers found");
210 continue;
211 }
212 StartCommunication(client++, udp_input_address, udp_input_port, pad);
213 } 204 }
205 StartCommunication(client++, udp_input_address, udp_input_port);
214 } 206 }
215} 207}
216 208
217std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const { 209std::size_t Client::GetClientNumber(std::string_view host, u16 port) const {
218 for (std::size_t client = 0; client < clients.size(); client++) { 210 for (std::size_t client = 0; client < clients.size(); client++) {
219 if (clients[client].active == -1) { 211 if (clients[client].active == -1) {
220 continue; 212 continue;
221 } 213 }
222 if (clients[client].host == host && clients[client].port == port && 214 if (clients[client].host == host && clients[client].port == port) {
223 clients[client].pad_index == pad) {
224 return client; 215 return client;
225 } 216 }
226 } 217 }
@@ -236,69 +227,75 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) {
236} 227}
237 228
238void Client::OnPadData(Response::PadData data, std::size_t client) { 229void Client::OnPadData(Response::PadData data, std::size_t client) {
239 // Accept packets only for the correct pad 230 const std::size_t pad_index = (client * PADS_PER_CLIENT) + data.info.id;
240 if (static_cast<u8>(clients[client].pad_index) != data.info.id) { 231
232 if (pad_index >= pads.size()) {
233 LOG_ERROR(Input, "Invalid pad id {}", data.info.id);
241 return; 234 return;
242 } 235 }
243 236
244 LOG_TRACE(Input, "PadData packet received"); 237 LOG_TRACE(Input, "PadData packet received");
245 if (data.packet_counter == clients[client].packet_sequence) { 238 if (data.packet_counter == pads[pad_index].packet_sequence) {
246 LOG_WARNING( 239 LOG_WARNING(
247 Input, 240 Input,
248 "PadData packet dropped because its stale info. Current count: {} Packet count: {}", 241 "PadData packet dropped because its stale info. Current count: {} Packet count: {}",
249 clients[client].packet_sequence, data.packet_counter); 242 pads[pad_index].packet_sequence, data.packet_counter);
243 pads[pad_index].connected = false;
250 return; 244 return;
251 } 245 }
252 clients[client].active = static_cast<s8>(data.info.is_pad_active); 246
253 clients[client].packet_sequence = data.packet_counter; 247 clients[client].active = 1;
248 pads[pad_index].connected = true;
249 pads[pad_index].packet_sequence = data.packet_counter;
250
254 const auto now = std::chrono::steady_clock::now(); 251 const auto now = std::chrono::steady_clock::now();
255 const auto time_difference = 252 const auto time_difference = static_cast<u64>(
256 static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( 253 std::chrono::duration_cast<std::chrono::microseconds>(now - pads[pad_index].last_update)
257 now - clients[client].last_motion_update) 254 .count());
258 .count()); 255 pads[pad_index].last_update = now;
259 clients[client].last_motion_update = now; 256
260 const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; 257 const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
261 clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); 258 pads[pad_index].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
262 // Gyroscope values are not it the correct scale from better joy. 259 // Gyroscope values are not it the correct scale from better joy.
263 // Dividing by 312 allows us to make one full turn = 1 turn 260 // Dividing by 312 allows us to make one full turn = 1 turn
264 // This must be a configurable valued called sensitivity 261 // This must be a configurable valued called sensitivity
265 clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f); 262 pads[pad_index].motion.SetGyroscope(raw_gyroscope / 312.0f);
266 clients[client].motion.UpdateRotation(time_difference); 263 pads[pad_index].motion.UpdateRotation(time_difference);
267 clients[client].motion.UpdateOrientation(time_difference); 264 pads[pad_index].motion.UpdateOrientation(time_difference);
268 265
269 { 266 {
270 std::lock_guard guard(clients[client].status.update_mutex); 267 std::lock_guard guard(pads[pad_index].status.update_mutex);
271 clients[client].status.motion_status = clients[client].motion.GetMotion(); 268 pads[pad_index].status.motion_status = pads[pad_index].motion.GetMotion();
272 269
273 for (std::size_t id = 0; id < data.touch.size(); ++id) { 270 for (std::size_t id = 0; id < data.touch.size(); ++id) {
274 UpdateTouchInput(data.touch[id], client, id); 271 UpdateTouchInput(data.touch[id], client, id);
275 } 272 }
276 273
277 if (configuring) { 274 if (configuring) {
278 const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); 275 const Common::Vec3f gyroscope = pads[pad_index].motion.GetGyroscope();
279 const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); 276 const Common::Vec3f accelerometer = pads[pad_index].motion.GetAcceleration();
280 UpdateYuzuSettings(client, accelerometer, gyroscope); 277 UpdateYuzuSettings(client, data.info.id, accelerometer, gyroscope);
281 } 278 }
282 } 279 }
283} 280}
284 281
285void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, 282void Client::StartCommunication(std::size_t client, const std::string& host, u16 port) {
286 std::size_t pad_index) {
287 SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, 283 SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
288 [this](Response::PortInfo info) { OnPortInfo(info); }, 284 [this](Response::PortInfo info) { OnPortInfo(info); },
289 [this, client](Response::PadData data) { OnPadData(data, client); }}; 285 [this, client](Response::PadData data) { OnPadData(data, client); }};
290 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port, 286 LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
291 pad_index);
292 clients[client].host = host; 287 clients[client].host = host;
293 clients[client].port = port; 288 clients[client].port = port;
294 clients[client].pad_index = pad_index;
295 clients[client].active = 0; 289 clients[client].active = 0;
296 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback); 290 clients[client].socket = std::make_unique<Socket>(host, port, callback);
297 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; 291 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
292
298 // Set motion parameters 293 // Set motion parameters
299 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode 294 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
300 // Real HW values are unknown, 0.0001 is an approximate to Standard 295 // Real HW values are unknown, 0.0001 is an approximate to Standard
301 clients[client].motion.SetGyroThreshold(0.0001f); 296 for (std::size_t pad = 0; pad < PADS_PER_CLIENT; pad++) {
297 pads[client * PADS_PER_CLIENT + pad].motion.SetGyroThreshold(0.0001f);
298 }
302} 299}
303 300
304void Client::Reset() { 301void Client::Reset() {
@@ -311,8 +308,8 @@ void Client::Reset() {
311 } 308 }
312} 309}
313 310
314void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 311void Client::UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
315 const Common::Vec3<float>& gyro) { 312 const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro) {
316 if (gyro.Length() > 0.2f) { 313 if (gyro.Length() > 0.2f) {
317 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, 314 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client,
318 gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); 315 gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]);
@@ -320,7 +317,7 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a
320 UDPPadStatus pad{ 317 UDPPadStatus pad{
321 .host = clients[client].host, 318 .host = clients[client].host,
322 .port = clients[client].port, 319 .port = clients[client].port,
323 .pad_index = clients[client].pad_index, 320 .pad_index = pad_index,
324 }; 321 };
325 for (std::size_t i = 0; i < 3; ++i) { 322 for (std::size_t i = 0; i < 3; ++i) {
326 if (gyro[i] > 5.0f || gyro[i] < -5.0f) { 323 if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
@@ -391,19 +388,19 @@ void Client::EndConfiguration() {
391} 388}
392 389
393DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { 390DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) {
394 const std::size_t client_number = GetClientNumber(host, port, pad); 391 const std::size_t client_number = GetClientNumber(host, port);
395 if (client_number == MAX_UDP_CLIENTS) { 392 if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
396 return clients[0].status; 393 return pads[0].status;
397 } 394 }
398 return clients[client_number].status; 395 return pads[(client_number * PADS_PER_CLIENT) + pad].status;
399} 396}
400 397
401const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { 398const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const {
402 const std::size_t client_number = GetClientNumber(host, port, pad); 399 const std::size_t client_number = GetClientNumber(host, port);
403 if (client_number == MAX_UDP_CLIENTS) { 400 if (client_number == MAX_UDP_CLIENTS || pad >= PADS_PER_CLIENT) {
404 return clients[0].status; 401 return pads[0].status;
405 } 402 }
406 return clients[client_number].status; 403 return pads[(client_number * PADS_PER_CLIENT) + pad].status;
407} 404}
408 405
409Input::TouchStatus& Client::GetTouchState() { 406Input::TouchStatus& Client::GetTouchState() {
@@ -422,7 +419,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
422 return pad_queue; 419 return pad_queue;
423} 420}
424 421
425void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, 422void TestCommunication(const std::string& host, u16 port,
426 const std::function<void()>& success_callback, 423 const std::function<void()>& success_callback,
427 const std::function<void()>& failure_callback) { 424 const std::function<void()>& failure_callback) {
428 std::thread([=] { 425 std::thread([=] {
@@ -432,9 +429,10 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
432 .port_info = [](Response::PortInfo) {}, 429 .port_info = [](Response::PortInfo) {},
433 .pad_data = [&](Response::PadData) { success_event.Set(); }, 430 .pad_data = [&](Response::PadData) { success_event.Set(); },
434 }; 431 };
435 Socket socket{host, port, pad_index, std::move(callback)}; 432 Socket socket{host, port, std::move(callback)};
436 std::thread worker_thread{SocketLoop, &socket}; 433 std::thread worker_thread{SocketLoop, &socket};
437 const bool result = success_event.WaitFor(std::chrono::seconds(5)); 434 const bool result =
435 success_event.WaitUntil(std::chrono::steady_clock::now() + std::chrono::seconds(10));
438 socket.Stop(); 436 socket.Stop();
439 worker_thread.join(); 437 worker_thread.join();
440 if (result) { 438 if (result) {
@@ -446,8 +444,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
446} 444}
447 445
448CalibrationConfigurationJob::CalibrationConfigurationJob( 446CalibrationConfigurationJob::CalibrationConfigurationJob(
449 const std::string& host, u16 port, std::size_t pad_index, 447 const std::string& host, u16 port, std::function<void(Status)> status_callback,
450 std::function<void(Status)> status_callback,
451 std::function<void(u16, u16, u16, u16)> data_callback) { 448 std::function<void(u16, u16, u16, u16)> data_callback) {
452 449
453 std::thread([=, this] { 450 std::thread([=, this] {
@@ -491,7 +488,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
491 complete_event.Set(); 488 complete_event.Set();
492 } 489 }
493 }}; 490 }};
494 Socket socket{host, port, pad_index, std::move(callback)}; 491 Socket socket{host, port, std::move(callback)};
495 std::thread worker_thread{SocketLoop, &socket}; 492 std::thread worker_thread{SocketLoop, &socket};
496 complete_event.Wait(); 493 complete_event.Wait();
497 socket.Stop(); 494 socket.Stop();
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h
index e9e438e88..a11ea3068 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/udp/client.h
@@ -84,7 +84,7 @@ public:
84 84
85 std::vector<Common::ParamPackage> GetInputDevices() const; 85 std::vector<Common::ParamPackage> GetInputDevices() const;
86 86
87 bool DeviceConnected(std::size_t client) const; 87 bool DeviceConnected(std::size_t pad) const;
88 void ReloadSockets(); 88 void ReloadSockets();
89 89
90 Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); 90 Common::SPSCQueue<UDPPadStatus>& GetPadQueue();
@@ -97,38 +97,40 @@ public:
97 const Input::TouchStatus& GetTouchState() const; 97 const Input::TouchStatus& GetTouchState() const;
98 98
99private: 99private:
100 struct ClientData { 100 struct PadData {
101 ClientData();
102 ~ClientData();
103
104 std::string host{"127.0.0.1"};
105 u16 port{26760};
106 std::size_t pad_index{}; 101 std::size_t pad_index{};
107 std::unique_ptr<Socket> socket; 102 bool connected{};
108 DeviceStatus status; 103 DeviceStatus status;
109 std::thread thread;
110 u64 packet_sequence{}; 104 u64 packet_sequence{};
111 s8 active{-1};
112 105
113 // Realtime values 106 // Realtime values
114 // motion is initalized with PID values for drift correction on joycons 107 // motion is initalized with PID values for drift correction on joycons
115 InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; 108 InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
116 std::chrono::time_point<std::chrono::steady_clock> last_motion_update; 109 std::chrono::time_point<std::chrono::steady_clock> last_update;
110 };
111
112 struct ClientConnection {
113 ClientConnection();
114 ~ClientConnection();
115 std::string host{"127.0.0.1"};
116 u16 port{26760};
117 s8 active{-1};
118 std::unique_ptr<Socket> socket;
119 std::thread thread;
117 }; 120 };
118 121
119 // For shutting down, clear all data, join all threads, release usb 122 // For shutting down, clear all data, join all threads, release usb
120 void Reset(); 123 void Reset();
121 124
122 // Translates configuration to client number 125 // Translates configuration to client number
123 std::size_t GetClientNumber(std::string_view host, u16 port, std::size_t pad) const; 126 std::size_t GetClientNumber(std::string_view host, u16 port) const;
124 127
125 void OnVersion(Response::Version); 128 void OnVersion(Response::Version);
126 void OnPortInfo(Response::PortInfo); 129 void OnPortInfo(Response::PortInfo);
127 void OnPadData(Response::PadData, std::size_t client); 130 void OnPadData(Response::PadData, std::size_t client);
128 void StartCommunication(std::size_t client, const std::string& host, u16 port, 131 void StartCommunication(std::size_t client, const std::string& host, u16 port);
129 std::size_t pad_index); 132 void UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
130 void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 133 const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro);
131 const Common::Vec3<float>& gyro);
132 134
133 // Returns an unused finger id, if there is no fingers available std::nullopt will be 135 // Returns an unused finger id, if there is no fingers available std::nullopt will be
134 // returned 136 // returned
@@ -140,10 +142,12 @@ private:
140 bool configuring = false; 142 bool configuring = false;
141 143
142 // Allocate clients for 8 udp servers 144 // Allocate clients for 8 udp servers
143 static constexpr std::size_t MAX_UDP_CLIENTS = 4 * 8; 145 static constexpr std::size_t MAX_UDP_CLIENTS = 8;
146 static constexpr std::size_t PADS_PER_CLIENT = 4;
144 // Each client can have up 2 touch inputs 147 // Each client can have up 2 touch inputs
145 static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; 148 static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2;
146 std::array<ClientData, MAX_UDP_CLIENTS> clients{}; 149 std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{};
150 std::array<ClientConnection, MAX_UDP_CLIENTS> clients{};
147 Common::SPSCQueue<UDPPadStatus> pad_queue{}; 151 Common::SPSCQueue<UDPPadStatus> pad_queue{};
148 Input::TouchStatus touch_status{}; 152 Input::TouchStatus touch_status{};
149 std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; 153 std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{};
@@ -164,7 +168,7 @@ public:
164 * @param status_callback Callback for job status updates 168 * @param status_callback Callback for job status updates
165 * @param data_callback Called when calibration data is ready 169 * @param data_callback Called when calibration data is ready
166 */ 170 */
167 explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, 171 explicit CalibrationConfigurationJob(const std::string& host, u16 port,
168 std::function<void(Status)> status_callback, 172 std::function<void(Status)> status_callback,
169 std::function<void(u16, u16, u16, u16)> data_callback); 173 std::function<void(u16, u16, u16, u16)> data_callback);
170 ~CalibrationConfigurationJob(); 174 ~CalibrationConfigurationJob();
@@ -174,7 +178,7 @@ private:
174 Common::Event complete_event; 178 Common::Event complete_event;
175}; 179};
176 180
177void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, 181void TestCommunication(const std::string& host, u16 port,
178 const std::function<void()>& success_callback, 182 const std::function<void()>& success_callback,
179 const std::function<void()>& failure_callback); 183 const std::function<void()>& failure_callback);
180 184
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 9b931976a..47190c464 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -236,7 +236,6 @@ add_library(video_core STATIC
236 texture_cache/types.h 236 texture_cache/types.h
237 texture_cache/util.cpp 237 texture_cache/util.cpp
238 texture_cache/util.h 238 texture_cache/util.h
239 textures/astc.cpp
240 textures/astc.h 239 textures/astc.h
241 textures/decoders.cpp 240 textures/decoders.cpp
242 textures/decoders.h 241 textures/decoders.h
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 4de1e37e5..32dcbd693 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -20,8 +20,8 @@
20#include "common/div_ceil.h" 20#include "common/div_ceil.h"
21#include "common/microprofile.h" 21#include "common/microprofile.h"
22#include "common/scope_exit.h" 22#include "common/scope_exit.h"
23#include "common/settings.h"
23#include "core/memory.h" 24#include "core/memory.h"
24#include "core/settings.h"
25#include "video_core/buffer_cache/buffer_base.h" 25#include "video_core/buffer_cache/buffer_base.h"
26#include "video_core/delayed_destruction_ring.h" 26#include "video_core/delayed_destruction_ring.h"
27#include "video_core/dirty_flags.h" 27#include "video_core/dirty_flags.h"
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp
index 59e586695..29bb31418 100644
--- a/src/video_core/command_classes/codecs/vp9.cpp
+++ b/src/video_core/command_classes/codecs/vp9.cpp
@@ -2,8 +2,9 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> // for std::memcpy 5#include <algorithm> // for std::copy
6#include <numeric> 6#include <numeric>
7#include "common/assert.h"
7#include "video_core/command_classes/codecs/vp9.h" 8#include "video_core/command_classes/codecs/vp9.h"
8#include "video_core/gpu.h" 9#include "video_core/gpu.h"
9#include "video_core/memory_manager.h" 10#include "video_core/memory_manager.h"
@@ -362,7 +363,8 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state)
362 // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following 363 // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following
363 // order: last, golden, altref, current. It may be worthwhile to track the updates done here 364 // order: last, golden, altref, current. It may be worthwhile to track the updates done here
364 // to avoid buffering frame data needed for reference frame updating in the header composition. 365 // to avoid buffering frame data needed for reference frame updating in the header composition.
365 std::memcpy(vp9_info.frame_offsets.data(), state.surface_luma_offset.data(), 4 * sizeof(u64)); 366 std::copy(state.surface_luma_offset.begin(), state.surface_luma_offset.begin() + 4,
367 vp9_info.frame_offsets.begin());
366 368
367 return vp9_info; 369 return vp9_info;
368} 370}
@@ -821,11 +823,11 @@ const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters
821 823
822 // Write headers and frame to buffer 824 // Write headers and frame to buffer
823 frame.resize(uncompressed_header.size() + compressed_header.size() + bitstream.size()); 825 frame.resize(uncompressed_header.size() + compressed_header.size() + bitstream.size());
824 std::memcpy(frame.data(), uncompressed_header.data(), uncompressed_header.size()); 826 std::copy(uncompressed_header.begin(), uncompressed_header.end(), frame.begin());
825 std::memcpy(frame.data() + uncompressed_header.size(), compressed_header.data(), 827 std::copy(compressed_header.begin(), compressed_header.end(),
826 compressed_header.size()); 828 frame.begin() + uncompressed_header.size());
827 std::memcpy(frame.data() + uncompressed_header.size() + compressed_header.size(), 829 std::copy(bitstream.begin(), bitstream.end(),
828 bitstream.data(), bitstream.size()); 830 frame.begin() + uncompressed_header.size() + compressed_header.size());
829 831
830 // keep track of frame number 832 // keep track of frame number
831 current_frame_number++; 833 current_frame_number++;
diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h
index 18a9db7e6..c7ffd68c5 100644
--- a/src/video_core/engines/engine_interface.h
+++ b/src/video_core/engines/engine_interface.h
@@ -4,13 +4,14 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <type_traits>
8#include "common/common_types.h" 7#include "common/common_types.h"
9 8
10namespace Tegra::Engines { 9namespace Tegra::Engines {
11 10
12class EngineInterface { 11class EngineInterface {
13public: 12public:
13 virtual ~EngineInterface() = default;
14
14 /// Write the value to the register identified by method. 15 /// Write the value to the register identified by method.
15 virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; 16 virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0;
16 17
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index c808a577d..a4170ffff 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -35,7 +35,7 @@ namespace Tegra::Engines {
35class Fermi2D final : public EngineInterface { 35class Fermi2D final : public EngineInterface {
36public: 36public:
37 explicit Fermi2D(); 37 explicit Fermi2D();
38 ~Fermi2D(); 38 ~Fermi2D() override;
39 39
40 /// Binds a rasterizer to this engine. 40 /// Binds a rasterizer to this engine.
41 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); 41 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index 19808a5c6..0d8ea09a9 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -36,7 +36,7 @@ namespace Tegra::Engines {
36class KeplerMemory final : public EngineInterface { 36class KeplerMemory final : public EngineInterface {
37public: 37public:
38 explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); 38 explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager);
39 ~KeplerMemory(); 39 ~KeplerMemory() override;
40 40
41 /// Write the value to the register identified by method. 41 /// Write the value to the register identified by method.
42 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; 42 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index a2f19559f..2ee980bab 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -4,8 +4,8 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/settings.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/settings.h"
9#include "video_core/engines/maxwell_3d.h" 9#include "video_core/engines/maxwell_3d.h"
10#include "video_core/engines/maxwell_dma.h" 10#include "video_core/engines/maxwell_dma.h"
11#include "video_core/memory_manager.h" 11#include "video_core/memory_manager.h"
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 3c59eeb13..c77f02a22 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -188,7 +188,7 @@ public:
188 static_assert(sizeof(RemapConst) == 12); 188 static_assert(sizeof(RemapConst) == 12);
189 189
190 explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); 190 explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_);
191 ~MaxwellDMA(); 191 ~MaxwellDMA() override;
192 192
193 /// Write the value to the register identified by method. 193 /// Write the value to the register identified by method.
194 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; 194 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 36c31fec2..7c42f1177 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -6,13 +6,13 @@
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/microprofile.h" 8#include "common/microprofile.h"
9#include "common/settings.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/core_timing_util.h" 12#include "core/core_timing_util.h"
12#include "core/frontend/emu_window.h" 13#include "core/frontend/emu_window.h"
13#include "core/hardware_interrupt_manager.h" 14#include "core/hardware_interrupt_manager.h"
14#include "core/memory.h" 15#include "core/memory.h"
15#include "core/settings.h"
16#include "video_core/engines/fermi_2d.h" 16#include "video_core/engines/fermi_2d.h"
17#include "video_core/engines/kepler_compute.h" 17#include "video_core/engines/kepler_compute.h"
18#include "video_core/engines/kepler_memory.h" 18#include "video_core/engines/kepler_memory.h"
@@ -519,8 +519,8 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const {
519 interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); 519 interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value);
520} 520}
521 521
522void GPU::WaitIdle() const { 522void GPU::ShutDown() {
523 gpu_thread.WaitIdle(); 523 gpu_thread.ShutDown();
524} 524}
525 525
526void GPU::OnCommandListEnd() { 526void GPU::OnCommandListEnd() {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index d40982a54..b1960ea86 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -219,8 +219,8 @@ public:
219 return *shader_notify; 219 return *shader_notify;
220 } 220 }
221 221
222 // Waits for the GPU to finish working 222 // Stops the GPU execution and waits for the GPU to finish working
223 void WaitIdle() const; 223 void ShutDown();
224 224
225 /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. 225 /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame.
226 void WaitFence(u32 syncpoint_id, u32 value); 226 void WaitFence(u32 syncpoint_id, u32 value);
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 99353f15f..cd1fbb9bf 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -5,10 +5,10 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8#include "common/settings.h"
8#include "common/thread.h" 9#include "common/thread.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/frontend/emu_window.h" 11#include "core/frontend/emu_window.h"
11#include "core/settings.h"
12#include "video_core/dma_pusher.h" 12#include "video_core/dma_pusher.h"
13#include "video_core/gpu.h" 13#include "video_core/gpu.h"
14#include "video_core/gpu_thread.h" 14#include "video_core/gpu_thread.h"
@@ -29,8 +29,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
29 system.RegisterHostThread(); 29 system.RegisterHostThread();
30 30
31 // Wait for first GPU command before acquiring the window context 31 // Wait for first GPU command before acquiring the window context
32 while (state.queue.Empty()) 32 state.queue.Wait();
33 ;
34 33
35 // If emulation was stopped during disk shader loading, abort before trying to acquire context 34 // If emulation was stopped during disk shader loading, abort before trying to acquire context
36 if (!state.is_running) { 35 if (!state.is_running) {
@@ -57,11 +56,17 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
57 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { 56 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
58 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); 57 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
59 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { 58 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
60 return; 59 ASSERT(state.is_running == false);
61 } else { 60 } else {
62 UNREACHABLE(); 61 UNREACHABLE();
63 } 62 }
64 state.signaled_fence.store(next.fence); 63 state.signaled_fence.store(next.fence);
64 if (next.block) {
65 // We have to lock the write_lock to ensure that the condition_variable wait not get a
66 // race between the check and the lock itself.
67 std::lock_guard lk(state.write_lock);
68 state.cv.notify_all();
69 }
65 } 70 }
66} 71}
67 72
@@ -69,13 +74,7 @@ ThreadManager::ThreadManager(Core::System& system_, bool is_async_)
69 : system{system_}, is_async{is_async_} {} 74 : system{system_}, is_async{is_async_} {}
70 75
71ThreadManager::~ThreadManager() { 76ThreadManager::~ThreadManager() {
72 if (!thread.joinable()) { 77 ShutDown();
73 return;
74 }
75
76 // Notify GPU thread that a shutdown is pending
77 PushCommand(EndProcessingCommand());
78 thread.join();
79} 78}
80 79
81void ThreadManager::StartThread(VideoCore::RendererBase& renderer, 80void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
@@ -112,9 +111,8 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
112 case Settings::GPUAccuracy::Extreme: { 111 case Settings::GPUAccuracy::Extreme: {
113 auto& gpu = system.GPU(); 112 auto& gpu = system.GPU();
114 u64 fence = gpu.RequestFlush(addr, size); 113 u64 fence = gpu.RequestFlush(addr, size);
115 PushCommand(GPUTickCommand()); 114 PushCommand(GPUTickCommand(), true);
116 while (fence > gpu.CurrentFlushRequestFence()) { 115 ASSERT(fence <= gpu.CurrentFlushRequestFence());
117 }
118 break; 116 break;
119 } 117 }
120 default: 118 default:
@@ -131,23 +129,45 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
131 rasterizer->OnCPUWrite(addr, size); 129 rasterizer->OnCPUWrite(addr, size);
132} 130}
133 131
134void ThreadManager::WaitIdle() const { 132void ThreadManager::ShutDown() {
135 while (state.last_fence > state.signaled_fence.load(std::memory_order_relaxed) && 133 if (!state.is_running) {
136 system.IsPoweredOn()) { 134 return;
137 } 135 }
136
137 {
138 std::lock_guard lk(state.write_lock);
139 state.is_running = false;
140 state.cv.notify_all();
141 }
142
143 if (!thread.joinable()) {
144 return;
145 }
146
147 // Notify GPU thread that a shutdown is pending
148 PushCommand(EndProcessingCommand());
149 thread.join();
138} 150}
139 151
140void ThreadManager::OnCommandListEnd() { 152void ThreadManager::OnCommandListEnd() {
141 PushCommand(OnCommandListEndCommand()); 153 PushCommand(OnCommandListEndCommand());
142} 154}
143 155
144u64 ThreadManager::PushCommand(CommandData&& command_data) { 156u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) {
145 const u64 fence{++state.last_fence};
146 state.queue.Push(CommandDataContainer(std::move(command_data), fence));
147
148 if (!is_async) { 157 if (!is_async) {
149 // In synchronous GPU mode, block the caller until the command has executed 158 // In synchronous GPU mode, block the caller until the command has executed
150 WaitIdle(); 159 block = true;
160 }
161
162 std::unique_lock lk(state.write_lock);
163 const u64 fence{++state.last_fence};
164 state.queue.Push(CommandDataContainer(std::move(command_data), fence, block));
165
166 if (block) {
167 state.cv.wait(lk, [this, fence] {
168 return fence <= state.signaled_fence.load(std::memory_order_relaxed) ||
169 !state.is_running;
170 });
151 } 171 }
152 172
153 return fence; 173 return fence;
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 18269e51c..11a648f38 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -90,21 +90,24 @@ using CommandData =
90struct CommandDataContainer { 90struct CommandDataContainer {
91 CommandDataContainer() = default; 91 CommandDataContainer() = default;
92 92
93 explicit CommandDataContainer(CommandData&& data_, u64 next_fence_) 93 explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
94 : data{std::move(data_)}, fence{next_fence_} {} 94 : data{std::move(data_)}, fence{next_fence_}, block(block_) {}
95 95
96 CommandData data; 96 CommandData data;
97 u64 fence{}; 97 u64 fence{};
98 bool block{};
98}; 99};
99 100
100/// Struct used to synchronize the GPU thread 101/// Struct used to synchronize the GPU thread
101struct SynchState final { 102struct SynchState final {
102 std::atomic_bool is_running{true}; 103 std::atomic_bool is_running{true};
103 104
104 using CommandQueue = Common::MPSCQueue<CommandDataContainer>; 105 using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
106 std::mutex write_lock;
105 CommandQueue queue; 107 CommandQueue queue;
106 u64 last_fence{}; 108 u64 last_fence{};
107 std::atomic<u64> signaled_fence{}; 109 std::atomic<u64> signaled_fence{};
110 std::condition_variable cv;
108}; 111};
109 112
110/// Class used to manage the GPU thread 113/// Class used to manage the GPU thread
@@ -132,14 +135,14 @@ public:
132 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 135 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
133 void FlushAndInvalidateRegion(VAddr addr, u64 size); 136 void FlushAndInvalidateRegion(VAddr addr, u64 size);
134 137
135 // Wait until the gpu thread is idle. 138 // Stops the GPU execution and waits for the GPU to finish working
136 void WaitIdle() const; 139 void ShutDown();
137 140
138 void OnCommandListEnd(); 141 void OnCommandListEnd();
139 142
140private: 143private:
141 /// Pushes a command to be executed by the GPU thread 144 /// Pushes a command to be executed by the GPU thread
142 u64 PushCommand(CommandData&& command_data); 145 u64 PushCommand(CommandData&& command_data, bool block = false);
143 146
144 Core::System& system; 147 Core::System& system;
145 const bool is_async; 148 const bool is_async;
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index 3494318ca..2208e1922 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -1,4 +1,5 @@
1set(SHADER_FILES 1set(SHADER_FILES
2 astc_decoder.comp
2 block_linear_unswizzle_2d.comp 3 block_linear_unswizzle_2d.comp
3 block_linear_unswizzle_3d.comp 4 block_linear_unswizzle_3d.comp
4 convert_depth_to_float.frag 5 convert_depth_to_float.frag
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake
index c0fc49768..1b4bc6103 100644
--- a/src/video_core/host_shaders/StringShaderHeader.cmake
+++ b/src/video_core/host_shaders/StringShaderHeader.cmake
@@ -6,7 +6,27 @@ get_filename_component(CONTENTS_NAME ${SOURCE_FILE} NAME)
6string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) 6string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME})
7string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) 7string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME)
8 8
9file(READ ${SOURCE_FILE} CONTENTS) 9FILE(READ ${SOURCE_FILE} line_contents)
10
11# Replace double quotes with single quotes,
12# as double quotes will be used to wrap the lines
13STRING(REGEX REPLACE "\"" "'" line_contents "${line_contents}")
14
15# CMake separates list elements with semicolons, but semicolons
16# are used extensively in the shader code.
17# Replace with a temporary marker, to be reverted later.
18STRING(REGEX REPLACE ";" "{{SEMICOLON}}" line_contents "${line_contents}")
19
20# Make every line an individual element in the CMake list.
21STRING(REGEX REPLACE "\n" ";" line_contents "${line_contents}")
22
23# Build the shader string, wrapping each line in double quotes.
24foreach(line IN LISTS line_contents)
25 string(CONCAT CONTENTS "${CONTENTS}" \"${line}\\n\"\n)
26endforeach()
27
28# Revert the original semicolons in the source.
29STRING(REGEX REPLACE "{{SEMICOLON}}" ";" CONTENTS "${CONTENTS}")
10 30
11get_filename_component(OUTPUT_DIR ${HEADER_FILE} DIRECTORY) 31get_filename_component(OUTPUT_DIR ${HEADER_FILE} DIRECTORY)
12make_directory(${OUTPUT_DIR}) 32make_directory(${OUTPUT_DIR})
diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp
new file mode 100644
index 000000000..703e34587
--- /dev/null
+++ b/src/video_core/host_shaders/astc_decoder.comp
@@ -0,0 +1,1339 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#version 450
6
7#ifdef VULKAN
8
9#define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants {
10#define END_PUSH_CONSTANTS };
11#define UNIFORM(n)
12#define BINDING_INPUT_BUFFER 0
13#define BINDING_ENC_BUFFER 1
14#define BINDING_6_TO_8_BUFFER 2
15#define BINDING_7_TO_8_BUFFER 3
16#define BINDING_8_TO_8_BUFFER 4
17#define BINDING_BYTE_TO_16_BUFFER 5
18#define BINDING_SWIZZLE_BUFFER 6
19#define BINDING_OUTPUT_IMAGE 7
20
21#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
22
23#define BEGIN_PUSH_CONSTANTS
24#define END_PUSH_CONSTANTS
25#define UNIFORM(n) layout(location = n) uniform
26#define BINDING_SWIZZLE_BUFFER 0
27#define BINDING_INPUT_BUFFER 1
28#define BINDING_ENC_BUFFER 2
29#define BINDING_6_TO_8_BUFFER 3
30#define BINDING_7_TO_8_BUFFER 4
31#define BINDING_8_TO_8_BUFFER 5
32#define BINDING_BYTE_TO_16_BUFFER 6
33#define BINDING_OUTPUT_IMAGE 0
34
35#endif
36
37layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
38
39BEGIN_PUSH_CONSTANTS
40UNIFORM(1) uvec2 block_dims;
41
42UNIFORM(2) uint bytes_per_block_log2;
43UNIFORM(3) uint layer_stride;
44UNIFORM(4) uint block_size;
45UNIFORM(5) uint x_shift;
46UNIFORM(6) uint block_height;
47UNIFORM(7) uint block_height_mask;
48END_PUSH_CONSTANTS
49
50struct EncodingData {
51 uint encoding;
52 uint num_bits;
53 uint bit_value;
54 uint quint_trit_value;
55};
56
57struct TexelWeightParams {
58 uvec2 size;
59 uint max_weight;
60 bool dual_plane;
61 bool error_state;
62 bool void_extent_ldr;
63 bool void_extent_hdr;
64};
65
66// Swizzle data
67layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable {
68 uint swizzle_table[];
69};
70
71layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU32 {
72 uint astc_data[];
73};
74
75// ASTC Encodings data
76layout(binding = BINDING_ENC_BUFFER, std430) readonly buffer EncodingsValues {
77 EncodingData encoding_values[];
78};
79// ASTC Precompiled tables
80layout(binding = BINDING_6_TO_8_BUFFER, std430) readonly buffer REPLICATE_6_BIT_TO_8 {
81 uint REPLICATE_6_BIT_TO_8_TABLE[];
82};
83layout(binding = BINDING_7_TO_8_BUFFER, std430) readonly buffer REPLICATE_7_BIT_TO_8 {
84 uint REPLICATE_7_BIT_TO_8_TABLE[];
85};
86layout(binding = BINDING_8_TO_8_BUFFER, std430) readonly buffer REPLICATE_8_BIT_TO_8 {
87 uint REPLICATE_8_BIT_TO_8_TABLE[];
88};
89layout(binding = BINDING_BYTE_TO_16_BUFFER, std430) readonly buffer REPLICATE_BYTE_TO_16 {
90 uint REPLICATE_BYTE_TO_16_TABLE[];
91};
92
93layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly image2DArray dest_image;
94
95const uint GOB_SIZE_X = 64;
96const uint GOB_SIZE_Y = 8;
97const uint GOB_SIZE_Z = 1;
98const uint GOB_SIZE = GOB_SIZE_X * GOB_SIZE_Y * GOB_SIZE_Z;
99
100const uint GOB_SIZE_X_SHIFT = 6;
101const uint GOB_SIZE_Y_SHIFT = 3;
102const uint GOB_SIZE_Z_SHIFT = 0;
103const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT;
104
105const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1);
106
107const int BLOCK_SIZE_IN_BYTES = 16;
108
109const int BLOCK_INFO_ERROR = 0;
110const int BLOCK_INFO_VOID_EXTENT_HDR = 1;
111const int BLOCK_INFO_VOID_EXTENT_LDR = 2;
112const int BLOCK_INFO_NORMAL = 3;
113
114const int JUST_BITS = 0;
115const int QUINT = 1;
116const int TRIT = 2;
117
118// The following constants are expanded variants of the Replicate()
119// function calls corresponding to the following arguments:
120// value: index into the generated table
121// num_bits: the after "REPLICATE" in the table name. i.e. 4 is num_bits in REPLICATE_4.
122// to_bit: the integer after "TO_"
123const uint REPLICATE_BIT_TO_7_TABLE[2] = uint[](0, 127);
124const uint REPLICATE_1_BIT_TO_9_TABLE[2] = uint[](0, 511);
125
126const uint REPLICATE_1_BIT_TO_8_TABLE[2] = uint[](0, 255);
127const uint REPLICATE_2_BIT_TO_8_TABLE[4] = uint[](0, 85, 170, 255);
128const uint REPLICATE_3_BIT_TO_8_TABLE[8] = uint[](0, 36, 73, 109, 146, 182, 219, 255);
129const uint REPLICATE_4_BIT_TO_8_TABLE[16] =
130 uint[](0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255);
131const uint REPLICATE_5_BIT_TO_8_TABLE[32] =
132 uint[](0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165,
133 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255);
134const uint REPLICATE_1_BIT_TO_6_TABLE[2] = uint[](0, 63);
135const uint REPLICATE_2_BIT_TO_6_TABLE[4] = uint[](0, 21, 42, 63);
136const uint REPLICATE_3_BIT_TO_6_TABLE[8] = uint[](0, 9, 18, 27, 36, 45, 54, 63);
137const uint REPLICATE_4_BIT_TO_6_TABLE[16] =
138 uint[](0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 63);
139const uint REPLICATE_5_BIT_TO_6_TABLE[32] =
140 uint[](0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 33, 35, 37, 39, 41, 43, 45,
141 47, 49, 51, 53, 55, 57, 59, 61, 63);
142
143// Input ASTC texture globals
144uint current_index = 0;
145int bitsread = 0;
146uint total_bitsread = 0;
147uint local_buff[16];
148
149// Color data globals
150uint color_endpoint_data[16];
151int color_bitsread = 0;
152uint total_color_bitsread = 0;
153int color_index = 0;
154
155// Four values, two endpoints, four maximum paritions
156uint color_values[32];
157int colvals_index = 0;
158
159// Weight data globals
160uint texel_weight_data[16];
161int texel_bitsread = 0;
162uint total_texel_bitsread = 0;
163int texel_index = 0;
164
165bool texel_flag = false;
166
167// Global "vectors" to be pushed into when decoding
168EncodingData result_vector[100];
169int result_index = 0;
170
171EncodingData texel_vector[100];
172int texel_vector_index = 0;
173
174uint unquantized_texel_weights[2][144];
175
176uint SwizzleOffset(uvec2 pos) {
177 pos = pos & SWIZZLE_MASK;
178 return swizzle_table[pos.y * 64 + pos.x];
179}
180
181uint ReadTexel(uint offset) {
182 // extract the 8-bit value from the 32-bit packed data.
183 return bitfieldExtract(astc_data[offset / 4], int((offset * 8) & 24), 8);
184}
185
186// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)]
187// is the same as [(num_bits - 1):0] and repeats all the way down.
188uint Replicate(uint val, uint num_bits, uint to_bit) {
189 if (num_bits == 0 || to_bit == 0) {
190 return 0;
191 }
192 const uint v = val & uint((1 << num_bits) - 1);
193 uint res = v;
194 uint reslen = num_bits;
195 while (reslen < to_bit) {
196 uint comp = 0;
197 if (num_bits > to_bit - reslen) {
198 uint newshift = to_bit - reslen;
199 comp = num_bits - newshift;
200 num_bits = newshift;
201 }
202 res = uint(res << num_bits);
203 res = uint(res | (v >> comp));
204 reslen += num_bits;
205 }
206 return res;
207}
208
209uvec4 ReplicateByteTo16(uvec4 value) {
210 return uvec4(REPLICATE_BYTE_TO_16_TABLE[value.x], REPLICATE_BYTE_TO_16_TABLE[value.y],
211 REPLICATE_BYTE_TO_16_TABLE[value.z], REPLICATE_BYTE_TO_16_TABLE[value.w]);
212}
213
214uint ReplicateBitTo7(uint value) {
215 return REPLICATE_BIT_TO_7_TABLE[value];
216}
217
218uint ReplicateBitTo9(uint value) {
219 return REPLICATE_1_BIT_TO_9_TABLE[value];
220}
221
222uint FastReplicateTo8(uint value, uint num_bits) {
223 switch (num_bits) {
224 case 1:
225 return REPLICATE_1_BIT_TO_8_TABLE[value];
226 case 2:
227 return REPLICATE_2_BIT_TO_8_TABLE[value];
228 case 3:
229 return REPLICATE_3_BIT_TO_8_TABLE[value];
230 case 4:
231 return REPLICATE_4_BIT_TO_8_TABLE[value];
232 case 5:
233 return REPLICATE_5_BIT_TO_8_TABLE[value];
234 case 6:
235 return REPLICATE_6_BIT_TO_8_TABLE[value];
236 case 7:
237 return REPLICATE_7_BIT_TO_8_TABLE[value];
238 case 8:
239 return REPLICATE_8_BIT_TO_8_TABLE[value];
240 }
241 return Replicate(value, num_bits, 8);
242}
243
244uint FastReplicateTo6(uint value, uint num_bits) {
245 switch (num_bits) {
246 case 1:
247 return REPLICATE_1_BIT_TO_6_TABLE[value];
248 case 2:
249 return REPLICATE_2_BIT_TO_6_TABLE[value];
250 case 3:
251 return REPLICATE_3_BIT_TO_6_TABLE[value];
252 case 4:
253 return REPLICATE_4_BIT_TO_6_TABLE[value];
254 case 5:
255 return REPLICATE_5_BIT_TO_6_TABLE[value];
256 }
257 return Replicate(value, num_bits, 6);
258}
259
260uint Div3Floor(uint v) {
261 return (v * 0x5556) >> 16;
262}
263
264uint Div3Ceil(uint v) {
265 return Div3Floor(v + 2);
266}
267
268uint Div5Floor(uint v) {
269 return (v * 0x3334) >> 16;
270}
271
272uint Div5Ceil(uint v) {
273 return Div5Floor(v + 4);
274}
275
276uint Hash52(uint p) {
277 p ^= p >> 15;
278 p -= p << 17;
279 p += p << 7;
280 p += p << 4;
281 p ^= p >> 5;
282 p += p << 16;
283 p ^= p >> 7;
284 p ^= p >> 3;
285 p ^= p << 6;
286 p ^= p >> 17;
287 return p;
288}
289
290uint SelectPartition(uint seed, uint x, uint y, uint z, uint partition_count, bool small_block) {
291 if (partition_count == 1) {
292 return 0;
293 }
294 if (small_block) {
295 x <<= 1;
296 y <<= 1;
297 z <<= 1;
298 }
299
300 seed += (partition_count - 1) * 1024;
301
302 uint rnum = Hash52(uint(seed));
303 uint seed1 = uint(rnum & 0xF);
304 uint seed2 = uint((rnum >> 4) & 0xF);
305 uint seed3 = uint((rnum >> 8) & 0xF);
306 uint seed4 = uint((rnum >> 12) & 0xF);
307 uint seed5 = uint((rnum >> 16) & 0xF);
308 uint seed6 = uint((rnum >> 20) & 0xF);
309 uint seed7 = uint((rnum >> 24) & 0xF);
310 uint seed8 = uint((rnum >> 28) & 0xF);
311 uint seed9 = uint((rnum >> 18) & 0xF);
312 uint seed10 = uint((rnum >> 22) & 0xF);
313 uint seed11 = uint((rnum >> 26) & 0xF);
314 uint seed12 = uint(((rnum >> 30) | (rnum << 2)) & 0xF);
315
316 seed1 = (seed1 * seed1);
317 seed2 = (seed2 * seed2);
318 seed3 = (seed3 * seed3);
319 seed4 = (seed4 * seed4);
320 seed5 = (seed5 * seed5);
321 seed6 = (seed6 * seed6);
322 seed7 = (seed7 * seed7);
323 seed8 = (seed8 * seed8);
324 seed9 = (seed9 * seed9);
325 seed10 = (seed10 * seed10);
326 seed11 = (seed11 * seed11);
327 seed12 = (seed12 * seed12);
328
329 int sh1, sh2, sh3;
330 if ((seed & 1) > 0) {
331 sh1 = (seed & 2) > 0 ? 4 : 5;
332 sh2 = (partition_count == 3) ? 6 : 5;
333 } else {
334 sh1 = (partition_count == 3) ? 6 : 5;
335 sh2 = (seed & 2) > 0 ? 4 : 5;
336 }
337 sh3 = (seed & 0x10) > 0 ? sh1 : sh2;
338
339 seed1 = (seed1 >> sh1);
340 seed2 = (seed2 >> sh2);
341 seed3 = (seed3 >> sh1);
342 seed4 = (seed4 >> sh2);
343 seed5 = (seed5 >> sh1);
344 seed6 = (seed6 >> sh2);
345 seed7 = (seed7 >> sh1);
346 seed8 = (seed8 >> sh2);
347 seed9 = (seed9 >> sh3);
348 seed10 = (seed10 >> sh3);
349 seed11 = (seed11 >> sh3);
350 seed12 = (seed12 >> sh3);
351
352 uint a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
353 uint b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
354 uint c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
355 uint d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
356
357 a &= 0x3F;
358 b &= 0x3F;
359 c &= 0x3F;
360 d &= 0x3F;
361
362 if (partition_count < 4) {
363 d = 0;
364 }
365 if (partition_count < 3) {
366 c = 0;
367 }
368
369 if (a >= b && a >= c && a >= d) {
370 return 0;
371 } else if (b >= c && b >= d) {
372 return 1;
373 } else if (c >= d) {
374 return 2;
375 } else {
376 return 3;
377 }
378}
379
380uint Select2DPartition(uint seed, uint x, uint y, uint partition_count, bool small_block) {
381 return SelectPartition(seed, x, y, 0, partition_count, small_block);
382}
383
384uint ReadBit() {
385 if (current_index >= local_buff.length()) {
386 return 0;
387 }
388 uint bit = bitfieldExtract(local_buff[current_index], bitsread, 1);
389 ++bitsread;
390 ++total_bitsread;
391 if (bitsread == 8) {
392 ++current_index;
393 bitsread = 0;
394 }
395 return bit;
396}
397
398uint StreamBits(uint num_bits) {
399 uint ret = 0;
400 for (uint i = 0; i < num_bits; i++) {
401 ret |= ((ReadBit() & 1) << i);
402 }
403 return ret;
404}
405
406uint ReadColorBit() {
407 uint bit = 0;
408 if (texel_flag) {
409 bit = bitfieldExtract(texel_weight_data[texel_index], texel_bitsread, 1);
410 ++texel_bitsread;
411 ++total_texel_bitsread;
412 if (texel_bitsread == 8) {
413 ++texel_index;
414 texel_bitsread = 0;
415 }
416 } else {
417 bit = bitfieldExtract(color_endpoint_data[color_index], color_bitsread, 1);
418 ++color_bitsread;
419 ++total_color_bitsread;
420 if (color_bitsread == 8) {
421 ++color_index;
422 color_bitsread = 0;
423 }
424 }
425 return bit;
426}
427
428uint StreamColorBits(uint num_bits) {
429 uint ret = 0;
430 for (uint i = 0; i < num_bits; i++) {
431 ret |= ((ReadColorBit() & 1) << i);
432 }
433 return ret;
434}
435
436void ResultEmplaceBack(EncodingData val) {
437 if (texel_flag) {
438 texel_vector[texel_vector_index] = val;
439 ++texel_vector_index;
440 } else {
441 result_vector[result_index] = val;
442 ++result_index;
443 }
444}
445
446// Returns the number of bits required to encode n_vals values.
447uint GetBitLength(uint n_vals, uint encoding_index) {
448 uint total_bits = encoding_values[encoding_index].num_bits * n_vals;
449 if (encoding_values[encoding_index].encoding == TRIT) {
450 total_bits += Div5Ceil(n_vals * 8);
451 } else if (encoding_values[encoding_index].encoding == QUINT) {
452 total_bits += Div3Ceil(n_vals * 7);
453 }
454 return total_bits;
455}
456
457uint GetNumWeightValues(uvec2 size, bool dual_plane) {
458 uint n_vals = size.x * size.y;
459 if (dual_plane) {
460 n_vals *= 2;
461 }
462 return n_vals;
463}
464
465uint GetPackedBitSize(uvec2 size, bool dual_plane, uint max_weight) {
466 uint n_vals = GetNumWeightValues(size, dual_plane);
467 return GetBitLength(n_vals, max_weight);
468}
469
470uint BitsBracket(uint bits, uint pos) {
471 return ((bits >> pos) & 1);
472}
473
474uint BitsOp(uint bits, uint start, uint end) {
475 if (start == end) {
476 return BitsBracket(bits, start);
477 } else if (start > end) {
478 uint t = start;
479 start = end;
480 end = t;
481 }
482
483 uint mask = (1 << (end - start + 1)) - 1;
484 return ((bits >> start) & mask);
485}
486
487void DecodeQuintBlock(uint num_bits) {
488 uint m[3];
489 uint q[3];
490 uint Q;
491 m[0] = StreamColorBits(num_bits);
492 Q = StreamColorBits(3);
493 m[1] = StreamColorBits(num_bits);
494 Q |= StreamColorBits(2) << 3;
495 m[2] = StreamColorBits(num_bits);
496 Q |= StreamColorBits(2) << 5;
497 if (BitsOp(Q, 1, 2) == 3 && BitsOp(Q, 5, 6) == 0) {
498 q[0] = 4;
499 q[1] = 4;
500 q[2] = (BitsBracket(Q, 0) << 2) | ((BitsBracket(Q, 4) & ~BitsBracket(Q, 0)) << 1) |
501 (BitsBracket(Q, 3) & ~BitsBracket(Q, 0));
502 } else {
503 uint C = 0;
504 if (BitsOp(Q, 1, 2) == 3) {
505 q[2] = 4;
506 C = (BitsOp(Q, 3, 4) << 3) | ((~BitsOp(Q, 5, 6) & 3) << 1) | BitsBracket(Q, 0);
507 } else {
508 q[2] = BitsOp(Q, 5, 6);
509 C = BitsOp(Q, 0, 4);
510 }
511 if (BitsOp(C, 0, 2) == 5) {
512 q[1] = 4;
513 q[0] = BitsOp(C, 3, 4);
514 } else {
515 q[1] = BitsOp(C, 3, 4);
516 q[0] = BitsOp(C, 0, 2);
517 }
518 }
519 for (uint i = 0; i < 3; i++) {
520 EncodingData val;
521 val.encoding = QUINT;
522 val.num_bits = num_bits;
523 val.bit_value = m[i];
524 val.quint_trit_value = q[i];
525 ResultEmplaceBack(val);
526 }
527}
528
529void DecodeTritBlock(uint num_bits) {
530 uint m[5];
531 uint t[5];
532 uint T;
533 m[0] = StreamColorBits(num_bits);
534 T = StreamColorBits(2);
535 m[1] = StreamColorBits(num_bits);
536 T |= StreamColorBits(2) << 2;
537 m[2] = StreamColorBits(num_bits);
538 T |= StreamColorBits(1) << 4;
539 m[3] = StreamColorBits(num_bits);
540 T |= StreamColorBits(2) << 5;
541 m[4] = StreamColorBits(num_bits);
542 T |= StreamColorBits(1) << 7;
543 uint C = 0;
544 if (BitsOp(T, 2, 4) == 7) {
545 C = (BitsOp(T, 5, 7) << 2) | BitsOp(T, 0, 1);
546 t[4] = 2;
547 t[3] = 2;
548 } else {
549 C = BitsOp(T, 0, 4);
550 if (BitsOp(T, 5, 6) == 3) {
551 t[4] = 2;
552 t[3] = BitsBracket(T, 7);
553 } else {
554 t[4] = BitsBracket(T, 7);
555 t[3] = BitsOp(T, 5, 6);
556 }
557 }
558 if (BitsOp(C, 0, 1) == 3) {
559 t[2] = 2;
560 t[1] = BitsBracket(C, 4);
561 t[0] = (BitsBracket(C, 3) << 1) | (BitsBracket(C, 2) & ~BitsBracket(C, 3));
562 } else if (BitsOp(C, 2, 3) == 3) {
563 t[2] = 2;
564 t[1] = 2;
565 t[0] = BitsOp(C, 0, 1);
566 } else {
567 t[2] = BitsBracket(C, 4);
568 t[1] = BitsOp(C, 2, 3);
569 t[0] = (BitsBracket(C, 1) << 1) | (BitsBracket(C, 0) & ~BitsBracket(C, 1));
570 }
571 for (uint i = 0; i < 5; i++) {
572 EncodingData val;
573 val.encoding = TRIT;
574 val.num_bits = num_bits;
575 val.bit_value = m[i];
576 val.quint_trit_value = t[i];
577 ResultEmplaceBack(val);
578 }
579}
580
581void DecodeIntegerSequence(uint max_range, uint num_values) {
582 EncodingData val = encoding_values[max_range];
583 uint vals_decoded = 0;
584 while (vals_decoded < num_values) {
585 switch (val.encoding) {
586 case QUINT:
587 DecodeQuintBlock(val.num_bits);
588 vals_decoded += 3;
589 break;
590 case TRIT:
591 DecodeTritBlock(val.num_bits);
592 vals_decoded += 5;
593 break;
594 case JUST_BITS:
595 val.bit_value = StreamColorBits(val.num_bits);
596 ResultEmplaceBack(val);
597 vals_decoded++;
598 break;
599 }
600 }
601}
602
603void DecodeColorValues(uvec4 modes, uint num_partitions, uint color_data_bits) {
604 uint num_values = 0;
605 for (uint i = 0; i < num_partitions; i++) {
606 num_values += ((modes[i] >> 2) + 1) << 1;
607 }
608 int range = 256;
609 while (--range > 0) {
610 EncodingData val = encoding_values[range];
611 uint bit_length = GetBitLength(num_values, range);
612 if (bit_length <= color_data_bits) {
613 while (--range > 0) {
614 EncodingData newval = encoding_values[range];
615 if (newval.encoding != val.encoding && newval.num_bits != val.num_bits) {
616 break;
617 }
618 }
619 ++range;
620 break;
621 }
622 }
623 DecodeIntegerSequence(range, num_values);
624 uint out_index = 0;
625 for (int itr = 0; itr < result_index; ++itr) {
626 if (out_index >= num_values) {
627 break;
628 }
629 EncodingData val = result_vector[itr];
630 uint bitlen = val.num_bits;
631 uint bitval = val.bit_value;
632 uint A = 0, B = 0, C = 0, D = 0;
633 A = ReplicateBitTo9((bitval & 1));
634 switch (val.encoding) {
635 case JUST_BITS:
636 color_values[out_index++] = FastReplicateTo8(bitval, bitlen);
637 break;
638 case TRIT: {
639 D = val.quint_trit_value;
640 switch (bitlen) {
641 case 1:
642 C = 204;
643 break;
644 case 2: {
645 C = 93;
646 uint b = (bitval >> 1) & 1;
647 B = (b << 8) | (b << 4) | (b << 2) | (b << 1);
648 break;
649 }
650 case 3: {
651 C = 44;
652 uint cb = (bitval >> 1) & 3;
653 B = (cb << 7) | (cb << 2) | cb;
654 break;
655 }
656 case 4: {
657 C = 22;
658 uint dcb = (bitval >> 1) & 7;
659 B = (dcb << 6) | dcb;
660 break;
661 }
662 case 5: {
663 C = 11;
664 uint edcb = (bitval >> 1) & 0xF;
665 B = (edcb << 5) | (edcb >> 2);
666 break;
667 }
668 case 6: {
669 C = 5;
670 uint fedcb = (bitval >> 1) & 0x1F;
671 B = (fedcb << 4) | (fedcb >> 4);
672 break;
673 }
674 }
675 break;
676 }
677 case QUINT: {
678 D = val.quint_trit_value;
679 switch (bitlen) {
680 case 1:
681 C = 113;
682 break;
683 case 2: {
684 C = 54;
685 uint b = (bitval >> 1) & 1;
686 B = (b << 8) | (b << 3) | (b << 2);
687 break;
688 }
689 case 3: {
690 C = 26;
691 uint cb = (bitval >> 1) & 3;
692 B = (cb << 7) | (cb << 1) | (cb >> 1);
693 break;
694 }
695 case 4: {
696 C = 13;
697 uint dcb = (bitval >> 1) & 7;
698 B = (dcb << 6) | (dcb >> 1);
699 break;
700 }
701 case 5: {
702 C = 6;
703 uint edcb = (bitval >> 1) & 0xF;
704 B = (edcb << 5) | (edcb >> 3);
705 break;
706 }
707 }
708 break;
709 }
710 }
711 if (val.encoding != JUST_BITS) {
712 uint T = (D * C) + B;
713 T ^= A;
714 T = (A & 0x80) | (T >> 2);
715 color_values[out_index++] = T;
716 }
717 }
718}
719
720ivec2 BitTransferSigned(int a, int b) {
721 ivec2 transferred;
722 transferred.y = b >> 1;
723 transferred.y |= a & 0x80;
724 transferred.x = a >> 1;
725 transferred.x &= 0x3F;
726 if ((transferred.x & 0x20) > 0) {
727 transferred.x -= 0x40;
728 }
729 return transferred;
730}
731
732uvec4 ClampByte(ivec4 color) {
733 for (uint i = 0; i < 4; ++i) {
734 color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]);
735 }
736 return uvec4(color);
737}
738
739ivec4 BlueContract(int a, int r, int g, int b) {
740 return ivec4(a, (r + b) >> 1, (g + b) >> 1, b);
741}
742
743void ComputeEndpoints(out uvec4 ep1, out uvec4 ep2, uint color_endpoint_mode) {
744#define READ_UINT_VALUES(N) \
745 uint v[N]; \
746 for (uint i = 0; i < N; i++) { \
747 v[i] = color_values[colvals_index++]; \
748 }
749
750#define READ_INT_VALUES(N) \
751 int v[N]; \
752 for (uint i = 0; i < N; i++) { \
753 v[i] = int(color_values[colvals_index++]); \
754 }
755
756 switch (color_endpoint_mode) {
757 case 0: {
758 READ_UINT_VALUES(2)
759 ep1 = uvec4(0xFF, v[0], v[0], v[0]);
760 ep2 = uvec4(0xFF, v[1], v[1], v[1]);
761 break;
762 }
763 case 1: {
764 READ_UINT_VALUES(2)
765 uint L0 = (v[0] >> 2) | (v[1] & 0xC0);
766 uint L1 = max(L0 + (v[1] & 0x3F), 0xFFU);
767 ep1 = uvec4(0xFF, L0, L0, L0);
768 ep2 = uvec4(0xFF, L1, L1, L1);
769 break;
770 }
771 case 4: {
772 READ_UINT_VALUES(4)
773 ep1 = uvec4(v[2], v[0], v[0], v[0]);
774 ep2 = uvec4(v[3], v[1], v[1], v[1]);
775 break;
776 }
777 case 5: {
778 READ_INT_VALUES(4)
779 ivec2 transferred = BitTransferSigned(v[1], v[0]);
780 v[1] = transferred.x;
781 v[0] = transferred.y;
782 transferred = BitTransferSigned(v[3], v[2]);
783 v[3] = transferred.x;
784 v[2] = transferred.y;
785 ep1 = ClampByte(ivec4(v[2], v[0], v[0], v[0]));
786 ep2 = ClampByte(ivec4(v[2] + v[3], v[0] + v[1], v[0] + v[1], v[0] + v[1]));
787 break;
788 }
789 case 6: {
790 READ_UINT_VALUES(4)
791 ep1 = uvec4(0xFF, (v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8);
792 ep2 = uvec4(0xFF, v[0], v[1], v[2]);
793 break;
794 }
795 case 8: {
796 READ_UINT_VALUES(6)
797 if ((v[1] + v[3] + v[5]) >= (v[0] + v[2] + v[4])) {
798 ep1 = uvec4(0xFF, v[0], v[2], v[4]);
799 ep2 = uvec4(0xFF, v[1], v[3], v[5]);
800 } else {
801 ep1 = uvec4(BlueContract(0xFF, int(v[1]), int(v[3]), int(v[5])));
802 ep2 = uvec4(BlueContract(0xFF, int(v[0]), int(v[2]), int(v[4])));
803 }
804 break;
805 }
806 case 9: {
807 READ_INT_VALUES(6)
808 ivec2 transferred = BitTransferSigned(v[1], v[0]);
809 v[1] = transferred.x;
810 v[0] = transferred.y;
811 transferred = BitTransferSigned(v[3], v[2]);
812 v[3] = transferred.x;
813 v[2] = transferred.y;
814 transferred = BitTransferSigned(v[5], v[4]);
815 v[5] = transferred.x;
816 v[4] = transferred.y;
817 if ((v[1] + v[3] + v[5]) >= 0) {
818 ep1 = ClampByte(ivec4(0xFF, v[0], v[2], v[4]));
819 ep2 = ClampByte(ivec4(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]));
820 } else {
821 ep1 = ClampByte(BlueContract(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]));
822 ep2 = ClampByte(BlueContract(0xFF, v[0], v[2], v[4]));
823 }
824 break;
825 }
826 case 10: {
827 READ_UINT_VALUES(6)
828 ep1 = uvec4(v[4], (v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8);
829 ep2 = uvec4(v[5], v[0], v[1], v[2]);
830 break;
831 }
832 case 12: {
833 READ_UINT_VALUES(8)
834 if ((v[1] + v[3] + v[5]) >= (v[0] + v[2] + v[4])) {
835 ep1 = uvec4(v[6], v[0], v[2], v[4]);
836 ep2 = uvec4(v[7], v[1], v[3], v[5]);
837 } else {
838 ep1 = uvec4(BlueContract(int(v[7]), int(v[1]), int(v[3]), int(v[5])));
839 ep2 = uvec4(BlueContract(int(v[6]), int(v[0]), int(v[2]), int(v[4])));
840 }
841 break;
842 }
843 case 13: {
844 READ_INT_VALUES(8)
845 ivec2 transferred = BitTransferSigned(v[1], v[0]);
846 v[1] = transferred.x;
847 v[0] = transferred.y;
848 transferred = BitTransferSigned(v[3], v[2]);
849 v[3] = transferred.x;
850 v[2] = transferred.y;
851
852 transferred = BitTransferSigned(v[5], v[4]);
853 v[5] = transferred.x;
854 v[4] = transferred.y;
855
856 transferred = BitTransferSigned(v[7], v[6]);
857 v[7] = transferred.x;
858 v[6] = transferred.y;
859
860 if ((v[1] + v[3] + v[5]) >= 0) {
861 ep1 = ClampByte(ivec4(v[6], v[0], v[2], v[4]));
862 ep2 = ClampByte(ivec4(v[7] + v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5]));
863 } else {
864 ep1 = ClampByte(BlueContract(v[6] + v[7], v[0] + v[1], v[2] + v[3], v[4] + v[5]));
865 ep2 = ClampByte(BlueContract(v[6], v[0], v[2], v[4]));
866 }
867 break;
868 }
869 default: {
870 // HDR mode, or more likely a bug computing the color_endpoint_mode
871 ep1 = uvec4(0xFF, 0xFF, 0, 0);
872 ep2 = uvec4(0xFF, 0xFF, 0, 0);
873 break;
874 }
875 }
876#undef READ_UINT_VALUES
877#undef READ_INT_VALUES
878}
879
880uint UnquantizeTexelWeight(EncodingData val) {
881 uint bitval = val.bit_value;
882 uint bitlen = val.num_bits;
883 uint A = ReplicateBitTo7((bitval & 1));
884 uint B = 0, C = 0, D = 0;
885 uint result = 0;
886 switch (val.encoding) {
887 case JUST_BITS:
888 result = FastReplicateTo6(bitval, bitlen);
889 break;
890 case TRIT: {
891 D = val.quint_trit_value;
892 switch (bitlen) {
893 case 0: {
894 uint results[3] = {0, 32, 63};
895 result = results[D];
896 break;
897 }
898 case 1: {
899 C = 50;
900 break;
901 }
902 case 2: {
903 C = 23;
904 uint b = (bitval >> 1) & 1;
905 B = (b << 6) | (b << 2) | b;
906 break;
907 }
908 case 3: {
909 C = 11;
910 uint cb = (bitval >> 1) & 3;
911 B = (cb << 5) | cb;
912 break;
913 }
914 default:
915 break;
916 }
917 break;
918 }
919 case QUINT: {
920 D = val.quint_trit_value;
921 switch (bitlen) {
922 case 0: {
923 uint results[5] = {0, 16, 32, 47, 63};
924 result = results[D];
925 break;
926 }
927 case 1: {
928 C = 28;
929 break;
930 }
931 case 2: {
932 C = 13;
933 uint b = (bitval >> 1) & 1;
934 B = (b << 6) | (b << 1);
935 break;
936 }
937 }
938 break;
939 }
940 }
941 if (val.encoding != JUST_BITS && bitlen > 0) {
942 result = D * C + B;
943 result ^= A;
944 result = (A & 0x20) | (result >> 2);
945 }
946 if (result > 32) {
947 result += 1;
948 }
949 return result;
950}
951
952void UnquantizeTexelWeights(bool dual_plane, uvec2 size) {
953 uint weight_idx = 0;
954 uint unquantized[2][144];
955 uint area = size.x * size.y;
956 for (uint itr = 0; itr < texel_vector_index; itr++) {
957 unquantized[0][weight_idx] = UnquantizeTexelWeight(texel_vector[itr]);
958 if (dual_plane) {
959 ++itr;
960 unquantized[1][weight_idx] = UnquantizeTexelWeight(texel_vector[itr]);
961 if (itr == texel_vector_index) {
962 break;
963 }
964 }
965 if (++weight_idx >= (area))
966 break;
967 }
968
969 const uint Ds = uint((block_dims.x * 0.5f + 1024) / (block_dims.x - 1));
970 const uint Dt = uint((block_dims.y * 0.5f + 1024) / (block_dims.y - 1));
971 const uint k_plane_scale = dual_plane ? 2 : 1;
972 for (uint plane = 0; plane < k_plane_scale; plane++) {
973 for (uint t = 0; t < block_dims.y; t++) {
974 for (uint s = 0; s < block_dims.x; s++) {
975 uint cs = Ds * s;
976 uint ct = Dt * t;
977 uint gs = (cs * (size.x - 1) + 32) >> 6;
978 uint gt = (ct * (size.y - 1) + 32) >> 6;
979 uint js = gs >> 4;
980 uint fs = gs & 0xF;
981 uint jt = gt >> 4;
982 uint ft = gt & 0x0F;
983 uint w11 = (fs * ft + 8) >> 4;
984 uint w10 = ft - w11;
985 uint w01 = fs - w11;
986 uint w00 = 16 - fs - ft + w11;
987 uvec4 w = uvec4(w00, w01, w10, w11);
988 uint v0 = jt * size.x + js;
989
990 uvec4 p = uvec4(0);
991 if (v0 < area) {
992 p.x = unquantized[plane][v0];
993 }
994 if ((v0 + 1) < (area)) {
995 p.y = unquantized[plane][v0 + 1];
996 }
997 if ((v0 + size.x) < (area)) {
998 p.z = unquantized[plane][(v0 + size.x)];
999 }
1000 if ((v0 + size.x + 1) < (area)) {
1001 p.w = unquantized[plane][(v0 + size.x + 1)];
1002 }
1003 unquantized_texel_weights[plane][t * block_dims.x + s] = (uint(dot(p, w)) + 8) >> 4;
1004 }
1005 }
1006 }
1007}
1008
1009int FindLayout(uint mode) {
1010 if ((mode & 3) != 0) {
1011 if ((mode & 8) != 0) {
1012 if ((mode & 4) != 0) {
1013 if ((mode & 0x100) != 0) {
1014 return 4;
1015 }
1016 return 3;
1017 }
1018 return 2;
1019 }
1020 if ((mode & 4) != 0) {
1021 return 1;
1022 }
1023 return 0;
1024 }
1025 if ((mode & 0x100) != 0) {
1026 if ((mode & 0x80) != 0) {
1027 if ((mode & 0x20) != 0) {
1028 return 8;
1029 }
1030 return 7;
1031 }
1032 return 9;
1033 }
1034 if ((mode & 0x80) != 0) {
1035 return 6;
1036 }
1037 return 5;
1038}
1039
1040TexelWeightParams DecodeBlockInfo(uint block_index) {
1041 TexelWeightParams params = TexelWeightParams(uvec2(0), 0, false, false, false, false);
1042 uint mode = StreamBits(11);
1043 if ((mode & 0x1ff) == 0x1fc) {
1044 if ((mode & 0x200) != 0) {
1045 params.void_extent_hdr = true;
1046 } else {
1047 params.void_extent_ldr = true;
1048 }
1049 if ((mode & 0x400) == 0 || StreamBits(1) == 0) {
1050 params.error_state = true;
1051 }
1052 return params;
1053 }
1054 if ((mode & 0xf) == 0) {
1055 params.error_state = true;
1056 return params;
1057 }
1058 if ((mode & 3) == 0 && (mode & 0x1c0) == 0x1c0) {
1059 params.error_state = true;
1060 return params;
1061 }
1062 uint A, B;
1063 uint mode_layout = FindLayout(mode);
1064 switch (mode_layout) {
1065 case 0:
1066 A = (mode >> 5) & 0x3;
1067 B = (mode >> 7) & 0x3;
1068 params.size = uvec2(B + 4, A + 2);
1069 break;
1070 case 1:
1071 A = (mode >> 5) & 0x3;
1072 B = (mode >> 7) & 0x3;
1073 params.size = uvec2(B + 8, A + 2);
1074 break;
1075 case 2:
1076 A = (mode >> 5) & 0x3;
1077 B = (mode >> 7) & 0x3;
1078 params.size = uvec2(A + 2, B + 8);
1079 break;
1080 case 3:
1081 A = (mode >> 5) & 0x3;
1082 B = (mode >> 7) & 0x1;
1083 params.size = uvec2(A + 2, B + 6);
1084 break;
1085 case 4:
1086 A = (mode >> 5) & 0x3;
1087 B = (mode >> 7) & 0x1;
1088 params.size = uvec2(B + 2, A + 2);
1089 break;
1090 case 5:
1091 A = (mode >> 5) & 0x3;
1092 params.size = uvec2(12, A + 2);
1093 break;
1094 case 6:
1095 A = (mode >> 5) & 0x3;
1096 params.size = uvec2(A + 2, 12);
1097 break;
1098 case 7:
1099 params.size = uvec2(6, 10);
1100 break;
1101 case 8:
1102 params.size = uvec2(10, 6);
1103 break;
1104 case 9:
1105 A = (mode >> 5) & 0x3;
1106 B = (mode >> 9) & 0x3;
1107 params.size = uvec2(A + 6, B + 6);
1108 break;
1109 default:
1110 params.error_state = true;
1111 break;
1112 }
1113 params.dual_plane = (mode_layout != 9) && ((mode & 0x400) != 0);
1114 uint weight_index = (mode & 0x10) != 0 ? 1 : 0;
1115 if (mode_layout < 5) {
1116 weight_index |= (mode & 0x3) << 1;
1117 } else {
1118 weight_index |= (mode & 0xc) >> 1;
1119 }
1120 weight_index -= 2;
1121 if ((mode_layout != 9) && ((mode & 0x200) != 0)) {
1122 const int max_weights[6] = int[6](9, 11, 15, 19, 23, 31);
1123 params.max_weight = max_weights[weight_index];
1124 } else {
1125 const int max_weights[6] = int[6](1, 2, 3, 4, 5, 7);
1126 params.max_weight = max_weights[weight_index];
1127 }
1128 return params;
1129}
1130
1131void FillError(ivec3 coord) {
1132 for (uint j = 0; j < block_dims.y; j++) {
1133 for (uint i = 0; i < block_dims.x; i++) {
1134 imageStore(dest_image, coord + ivec3(i, j, 0), vec4(1.0, 1.0, 0.0, 1.0));
1135 }
1136 }
1137}
1138
1139void FillVoidExtentLDR(ivec3 coord) {
1140 StreamBits(52);
1141 uint r_u = StreamBits(16);
1142 uint g_u = StreamBits(16);
1143 uint b_u = StreamBits(16);
1144 uint a_u = StreamBits(16);
1145 float a = float(a_u) / 65535.0f;
1146 float r = float(r_u) / 65535.0f;
1147 float g = float(g_u) / 65535.0f;
1148 float b = float(b_u) / 65535.0f;
1149 for (uint j = 0; j < block_dims.y; j++) {
1150 for (uint i = 0; i < block_dims.x; i++) {
1151 imageStore(dest_image, coord + ivec3(i, j, 0), vec4(r, g, b, a));
1152 }
1153 }
1154}
1155
1156void DecompressBlock(ivec3 coord, uint block_index) {
1157 TexelWeightParams params = DecodeBlockInfo(block_index);
1158 if (params.error_state) {
1159 FillError(coord);
1160 return;
1161 }
1162 if (params.void_extent_hdr) {
1163 FillError(coord);
1164 return;
1165 }
1166 if (params.void_extent_ldr) {
1167 FillVoidExtentLDR(coord);
1168 return;
1169 }
1170 if ((params.size.x > block_dims.x) || (params.size.y > block_dims.y)) {
1171 FillError(coord);
1172 return;
1173 }
1174 uint num_partitions = StreamBits(2) + 1;
1175 if (num_partitions > 4 || (num_partitions == 4 && params.dual_plane)) {
1176 FillError(coord);
1177 return;
1178 }
1179 int plane_index = -1;
1180 uint partition_index = 1;
1181 uvec4 color_endpoint_mode = uvec4(0);
1182 uint ced_pointer = 0;
1183 uint base_cem = 0;
1184 if (num_partitions == 1) {
1185 color_endpoint_mode.x = StreamBits(4);
1186 partition_index = 0;
1187 } else {
1188 partition_index = StreamBits(10);
1189 base_cem = StreamBits(6);
1190 }
1191 uint base_mode = base_cem & 3;
1192 uint weight_bits = GetPackedBitSize(params.size, params.dual_plane, params.max_weight);
1193 uint remaining_bits = 128 - weight_bits - total_bitsread;
1194 uint extra_cem_bits = 0;
1195 if (base_mode > 0) {
1196 switch (num_partitions) {
1197 case 2:
1198 extra_cem_bits += 2;
1199 break;
1200 case 3:
1201 extra_cem_bits += 5;
1202 break;
1203 case 4:
1204 extra_cem_bits += 8;
1205 break;
1206 default:
1207 return;
1208 }
1209 }
1210 remaining_bits -= extra_cem_bits;
1211 uint plane_selector_bits = 0;
1212 if (params.dual_plane) {
1213 plane_selector_bits = 2;
1214 }
1215 remaining_bits -= plane_selector_bits;
1216 if (remaining_bits > 128) {
1217 // Bad data, more remaining bits than 4 bytes
1218 // return early
1219 return;
1220 }
1221 // Read color data...
1222 uint color_data_bits = remaining_bits;
1223 while (remaining_bits > 0) {
1224 int nb = int(min(remaining_bits, 8U));
1225 uint b = StreamBits(nb);
1226 color_endpoint_data[ced_pointer] = uint(bitfieldExtract(b, 0, nb));
1227 ++ced_pointer;
1228 remaining_bits -= nb;
1229 }
1230 plane_index = int(StreamBits(plane_selector_bits));
1231 if (base_mode > 0) {
1232 uint extra_cem = StreamBits(extra_cem_bits);
1233 uint cem = (extra_cem << 6) | base_cem;
1234 cem >>= 2;
1235 uvec4 C = uvec4(0);
1236 for (uint i = 0; i < num_partitions; i++) {
1237 C[i] = (cem & 1);
1238 cem >>= 1;
1239 }
1240 uvec4 M = uvec4(0);
1241 for (uint i = 0; i < num_partitions; i++) {
1242 M[i] = cem & 3;
1243 cem >>= 2;
1244 }
1245 for (uint i = 0; i < num_partitions; i++) {
1246 color_endpoint_mode[i] = base_mode;
1247 if (C[i] == 0) {
1248 --color_endpoint_mode[i];
1249 }
1250 color_endpoint_mode[i] <<= 2;
1251 color_endpoint_mode[i] |= M[i];
1252 }
1253 } else if (num_partitions > 1) {
1254 uint cem = base_cem >> 2;
1255 for (uint i = 0; i < num_partitions; i++) {
1256 color_endpoint_mode[i] = cem;
1257 }
1258 }
1259 DecodeColorValues(color_endpoint_mode, num_partitions, color_data_bits);
1260
1261 uvec4 endpoints[4][2];
1262 for (uint i = 0; i < num_partitions; i++) {
1263 ComputeEndpoints(endpoints[i][0], endpoints[i][1], color_endpoint_mode[i]);
1264 }
1265
1266 for (uint i = 0; i < 16; i++) {
1267 texel_weight_data[i] = local_buff[i];
1268 }
1269 for (uint i = 0; i < 8; i++) {
1270#define REVERSE_BYTE(b) ((b * 0x0802U & 0x22110U) | (b * 0x8020U & 0x88440U)) * 0x10101U >> 16
1271 uint a = REVERSE_BYTE(texel_weight_data[i]);
1272 uint b = REVERSE_BYTE(texel_weight_data[15 - i]);
1273#undef REVERSE_BYTE
1274 texel_weight_data[i] = uint(bitfieldExtract(b, 0, 8));
1275 texel_weight_data[15 - i] = uint(bitfieldExtract(a, 0, 8));
1276 }
1277 uint clear_byte_start =
1278 (GetPackedBitSize(params.size, params.dual_plane, params.max_weight) >> 3) + 1;
1279 texel_weight_data[clear_byte_start - 1] =
1280 texel_weight_data[clear_byte_start - 1] &
1281 uint(
1282 ((1 << (GetPackedBitSize(params.size, params.dual_plane, params.max_weight) % 8)) - 1));
1283 for (uint i = 0; i < 16 - clear_byte_start; i++) {
1284 texel_weight_data[clear_byte_start + i] = 0U;
1285 }
1286 texel_flag = true; // use texel "vector" and bit stream in integer decoding
1287 DecodeIntegerSequence(params.max_weight, GetNumWeightValues(params.size, params.dual_plane));
1288
1289 UnquantizeTexelWeights(params.dual_plane, params.size);
1290
1291 for (uint j = 0; j < block_dims.y; j++) {
1292 for (uint i = 0; i < block_dims.x; i++) {
1293 uint local_partition = Select2DPartition(partition_index, i, j, num_partitions,
1294 (block_dims.y * block_dims.x) < 32);
1295 vec4 p;
1296 uvec4 C0 = ReplicateByteTo16(endpoints[local_partition][0]);
1297 uvec4 C1 = ReplicateByteTo16(endpoints[local_partition][1]);
1298 uvec4 plane_vec = uvec4(0);
1299 uvec4 weight_vec = uvec4(0);
1300 for (uint c = 0; c < 4; c++) {
1301 if (params.dual_plane && (((plane_index + 1) & 3) == c)) {
1302 plane_vec[c] = 1;
1303 }
1304 weight_vec[c] = unquantized_texel_weights[plane_vec[c]][j * block_dims.x + i];
1305 }
1306 vec4 Cf = vec4((C0 * (uvec4(64) - weight_vec) + C1 * weight_vec + uvec4(32)) / 64);
1307 p = (Cf / 65535.0);
1308 imageStore(dest_image, coord + ivec3(i, j, 0), p.gbar);
1309 }
1310 }
1311}
1312
1313void main() {
1314 uvec3 pos = gl_GlobalInvocationID;
1315 pos.x <<= bytes_per_block_log2;
1316
1317 // Read as soon as possible due to its latency
1318 const uint swizzle = SwizzleOffset(pos.xy);
1319
1320 const uint block_y = pos.y >> GOB_SIZE_Y_SHIFT;
1321
1322 uint offset = 0;
1323 offset += pos.z * layer_stride;
1324 offset += (block_y >> block_height) * block_size;
1325 offset += (block_y & block_height_mask) << GOB_SIZE_SHIFT;
1326 offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift;
1327 offset += swizzle;
1328
1329 const ivec3 coord = ivec3(gl_GlobalInvocationID * uvec3(block_dims, 1));
1330 uint block_index =
1331 pos.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + pos.y * gl_WorkGroupSize.x + pos.x;
1332
1333 current_index = 0;
1334 bitsread = 0;
1335 for (int i = 0; i < 16; i++) {
1336 local_buff[i] = ReadTexel(offset + i);
1337 }
1338 DecompressBlock(coord, block_index);
1339}
diff --git a/src/video_core/host_shaders/source_shader.h.in b/src/video_core/host_shaders/source_shader.h.in
index ccdb0d2a9..929dec39b 100644
--- a/src/video_core/host_shaders/source_shader.h.in
+++ b/src/video_core/host_shaders/source_shader.h.in
@@ -4,6 +4,8 @@
4 4
5namespace HostShaders { 5namespace HostShaders {
6 6
7constexpr std::string_view @CONTENTS_NAME@ = R"(@CONTENTS@)"; 7constexpr std::string_view @CONTENTS_NAME@ = {
8@CONTENTS@
9};
8 10
9} // namespace HostShaders 11} // namespace HostShaders
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp
index cd21a2112..d7fabe605 100644
--- a/src/video_core/macro/macro.cpp
+++ b/src/video_core/macro/macro.cpp
@@ -6,7 +6,7 @@
6#include <boost/container_hash/hash.hpp> 6#include <boost/container_hash/hash.hpp>
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/settings.h" 9#include "common/settings.h"
10#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
11#include "video_core/macro/macro.h" 11#include "video_core/macro/macro.h"
12#include "video_core/macro/macro_hle.h" 12#include "video_core/macro/macro_hle.h"
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 203f2af05..aac851253 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -16,8 +16,8 @@
16#include <vector> 16#include <vector>
17 17
18#include "common/assert.h" 18#include "common/assert.h"
19#include "common/settings.h"
19#include "core/core.h" 20#include "core/core.h"
20#include "core/settings.h"
21#include "video_core/engines/maxwell_3d.h" 21#include "video_core/engines/maxwell_3d.h"
22#include "video_core/gpu.h" 22#include "video_core/gpu.h"
23#include "video_core/memory_manager.h" 23#include "video_core/memory_manager.h"
@@ -208,9 +208,9 @@ public:
208private: 208private:
209 /// Flushes a memory range to guest memory and removes it from the cache. 209 /// Flushes a memory range to guest memory and removes it from the cache.
210 void FlushAndRemoveRegion(VAddr addr, std::size_t size) { 210 void FlushAndRemoveRegion(VAddr addr, std::size_t size) {
211 const u64 addr_begin = static_cast<u64>(addr); 211 const u64 addr_begin = addr;
212 const u64 addr_end = addr_begin + static_cast<u64>(size); 212 const u64 addr_end = addr_begin + size;
213 const auto in_range = [addr_begin, addr_end](CachedQuery& query) { 213 const auto in_range = [addr_begin, addr_end](const CachedQuery& query) {
214 const u64 cache_begin = query.GetCpuAddr(); 214 const u64 cache_begin = query.GetCpuAddr();
215 const u64 cache_end = cache_begin + query.SizeInBytes(); 215 const u64 cache_end = cache_begin + query.SizeInBytes();
216 return cache_begin < addr_end && addr_begin < cache_end; 216 return cache_begin < addr_end && addr_begin < cache_end;
@@ -230,8 +230,7 @@ private:
230 rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); 230 rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1);
231 query.Flush(); 231 query.Flush();
232 } 232 }
233 contents.erase(std::remove_if(std::begin(contents), std::end(contents), in_range), 233 std::erase_if(contents, in_range);
234 std::end(contents));
235 } 234 }
236 } 235 }
237 236
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index a93a1732c..c9a360aaf 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -3,8 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/settings.h"
6#include "core/frontend/emu_window.h" 7#include "core/frontend/emu_window.h"
7#include "core/settings.h"
8#include "video_core/renderer_base.h" 8#include "video_core/renderer_base.h"
9 9
10namespace VideoCore { 10namespace VideoCore {
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 5776fccdc..b113f54db 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -16,7 +16,7 @@
16 16
17#include "common/logging/log.h" 17#include "common/logging/log.h"
18#include "common/scope_exit.h" 18#include "common/scope_exit.h"
19#include "core/settings.h" 19#include "common/settings.h"
20#include "video_core/renderer_opengl/gl_device.h" 20#include "video_core/renderer_opengl/gl_device.h"
21#include "video_core/renderer_opengl/gl_resource_manager.h" 21#include "video_core/renderer_opengl/gl_resource_manager.h"
22 22
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 4610fd160..0863904e9 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -17,10 +17,10 @@
17#include "common/math_util.h" 17#include "common/math_util.h"
18#include "common/microprofile.h" 18#include "common/microprofile.h"
19#include "common/scope_exit.h" 19#include "common/scope_exit.h"
20#include "common/settings.h"
20#include "core/core.h" 21#include "core/core.h"
21#include "core/hle/kernel/process.h" 22#include "core/hle/kernel/process.h"
22#include "core/memory.h" 23#include "core/memory.h"
23#include "core/settings.h"
24#include "video_core/engines/kepler_compute.h" 24#include "video_core/engines/kepler_compute.h"
25#include "video_core/engines/maxwell_3d.h" 25#include "video_core/engines/maxwell_3d.h"
26#include "video_core/engines/shader_type.h" 26#include "video_core/engines/shader_type.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 955b2abc4..97fb11ac6 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -12,10 +12,10 @@
12#include "common/file_util.h" 12#include "common/file_util.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/scm_rev.h" 14#include "common/scm_rev.h"
15#include "common/settings.h"
15#include "common/zstd_compression.h" 16#include "common/zstd_compression.h"
16#include "core/core.h" 17#include "core/core.h"
17#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
18#include "core/settings.h"
19#include "video_core/engines/shader_type.h" 19#include "video_core/engines/shader_type.h"
20#include "video_core/renderer_opengl/gl_shader_cache.h" 20#include "video_core/renderer_opengl/gl_shader_cache.h"
21#include "video_core/renderer_opengl/gl_shader_disk_cache.h" 21#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index e028677e9..623b43d8a 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -307,7 +307,8 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
307 307
308[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime, 308[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
309 const VideoCommon::ImageInfo& info) { 309 const VideoCommon::ImageInfo& info) {
310 // Disable accelerated uploads for now as they don't implement swizzled uploads 310 return !runtime.HasNativeASTC() && IsPixelFormatASTC(info.format);
311 // Disable other accelerated uploads for now as they don't implement swizzled uploads
311 return false; 312 return false;
312 switch (info.type) { 313 switch (info.type) {
313 case ImageType::e2D: 314 case ImageType::e2D:
@@ -569,7 +570,11 @@ void TextureCacheRuntime::AccelerateImageUpload(Image& image, const ImageBufferM
569 std::span<const SwizzleParameters> swizzles) { 570 std::span<const SwizzleParameters> swizzles) {
570 switch (image.info.type) { 571 switch (image.info.type) {
571 case ImageType::e2D: 572 case ImageType::e2D:
572 return util_shaders.BlockLinearUpload2D(image, map, swizzles); 573 if (IsPixelFormatASTC(image.info.format)) {
574 return util_shaders.ASTCDecode(image, map, swizzles);
575 } else {
576 return util_shaders.BlockLinearUpload2D(image, map, swizzles);
577 }
573 case ImageType::e3D: 578 case ImageType::e3D:
574 return util_shaders.BlockLinearUpload3D(image, map, swizzles); 579 return util_shaders.BlockLinearUpload3D(image, map, swizzles);
575 case ImageType::Linear: 580 case ImageType::Linear:
@@ -599,6 +604,10 @@ FormatProperties TextureCacheRuntime::FormatInfo(ImageType type, GLenum internal
599 } 604 }
600} 605}
601 606
607bool TextureCacheRuntime::HasNativeASTC() const noexcept {
608 return device.HasASTC();
609}
610
602TextureCacheRuntime::StagingBuffers::StagingBuffers(GLenum storage_flags_, GLenum map_flags_) 611TextureCacheRuntime::StagingBuffers::StagingBuffers(GLenum storage_flags_, GLenum map_flags_)
603 : storage_flags{storage_flags_}, map_flags{map_flags_} {} 612 : storage_flags{storage_flags_}, map_flags{map_flags_} {}
604 613
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 3fbaa102f..3c871541b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -95,6 +95,8 @@ public:
95 return has_broken_texture_view_formats; 95 return has_broken_texture_view_formats;
96 } 96 }
97 97
98 bool HasNativeASTC() const noexcept;
99
98private: 100private:
99 struct StagingBuffers { 101 struct StagingBuffers {
100 explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); 102 explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 9d2acd4d9..cc2e499f9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -13,13 +13,13 @@
13#include "common/assert.h" 13#include "common/assert.h"
14#include "common/logging/log.h" 14#include "common/logging/log.h"
15#include "common/microprofile.h" 15#include "common/microprofile.h"
16#include "common/settings.h"
16#include "common/telemetry.h" 17#include "common/telemetry.h"
17#include "core/core.h" 18#include "core/core.h"
18#include "core/core_timing.h" 19#include "core/core_timing.h"
19#include "core/frontend/emu_window.h" 20#include "core/frontend/emu_window.h"
20#include "core/memory.h" 21#include "core/memory.h"
21#include "core/perf_stats.h" 22#include "core/perf_stats.h"
22#include "core/settings.h"
23#include "core/telemetry_session.h" 23#include "core/telemetry_session.h"
24#include "video_core/host_shaders/opengl_present_frag.h" 24#include "video_core/host_shaders/opengl_present_frag.h"
25#include "video_core/host_shaders/opengl_present_vert.h" 25#include "video_core/host_shaders/opengl_present_vert.h"
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp
index 2fe4799bc..47fddcb6e 100644
--- a/src/video_core/renderer_opengl/util_shaders.cpp
+++ b/src/video_core/renderer_opengl/util_shaders.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bit>
6#include <span> 5#include <span>
7#include <string_view> 6#include <string_view>
8 7
@@ -11,6 +10,7 @@
11#include "common/assert.h" 10#include "common/assert.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "common/div_ceil.h" 12#include "common/div_ceil.h"
13#include "video_core/host_shaders/astc_decoder_comp.h"
14#include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h" 14#include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h"
15#include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h" 15#include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h"
16#include "video_core/host_shaders/opengl_copy_bc4_comp.h" 16#include "video_core/host_shaders/opengl_copy_bc4_comp.h"
@@ -20,16 +20,18 @@
20#include "video_core/renderer_opengl/gl_shader_manager.h" 20#include "video_core/renderer_opengl/gl_shader_manager.h"
21#include "video_core/renderer_opengl/gl_texture_cache.h" 21#include "video_core/renderer_opengl/gl_texture_cache.h"
22#include "video_core/renderer_opengl/util_shaders.h" 22#include "video_core/renderer_opengl/util_shaders.h"
23#include "video_core/surface.h"
24#include "video_core/texture_cache/accelerated_swizzle.h" 23#include "video_core/texture_cache/accelerated_swizzle.h"
25#include "video_core/texture_cache/types.h" 24#include "video_core/texture_cache/types.h"
26#include "video_core/texture_cache/util.h" 25#include "video_core/texture_cache/util.h"
26#include "video_core/textures/astc.h"
27#include "video_core/textures/decoders.h" 27#include "video_core/textures/decoders.h"
28 28
29namespace OpenGL { 29namespace OpenGL {
30 30
31using namespace HostShaders; 31using namespace HostShaders;
32using namespace Tegra::Texture::ASTC;
32 33
34using VideoCommon::Extent2D;
33using VideoCommon::Extent3D; 35using VideoCommon::Extent3D;
34using VideoCommon::ImageCopy; 36using VideoCommon::ImageCopy;
35using VideoCommon::ImageType; 37using VideoCommon::ImageType;
@@ -57,7 +59,7 @@ size_t NumPixelsInCopy(const VideoCommon::ImageCopy& copy) {
57} // Anonymous namespace 59} // Anonymous namespace
58 60
59UtilShaders::UtilShaders(ProgramManager& program_manager_) 61UtilShaders::UtilShaders(ProgramManager& program_manager_)
60 : program_manager{program_manager_}, 62 : program_manager{program_manager_}, astc_decoder_program(MakeProgram(ASTC_DECODER_COMP)),
61 block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)), 63 block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)),
62 block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)), 64 block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)),
63 pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)), 65 pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)),
@@ -65,11 +67,79 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
65 copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) { 67 copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) {
66 const auto swizzle_table = Tegra::Texture::MakeSwizzleTable(); 68 const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
67 swizzle_table_buffer.Create(); 69 swizzle_table_buffer.Create();
70 astc_buffer.Create();
68 glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0); 71 glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0);
72 glNamedBufferStorage(astc_buffer.handle, sizeof(ASTC_BUFFER_DATA), &ASTC_BUFFER_DATA, 0);
69} 73}
70 74
71UtilShaders::~UtilShaders() = default; 75UtilShaders::~UtilShaders() = default;
72 76
77void UtilShaders::ASTCDecode(Image& image, const ImageBufferMap& map,
78 std::span<const VideoCommon::SwizzleParameters> swizzles) {
79 static constexpr GLuint BINDING_SWIZZLE_BUFFER = 0;
80 static constexpr GLuint BINDING_INPUT_BUFFER = 1;
81 static constexpr GLuint BINDING_ENC_BUFFER = 2;
82
83 static constexpr GLuint BINDING_6_TO_8_BUFFER = 3;
84 static constexpr GLuint BINDING_7_TO_8_BUFFER = 4;
85 static constexpr GLuint BINDING_8_TO_8_BUFFER = 5;
86 static constexpr GLuint BINDING_BYTE_TO_16_BUFFER = 6;
87
88 static constexpr GLuint BINDING_OUTPUT_IMAGE = 0;
89
90 const Extent2D tile_size{
91 .width = VideoCore::Surface::DefaultBlockWidth(image.info.format),
92 .height = VideoCore::Surface::DefaultBlockHeight(image.info.format),
93 };
94 program_manager.BindHostCompute(astc_decoder_program.handle);
95 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle);
96 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_ENC_BUFFER, astc_buffer.handle,
97 offsetof(AstcBufferData, encoding_values),
98 sizeof(AstcBufferData::encoding_values));
99 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_6_TO_8_BUFFER, astc_buffer.handle,
100 offsetof(AstcBufferData, replicate_6_to_8),
101 sizeof(AstcBufferData::replicate_6_to_8));
102 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_7_TO_8_BUFFER, astc_buffer.handle,
103 offsetof(AstcBufferData, replicate_7_to_8),
104 sizeof(AstcBufferData::replicate_7_to_8));
105 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_8_TO_8_BUFFER, astc_buffer.handle,
106 offsetof(AstcBufferData, replicate_8_to_8),
107 sizeof(AstcBufferData::replicate_8_to_8));
108 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_BYTE_TO_16_BUFFER, astc_buffer.handle,
109 offsetof(AstcBufferData, replicate_byte_to_16),
110 sizeof(AstcBufferData::replicate_byte_to_16));
111
112 glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes);
113 glUniform2ui(1, tile_size.width, tile_size.height);
114 // Ensure buffer data is valid before dispatching
115 glFlush();
116 for (const SwizzleParameters& swizzle : swizzles) {
117 const size_t input_offset = swizzle.buffer_offset + map.offset;
118 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U);
119 const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U);
120
121 const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info);
122 ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0}));
123 ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0}));
124
125 glUniform1ui(2, params.bytes_per_block_log2);
126 glUniform1ui(3, params.layer_stride);
127 glUniform1ui(4, params.block_size);
128 glUniform1ui(5, params.x_shift);
129 glUniform1ui(6, params.block_height);
130 glUniform1ui(7, params.block_height_mask);
131
132 glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
133 GL_WRITE_ONLY, GL_RGBA8);
134 // ASTC texture data
135 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
136 image.guest_size_bytes - swizzle.buffer_offset);
137
138 glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
139 }
140 program_manager.RestoreGuestCompute();
141}
142
73void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map, 143void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map,
74 std::span<const SwizzleParameters> swizzles) { 144 std::span<const SwizzleParameters> swizzles) {
75 static constexpr Extent3D WORKGROUP_SIZE{32, 32, 1}; 145 static constexpr Extent3D WORKGROUP_SIZE{32, 32, 1};
diff --git a/src/video_core/renderer_opengl/util_shaders.h b/src/video_core/renderer_opengl/util_shaders.h
index 93b009743..53d65f368 100644
--- a/src/video_core/renderer_opengl/util_shaders.h
+++ b/src/video_core/renderer_opengl/util_shaders.h
@@ -40,6 +40,9 @@ public:
40 explicit UtilShaders(ProgramManager& program_manager); 40 explicit UtilShaders(ProgramManager& program_manager);
41 ~UtilShaders(); 41 ~UtilShaders();
42 42
43 void ASTCDecode(Image& image, const ImageBufferMap& map,
44 std::span<const VideoCommon::SwizzleParameters> swizzles);
45
43 void BlockLinearUpload2D(Image& image, const ImageBufferMap& map, 46 void BlockLinearUpload2D(Image& image, const ImageBufferMap& map,
44 std::span<const VideoCommon::SwizzleParameters> swizzles); 47 std::span<const VideoCommon::SwizzleParameters> swizzles);
45 48
@@ -59,7 +62,9 @@ private:
59 ProgramManager& program_manager; 62 ProgramManager& program_manager;
60 63
61 OGLBuffer swizzle_table_buffer; 64 OGLBuffer swizzle_table_buffer;
65 OGLBuffer astc_buffer;
62 66
67 OGLProgram astc_decoder_program;
63 OGLProgram block_linear_unswizzle_2d_program; 68 OGLProgram block_linear_unswizzle_2d_program;
64 OGLProgram block_linear_unswizzle_3d_program; 69 OGLProgram block_linear_unswizzle_3d_program;
65 OGLProgram pitch_unswizzle_program; 70 OGLProgram pitch_unswizzle_program;
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 19aaf034f..f088447e9 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -166,7 +166,7 @@ struct FormatTuple {
166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT 166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT
167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM 167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM
168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT 168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT
169 {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // A8B8G8R8_SRGB 169 {VK_FORMAT_A8B8G8R8_SRGB_PACK32, Attachable}, // A8B8G8R8_SRGB
170 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM 170 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM
171 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM 171 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM
172 {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT 172 {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 1cc720ddd..2e0cf4232 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -13,11 +13,11 @@
13#include <fmt/format.h> 13#include <fmt/format.h>
14 14
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/settings.h"
16#include "common/telemetry.h" 17#include "common/telemetry.h"
17#include "core/core.h" 18#include "core/core.h"
18#include "core/core_timing.h" 19#include "core/core_timing.h"
19#include "core/frontend/emu_window.h" 20#include "core/frontend/emu_window.h"
20#include "core/settings.h"
21#include "core/telemetry_session.h" 21#include "core/telemetry_session.h"
22#include "video_core/gpu.h" 22#include "video_core/gpu.h"
23#include "video_core/renderer_vulkan/renderer_vulkan.h" 23#include "video_core/renderer_vulkan/renderer_vulkan.h"
@@ -143,7 +143,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
143 143
144 scheduler.WaitWorker(); 144 scheduler.WaitWorker();
145 145
146 swapchain.AcquireNextImage(); 146 while (!swapchain.AcquireNextImage()) {
147 swapchain.Create(layout.width, layout.height, is_srgb);
148 blit_screen.Recreate();
149 }
147 const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated); 150 const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated);
148 151
149 scheduler.Flush(render_semaphore); 152 scheduler.Flush(render_semaphore);
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 668633e7b..8cb65e588 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -176,7 +176,7 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset
176 u32 stride) { 176 u32 stride) {
177 if (device.IsExtExtendedDynamicStateSupported()) { 177 if (device.IsExtExtendedDynamicStateSupported()) {
178 scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { 178 scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) {
179 const VkDeviceSize vk_offset = offset; 179 const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0;
180 const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; 180 const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE;
181 const VkDeviceSize vk_stride = stride; 181 const VkDeviceSize vk_stride = stride;
182 cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); 182 cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride);
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 2f9a7b028..e11406e58 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -11,18 +11,39 @@
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/div_ceil.h" 13#include "common/div_ceil.h"
14#include "video_core/host_shaders/astc_decoder_comp_spv.h"
14#include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h" 15#include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h"
15#include "video_core/host_shaders/vulkan_uint8_comp_spv.h" 16#include "video_core/host_shaders/vulkan_uint8_comp_spv.h"
16#include "video_core/renderer_vulkan/vk_compute_pass.h" 17#include "video_core/renderer_vulkan/vk_compute_pass.h"
17#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 18#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
18#include "video_core/renderer_vulkan/vk_scheduler.h" 19#include "video_core/renderer_vulkan/vk_scheduler.h"
19#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 20#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
21#include "video_core/renderer_vulkan/vk_texture_cache.h"
20#include "video_core/renderer_vulkan/vk_update_descriptor.h" 22#include "video_core/renderer_vulkan/vk_update_descriptor.h"
23#include "video_core/texture_cache/accelerated_swizzle.h"
24#include "video_core/texture_cache/types.h"
25#include "video_core/textures/astc.h"
26#include "video_core/textures/decoders.h"
21#include "video_core/vulkan_common/vulkan_device.h" 27#include "video_core/vulkan_common/vulkan_device.h"
22#include "video_core/vulkan_common/vulkan_wrapper.h" 28#include "video_core/vulkan_common/vulkan_wrapper.h"
23 29
24namespace Vulkan { 30namespace Vulkan {
31
32using Tegra::Texture::SWIZZLE_TABLE;
33using Tegra::Texture::ASTC::EncodingsValues;
34using namespace Tegra::Texture::ASTC;
35
25namespace { 36namespace {
37
38constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0;
39constexpr u32 ASTC_BINDING_ENC_BUFFER = 1;
40constexpr u32 ASTC_BINDING_6_TO_8_BUFFER = 2;
41constexpr u32 ASTC_BINDING_7_TO_8_BUFFER = 3;
42constexpr u32 ASTC_BINDING_8_TO_8_BUFFER = 4;
43constexpr u32 ASTC_BINDING_BYTE_TO_16_BUFFER = 5;
44constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 6;
45constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 7;
46
26VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { 47VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
27 return { 48 return {
28 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, 49 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
@@ -50,6 +71,67 @@ std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBinding
50 }}; 71 }};
51} 72}
52 73
74std::array<VkDescriptorSetLayoutBinding, 8> BuildASTCDescriptorSetBindings() {
75 return {{
76 {
77 .binding = ASTC_BINDING_INPUT_BUFFER,
78 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
79 .descriptorCount = 1,
80 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
81 .pImmutableSamplers = nullptr,
82 },
83 {
84 .binding = ASTC_BINDING_ENC_BUFFER,
85 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
86 .descriptorCount = 1,
87 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
88 .pImmutableSamplers = nullptr,
89 },
90 {
91 .binding = ASTC_BINDING_6_TO_8_BUFFER,
92 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
93 .descriptorCount = 1,
94 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
95 .pImmutableSamplers = nullptr,
96 },
97 {
98 .binding = ASTC_BINDING_7_TO_8_BUFFER,
99 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
100 .descriptorCount = 1,
101 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
102 .pImmutableSamplers = nullptr,
103 },
104 {
105 .binding = ASTC_BINDING_8_TO_8_BUFFER,
106 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
107 .descriptorCount = 1,
108 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
109 .pImmutableSamplers = nullptr,
110 },
111 {
112 .binding = ASTC_BINDING_BYTE_TO_16_BUFFER,
113 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
114 .descriptorCount = 1,
115 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
116 .pImmutableSamplers = nullptr,
117 },
118 {
119 .binding = ASTC_BINDING_SWIZZLE_BUFFER,
120 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
121 .descriptorCount = 1,
122 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
123 .pImmutableSamplers = nullptr,
124 },
125 {
126 .binding = ASTC_BINDING_OUTPUT_IMAGE,
127 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
128 .descriptorCount = 1,
129 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
130 .pImmutableSamplers = nullptr,
131 },
132 }};
133}
134
53VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { 135VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
54 return { 136 return {
55 .dstBinding = 0, 137 .dstBinding = 0,
@@ -61,6 +143,94 @@ VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
61 }; 143 };
62} 144}
63 145
146std::array<VkDescriptorUpdateTemplateEntryKHR, 8> BuildASTCPassDescriptorUpdateTemplateEntry() {
147 return {{
148 {
149 .dstBinding = ASTC_BINDING_INPUT_BUFFER,
150 .dstArrayElement = 0,
151 .descriptorCount = 1,
152 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
153 .offset = ASTC_BINDING_INPUT_BUFFER * sizeof(DescriptorUpdateEntry),
154 .stride = sizeof(DescriptorUpdateEntry),
155 },
156 {
157 .dstBinding = ASTC_BINDING_ENC_BUFFER,
158 .dstArrayElement = 0,
159 .descriptorCount = 1,
160 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
161 .offset = ASTC_BINDING_ENC_BUFFER * sizeof(DescriptorUpdateEntry),
162 .stride = sizeof(DescriptorUpdateEntry),
163 },
164 {
165 .dstBinding = ASTC_BINDING_6_TO_8_BUFFER,
166 .dstArrayElement = 0,
167 .descriptorCount = 1,
168 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
169 .offset = ASTC_BINDING_6_TO_8_BUFFER * sizeof(DescriptorUpdateEntry),
170 .stride = sizeof(DescriptorUpdateEntry),
171 },
172 {
173 .dstBinding = ASTC_BINDING_7_TO_8_BUFFER,
174 .dstArrayElement = 0,
175 .descriptorCount = 1,
176 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
177 .offset = ASTC_BINDING_7_TO_8_BUFFER * sizeof(DescriptorUpdateEntry),
178 .stride = sizeof(DescriptorUpdateEntry),
179 },
180 {
181 .dstBinding = ASTC_BINDING_8_TO_8_BUFFER,
182 .dstArrayElement = 0,
183 .descriptorCount = 1,
184 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
185 .offset = ASTC_BINDING_8_TO_8_BUFFER * sizeof(DescriptorUpdateEntry),
186 .stride = sizeof(DescriptorUpdateEntry),
187 },
188 {
189 .dstBinding = ASTC_BINDING_BYTE_TO_16_BUFFER,
190 .dstArrayElement = 0,
191 .descriptorCount = 1,
192 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
193 .offset = ASTC_BINDING_BYTE_TO_16_BUFFER * sizeof(DescriptorUpdateEntry),
194 .stride = sizeof(DescriptorUpdateEntry),
195 },
196 {
197 .dstBinding = ASTC_BINDING_SWIZZLE_BUFFER,
198 .dstArrayElement = 0,
199 .descriptorCount = 1,
200 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
201 .offset = ASTC_BINDING_SWIZZLE_BUFFER * sizeof(DescriptorUpdateEntry),
202 .stride = sizeof(DescriptorUpdateEntry),
203 },
204 {
205 .dstBinding = ASTC_BINDING_OUTPUT_IMAGE,
206 .dstArrayElement = 0,
207 .descriptorCount = 1,
208 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
209 .offset = ASTC_BINDING_OUTPUT_IMAGE * sizeof(DescriptorUpdateEntry),
210 .stride = sizeof(DescriptorUpdateEntry),
211 },
212 }};
213}
214
215struct AstcPushConstants {
216 std::array<u32, 2> blocks_dims;
217 u32 bytes_per_block_log2;
218 u32 layer_stride;
219 u32 block_size;
220 u32 x_shift;
221 u32 block_height;
222 u32 block_height_mask;
223};
224
225struct AstcBufferData {
226 decltype(SWIZZLE_TABLE) swizzle_table_buffer = SWIZZLE_TABLE;
227 decltype(EncodingsValues) encoding_values = EncodingsValues;
228 decltype(REPLICATE_6_BIT_TO_8_TABLE) replicate_6_to_8 = REPLICATE_6_BIT_TO_8_TABLE;
229 decltype(REPLICATE_7_BIT_TO_8_TABLE) replicate_7_to_8 = REPLICATE_7_BIT_TO_8_TABLE;
230 decltype(REPLICATE_8_BIT_TO_8_TABLE) replicate_8_to_8 = REPLICATE_8_BIT_TO_8_TABLE;
231 decltype(REPLICATE_BYTE_TO_16_TABLE) replicate_byte_to_16 = REPLICATE_BYTE_TO_16_TABLE;
232} constexpr ASTC_BUFFER_DATA;
233
64} // Anonymous namespace 234} // Anonymous namespace
65 235
66VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool, 236VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool,
@@ -238,4 +408,167 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
238 return {staging.buffer, staging.offset}; 408 return {staging.buffer, staging.offset};
239} 409}
240 410
411ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_,
412 VKDescriptorPool& descriptor_pool_,
413 StagingBufferPool& staging_buffer_pool_,
414 VKUpdateDescriptorQueue& update_descriptor_queue_,
415 MemoryAllocator& memory_allocator_)
416 : VKComputePass(device_, descriptor_pool_, BuildASTCDescriptorSetBindings(),
417 BuildASTCPassDescriptorUpdateTemplateEntry(),
418 BuildComputePushConstantRange(sizeof(AstcPushConstants)),
419 ASTC_DECODER_COMP_SPV),
420 device{device_}, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
421 update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {}
422
423ASTCDecoderPass::~ASTCDecoderPass() = default;
424
425void ASTCDecoderPass::MakeDataBuffer() {
426 constexpr size_t TOTAL_BUFFER_SIZE = sizeof(ASTC_BUFFER_DATA) + sizeof(SWIZZLE_TABLE);
427 data_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
428 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
429 .pNext = nullptr,
430 .flags = 0,
431 .size = TOTAL_BUFFER_SIZE,
432 .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
433 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
434 .queueFamilyIndexCount = 0,
435 .pQueueFamilyIndices = nullptr,
436 });
437 data_buffer_commit = memory_allocator.Commit(data_buffer, MemoryUsage::Upload);
438
439 const auto staging_ref = staging_buffer_pool.Request(TOTAL_BUFFER_SIZE, MemoryUsage::Upload);
440 std::memcpy(staging_ref.mapped_span.data(), &ASTC_BUFFER_DATA, sizeof(ASTC_BUFFER_DATA));
441 // Tack on the swizzle table at the end of the buffer
442 std::memcpy(staging_ref.mapped_span.data() + sizeof(ASTC_BUFFER_DATA), &SWIZZLE_TABLE,
443 sizeof(SWIZZLE_TABLE));
444
445 scheduler.Record([src = staging_ref.buffer, offset = staging_ref.offset, dst = *data_buffer,
446 TOTAL_BUFFER_SIZE](vk::CommandBuffer cmdbuf) {
447 cmdbuf.CopyBuffer(src, dst,
448 VkBufferCopy{
449 .srcOffset = offset,
450 .dstOffset = 0,
451 .size = TOTAL_BUFFER_SIZE,
452 });
453 cmdbuf.PipelineBarrier(
454 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
455 VkMemoryBarrier{
456 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
457 .pNext = nullptr,
458 .srcAccessMask = 0,
459 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
460 });
461 });
462}
463
464void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
465 std::span<const VideoCommon::SwizzleParameters> swizzles) {
466 using namespace VideoCommon::Accelerated;
467 const std::array<u32, 2> block_dims{
468 VideoCore::Surface::DefaultBlockWidth(image.info.format),
469 VideoCore::Surface::DefaultBlockHeight(image.info.format),
470 };
471 scheduler.RequestOutsideRenderPassOperationContext();
472 if (!data_buffer) {
473 MakeDataBuffer();
474 }
475 const VkPipeline vk_pipeline = *pipeline;
476 const VkImageAspectFlags aspect_mask = image.AspectMask();
477 const VkImage vk_image = image.Handle();
478 const bool is_initialized = image.ExchangeInitialization();
479 scheduler.Record(
480 [vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) {
481 const VkImageMemoryBarrier image_barrier{
482 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
483 .pNext = nullptr,
484 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
485 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
486 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
487 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
488 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
489 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
490 .image = vk_image,
491 .subresourceRange{
492 .aspectMask = aspect_mask,
493 .baseMipLevel = 0,
494 .levelCount = VK_REMAINING_MIP_LEVELS,
495 .baseArrayLayer = 0,
496 .layerCount = VK_REMAINING_ARRAY_LAYERS,
497 },
498 };
499 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : 0,
500 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
501 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
502 });
503 for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
504 const size_t input_offset = swizzle.buffer_offset + map.offset;
505 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 32U);
506 const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U);
507 const u32 num_dispatches_z = image.info.resources.layers;
508
509 update_descriptor_queue.Acquire();
510 update_descriptor_queue.AddBuffer(map.buffer, input_offset,
511 image.guest_size_bytes - swizzle.buffer_offset);
512 update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, encoding_values),
513 sizeof(AstcBufferData::encoding_values));
514 update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_6_to_8),
515 sizeof(AstcBufferData::replicate_6_to_8));
516 update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_7_to_8),
517 sizeof(AstcBufferData::replicate_7_to_8));
518 update_descriptor_queue.AddBuffer(*data_buffer, offsetof(AstcBufferData, replicate_8_to_8),
519 sizeof(AstcBufferData::replicate_8_to_8));
520 update_descriptor_queue.AddBuffer(*data_buffer,
521 offsetof(AstcBufferData, replicate_byte_to_16),
522 sizeof(AstcBufferData::replicate_byte_to_16));
523 update_descriptor_queue.AddBuffer(*data_buffer, sizeof(AstcBufferData),
524 sizeof(SWIZZLE_TABLE));
525 update_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
526
527 const VkDescriptorSet set = CommitDescriptorSet(update_descriptor_queue);
528 const VkPipelineLayout vk_layout = *layout;
529
530 // To unswizzle the ASTC data
531 const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info);
532 ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0}));
533 ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0}));
534 scheduler.Record([vk_layout, num_dispatches_x, num_dispatches_y, num_dispatches_z,
535 block_dims, params, set](vk::CommandBuffer cmdbuf) {
536 const AstcPushConstants uniforms{
537 .blocks_dims = block_dims,
538 .bytes_per_block_log2 = params.bytes_per_block_log2,
539 .layer_stride = params.layer_stride,
540 .block_size = params.block_size,
541 .x_shift = params.x_shift,
542 .block_height = params.block_height,
543 .block_height_mask = params.block_height_mask,
544 };
545 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, vk_layout, 0, set, {});
546 cmdbuf.PushConstants(vk_layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
547 cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, num_dispatches_z);
548 });
549 }
550 scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) {
551 const VkImageMemoryBarrier image_barrier{
552 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
553 .pNext = nullptr,
554 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
555 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
556 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
557 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
558 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
559 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
560 .image = vk_image,
561 .subresourceRange{
562 .aspectMask = aspect_mask,
563 .baseMipLevel = 0,
564 .levelCount = VK_REMAINING_MIP_LEVELS,
565 .baseArrayLayer = 0,
566 .layerCount = VK_REMAINING_ARRAY_LAYERS,
567 },
568 };
569 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
570 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, image_barrier);
571 });
572}
573
241} // namespace Vulkan 574} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index 17d781d99..5ea187c30 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -11,14 +11,21 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/maxwell_3d.h" 12#include "video_core/engines/maxwell_3d.h"
13#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 13#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
14#include "video_core/vulkan_common/vulkan_memory_allocator.h"
14#include "video_core/vulkan_common/vulkan_wrapper.h" 15#include "video_core/vulkan_common/vulkan_wrapper.h"
15 16
17namespace VideoCommon {
18struct SwizzleParameters;
19}
20
16namespace Vulkan { 21namespace Vulkan {
17 22
18class Device; 23class Device;
19class StagingBufferPool; 24class StagingBufferPool;
20class VKScheduler; 25class VKScheduler;
21class VKUpdateDescriptorQueue; 26class VKUpdateDescriptorQueue;
27class Image;
28struct StagingBufferRef;
22 29
23class VKComputePass { 30class VKComputePass {
24public: 31public:
@@ -77,4 +84,29 @@ private:
77 VKUpdateDescriptorQueue& update_descriptor_queue; 84 VKUpdateDescriptorQueue& update_descriptor_queue;
78}; 85};
79 86
87class ASTCDecoderPass final : public VKComputePass {
88public:
89 explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_,
90 VKDescriptorPool& descriptor_pool_,
91 StagingBufferPool& staging_buffer_pool_,
92 VKUpdateDescriptorQueue& update_descriptor_queue_,
93 MemoryAllocator& memory_allocator_);
94 ~ASTCDecoderPass();
95
96 void Assemble(Image& image, const StagingBufferRef& map,
97 std::span<const VideoCommon::SwizzleParameters> swizzles);
98
99private:
100 void MakeDataBuffer();
101
102 const Device& device;
103 VKScheduler& scheduler;
104 StagingBufferPool& staging_buffer_pool;
105 VKUpdateDescriptorQueue& update_descriptor_queue;
106 MemoryAllocator& memory_allocator;
107
108 vk::Buffer data_buffer;
109 MemoryCommit data_buffer_commit;
110};
111
80} // namespace Vulkan 112} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index 56ec5e380..db78ce3d9 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -5,7 +5,7 @@
5#include <atomic> 5#include <atomic>
6#include <chrono> 6#include <chrono>
7 7
8#include "core/settings.h" 8#include "common/settings.h"
9#include "video_core/renderer_vulkan/vk_master_semaphore.h" 9#include "video_core/renderer_vulkan/vk_master_semaphore.h"
10#include "video_core/vulkan_common/vulkan_device.h" 10#include "video_core/vulkan_common/vulkan_device.h"
11#include "video_core/vulkan_common/vulkan_wrapper.h" 11#include "video_core/vulkan_common/vulkan_wrapper.h"
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index 2c7ed654d..4b6d64daa 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -35,8 +35,8 @@ public:
35 } 35 }
36 36
37 /// Returns true when a tick has been hit by the GPU. 37 /// Returns true when a tick has been hit by the GPU.
38 [[nodiscard]] bool IsFree(u64 tick) { 38 [[nodiscard]] bool IsFree(u64 tick) const noexcept {
39 return gpu_tick.load(std::memory_order_relaxed) >= tick; 39 return KnownGpuTick() >= tick;
40 } 40 }
41 41
42 /// Advance to the logical tick. 42 /// Advance to the logical tick.
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index dfd38f575..e9a0e7811 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -13,8 +13,8 @@
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/microprofile.h" 14#include "common/microprofile.h"
15#include "common/scope_exit.h" 15#include "common/scope_exit.h"
16#include "common/settings.h"
16#include "core/core.h" 17#include "core/core.h"
17#include "core/settings.h"
18#include "video_core/engines/kepler_compute.h" 18#include "video_core/engines/kepler_compute.h"
19#include "video_core/engines/maxwell_3d.h" 19#include "video_core/engines/maxwell_3d.h"
20#include "video_core/renderer_vulkan/blit_image.h" 20#include "video_core/renderer_vulkan/blit_image.h"
@@ -241,7 +241,10 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
241 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), 241 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
242 update_descriptor_queue(device, scheduler), 242 update_descriptor_queue(device, scheduler),
243 blit_image(device, scheduler, state_tracker, descriptor_pool), 243 blit_image(device, scheduler, state_tracker, descriptor_pool),
244 texture_cache_runtime{device, scheduler, memory_allocator, staging_pool, blit_image}, 244 astc_decoder_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue,
245 memory_allocator),
246 texture_cache_runtime{device, scheduler, memory_allocator,
247 staging_pool, blit_image, astc_decoder_pass},
245 texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), 248 texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory),
246 buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, 249 buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool,
247 update_descriptor_queue, descriptor_pool), 250 update_descriptor_queue, descriptor_pool),
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index acea1ba2d..235afc6f3 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -173,6 +173,7 @@ private:
173 VKDescriptorPool descriptor_pool; 173 VKDescriptorPool descriptor_pool;
174 VKUpdateDescriptorQueue update_descriptor_queue; 174 VKUpdateDescriptorQueue update_descriptor_queue;
175 BlitImageHelper blit_image; 175 BlitImageHelper blit_image;
176 ASTCDecoderPass astc_decoder_pass;
176 177
177 GraphicsPipelineCacheKey graphics_key; 178 GraphicsPipelineCacheKey graphics_key;
178 179
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 0b63bd6c8..dfd5c65ba 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -82,11 +82,13 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
82 resource_ticks.resize(image_count); 82 resource_ticks.resize(image_count);
83} 83}
84 84
85void VKSwapchain::AcquireNextImage() { 85bool VKSwapchain::AcquireNextImage() {
86 device.GetLogical().AcquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(), 86 const VkResult result =
87 *present_semaphores[frame_index], {}, &image_index); 87 device.GetLogical().AcquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(),
88 *present_semaphores[frame_index], {}, &image_index);
88 89
89 scheduler.Wait(resource_ticks[image_index]); 90 scheduler.Wait(resource_ticks[image_index]);
91 return result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR;
90} 92}
91 93
92bool VKSwapchain::Present(VkSemaphore render_semaphore) { 94bool VKSwapchain::Present(VkSemaphore render_semaphore) {
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index a728511e0..adc8d27cf 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -28,7 +28,7 @@ public:
28 void Create(u32 width, u32 height, bool srgb); 28 void Create(u32 width, u32 height, bool srgb);
29 29
30 /// Acquires the next image in the swapchain, waits as needed. 30 /// Acquires the next image in the swapchain, waits as needed.
31 void AcquireNextImage(); 31 bool AcquireNextImage();
32 32
33 /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be 33 /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be
34 /// recreated. Takes responsability for the ownership of fence. 34 /// recreated. Takes responsability for the ownership of fence.
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 22a1014a9..bc2a53841 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -7,9 +7,12 @@
7#include <span> 7#include <span>
8#include <vector> 8#include <vector>
9 9
10#include "common/bit_cast.h"
11
10#include "video_core/engines/fermi_2d.h" 12#include "video_core/engines/fermi_2d.h"
11#include "video_core/renderer_vulkan/blit_image.h" 13#include "video_core/renderer_vulkan/blit_image.h"
12#include "video_core/renderer_vulkan/maxwell_to_vk.h" 14#include "video_core/renderer_vulkan/maxwell_to_vk.h"
15#include "video_core/renderer_vulkan/vk_compute_pass.h"
13#include "video_core/renderer_vulkan/vk_rasterizer.h" 16#include "video_core/renderer_vulkan/vk_rasterizer.h"
14#include "video_core/renderer_vulkan/vk_scheduler.h" 17#include "video_core/renderer_vulkan/vk_scheduler.h"
15#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 18#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
@@ -807,7 +810,7 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
807 commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); 810 commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
808 } 811 }
809 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { 812 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
810 flags |= VideoCommon::ImageFlagBits::Converted; 813 flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
811 } 814 }
812 if (runtime.device.HasDebuggingToolAttached()) { 815 if (runtime.device.HasDebuggingToolAttached()) {
813 if (image) { 816 if (image) {
@@ -816,6 +819,38 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
816 buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); 819 buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
817 } 820 }
818 } 821 }
822 static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
823 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
824 .pNext = nullptr,
825 .usage = VK_IMAGE_USAGE_STORAGE_BIT,
826 };
827 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
828 const auto& device = runtime.device.GetLogical();
829 storage_image_views.reserve(info.resources.levels);
830 for (s32 level = 0; level < info.resources.levels; ++level) {
831 storage_image_views.push_back(device.CreateImageView(VkImageViewCreateInfo{
832 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
833 .pNext = &storage_image_view_usage_create_info,
834 .flags = 0,
835 .image = *image,
836 .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
837 .format = VK_FORMAT_A8B8G8R8_UNORM_PACK32,
838 .components{
839 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
840 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
841 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
842 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
843 },
844 .subresourceRange{
845 .aspectMask = aspect_mask,
846 .baseMipLevel = static_cast<u32>(level),
847 .levelCount = 1,
848 .baseArrayLayer = 0,
849 .layerCount = VK_REMAINING_ARRAY_LAYERS,
850 },
851 }));
852 }
853 }
819} 854}
820 855
821void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { 856void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
@@ -918,7 +953,6 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
918 } 953 }
919 } 954 }
920 const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); 955 const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
921 const VkFormat vk_format = format_info.format;
922 const VkImageViewUsageCreateInfo image_view_usage{ 956 const VkImageViewUsageCreateInfo image_view_usage{
923 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, 957 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
924 .pNext = nullptr, 958 .pNext = nullptr,
@@ -930,7 +964,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
930 .flags = 0, 964 .flags = 0,
931 .image = image.Handle(), 965 .image = image.Handle(),
932 .viewType = VkImageViewType{}, 966 .viewType = VkImageViewType{},
933 .format = vk_format, 967 .format = format_info.format,
934 .components{ 968 .components{
935 .r = ComponentSwizzle(swizzle[0]), 969 .r = ComponentSwizzle(swizzle[0]),
936 .g = ComponentSwizzle(swizzle[1]), 970 .g = ComponentSwizzle(swizzle[1]),
@@ -982,7 +1016,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
982 .pNext = nullptr, 1016 .pNext = nullptr,
983 .flags = 0, 1017 .flags = 0,
984 .buffer = image.Buffer(), 1018 .buffer = image.Buffer(),
985 .format = vk_format, 1019 .format = format_info.format,
986 .offset = 0, // TODO: Redesign buffer cache to support this 1020 .offset = 0, // TODO: Redesign buffer cache to support this
987 .range = image.guest_size_bytes, 1021 .range = image.guest_size_bytes,
988 }); 1022 });
@@ -1030,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) {
1030Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { 1064Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
1031 const auto& device = runtime.device; 1065 const auto& device = runtime.device;
1032 const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); 1066 const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported();
1033 const std::array<float, 4> color = tsc.BorderColor(); 1067 const auto color = tsc.BorderColor();
1034 // C++20 bit_cast 1068
1035 VkClearColorValue border_color;
1036 std::memcpy(&border_color, &color, sizeof(color));
1037 const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ 1069 const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
1038 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, 1070 .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
1039 .pNext = nullptr, 1071 .pNext = nullptr,
1040 .customBorderColor = border_color, 1072 // TODO: Make use of std::bit_cast once libc++ supports it.
1073 .customBorderColor = Common::BitCast<VkClearColorValue>(color),
1041 .format = VK_FORMAT_UNDEFINED, 1074 .format = VK_FORMAT_UNDEFINED,
1042 }; 1075 };
1043 const void* pnext = nullptr; 1076 const void* pnext = nullptr;
@@ -1167,4 +1200,13 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
1167 } 1200 }
1168} 1201}
1169 1202
1203void TextureCacheRuntime::AccelerateImageUpload(
1204 Image& image, const StagingBufferRef& map,
1205 std::span<const VideoCommon::SwizzleParameters> swizzles) {
1206 if (IsPixelFormatASTC(image.info.format)) {
1207 return astc_decoder_pass.Assemble(image, map, swizzles);
1208 }
1209 UNREACHABLE();
1210}
1211
1170} // namespace Vulkan 1212} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 3aee27ce0..628785d5e 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -20,6 +20,7 @@ using VideoCommon::Offset2D;
20using VideoCommon::RenderTargets; 20using VideoCommon::RenderTargets;
21using VideoCore::Surface::PixelFormat; 21using VideoCore::Surface::PixelFormat;
22 22
23class ASTCDecoderPass;
23class BlitImageHelper; 24class BlitImageHelper;
24class Device; 25class Device;
25class Image; 26class Image;
@@ -60,6 +61,7 @@ struct TextureCacheRuntime {
60 MemoryAllocator& memory_allocator; 61 MemoryAllocator& memory_allocator;
61 StagingBufferPool& staging_buffer_pool; 62 StagingBufferPool& staging_buffer_pool;
62 BlitImageHelper& blit_image_helper; 63 BlitImageHelper& blit_image_helper;
64 ASTCDecoderPass& astc_decoder_pass;
63 std::unordered_map<RenderPassKey, vk::RenderPass> renderpass_cache{}; 65 std::unordered_map<RenderPassKey, vk::RenderPass> renderpass_cache{};
64 66
65 void Finish(); 67 void Finish();
@@ -83,9 +85,7 @@ struct TextureCacheRuntime {
83 } 85 }
84 86
85 void AccelerateImageUpload(Image&, const StagingBufferRef&, 87 void AccelerateImageUpload(Image&, const StagingBufferRef&,
86 std::span<const VideoCommon::SwizzleParameters>) { 88 std::span<const VideoCommon::SwizzleParameters>);
87 UNREACHABLE();
88 }
89 89
90 void InsertUploadMemoryBarrier() {} 90 void InsertUploadMemoryBarrier() {}
91 91
@@ -121,15 +121,26 @@ public:
121 return *buffer; 121 return *buffer;
122 } 122 }
123 123
124 [[nodiscard]] VkImageCreateFlags AspectMask() const noexcept { 124 [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
125 return aspect_mask; 125 return aspect_mask;
126 } 126 }
127 127
128 [[nodiscard]] VkImageView StorageImageView(s32 level) const noexcept {
129 return *storage_image_views[level];
130 }
131
132 /// Returns true when the image is already initialized and mark it as initialized
133 [[nodiscard]] bool ExchangeInitialization() noexcept {
134 return std::exchange(initialized, true);
135 }
136
128private: 137private:
129 VKScheduler* scheduler; 138 VKScheduler* scheduler;
130 vk::Image image; 139 vk::Image image;
131 vk::Buffer buffer; 140 vk::Buffer buffer;
132 MemoryCommit commit; 141 MemoryCommit commit;
142 vk::ImageView image_view;
143 std::vector<vk::ImageView> storage_image_views;
133 VkImageAspectFlags aspect_mask = 0; 144 VkImageAspectFlags aspect_mask = 0;
134 bool initialized = false; 145 bool initialized = false;
135}; 146};
diff --git a/src/video_core/texture_cache/accelerated_swizzle.h b/src/video_core/texture_cache/accelerated_swizzle.h
index 6ec5c78c4..a11c924e1 100644
--- a/src/video_core/texture_cache/accelerated_swizzle.h
+++ b/src/video_core/texture_cache/accelerated_swizzle.h
@@ -13,8 +13,8 @@
13namespace VideoCommon::Accelerated { 13namespace VideoCommon::Accelerated {
14 14
15struct BlockLinearSwizzle2DParams { 15struct BlockLinearSwizzle2DParams {
16 std::array<u32, 3> origin; 16 alignas(16) std::array<u32, 3> origin;
17 std::array<s32, 3> destination; 17 alignas(16) std::array<s32, 3> destination;
18 u32 bytes_per_block_log2; 18 u32 bytes_per_block_log2;
19 u32 layer_stride; 19 u32 layer_stride;
20 u32 block_size; 20 u32 block_size;
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index f89a40b4c..e8d632f9e 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -5,7 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "core/settings.h" 8#include "common/settings.h"
9#include "video_core/compatible_formats.h" 9#include "video_core/compatible_formats.h"
10#include "video_core/surface.h" 10#include "video_core/surface.h"
11#include "video_core/texture_cache/formatter.h" 11#include "video_core/texture_cache/formatter.h"
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 2c42d1449..0ab297413 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -47,7 +47,6 @@
47#include "video_core/texture_cache/formatter.h" 47#include "video_core/texture_cache/formatter.h"
48#include "video_core/texture_cache/samples_helper.h" 48#include "video_core/texture_cache/samples_helper.h"
49#include "video_core/texture_cache/util.h" 49#include "video_core/texture_cache/util.h"
50#include "video_core/textures/astc.h"
51#include "video_core/textures/decoders.h" 50#include "video_core/textures/decoders.h"
52 51
53namespace VideoCommon { 52namespace VideoCommon {
@@ -269,16 +268,19 @@ template <u32 GOB_EXTENT>
269 return num_tiles << shift; 268 return num_tiles << shift;
270} 269}
271 270
272[[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info, 271[[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) {
273 u32 num_levels) {
274 ASSERT(num_levels <= MAX_MIP_LEVELS); 272 ASSERT(num_levels <= MAX_MIP_LEVELS);
275 std::array<u32, MAX_MIP_LEVELS> sizes{}; 273 LevelArray sizes{};
276 for (u32 level = 0; level < num_levels; ++level) { 274 for (u32 level = 0; level < num_levels; ++level) {
277 sizes[level] = CalculateLevelSize(info, level); 275 sizes[level] = CalculateLevelSize(info, level);
278 } 276 }
279 return sizes; 277 return sizes;
280} 278}
281 279
280[[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) {
281 return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U);
282}
283
282[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, 284[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
283 u32 num_samples, u32 tile_width_spacing) { 285 u32 num_samples, u32 tile_width_spacing) {
284 const auto [samples_x, samples_y] = Samples(num_samples); 286 const auto [samples_x, samples_y] = Samples(num_samples);
@@ -567,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
567 569
568 const u32 num_levels = info.resources.levels; 570 const u32 num_levels = info.resources.levels;
569 const std::array sizes = CalculateLevelSizes(level_info, num_levels); 571 const std::array sizes = CalculateLevelSizes(level_info, num_levels);
570 size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0); 572 size_t guest_offset = CalculateLevelBytes(sizes, level);
571 const size_t layer_stride = 573 const size_t layer_stride =
572 AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size, 574 AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block,
573 level_info.block, tile_size.height, info.tile_width_spacing); 575 tile_size.height, info.tile_width_spacing);
574 const size_t subresource_size = sizes[level]; 576 const size_t subresource_size = sizes[level];
575 577
576 const auto dst_data = std::make_unique<u8[]>(subresource_size); 578 const auto dst_data = std::make_unique<u8[]>(subresource_size);
@@ -644,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept {
644 info.tile_width_spacing, info.resources.levels); 646 info.tile_width_spacing, info.resources.levels);
645} 647}
646 648
647std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { 649LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
648 ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); 650 ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS));
649 const LevelInfo level_info = MakeLevelInfo(info); 651 const LevelInfo level_info = MakeLevelInfo(info);
650 std::array<u32, MAX_MIP_LEVELS> offsets{}; 652 LevelArray offsets{};
651 u32 offset = 0; 653 u32 offset = 0;
652 for (s32 level = 0; level < info.resources.levels; ++level) { 654 for (s32 level = 0; level < info.resources.levels; ++level) {
653 offsets[level] = offset; 655 offsets[level] = offset;
@@ -813,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP
813 const Extent2D tile_size = DefaultBlockSize(info.format); 815 const Extent2D tile_size = DefaultBlockSize(info.format);
814 const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); 816 const std::array level_sizes = CalculateLevelSizes(level_info, num_levels);
815 const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); 817 const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing);
816 const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0); 818 const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels);
817 const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, 819 const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height,
818 info.tile_width_spacing); 820 info.tile_width_spacing);
819 size_t guest_offset = 0; 821 size_t guest_offset = 0;
@@ -879,17 +881,8 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
879 ASSERT(copy.image_extent == mip_size); 881 ASSERT(copy.image_extent == mip_size);
880 ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width)); 882 ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width));
881 ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height)); 883 ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height));
882 884 DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent,
883 if (IsPixelFormatASTC(info.format)) { 885 output.subspan(output_offset));
884 ASSERT(copy.image_extent.depth == 1);
885 Tegra::Texture::ASTC::Decompress(input.subspan(copy.buffer_offset),
886 copy.image_extent.width, copy.image_extent.height,
887 copy.image_subresource.num_layers, tile_size.width,
888 tile_size.height, output.subspan(output_offset));
889 } else {
890 DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent,
891 output.subspan(output_offset));
892 }
893 copy.buffer_offset = output_offset; 886 copy.buffer_offset = output_offset;
894 copy.buffer_row_length = mip_size.width; 887 copy.buffer_row_length = mip_size.width;
895 copy.buffer_image_height = mip_size.height; 888 copy.buffer_image_height = mip_size.height;
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index 4d0072867..cdc5cbc75 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -20,6 +20,8 @@ namespace VideoCommon {
20 20
21using Tegra::Texture::TICEntry; 21using Tegra::Texture::TICEntry;
22 22
23using LevelArray = std::array<u32, MAX_MIP_LEVELS>;
24
23struct OverlapResult { 25struct OverlapResult {
24 GPUVAddr gpu_addr; 26 GPUVAddr gpu_addr;
25 VAddr cpu_addr; 27 VAddr cpu_addr;
@@ -36,8 +38,7 @@ struct OverlapResult {
36 38
37[[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; 39[[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept;
38 40
39[[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets( 41[[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept;
40 const ImageInfo& info) noexcept;
41 42
42[[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); 43[[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info);
43 44
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
deleted file mode 100644
index 3625b666c..000000000
--- a/src/video_core/textures/astc.cpp
+++ /dev/null
@@ -1,1710 +0,0 @@
1// Copyright 2016 The University of North Carolina at Chapel Hill
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
16// <http://gamma.cs.unc.edu/FasTC/>
17
18#include <algorithm>
19#include <cassert>
20#include <cstring>
21#include <span>
22#include <vector>
23
24#include <boost/container/static_vector.hpp>
25
26#include "common/common_types.h"
27
28#include "video_core/textures/astc.h"
29
30namespace {
31
32/// Count the number of bits set in a number.
33constexpr u32 Popcnt(u32 n) {
34 u32 c = 0;
35 for (; n; c++) {
36 n &= n - 1;
37 }
38 return c;
39}
40
41} // Anonymous namespace
42
43class InputBitStream {
44public:
45 constexpr explicit InputBitStream(std::span<const u8> data, size_t start_offset = 0)
46 : cur_byte{data.data()}, total_bits{data.size()}, next_bit{start_offset % 8} {}
47
48 constexpr size_t GetBitsRead() const {
49 return bits_read;
50 }
51
52 constexpr bool ReadBit() {
53 if (bits_read >= total_bits * 8) {
54 return 0;
55 }
56 const bool bit = ((*cur_byte >> next_bit) & 1) != 0;
57 ++next_bit;
58 while (next_bit >= 8) {
59 next_bit -= 8;
60 ++cur_byte;
61 }
62 ++bits_read;
63 return bit;
64 }
65
66 constexpr u32 ReadBits(std::size_t nBits) {
67 u32 ret = 0;
68 for (std::size_t i = 0; i < nBits; ++i) {
69 ret |= (ReadBit() & 1) << i;
70 }
71 return ret;
72 }
73
74 template <std::size_t nBits>
75 constexpr u32 ReadBits() {
76 u32 ret = 0;
77 for (std::size_t i = 0; i < nBits; ++i) {
78 ret |= (ReadBit() & 1) << i;
79 }
80 return ret;
81 }
82
83private:
84 const u8* cur_byte;
85 size_t total_bits = 0;
86 size_t next_bit = 0;
87 size_t bits_read = 0;
88};
89
90class OutputBitStream {
91public:
92 constexpr explicit OutputBitStream(u8* ptr, std::size_t bits = 0, std::size_t start_offset = 0)
93 : cur_byte{ptr}, num_bits{bits}, next_bit{start_offset % 8} {}
94
95 constexpr std::size_t GetBitsWritten() const {
96 return bits_written;
97 }
98
99 constexpr void WriteBitsR(u32 val, u32 nBits) {
100 for (u32 i = 0; i < nBits; i++) {
101 WriteBit((val >> (nBits - i - 1)) & 1);
102 }
103 }
104
105 constexpr void WriteBits(u32 val, u32 nBits) {
106 for (u32 i = 0; i < nBits; i++) {
107 WriteBit((val >> i) & 1);
108 }
109 }
110
111private:
112 constexpr void WriteBit(bool b) {
113 if (bits_written >= num_bits) {
114 return;
115 }
116
117 const u32 mask = 1 << next_bit++;
118
119 // clear the bit
120 *cur_byte &= static_cast<u8>(~mask);
121
122 // Write the bit, if necessary
123 if (b)
124 *cur_byte |= static_cast<u8>(mask);
125
126 // Next byte?
127 if (next_bit >= 8) {
128 cur_byte += 1;
129 next_bit = 0;
130 }
131 }
132
133 u8* cur_byte;
134 std::size_t num_bits;
135 std::size_t bits_written = 0;
136 std::size_t next_bit = 0;
137};
138
139template <typename IntType>
140class Bits {
141public:
142 explicit Bits(const IntType& v) : m_Bits(v) {}
143
144 Bits(const Bits&) = delete;
145 Bits& operator=(const Bits&) = delete;
146
147 u8 operator[](u32 bitPos) const {
148 return static_cast<u8>((m_Bits >> bitPos) & 1);
149 }
150
151 IntType operator()(u32 start, u32 end) const {
152 if (start == end) {
153 return (*this)[start];
154 } else if (start > end) {
155 u32 t = start;
156 start = end;
157 end = t;
158 }
159
160 u64 mask = (1 << (end - start + 1)) - 1;
161 return (m_Bits >> start) & static_cast<IntType>(mask);
162 }
163
164private:
165 const IntType& m_Bits;
166};
167
168enum class IntegerEncoding { JustBits, Qus32, Trit };
169
170struct IntegerEncodedValue {
171 constexpr IntegerEncodedValue() = default;
172
173 constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
174 : encoding{encoding_}, num_bits{num_bits_} {}
175
176 constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
177 return encoding == other.encoding && num_bits == other.num_bits;
178 }
179
180 // Returns the number of bits required to encode nVals values.
181 u32 GetBitLength(u32 nVals) const {
182 u32 totalBits = num_bits * nVals;
183 if (encoding == IntegerEncoding::Trit) {
184 totalBits += (nVals * 8 + 4) / 5;
185 } else if (encoding == IntegerEncoding::Qus32) {
186 totalBits += (nVals * 7 + 2) / 3;
187 }
188 return totalBits;
189 }
190
191 IntegerEncoding encoding{};
192 u32 num_bits = 0;
193 u32 bit_value = 0;
194 union {
195 u32 qus32_value = 0;
196 u32 trit_value;
197 };
198};
199using IntegerEncodedVector = boost::container::static_vector<
200 IntegerEncodedValue, 256,
201 boost::container::static_vector_options<
202 boost::container::inplace_alignment<alignof(IntegerEncodedValue)>,
203 boost::container::throw_on_overflow<false>>::type>;
204
205static void DecodeTritBlock(InputBitStream& bits, IntegerEncodedVector& result, u32 nBitsPerValue) {
206 // Implement the algorithm in section C.2.12
207 std::array<u32, 5> m;
208 std::array<u32, 5> t;
209 u32 T;
210
211 // Read the trit encoded block according to
212 // table C.2.14
213 m[0] = bits.ReadBits(nBitsPerValue);
214 T = bits.ReadBits<2>();
215 m[1] = bits.ReadBits(nBitsPerValue);
216 T |= bits.ReadBits<2>() << 2;
217 m[2] = bits.ReadBits(nBitsPerValue);
218 T |= bits.ReadBit() << 4;
219 m[3] = bits.ReadBits(nBitsPerValue);
220 T |= bits.ReadBits<2>() << 5;
221 m[4] = bits.ReadBits(nBitsPerValue);
222 T |= bits.ReadBit() << 7;
223
224 u32 C = 0;
225
226 Bits<u32> Tb(T);
227 if (Tb(2, 4) == 7) {
228 C = (Tb(5, 7) << 2) | Tb(0, 1);
229 t[4] = t[3] = 2;
230 } else {
231 C = Tb(0, 4);
232 if (Tb(5, 6) == 3) {
233 t[4] = 2;
234 t[3] = Tb[7];
235 } else {
236 t[4] = Tb[7];
237 t[3] = Tb(5, 6);
238 }
239 }
240
241 Bits<u32> Cb(C);
242 if (Cb(0, 1) == 3) {
243 t[2] = 2;
244 t[1] = Cb[4];
245 t[0] = (Cb[3] << 1) | (Cb[2] & ~Cb[3]);
246 } else if (Cb(2, 3) == 3) {
247 t[2] = 2;
248 t[1] = 2;
249 t[0] = Cb(0, 1);
250 } else {
251 t[2] = Cb[4];
252 t[1] = Cb(2, 3);
253 t[0] = (Cb[1] << 1) | (Cb[0] & ~Cb[1]);
254 }
255
256 for (std::size_t i = 0; i < 5; ++i) {
257 IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Trit, nBitsPerValue);
258 val.bit_value = m[i];
259 val.trit_value = t[i];
260 }
261}
262
263static void DecodeQus32Block(InputBitStream& bits, IntegerEncodedVector& result,
264 u32 nBitsPerValue) {
265 // Implement the algorithm in section C.2.12
266 u32 m[3];
267 u32 q[3];
268 u32 Q;
269
270 // Read the trit encoded block according to
271 // table C.2.15
272 m[0] = bits.ReadBits(nBitsPerValue);
273 Q = bits.ReadBits<3>();
274 m[1] = bits.ReadBits(nBitsPerValue);
275 Q |= bits.ReadBits<2>() << 3;
276 m[2] = bits.ReadBits(nBitsPerValue);
277 Q |= bits.ReadBits<2>() << 5;
278
279 Bits<u32> Qb(Q);
280 if (Qb(1, 2) == 3 && Qb(5, 6) == 0) {
281 q[0] = q[1] = 4;
282 q[2] = (Qb[0] << 2) | ((Qb[4] & ~Qb[0]) << 1) | (Qb[3] & ~Qb[0]);
283 } else {
284 u32 C = 0;
285 if (Qb(1, 2) == 3) {
286 q[2] = 4;
287 C = (Qb(3, 4) << 3) | ((~Qb(5, 6) & 3) << 1) | Qb[0];
288 } else {
289 q[2] = Qb(5, 6);
290 C = Qb(0, 4);
291 }
292
293 Bits<u32> Cb(C);
294 if (Cb(0, 2) == 5) {
295 q[1] = 4;
296 q[0] = Cb(3, 4);
297 } else {
298 q[1] = Cb(3, 4);
299 q[0] = Cb(0, 2);
300 }
301 }
302
303 for (std::size_t i = 0; i < 3; ++i) {
304 IntegerEncodedValue& val = result.emplace_back(IntegerEncoding::Qus32, nBitsPerValue);
305 val.bit_value = m[i];
306 val.qus32_value = q[i];
307 }
308}
309
310// Returns a new instance of this struct that corresponds to the
311// can take no more than maxval values
312static constexpr IntegerEncodedValue CreateEncoding(u32 maxVal) {
313 while (maxVal > 0) {
314 u32 check = maxVal + 1;
315
316 // Is maxVal a power of two?
317 if (!(check & (check - 1))) {
318 return IntegerEncodedValue(IntegerEncoding::JustBits, Popcnt(maxVal));
319 }
320
321 // Is maxVal of the type 3*2^n - 1?
322 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
323 return IntegerEncodedValue(IntegerEncoding::Trit, Popcnt(check / 3 - 1));
324 }
325
326 // Is maxVal of the type 5*2^n - 1?
327 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
328 return IntegerEncodedValue(IntegerEncoding::Qus32, Popcnt(check / 5 - 1));
329 }
330
331 // Apparently it can't be represented with a bounded integer sequence...
332 // just iterate.
333 maxVal--;
334 }
335 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
336}
337
338static constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
339 std::array<IntegerEncodedValue, 256> encodings{};
340 for (std::size_t i = 0; i < encodings.size(); ++i) {
341 encodings[i] = CreateEncoding(static_cast<u32>(i));
342 }
343 return encodings;
344}
345
346static constexpr std::array EncodingsValues = MakeEncodedValues();
347
348// Fills result with the values that are encoded in the given
349// bitstream. We must know beforehand what the maximum possible
350// value is, and how many values we're decoding.
351static void DecodeIntegerSequence(IntegerEncodedVector& result, InputBitStream& bits, u32 maxRange,
352 u32 nValues) {
353 // Determine encoding parameters
354 IntegerEncodedValue val = EncodingsValues[maxRange];
355
356 // Start decoding
357 u32 nValsDecoded = 0;
358 while (nValsDecoded < nValues) {
359 switch (val.encoding) {
360 case IntegerEncoding::Qus32:
361 DecodeQus32Block(bits, result, val.num_bits);
362 nValsDecoded += 3;
363 break;
364
365 case IntegerEncoding::Trit:
366 DecodeTritBlock(bits, result, val.num_bits);
367 nValsDecoded += 5;
368 break;
369
370 case IntegerEncoding::JustBits:
371 val.bit_value = bits.ReadBits(val.num_bits);
372 result.push_back(val);
373 nValsDecoded++;
374 break;
375 }
376 }
377}
378
379namespace ASTCC {
380
381struct TexelWeightParams {
382 u32 m_Width = 0;
383 u32 m_Height = 0;
384 bool m_bDualPlane = false;
385 u32 m_MaxWeight = 0;
386 bool m_bError = false;
387 bool m_bVoidExtentLDR = false;
388 bool m_bVoidExtentHDR = false;
389
390 u32 GetPackedBitSize() const {
391 // How many indices do we have?
392 u32 nIdxs = m_Height * m_Width;
393 if (m_bDualPlane) {
394 nIdxs *= 2;
395 }
396
397 return EncodingsValues[m_MaxWeight].GetBitLength(nIdxs);
398 }
399
400 u32 GetNumWeightValues() const {
401 u32 ret = m_Width * m_Height;
402 if (m_bDualPlane) {
403 ret *= 2;
404 }
405 return ret;
406 }
407};
408
409static TexelWeightParams DecodeBlockInfo(InputBitStream& strm) {
410 TexelWeightParams params;
411
412 // Read the entire block mode all at once
413 u16 modeBits = static_cast<u16>(strm.ReadBits<11>());
414
415 // Does this match the void extent block mode?
416 if ((modeBits & 0x01FF) == 0x1FC) {
417 if (modeBits & 0x200) {
418 params.m_bVoidExtentHDR = true;
419 } else {
420 params.m_bVoidExtentLDR = true;
421 }
422
423 // Next two bits must be one.
424 if (!(modeBits & 0x400) || !strm.ReadBit()) {
425 params.m_bError = true;
426 }
427
428 return params;
429 }
430
431 // First check if the last four bits are zero
432 if ((modeBits & 0xF) == 0) {
433 params.m_bError = true;
434 return params;
435 }
436
437 // If the last two bits are zero, then if bits
438 // [6-8] are all ones, this is also reserved.
439 if ((modeBits & 0x3) == 0 && (modeBits & 0x1C0) == 0x1C0) {
440 params.m_bError = true;
441 return params;
442 }
443
444 // Otherwise, there is no error... Figure out the layout
445 // of the block mode. Layout is determined by a number
446 // between 0 and 9 corresponding to table C.2.8 of the
447 // ASTC spec.
448 u32 layout = 0;
449
450 if ((modeBits & 0x1) || (modeBits & 0x2)) {
451 // layout is in [0-4]
452 if (modeBits & 0x8) {
453 // layout is in [2-4]
454 if (modeBits & 0x4) {
455 // layout is in [3-4]
456 if (modeBits & 0x100) {
457 layout = 4;
458 } else {
459 layout = 3;
460 }
461 } else {
462 layout = 2;
463 }
464 } else {
465 // layout is in [0-1]
466 if (modeBits & 0x4) {
467 layout = 1;
468 } else {
469 layout = 0;
470 }
471 }
472 } else {
473 // layout is in [5-9]
474 if (modeBits & 0x100) {
475 // layout is in [7-9]
476 if (modeBits & 0x80) {
477 // layout is in [7-8]
478 assert((modeBits & 0x40) == 0U);
479 if (modeBits & 0x20) {
480 layout = 8;
481 } else {
482 layout = 7;
483 }
484 } else {
485 layout = 9;
486 }
487 } else {
488 // layout is in [5-6]
489 if (modeBits & 0x80) {
490 layout = 6;
491 } else {
492 layout = 5;
493 }
494 }
495 }
496
497 assert(layout < 10);
498
499 // Determine R
500 u32 R = !!(modeBits & 0x10);
501 if (layout < 5) {
502 R |= (modeBits & 0x3) << 1;
503 } else {
504 R |= (modeBits & 0xC) >> 1;
505 }
506 assert(2 <= R && R <= 7);
507
508 // Determine width & height
509 switch (layout) {
510 case 0: {
511 u32 A = (modeBits >> 5) & 0x3;
512 u32 B = (modeBits >> 7) & 0x3;
513 params.m_Width = B + 4;
514 params.m_Height = A + 2;
515 break;
516 }
517
518 case 1: {
519 u32 A = (modeBits >> 5) & 0x3;
520 u32 B = (modeBits >> 7) & 0x3;
521 params.m_Width = B + 8;
522 params.m_Height = A + 2;
523 break;
524 }
525
526 case 2: {
527 u32 A = (modeBits >> 5) & 0x3;
528 u32 B = (modeBits >> 7) & 0x3;
529 params.m_Width = A + 2;
530 params.m_Height = B + 8;
531 break;
532 }
533
534 case 3: {
535 u32 A = (modeBits >> 5) & 0x3;
536 u32 B = (modeBits >> 7) & 0x1;
537 params.m_Width = A + 2;
538 params.m_Height = B + 6;
539 break;
540 }
541
542 case 4: {
543 u32 A = (modeBits >> 5) & 0x3;
544 u32 B = (modeBits >> 7) & 0x1;
545 params.m_Width = B + 2;
546 params.m_Height = A + 2;
547 break;
548 }
549
550 case 5: {
551 u32 A = (modeBits >> 5) & 0x3;
552 params.m_Width = 12;
553 params.m_Height = A + 2;
554 break;
555 }
556
557 case 6: {
558 u32 A = (modeBits >> 5) & 0x3;
559 params.m_Width = A + 2;
560 params.m_Height = 12;
561 break;
562 }
563
564 case 7: {
565 params.m_Width = 6;
566 params.m_Height = 10;
567 break;
568 }
569
570 case 8: {
571 params.m_Width = 10;
572 params.m_Height = 6;
573 break;
574 }
575
576 case 9: {
577 u32 A = (modeBits >> 5) & 0x3;
578 u32 B = (modeBits >> 9) & 0x3;
579 params.m_Width = A + 6;
580 params.m_Height = B + 6;
581 break;
582 }
583
584 default:
585 assert(false && "Don't know this layout...");
586 params.m_bError = true;
587 break;
588 }
589
590 // Determine whether or not we're using dual planes
591 // and/or high precision layouts.
592 bool D = (layout != 9) && (modeBits & 0x400);
593 bool H = (layout != 9) && (modeBits & 0x200);
594
595 if (H) {
596 const u32 maxWeights[6] = {9, 11, 15, 19, 23, 31};
597 params.m_MaxWeight = maxWeights[R - 2];
598 } else {
599 const u32 maxWeights[6] = {1, 2, 3, 4, 5, 7};
600 params.m_MaxWeight = maxWeights[R - 2];
601 }
602
603 params.m_bDualPlane = D;
604
605 return params;
606}
607
608static void FillVoidExtentLDR(InputBitStream& strm, std::span<u32> outBuf, u32 blockWidth,
609 u32 blockHeight) {
610 // Don't actually care about the void extent, just read the bits...
611 for (s32 i = 0; i < 4; ++i) {
612 strm.ReadBits<13>();
613 }
614
615 // Decode the RGBA components and renormalize them to the range [0, 255]
616 u16 r = static_cast<u16>(strm.ReadBits<16>());
617 u16 g = static_cast<u16>(strm.ReadBits<16>());
618 u16 b = static_cast<u16>(strm.ReadBits<16>());
619 u16 a = static_cast<u16>(strm.ReadBits<16>());
620
621 u32 rgba = (r >> 8) | (g & 0xFF00) | (static_cast<u32>(b) & 0xFF00) << 8 |
622 (static_cast<u32>(a) & 0xFF00) << 16;
623
624 for (u32 j = 0; j < blockHeight; j++) {
625 for (u32 i = 0; i < blockWidth; i++) {
626 outBuf[j * blockWidth + i] = rgba;
627 }
628 }
629}
630
631static void FillError(std::span<u32> outBuf, u32 blockWidth, u32 blockHeight) {
632 for (u32 j = 0; j < blockHeight; j++) {
633 for (u32 i = 0; i < blockWidth; i++) {
634 outBuf[j * blockWidth + i] = 0xFFFF00FF;
635 }
636 }
637}
638
639// Replicates low numBits such that [(toBit - 1):(toBit - 1 - fromBit)]
640// is the same as [(numBits - 1):0] and repeats all the way down.
641template <typename IntType>
642static constexpr IntType Replicate(IntType val, u32 numBits, u32 toBit) {
643 if (numBits == 0) {
644 return 0;
645 }
646 if (toBit == 0) {
647 return 0;
648 }
649 const IntType v = val & static_cast<IntType>((1 << numBits) - 1);
650 IntType res = v;
651 u32 reslen = numBits;
652 while (reslen < toBit) {
653 u32 comp = 0;
654 if (numBits > toBit - reslen) {
655 u32 newshift = toBit - reslen;
656 comp = numBits - newshift;
657 numBits = newshift;
658 }
659 res = static_cast<IntType>(res << numBits);
660 res = static_cast<IntType>(res | (v >> comp));
661 reslen += numBits;
662 }
663 return res;
664}
665
666static constexpr std::size_t NumReplicateEntries(u32 num_bits) {
667 return std::size_t(1) << num_bits;
668}
669
670template <typename IntType, u32 num_bits, u32 to_bit>
671static constexpr auto MakeReplicateTable() {
672 std::array<IntType, NumReplicateEntries(num_bits)> table{};
673 for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) {
674 table[value] = Replicate(value, num_bits, to_bit);
675 }
676 return table;
677}
678
679static constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>();
680static constexpr u32 ReplicateByteTo16(std::size_t value) {
681 return REPLICATE_BYTE_TO_16_TABLE[value];
682}
683
684static constexpr auto REPLICATE_BIT_TO_7_TABLE = MakeReplicateTable<u32, 1, 7>();
685static constexpr u32 ReplicateBitTo7(std::size_t value) {
686 return REPLICATE_BIT_TO_7_TABLE[value];
687}
688
689static constexpr auto REPLICATE_BIT_TO_9_TABLE = MakeReplicateTable<u32, 1, 9>();
690static constexpr u32 ReplicateBitTo9(std::size_t value) {
691 return REPLICATE_BIT_TO_9_TABLE[value];
692}
693
694static constexpr auto REPLICATE_1_BIT_TO_8_TABLE = MakeReplicateTable<u32, 1, 8>();
695static constexpr auto REPLICATE_2_BIT_TO_8_TABLE = MakeReplicateTable<u32, 2, 8>();
696static constexpr auto REPLICATE_3_BIT_TO_8_TABLE = MakeReplicateTable<u32, 3, 8>();
697static constexpr auto REPLICATE_4_BIT_TO_8_TABLE = MakeReplicateTable<u32, 4, 8>();
698static constexpr auto REPLICATE_5_BIT_TO_8_TABLE = MakeReplicateTable<u32, 5, 8>();
699static constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>();
700static constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>();
701static constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>();
702/// Use a precompiled table with the most common usages, if it's not in the expected range, fallback
703/// to the runtime implementation
704static constexpr u32 FastReplicateTo8(u32 value, u32 num_bits) {
705 switch (num_bits) {
706 case 1:
707 return REPLICATE_1_BIT_TO_8_TABLE[value];
708 case 2:
709 return REPLICATE_2_BIT_TO_8_TABLE[value];
710 case 3:
711 return REPLICATE_3_BIT_TO_8_TABLE[value];
712 case 4:
713 return REPLICATE_4_BIT_TO_8_TABLE[value];
714 case 5:
715 return REPLICATE_5_BIT_TO_8_TABLE[value];
716 case 6:
717 return REPLICATE_6_BIT_TO_8_TABLE[value];
718 case 7:
719 return REPLICATE_7_BIT_TO_8_TABLE[value];
720 case 8:
721 return REPLICATE_8_BIT_TO_8_TABLE[value];
722 default:
723 return Replicate(value, num_bits, 8);
724 }
725}
726
727static constexpr auto REPLICATE_1_BIT_TO_6_TABLE = MakeReplicateTable<u32, 1, 6>();
728static constexpr auto REPLICATE_2_BIT_TO_6_TABLE = MakeReplicateTable<u32, 2, 6>();
729static constexpr auto REPLICATE_3_BIT_TO_6_TABLE = MakeReplicateTable<u32, 3, 6>();
730static constexpr auto REPLICATE_4_BIT_TO_6_TABLE = MakeReplicateTable<u32, 4, 6>();
731static constexpr auto REPLICATE_5_BIT_TO_6_TABLE = MakeReplicateTable<u32, 5, 6>();
732static constexpr u32 FastReplicateTo6(u32 value, u32 num_bits) {
733 switch (num_bits) {
734 case 1:
735 return REPLICATE_1_BIT_TO_6_TABLE[value];
736 case 2:
737 return REPLICATE_2_BIT_TO_6_TABLE[value];
738 case 3:
739 return REPLICATE_3_BIT_TO_6_TABLE[value];
740 case 4:
741 return REPLICATE_4_BIT_TO_6_TABLE[value];
742 case 5:
743 return REPLICATE_5_BIT_TO_6_TABLE[value];
744 default:
745 return Replicate(value, num_bits, 6);
746 }
747}
748
749class Pixel {
750protected:
751 using ChannelType = s16;
752 u8 m_BitDepth[4] = {8, 8, 8, 8};
753 s16 color[4] = {};
754
755public:
756 Pixel() = default;
757 Pixel(u32 a, u32 r, u32 g, u32 b, u32 bitDepth = 8)
758 : m_BitDepth{u8(bitDepth), u8(bitDepth), u8(bitDepth), u8(bitDepth)},
759 color{static_cast<ChannelType>(a), static_cast<ChannelType>(r),
760 static_cast<ChannelType>(g), static_cast<ChannelType>(b)} {}
761
762 // Changes the depth of each pixel. This scales the values to
763 // the appropriate bit depth by either truncating the least
764 // significant bits when going from larger to smaller bit depth
765 // or by repeating the most significant bits when going from
766 // smaller to larger bit depths.
767 void ChangeBitDepth() {
768 for (u32 i = 0; i < 4; i++) {
769 Component(i) = ChangeBitDepth(Component(i), m_BitDepth[i]);
770 m_BitDepth[i] = 8;
771 }
772 }
773
774 template <typename IntType>
775 static float ConvertChannelToFloat(IntType channel, u8 bitDepth) {
776 float denominator = static_cast<float>((1 << bitDepth) - 1);
777 return static_cast<float>(channel) / denominator;
778 }
779
780 // Changes the bit depth of a single component. See the comment
781 // above for how we do this.
782 static ChannelType ChangeBitDepth(Pixel::ChannelType val, u8 oldDepth) {
783 assert(oldDepth <= 8);
784
785 if (oldDepth == 8) {
786 // Do nothing
787 return val;
788 } else if (oldDepth == 0) {
789 return static_cast<ChannelType>((1 << 8) - 1);
790 } else if (8 > oldDepth) {
791 return static_cast<ChannelType>(FastReplicateTo8(static_cast<u32>(val), oldDepth));
792 } else {
793 // oldDepth > newDepth
794 const u8 bitsWasted = static_cast<u8>(oldDepth - 8);
795 u16 v = static_cast<u16>(val);
796 v = static_cast<u16>((v + (1 << (bitsWasted - 1))) >> bitsWasted);
797 v = ::std::min<u16>(::std::max<u16>(0, v), static_cast<u16>((1 << 8) - 1));
798 return static_cast<u8>(v);
799 }
800
801 assert(false && "We shouldn't get here.");
802 return 0;
803 }
804
805 const ChannelType& A() const {
806 return color[0];
807 }
808 ChannelType& A() {
809 return color[0];
810 }
811 const ChannelType& R() const {
812 return color[1];
813 }
814 ChannelType& R() {
815 return color[1];
816 }
817 const ChannelType& G() const {
818 return color[2];
819 }
820 ChannelType& G() {
821 return color[2];
822 }
823 const ChannelType& B() const {
824 return color[3];
825 }
826 ChannelType& B() {
827 return color[3];
828 }
829 const ChannelType& Component(u32 idx) const {
830 return color[idx];
831 }
832 ChannelType& Component(u32 idx) {
833 return color[idx];
834 }
835
836 void GetBitDepth(u8 (&outDepth)[4]) const {
837 for (s32 i = 0; i < 4; i++) {
838 outDepth[i] = m_BitDepth[i];
839 }
840 }
841
842 // Take all of the components, transform them to their 8-bit variants,
843 // and then pack each channel into an R8G8B8A8 32-bit integer. We assume
844 // that the architecture is little-endian, so the alpha channel will end
845 // up in the most-significant byte.
846 u32 Pack() const {
847 Pixel eightBit(*this);
848 eightBit.ChangeBitDepth();
849
850 u32 r = 0;
851 r |= eightBit.A();
852 r <<= 8;
853 r |= eightBit.B();
854 r <<= 8;
855 r |= eightBit.G();
856 r <<= 8;
857 r |= eightBit.R();
858 return r;
859 }
860
861 // Clamps the pixel to the range [0,255]
862 void ClampByte() {
863 for (u32 i = 0; i < 4; i++) {
864 color[i] = (color[i] < 0) ? 0 : ((color[i] > 255) ? 255 : color[i]);
865 }
866 }
867
868 void MakeOpaque() {
869 A() = 255;
870 }
871};
872
873static void DecodeColorValues(u32* out, std::span<u8> data, const u32* modes, const u32 nPartitions,
874 const u32 nBitsForColorData) {
875 // First figure out how many color values we have
876 u32 nValues = 0;
877 for (u32 i = 0; i < nPartitions; i++) {
878 nValues += ((modes[i] >> 2) + 1) << 1;
879 }
880
881 // Then based on the number of values and the remaining number of bits,
882 // figure out the max value for each of them...
883 u32 range = 256;
884 while (--range > 0) {
885 IntegerEncodedValue val = EncodingsValues[range];
886 u32 bitLength = val.GetBitLength(nValues);
887 if (bitLength <= nBitsForColorData) {
888 // Find the smallest possible range that matches the given encoding
889 while (--range > 0) {
890 IntegerEncodedValue newval = EncodingsValues[range];
891 if (!newval.MatchesEncoding(val)) {
892 break;
893 }
894 }
895
896 // Return to last matching range.
897 range++;
898 break;
899 }
900 }
901
902 // We now have enough to decode our integer sequence.
903 IntegerEncodedVector decodedColorValues;
904
905 InputBitStream colorStream(data, 0);
906 DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
907
908 // Once we have the decoded values, we need to dequantize them to the 0-255 range
909 // This procedure is outlined in ASTC spec C.2.13
910 u32 outIdx = 0;
911 for (auto itr = decodedColorValues.begin(); itr != decodedColorValues.end(); ++itr) {
912 // Have we already decoded all that we need?
913 if (outIdx >= nValues) {
914 break;
915 }
916
917 const IntegerEncodedValue& val = *itr;
918 u32 bitlen = val.num_bits;
919 u32 bitval = val.bit_value;
920
921 assert(bitlen >= 1);
922
923 u32 A = 0, B = 0, C = 0, D = 0;
924 // A is just the lsb replicated 9 times.
925 A = ReplicateBitTo9(bitval & 1);
926
927 switch (val.encoding) {
928 // Replicate bits
929 case IntegerEncoding::JustBits:
930 out[outIdx++] = FastReplicateTo8(bitval, bitlen);
931 break;
932
933 // Use algorithm in C.2.13
934 case IntegerEncoding::Trit: {
935
936 D = val.trit_value;
937
938 switch (bitlen) {
939 case 1: {
940 C = 204;
941 } break;
942
943 case 2: {
944 C = 93;
945 // B = b000b0bb0
946 u32 b = (bitval >> 1) & 1;
947 B = (b << 8) | (b << 4) | (b << 2) | (b << 1);
948 } break;
949
950 case 3: {
951 C = 44;
952 // B = cb000cbcb
953 u32 cb = (bitval >> 1) & 3;
954 B = (cb << 7) | (cb << 2) | cb;
955 } break;
956
957 case 4: {
958 C = 22;
959 // B = dcb000dcb
960 u32 dcb = (bitval >> 1) & 7;
961 B = (dcb << 6) | dcb;
962 } break;
963
964 case 5: {
965 C = 11;
966 // B = edcb000ed
967 u32 edcb = (bitval >> 1) & 0xF;
968 B = (edcb << 5) | (edcb >> 2);
969 } break;
970
971 case 6: {
972 C = 5;
973 // B = fedcb000f
974 u32 fedcb = (bitval >> 1) & 0x1F;
975 B = (fedcb << 4) | (fedcb >> 4);
976 } break;
977
978 default:
979 assert(false && "Unsupported trit encoding for color values!");
980 break;
981 } // switch(bitlen)
982 } // case IntegerEncoding::Trit
983 break;
984
985 case IntegerEncoding::Qus32: {
986
987 D = val.qus32_value;
988
989 switch (bitlen) {
990 case 1: {
991 C = 113;
992 } break;
993
994 case 2: {
995 C = 54;
996 // B = b0000bb00
997 u32 b = (bitval >> 1) & 1;
998 B = (b << 8) | (b << 3) | (b << 2);
999 } break;
1000
1001 case 3: {
1002 C = 26;
1003 // B = cb0000cbc
1004 u32 cb = (bitval >> 1) & 3;
1005 B = (cb << 7) | (cb << 1) | (cb >> 1);
1006 } break;
1007
1008 case 4: {
1009 C = 13;
1010 // B = dcb0000dc
1011 u32 dcb = (bitval >> 1) & 7;
1012 B = (dcb << 6) | (dcb >> 1);
1013 } break;
1014
1015 case 5: {
1016 C = 6;
1017 // B = edcb0000e
1018 u32 edcb = (bitval >> 1) & 0xF;
1019 B = (edcb << 5) | (edcb >> 3);
1020 } break;
1021
1022 default:
1023 assert(false && "Unsupported quint encoding for color values!");
1024 break;
1025 } // switch(bitlen)
1026 } // case IntegerEncoding::Qus32
1027 break;
1028 } // switch(val.encoding)
1029
1030 if (val.encoding != IntegerEncoding::JustBits) {
1031 u32 T = D * C + B;
1032 T ^= A;
1033 T = (A & 0x80) | (T >> 2);
1034 out[outIdx++] = T;
1035 }
1036 }
1037
1038 // Make sure that each of our values is in the proper range...
1039 for (u32 i = 0; i < nValues; i++) {
1040 assert(out[i] <= 255);
1041 }
1042}
1043
1044static u32 UnquantizeTexelWeight(const IntegerEncodedValue& val) {
1045 u32 bitval = val.bit_value;
1046 u32 bitlen = val.num_bits;
1047
1048 u32 A = ReplicateBitTo7(bitval & 1);
1049 u32 B = 0, C = 0, D = 0;
1050
1051 u32 result = 0;
1052 switch (val.encoding) {
1053 case IntegerEncoding::JustBits:
1054 result = FastReplicateTo6(bitval, bitlen);
1055 break;
1056
1057 case IntegerEncoding::Trit: {
1058 D = val.trit_value;
1059 assert(D < 3);
1060
1061 switch (bitlen) {
1062 case 0: {
1063 u32 results[3] = {0, 32, 63};
1064 result = results[D];
1065 } break;
1066
1067 case 1: {
1068 C = 50;
1069 } break;
1070
1071 case 2: {
1072 C = 23;
1073 u32 b = (bitval >> 1) & 1;
1074 B = (b << 6) | (b << 2) | b;
1075 } break;
1076
1077 case 3: {
1078 C = 11;
1079 u32 cb = (bitval >> 1) & 3;
1080 B = (cb << 5) | cb;
1081 } break;
1082
1083 default:
1084 assert(false && "Invalid trit encoding for texel weight");
1085 break;
1086 }
1087 } break;
1088
1089 case IntegerEncoding::Qus32: {
1090 D = val.qus32_value;
1091 assert(D < 5);
1092
1093 switch (bitlen) {
1094 case 0: {
1095 u32 results[5] = {0, 16, 32, 47, 63};
1096 result = results[D];
1097 } break;
1098
1099 case 1: {
1100 C = 28;
1101 } break;
1102
1103 case 2: {
1104 C = 13;
1105 u32 b = (bitval >> 1) & 1;
1106 B = (b << 6) | (b << 1);
1107 } break;
1108
1109 default:
1110 assert(false && "Invalid quint encoding for texel weight");
1111 break;
1112 }
1113 } break;
1114 }
1115
1116 if (val.encoding != IntegerEncoding::JustBits && bitlen > 0) {
1117 // Decode the value...
1118 result = D * C + B;
1119 result ^= A;
1120 result = (A & 0x20) | (result >> 2);
1121 }
1122
1123 assert(result < 64);
1124
1125 // Change from [0,63] to [0,64]
1126 if (result > 32) {
1127 result += 1;
1128 }
1129
1130 return result;
1131}
1132
1133static void UnquantizeTexelWeights(u32 out[2][144], const IntegerEncodedVector& weights,
1134 const TexelWeightParams& params, const u32 blockWidth,
1135 const u32 blockHeight) {
1136 u32 weightIdx = 0;
1137 u32 unquantized[2][144];
1138
1139 for (auto itr = weights.begin(); itr != weights.end(); ++itr) {
1140 unquantized[0][weightIdx] = UnquantizeTexelWeight(*itr);
1141
1142 if (params.m_bDualPlane) {
1143 ++itr;
1144 unquantized[1][weightIdx] = UnquantizeTexelWeight(*itr);
1145 if (itr == weights.end()) {
1146 break;
1147 }
1148 }
1149
1150 if (++weightIdx >= (params.m_Width * params.m_Height))
1151 break;
1152 }
1153
1154 // Do infill if necessary (Section C.2.18) ...
1155 u32 Ds = (1024 + (blockWidth / 2)) / (blockWidth - 1);
1156 u32 Dt = (1024 + (blockHeight / 2)) / (blockHeight - 1);
1157
1158 const u32 kPlaneScale = params.m_bDualPlane ? 2U : 1U;
1159 for (u32 plane = 0; plane < kPlaneScale; plane++)
1160 for (u32 t = 0; t < blockHeight; t++)
1161 for (u32 s = 0; s < blockWidth; s++) {
1162 u32 cs = Ds * s;
1163 u32 ct = Dt * t;
1164
1165 u32 gs = (cs * (params.m_Width - 1) + 32) >> 6;
1166 u32 gt = (ct * (params.m_Height - 1) + 32) >> 6;
1167
1168 u32 js = gs >> 4;
1169 u32 fs = gs & 0xF;
1170
1171 u32 jt = gt >> 4;
1172 u32 ft = gt & 0x0F;
1173
1174 u32 w11 = (fs * ft + 8) >> 4;
1175 u32 w10 = ft - w11;
1176 u32 w01 = fs - w11;
1177 u32 w00 = 16 - fs - ft + w11;
1178
1179 u32 v0 = js + jt * params.m_Width;
1180
1181#define FIND_TEXEL(tidx, bidx) \
1182 u32 p##bidx = 0; \
1183 do { \
1184 if ((tidx) < (params.m_Width * params.m_Height)) { \
1185 p##bidx = unquantized[plane][(tidx)]; \
1186 } \
1187 } while (0)
1188
1189 FIND_TEXEL(v0, 00);
1190 FIND_TEXEL(v0 + 1, 01);
1191 FIND_TEXEL(v0 + params.m_Width, 10);
1192 FIND_TEXEL(v0 + params.m_Width + 1, 11);
1193
1194#undef FIND_TEXEL
1195
1196 out[plane][t * blockWidth + s] =
1197 (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;
1198 }
1199}
1200
1201// Transfers a bit as described in C.2.14
1202static inline void BitTransferSigned(s32& a, s32& b) {
1203 b >>= 1;
1204 b |= a & 0x80;
1205 a >>= 1;
1206 a &= 0x3F;
1207 if (a & 0x20)
1208 a -= 0x40;
1209}
1210
1211// Adds more precision to the blue channel as described
1212// in C.2.14
1213static inline Pixel BlueContract(s32 a, s32 r, s32 g, s32 b) {
1214 return Pixel(static_cast<s16>(a), static_cast<s16>((r + b) >> 1),
1215 static_cast<s16>((g + b) >> 1), static_cast<s16>(b));
1216}
1217
1218// Partition selection functions as specified in
1219// C.2.21
1220static inline u32 hash52(u32 p) {
1221 p ^= p >> 15;
1222 p -= p << 17;
1223 p += p << 7;
1224 p += p << 4;
1225 p ^= p >> 5;
1226 p += p << 16;
1227 p ^= p >> 7;
1228 p ^= p >> 3;
1229 p ^= p << 6;
1230 p ^= p >> 17;
1231 return p;
1232}
1233
1234static u32 SelectPartition(s32 seed, s32 x, s32 y, s32 z, s32 partitionCount, s32 smallBlock) {
1235 if (1 == partitionCount)
1236 return 0;
1237
1238 if (smallBlock) {
1239 x <<= 1;
1240 y <<= 1;
1241 z <<= 1;
1242 }
1243
1244 seed += (partitionCount - 1) * 1024;
1245
1246 u32 rnum = hash52(static_cast<u32>(seed));
1247 u8 seed1 = static_cast<u8>(rnum & 0xF);
1248 u8 seed2 = static_cast<u8>((rnum >> 4) & 0xF);
1249 u8 seed3 = static_cast<u8>((rnum >> 8) & 0xF);
1250 u8 seed4 = static_cast<u8>((rnum >> 12) & 0xF);
1251 u8 seed5 = static_cast<u8>((rnum >> 16) & 0xF);
1252 u8 seed6 = static_cast<u8>((rnum >> 20) & 0xF);
1253 u8 seed7 = static_cast<u8>((rnum >> 24) & 0xF);
1254 u8 seed8 = static_cast<u8>((rnum >> 28) & 0xF);
1255 u8 seed9 = static_cast<u8>((rnum >> 18) & 0xF);
1256 u8 seed10 = static_cast<u8>((rnum >> 22) & 0xF);
1257 u8 seed11 = static_cast<u8>((rnum >> 26) & 0xF);
1258 u8 seed12 = static_cast<u8>(((rnum >> 30) | (rnum << 2)) & 0xF);
1259
1260 seed1 = static_cast<u8>(seed1 * seed1);
1261 seed2 = static_cast<u8>(seed2 * seed2);
1262 seed3 = static_cast<u8>(seed3 * seed3);
1263 seed4 = static_cast<u8>(seed4 * seed4);
1264 seed5 = static_cast<u8>(seed5 * seed5);
1265 seed6 = static_cast<u8>(seed6 * seed6);
1266 seed7 = static_cast<u8>(seed7 * seed7);
1267 seed8 = static_cast<u8>(seed8 * seed8);
1268 seed9 = static_cast<u8>(seed9 * seed9);
1269 seed10 = static_cast<u8>(seed10 * seed10);
1270 seed11 = static_cast<u8>(seed11 * seed11);
1271 seed12 = static_cast<u8>(seed12 * seed12);
1272
1273 s32 sh1, sh2, sh3;
1274 if (seed & 1) {
1275 sh1 = (seed & 2) ? 4 : 5;
1276 sh2 = (partitionCount == 3) ? 6 : 5;
1277 } else {
1278 sh1 = (partitionCount == 3) ? 6 : 5;
1279 sh2 = (seed & 2) ? 4 : 5;
1280 }
1281 sh3 = (seed & 0x10) ? sh1 : sh2;
1282
1283 seed1 = static_cast<u8>(seed1 >> sh1);
1284 seed2 = static_cast<u8>(seed2 >> sh2);
1285 seed3 = static_cast<u8>(seed3 >> sh1);
1286 seed4 = static_cast<u8>(seed4 >> sh2);
1287 seed5 = static_cast<u8>(seed5 >> sh1);
1288 seed6 = static_cast<u8>(seed6 >> sh2);
1289 seed7 = static_cast<u8>(seed7 >> sh1);
1290 seed8 = static_cast<u8>(seed8 >> sh2);
1291 seed9 = static_cast<u8>(seed9 >> sh3);
1292 seed10 = static_cast<u8>(seed10 >> sh3);
1293 seed11 = static_cast<u8>(seed11 >> sh3);
1294 seed12 = static_cast<u8>(seed12 >> sh3);
1295
1296 s32 a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
1297 s32 b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
1298 s32 c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
1299 s32 d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
1300
1301 a &= 0x3F;
1302 b &= 0x3F;
1303 c &= 0x3F;
1304 d &= 0x3F;
1305
1306 if (partitionCount < 4)
1307 d = 0;
1308 if (partitionCount < 3)
1309 c = 0;
1310
1311 if (a >= b && a >= c && a >= d)
1312 return 0;
1313 else if (b >= c && b >= d)
1314 return 1;
1315 else if (c >= d)
1316 return 2;
1317 return 3;
1318}
1319
1320static inline u32 Select2DPartition(s32 seed, s32 x, s32 y, s32 partitionCount, s32 smallBlock) {
1321 return SelectPartition(seed, x, y, 0, partitionCount, smallBlock);
1322}
1323
1324// Section C.2.14
1325static void ComputeEndpos32s(Pixel& ep1, Pixel& ep2, const u32*& colorValues,
1326 u32 colorEndpos32Mode) {
1327#define READ_UINT_VALUES(N) \
1328 u32 v[N]; \
1329 for (u32 i = 0; i < N; i++) { \
1330 v[i] = *(colorValues++); \
1331 }
1332
1333#define READ_INT_VALUES(N) \
1334 s32 v[N]; \
1335 for (u32 i = 0; i < N; i++) { \
1336 v[i] = static_cast<s32>(*(colorValues++)); \
1337 }
1338
1339 switch (colorEndpos32Mode) {
1340 case 0: {
1341 READ_UINT_VALUES(2)
1342 ep1 = Pixel(0xFF, v[0], v[0], v[0]);
1343 ep2 = Pixel(0xFF, v[1], v[1], v[1]);
1344 } break;
1345
1346 case 1: {
1347 READ_UINT_VALUES(2)
1348 u32 L0 = (v[0] >> 2) | (v[1] & 0xC0);
1349 u32 L1 = std::max(L0 + (v[1] & 0x3F), 0xFFU);
1350 ep1 = Pixel(0xFF, L0, L0, L0);
1351 ep2 = Pixel(0xFF, L1, L1, L1);
1352 } break;
1353
1354 case 4: {
1355 READ_UINT_VALUES(4)
1356 ep1 = Pixel(v[2], v[0], v[0], v[0]);
1357 ep2 = Pixel(v[3], v[1], v[1], v[1]);
1358 } break;
1359
1360 case 5: {
1361 READ_INT_VALUES(4)
1362 BitTransferSigned(v[1], v[0]);
1363 BitTransferSigned(v[3], v[2]);
1364 ep1 = Pixel(v[2], v[0], v[0], v[0]);
1365 ep2 = Pixel(v[2] + v[3], v[0] + v[1], v[0] + v[1], v[0] + v[1]);
1366 ep1.ClampByte();
1367 ep2.ClampByte();
1368 } break;
1369
1370 case 6: {
1371 READ_UINT_VALUES(4)
1372 ep1 = Pixel(0xFF, v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8);
1373 ep2 = Pixel(0xFF, v[0], v[1], v[2]);
1374 } break;
1375
1376 case 8: {
1377 READ_UINT_VALUES(6)
1378 if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4]) {
1379 ep1 = Pixel(0xFF, v[0], v[2], v[4]);
1380 ep2 = Pixel(0xFF, v[1], v[3], v[5]);
1381 } else {
1382 ep1 = BlueContract(0xFF, v[1], v[3], v[5]);
1383 ep2 = BlueContract(0xFF, v[0], v[2], v[4]);
1384 }
1385 } break;
1386
1387 case 9: {
1388 READ_INT_VALUES(6)
1389 BitTransferSigned(v[1], v[0]);
1390 BitTransferSigned(v[3], v[2]);
1391 BitTransferSigned(v[5], v[4]);
1392 if (v[1] + v[3] + v[5] >= 0) {
1393 ep1 = Pixel(0xFF, v[0], v[2], v[4]);
1394 ep2 = Pixel(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]);
1395 } else {
1396 ep1 = BlueContract(0xFF, v[0] + v[1], v[2] + v[3], v[4] + v[5]);
1397 ep2 = BlueContract(0xFF, v[0], v[2], v[4]);
1398 }
1399 ep1.ClampByte();
1400 ep2.ClampByte();
1401 } break;
1402
1403 case 10: {
1404 READ_UINT_VALUES(6)
1405 ep1 = Pixel(v[4], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8);
1406 ep2 = Pixel(v[5], v[0], v[1], v[2]);
1407 } break;
1408
1409 case 12: {
1410 READ_UINT_VALUES(8)
1411 if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4]) {
1412 ep1 = Pixel(v[6], v[0], v[2], v[4]);
1413 ep2 = Pixel(v[7], v[1], v[3], v[5]);
1414 } else {
1415 ep1 = BlueContract(v[7], v[1], v[3], v[5]);
1416 ep2 = BlueContract(v[6], v[0], v[2], v[4]);
1417 }
1418 } break;
1419
1420 case 13: {
1421 READ_INT_VALUES(8)
1422 BitTransferSigned(v[1], v[0]);
1423 BitTransferSigned(v[3], v[2]);
1424 BitTransferSigned(v[5], v[4]);
1425 BitTransferSigned(v[7], v[6]);
1426 if (v[1] + v[3] + v[5] >= 0) {
1427 ep1 = Pixel(v[6], v[0], v[2], v[4]);
1428 ep2 = Pixel(v[7] + v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5]);
1429 } else {
1430 ep1 = BlueContract(v[6] + v[7], v[0] + v[1], v[2] + v[3], v[4] + v[5]);
1431 ep2 = BlueContract(v[6], v[0], v[2], v[4]);
1432 }
1433 ep1.ClampByte();
1434 ep2.ClampByte();
1435 } break;
1436
1437 default:
1438 assert(false && "Unsupported color endpoint mode (is it HDR?)");
1439 break;
1440 }
1441
1442#undef READ_UINT_VALUES
1443#undef READ_INT_VALUES
1444}
1445
1446static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
1447 const u32 blockHeight, std::span<u32, 12 * 12> outBuf) {
1448 InputBitStream strm(inBuf);
1449 TexelWeightParams weightParams = DecodeBlockInfo(strm);
1450
1451 // Was there an error?
1452 if (weightParams.m_bError) {
1453 assert(false && "Invalid block mode");
1454 FillError(outBuf, blockWidth, blockHeight);
1455 return;
1456 }
1457
1458 if (weightParams.m_bVoidExtentLDR) {
1459 FillVoidExtentLDR(strm, outBuf, blockWidth, blockHeight);
1460 return;
1461 }
1462
1463 if (weightParams.m_bVoidExtentHDR) {
1464 assert(false && "HDR void extent blocks are unsupported!");
1465 FillError(outBuf, blockWidth, blockHeight);
1466 return;
1467 }
1468
1469 if (weightParams.m_Width > blockWidth) {
1470 assert(false && "Texel weight grid width should be smaller than block width");
1471 FillError(outBuf, blockWidth, blockHeight);
1472 return;
1473 }
1474
1475 if (weightParams.m_Height > blockHeight) {
1476 assert(false && "Texel weight grid height should be smaller than block height");
1477 FillError(outBuf, blockWidth, blockHeight);
1478 return;
1479 }
1480
1481 // Read num partitions
1482 u32 nPartitions = strm.ReadBits<2>() + 1;
1483 assert(nPartitions <= 4);
1484
1485 if (nPartitions == 4 && weightParams.m_bDualPlane) {
1486 assert(false && "Dual plane mode is incompatible with four partition blocks");
1487 FillError(outBuf, blockWidth, blockHeight);
1488 return;
1489 }
1490
1491 // Based on the number of partitions, read the color endpos32 mode for
1492 // each partition.
1493
1494 // Determine partitions, partition index, and color endpos32 modes
1495 s32 planeIdx = -1;
1496 u32 partitionIndex;
1497 u32 colorEndpos32Mode[4] = {0, 0, 0, 0};
1498
1499 // Define color data.
1500 u8 colorEndpos32Data[16];
1501 memset(colorEndpos32Data, 0, sizeof(colorEndpos32Data));
1502 OutputBitStream colorEndpos32Stream(colorEndpos32Data, 16 * 8, 0);
1503
1504 // Read extra config data...
1505 u32 baseCEM = 0;
1506 if (nPartitions == 1) {
1507 colorEndpos32Mode[0] = strm.ReadBits<4>();
1508 partitionIndex = 0;
1509 } else {
1510 partitionIndex = strm.ReadBits<10>();
1511 baseCEM = strm.ReadBits<6>();
1512 }
1513 u32 baseMode = (baseCEM & 3);
1514
1515 // Remaining bits are color endpos32 data...
1516 u32 nWeightBits = weightParams.GetPackedBitSize();
1517 s32 remainingBits = 128 - nWeightBits - static_cast<s32>(strm.GetBitsRead());
1518
1519 // Consider extra bits prior to texel data...
1520 u32 extraCEMbits = 0;
1521 if (baseMode) {
1522 switch (nPartitions) {
1523 case 2:
1524 extraCEMbits += 2;
1525 break;
1526 case 3:
1527 extraCEMbits += 5;
1528 break;
1529 case 4:
1530 extraCEMbits += 8;
1531 break;
1532 default:
1533 assert(false);
1534 break;
1535 }
1536 }
1537 remainingBits -= extraCEMbits;
1538
1539 // Do we have a dual plane situation?
1540 u32 planeSelectorBits = 0;
1541 if (weightParams.m_bDualPlane) {
1542 planeSelectorBits = 2;
1543 }
1544 remainingBits -= planeSelectorBits;
1545
1546 // Read color data...
1547 u32 colorDataBits = remainingBits;
1548 while (remainingBits > 0) {
1549 u32 nb = std::min(remainingBits, 8);
1550 u32 b = strm.ReadBits(nb);
1551 colorEndpos32Stream.WriteBits(b, nb);
1552 remainingBits -= 8;
1553 }
1554
1555 // Read the plane selection bits
1556 planeIdx = strm.ReadBits(planeSelectorBits);
1557
1558 // Read the rest of the CEM
1559 if (baseMode) {
1560 u32 extraCEM = strm.ReadBits(extraCEMbits);
1561 u32 CEM = (extraCEM << 6) | baseCEM;
1562 CEM >>= 2;
1563
1564 bool C[4] = {0};
1565 for (u32 i = 0; i < nPartitions; i++) {
1566 C[i] = CEM & 1;
1567 CEM >>= 1;
1568 }
1569
1570 u8 M[4] = {0};
1571 for (u32 i = 0; i < nPartitions; i++) {
1572 M[i] = CEM & 3;
1573 CEM >>= 2;
1574 assert(M[i] <= 3);
1575 }
1576
1577 for (u32 i = 0; i < nPartitions; i++) {
1578 colorEndpos32Mode[i] = baseMode;
1579 if (!(C[i]))
1580 colorEndpos32Mode[i] -= 1;
1581 colorEndpos32Mode[i] <<= 2;
1582 colorEndpos32Mode[i] |= M[i];
1583 }
1584 } else if (nPartitions > 1) {
1585 u32 CEM = baseCEM >> 2;
1586 for (u32 i = 0; i < nPartitions; i++) {
1587 colorEndpos32Mode[i] = CEM;
1588 }
1589 }
1590
1591 // Make sure everything up till here is sane.
1592 for (u32 i = 0; i < nPartitions; i++) {
1593 assert(colorEndpos32Mode[i] < 16);
1594 }
1595 assert(strm.GetBitsRead() + weightParams.GetPackedBitSize() == 128);
1596
1597 // Decode both color data and texel weight data
1598 u32 colorValues[32]; // Four values, two endpos32s, four maximum paritions
1599 DecodeColorValues(colorValues, colorEndpos32Data, colorEndpos32Mode, nPartitions,
1600 colorDataBits);
1601
1602 Pixel endpos32s[4][2];
1603 const u32* colorValuesPtr = colorValues;
1604 for (u32 i = 0; i < nPartitions; i++) {
1605 ComputeEndpos32s(endpos32s[i][0], endpos32s[i][1], colorValuesPtr, colorEndpos32Mode[i]);
1606 }
1607
1608 // Read the texel weight data..
1609 std::array<u8, 16> texelWeightData;
1610 std::ranges::copy(inBuf, texelWeightData.begin());
1611
1612 // Reverse everything
1613 for (u32 i = 0; i < 8; i++) {
1614// Taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits
1615#define REVERSE_BYTE(b) (((b)*0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32
1616 u8 a = static_cast<u8>(REVERSE_BYTE(texelWeightData[i]));
1617 u8 b = static_cast<u8>(REVERSE_BYTE(texelWeightData[15 - i]));
1618#undef REVERSE_BYTE
1619
1620 texelWeightData[i] = b;
1621 texelWeightData[15 - i] = a;
1622 }
1623
1624 // Make sure that higher non-texel bits are set to zero
1625 const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1;
1626 if (clearByteStart > 0 && clearByteStart <= texelWeightData.size()) {
1627 texelWeightData[clearByteStart - 1] &=
1628 static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1);
1629 std::memset(texelWeightData.data() + clearByteStart, 0,
1630 std::min(16U - clearByteStart, 16U));
1631 }
1632
1633 IntegerEncodedVector texelWeightValues;
1634
1635 InputBitStream weightStream(texelWeightData);
1636
1637 DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight,
1638 weightParams.GetNumWeightValues());
1639
1640 // Blocks can be at most 12x12, so we can have as many as 144 weights
1641 u32 weights[2][144];
1642 UnquantizeTexelWeights(weights, texelWeightValues, weightParams, blockWidth, blockHeight);
1643
1644 // Now that we have endpos32s and weights, we can s32erpolate and generate
1645 // the proper decoding...
1646 for (u32 j = 0; j < blockHeight; j++)
1647 for (u32 i = 0; i < blockWidth; i++) {
1648 u32 partition = Select2DPartition(partitionIndex, i, j, nPartitions,
1649 (blockHeight * blockWidth) < 32);
1650 assert(partition < nPartitions);
1651
1652 Pixel p;
1653 for (u32 c = 0; c < 4; c++) {
1654 u32 C0 = endpos32s[partition][0].Component(c);
1655 C0 = ReplicateByteTo16(C0);
1656 u32 C1 = endpos32s[partition][1].Component(c);
1657 C1 = ReplicateByteTo16(C1);
1658
1659 u32 plane = 0;
1660 if (weightParams.m_bDualPlane && (((planeIdx + 1) & 3) == c)) {
1661 plane = 1;
1662 }
1663
1664 u32 weight = weights[plane][j * blockWidth + i];
1665 u32 C = (C0 * (64 - weight) + C1 * weight + 32) / 64;
1666 if (C == 65535) {
1667 p.Component(c) = 255;
1668 } else {
1669 double Cf = static_cast<double>(C);
1670 p.Component(c) = static_cast<u16>(255.0 * (Cf / 65536.0) + 0.5);
1671 }
1672 }
1673
1674 outBuf[j * blockWidth + i] = p.Pack();
1675 }
1676}
1677
1678} // namespace ASTCC
1679
1680namespace Tegra::Texture::ASTC {
1681
1682void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
1683 uint32_t block_width, uint32_t block_height, std::span<uint8_t> output) {
1684 u32 block_index = 0;
1685 std::size_t depth_offset = 0;
1686 for (u32 z = 0; z < depth; z++) {
1687 for (u32 y = 0; y < height; y += block_height) {
1688 for (u32 x = 0; x < width; x += block_width) {
1689 const std::span<const u8, 16> blockPtr{data.subspan(block_index * 16, 16)};
1690
1691 // Blocks can be at most 12x12
1692 std::array<u32, 12 * 12> uncompData;
1693 ASTCC::DecompressBlock(blockPtr, block_width, block_height, uncompData);
1694
1695 u32 decompWidth = std::min(block_width, width - x);
1696 u32 decompHeight = std::min(block_height, height - y);
1697
1698 const std::span<u8> outRow = output.subspan(depth_offset + (y * width + x) * 4);
1699 for (u32 jj = 0; jj < decompHeight; jj++) {
1700 std::memcpy(outRow.data() + jj * width * 4,
1701 uncompData.data() + jj * block_width, decompWidth * 4);
1702 }
1703 ++block_index;
1704 }
1705 }
1706 depth_offset += height * width * 4;
1707 }
1708}
1709
1710} // namespace Tegra::Texture::ASTC
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h
index 9105119bc..c1c73fda5 100644
--- a/src/video_core/textures/astc.h
+++ b/src/video_core/textures/astc.h
@@ -4,11 +4,129 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstdint> 7#include <bit>
8#include "common/common_types.h"
8 9
9namespace Tegra::Texture::ASTC { 10namespace Tegra::Texture::ASTC {
10 11
11void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth, 12enum class IntegerEncoding { JustBits, Quint, Trit };
12 uint32_t block_width, uint32_t block_height, std::span<uint8_t> output); 13
14struct IntegerEncodedValue {
15 constexpr IntegerEncodedValue() = default;
16
17 constexpr IntegerEncodedValue(IntegerEncoding encoding_, u32 num_bits_)
18 : encoding{encoding_}, num_bits{num_bits_} {}
19
20 constexpr bool MatchesEncoding(const IntegerEncodedValue& other) const {
21 return encoding == other.encoding && num_bits == other.num_bits;
22 }
23
24 // Returns the number of bits required to encode num_vals values.
25 u32 GetBitLength(u32 num_vals) const {
26 u32 total_bits = num_bits * num_vals;
27 if (encoding == IntegerEncoding::Trit) {
28 total_bits += (num_vals * 8 + 4) / 5;
29 } else if (encoding == IntegerEncoding::Quint) {
30 total_bits += (num_vals * 7 + 2) / 3;
31 }
32 return total_bits;
33 }
34
35 IntegerEncoding encoding{};
36 u32 num_bits = 0;
37 u32 bit_value = 0;
38 union {
39 u32 quint_value = 0;
40 u32 trit_value;
41 };
42};
43
44// Returns a new instance of this struct that corresponds to the
45// can take no more than mav_value values
46constexpr IntegerEncodedValue CreateEncoding(u32 mav_value) {
47 while (mav_value > 0) {
48 u32 check = mav_value + 1;
49
50 // Is mav_value a power of two?
51 if (!(check & (check - 1))) {
52 return IntegerEncodedValue(IntegerEncoding::JustBits, std::popcount(mav_value));
53 }
54
55 // Is mav_value of the type 3*2^n - 1?
56 if ((check % 3 == 0) && !((check / 3) & ((check / 3) - 1))) {
57 return IntegerEncodedValue(IntegerEncoding::Trit, std::popcount(check / 3 - 1));
58 }
59
60 // Is mav_value of the type 5*2^n - 1?
61 if ((check % 5 == 0) && !((check / 5) & ((check / 5) - 1))) {
62 return IntegerEncodedValue(IntegerEncoding::Quint, std::popcount(check / 5 - 1));
63 }
64
65 // Apparently it can't be represented with a bounded integer sequence...
66 // just iterate.
67 mav_value--;
68 }
69 return IntegerEncodedValue(IntegerEncoding::JustBits, 0);
70}
71
72constexpr std::array<IntegerEncodedValue, 256> MakeEncodedValues() {
73 std::array<IntegerEncodedValue, 256> encodings{};
74 for (std::size_t i = 0; i < encodings.size(); ++i) {
75 encodings[i] = CreateEncoding(static_cast<u32>(i));
76 }
77 return encodings;
78}
79
80constexpr std::array<IntegerEncodedValue, 256> EncodingsValues = MakeEncodedValues();
81
82// Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)]
83// is the same as [(num_bits - 1):0] and repeats all the way down.
84template <typename IntType>
85constexpr IntType Replicate(IntType val, u32 num_bits, u32 to_bit) {
86 if (num_bits == 0 || to_bit == 0) {
87 return 0;
88 }
89 const IntType v = val & static_cast<IntType>((1 << num_bits) - 1);
90 IntType res = v;
91 u32 reslen = num_bits;
92 while (reslen < to_bit) {
93 u32 comp = 0;
94 if (num_bits > to_bit - reslen) {
95 u32 newshift = to_bit - reslen;
96 comp = num_bits - newshift;
97 num_bits = newshift;
98 }
99 res = static_cast<IntType>(res << num_bits);
100 res = static_cast<IntType>(res | (v >> comp));
101 reslen += num_bits;
102 }
103 return res;
104}
105
106constexpr std::size_t NumReplicateEntries(u32 num_bits) {
107 return std::size_t(1) << num_bits;
108}
109
110template <typename IntType, u32 num_bits, u32 to_bit>
111constexpr auto MakeReplicateTable() {
112 std::array<IntType, NumReplicateEntries(num_bits)> table{};
113 for (IntType value = 0; value < static_cast<IntType>(std::size(table)); ++value) {
114 table[value] = Replicate(value, num_bits, to_bit);
115 }
116 return table;
117}
118
119constexpr auto REPLICATE_BYTE_TO_16_TABLE = MakeReplicateTable<u32, 8, 16>();
120constexpr auto REPLICATE_6_BIT_TO_8_TABLE = MakeReplicateTable<u32, 6, 8>();
121constexpr auto REPLICATE_7_BIT_TO_8_TABLE = MakeReplicateTable<u32, 7, 8>();
122constexpr auto REPLICATE_8_BIT_TO_8_TABLE = MakeReplicateTable<u32, 8, 8>();
123
124struct AstcBufferData {
125 decltype(EncodingsValues) encoding_values = EncodingsValues;
126 decltype(REPLICATE_6_BIT_TO_8_TABLE) replicate_6_to_8 = REPLICATE_6_BIT_TO_8_TABLE;
127 decltype(REPLICATE_7_BIT_TO_8_TABLE) replicate_7_to_8 = REPLICATE_7_BIT_TO_8_TABLE;
128 decltype(REPLICATE_8_BIT_TO_8_TABLE) replicate_8_to_8 = REPLICATE_8_BIT_TO_8_TABLE;
129 decltype(REPLICATE_BYTE_TO_16_TABLE) replicate_byte_to_16 = REPLICATE_BYTE_TO_16_TABLE;
130} constexpr ASTC_BUFFER_DATA;
13 131
14} // namespace Tegra::Texture::ASTC 132} // namespace Tegra::Texture::ASTC
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 62685a183..3a463d5db 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -17,26 +17,7 @@
17#include "video_core/textures/texture.h" 17#include "video_core/textures/texture.h"
18 18
19namespace Tegra::Texture { 19namespace Tegra::Texture {
20
21namespace { 20namespace {
22/**
23 * This table represents the internal swizzle of a gob, in format 16 bytes x 2 sector packing.
24 * Calculates the offset of an (x, y) position within a swizzled texture.
25 * Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188
26 */
27constexpr SwizzleTable MakeSwizzleTableConst() {
28 SwizzleTable table{};
29 for (u32 y = 0; y < table.size(); ++y) {
30 for (u32 x = 0; x < table[0].size(); ++x) {
31 table[y][x] = ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
32 (y % 2) * 16 + (x % 16);
33 }
34 }
35 return table;
36}
37
38constexpr SwizzleTable SWIZZLE_TABLE = MakeSwizzleTableConst();
39
40template <bool TO_LINEAR> 21template <bool TO_LINEAR>
41void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, u32 width, 22void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, u32 width,
42 u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) { 23 u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) {
@@ -91,10 +72,6 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe
91} 72}
92} // Anonymous namespace 73} // Anonymous namespace
93 74
94SwizzleTable MakeSwizzleTable() {
95 return SWIZZLE_TABLE;
96}
97
98void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, 75void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel,
99 u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth, 76 u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth,
100 u32 stride_alignment) { 77 u32 stride_alignment) {
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index d7cdc81e8..4c14cefbf 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -23,8 +23,22 @@ constexpr u32 GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_
23 23
24using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>; 24using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>;
25 25
26/// Returns a z-order swizzle table 26/**
27SwizzleTable MakeSwizzleTable(); 27 * This table represents the internal swizzle of a gob, in format 16 bytes x 2 sector packing.
28 * Calculates the offset of an (x, y) position within a swizzled texture.
29 * Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188
30 */
31constexpr SwizzleTable MakeSwizzleTable() {
32 SwizzleTable table{};
33 for (u32 y = 0; y < table.size(); ++y) {
34 for (u32 x = 0; x < table[0].size(); ++x) {
35 table[y][x] = ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
36 (y % 2) * 16 + (x % 16);
37 }
38 }
39 return table;
40}
41constexpr SwizzleTable SWIZZLE_TABLE = MakeSwizzleTable();
28 42
29/// Unswizzles a block linear texture into linear memory. 43/// Unswizzles a block linear texture into linear memory.
30void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel, 44void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel,
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp
index ae5621a7d..a552543ed 100644
--- a/src/video_core/textures/texture.cpp
+++ b/src/video_core/textures/texture.cpp
@@ -6,7 +6,7 @@
6#include <array> 6#include <array>
7 7
8#include "common/cityhash.h" 8#include "common/cityhash.h"
9#include "core/settings.h" 9#include "common/settings.h"
10#include "video_core/textures/texture.h" 10#include "video_core/textures/texture.h"
11 11
12using Tegra::Texture::TICEntry; 12using Tegra::Texture::TICEntry;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index e1b38c6ac..3b575db4d 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -5,8 +5,8 @@
5#include <memory> 5#include <memory>
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "common/settings.h"
8#include "core/core.h" 9#include "core/core.h"
9#include "core/settings.h"
10#include "video_core/renderer_base.h" 10#include "video_core/renderer_base.h"
11#include "video_core/renderer_opengl/renderer_opengl.h" 11#include "video_core/renderer_opengl/renderer_opengl.h"
12#include "video_core/renderer_vulkan/renderer_vulkan.h" 12#include "video_core/renderer_vulkan/renderer_vulkan.h"
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 34d396434..64206b3d2 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -12,7 +12,7 @@
12#include <vector> 12#include <vector>
13 13
14#include "common/assert.h" 14#include "common/assert.h"
15#include "core/settings.h" 15#include "common/settings.h"
16#include "video_core/vulkan_common/nsight_aftermath_tracker.h" 16#include "video_core/vulkan_common/nsight_aftermath_tracker.h"
17#include "video_core/vulkan_common/vulkan_device.h" 17#include "video_core/vulkan_common/vulkan_device.h"
18#include "video_core/vulkan_common/vulkan_wrapper.h" 18#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -51,7 +51,7 @@ constexpr std::array REQUIRED_EXTENSIONS{
51#ifdef _WIN32 51#ifdef _WIN32
52 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, 52 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
53#endif 53#endif
54#ifdef __linux__ 54#ifdef __unix__
55 VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, 55 VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
56#endif 56#endif
57}; 57};
@@ -294,6 +294,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
294 }; 294 };
295 SetNext(next, bit8_storage); 295 SetNext(next, bit8_storage);
296 296
297 VkPhysicalDeviceRobustness2FeaturesEXT robustness2{
298 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT,
299 .pNext = nullptr,
300 .robustBufferAccess2 = true,
301 .robustImageAccess2 = true,
302 .nullDescriptor = true,
303 };
304 SetNext(next, robustness2);
305
297 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{ 306 VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{
298 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT, 307 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT,
299 .pNext = nullptr, 308 .pNext = nullptr,
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index 2a8b7a907..fa37aa79a 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -62,7 +62,7 @@ public:
62 : memory{std::move(memory_)}, allocation_size{allocation_size_}, property_flags{properties}, 62 : memory{std::move(memory_)}, allocation_size{allocation_size_}, property_flags{properties},
63 shifted_memory_type{1U << type} {} 63 shifted_memory_type{1U << type} {}
64 64
65#if defined(_WIN32) || defined(__linux__) 65#if defined(_WIN32) || defined(__unix__)
66 ~MemoryAllocation() { 66 ~MemoryAllocation() {
67 if (owning_opengl_handle != 0) { 67 if (owning_opengl_handle != 0) {
68 glDeleteMemoryObjectsEXT(1, &owning_opengl_handle); 68 glDeleteMemoryObjectsEXT(1, &owning_opengl_handle);
@@ -114,7 +114,7 @@ public:
114 } 114 }
115 return owning_opengl_handle; 115 return owning_opengl_handle;
116 } 116 }
117#elif __linux__ 117#elif __unix__
118 [[nodiscard]] u32 ExportOpenGLHandle() { 118 [[nodiscard]] u32 ExportOpenGLHandle() {
119 if (!owning_opengl_handle) { 119 if (!owning_opengl_handle) {
120 glCreateMemoryObjectsEXT(1, &owning_opengl_handle); 120 glCreateMemoryObjectsEXT(1, &owning_opengl_handle);
@@ -165,7 +165,7 @@ private:
165 const u32 shifted_memory_type; ///< Shifted Vulkan memory type. 165 const u32 shifted_memory_type; ///< Shifted Vulkan memory type.
166 std::vector<Range> commits; ///< All commit ranges done from this allocation. 166 std::vector<Range> commits; ///< All commit ranges done from this allocation.
167 std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before. 167 std::span<u8> memory_mapped_span; ///< Memory mapped span. Empty if not queried before.
168#if defined(_WIN32) || defined(__linux__) 168#if defined(_WIN32) || defined(__unix__)
169 u32 owning_opengl_handle{}; ///< Owning OpenGL memory object handle. 169 u32 owning_opengl_handle{}; ///< Owning OpenGL memory object handle.
170#endif 170#endif
171}; 171};
@@ -249,7 +249,7 @@ void MemoryAllocator::AllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u6
249 .pNext = nullptr, 249 .pNext = nullptr,
250#ifdef _WIN32 250#ifdef _WIN32
251 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, 251 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
252#elif __linux__ 252#elif __unix__
253 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, 253 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
254#else 254#else
255 .handleTypes = 0, 255 .handleTypes = 0,
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index b025ced1c..cc0790e07 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -18,6 +18,7 @@ add_executable(yuzu
18 applets/profile_select.h 18 applets/profile_select.h
19 applets/software_keyboard.cpp 19 applets/software_keyboard.cpp
20 applets/software_keyboard.h 20 applets/software_keyboard.h
21 applets/software_keyboard.ui
21 applets/web_browser.cpp 22 applets/web_browser.cpp
22 applets/web_browser.h 23 applets/web_browser.h
23 bootmanager.cpp 24 bootmanager.cpp
@@ -143,6 +144,9 @@ add_executable(yuzu
143 uisettings.h 144 uisettings.h
144 util/limitable_input_dialog.cpp 145 util/limitable_input_dialog.cpp
145 util/limitable_input_dialog.h 146 util/limitable_input_dialog.h
147 util/overlay_dialog.cpp
148 util/overlay_dialog.h
149 util/overlay_dialog.ui
146 util/sequence_dialog/sequence_dialog.cpp 150 util/sequence_dialog/sequence_dialog.cpp
147 util/sequence_dialog/sequence_dialog.h 151 util/sequence_dialog/sequence_dialog.h
148 util/url_request_interceptor.cpp 152 util/url_request_interceptor.cpp
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp
index b92cd6886..836d90fda 100644
--- a/src/yuzu/applets/controller.cpp
+++ b/src/yuzu/applets/controller.cpp
@@ -16,6 +16,7 @@
16#include "yuzu/applets/controller.h" 16#include "yuzu/applets/controller.h"
17#include "yuzu/configuration/configure_input.h" 17#include "yuzu/configuration/configure_input.h"
18#include "yuzu/configuration/configure_input_profile_dialog.h" 18#include "yuzu/configuration/configure_input_profile_dialog.h"
19#include "yuzu/configuration/configure_motion_touch.h"
19#include "yuzu/configuration/configure_vibration.h" 20#include "yuzu/configuration/configure_vibration.h"
20#include "yuzu/configuration/input_profiles.h" 21#include "yuzu/configuration/input_profiles.h"
21#include "yuzu/main.h" 22#include "yuzu/main.h"
@@ -206,6 +207,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
206 connect(ui->vibrationButton, &QPushButton::clicked, this, 207 connect(ui->vibrationButton, &QPushButton::clicked, this,
207 &QtControllerSelectorDialog::CallConfigureVibrationDialog); 208 &QtControllerSelectorDialog::CallConfigureVibrationDialog);
208 209
210 connect(ui->motionButton, &QPushButton::clicked, this,
211 &QtControllerSelectorDialog::CallConfigureMotionTouchDialog);
212
209 connect(ui->inputConfigButton, &QPushButton::clicked, this, 213 connect(ui->inputConfigButton, &QPushButton::clicked, this,
210 &QtControllerSelectorDialog::CallConfigureInputProfileDialog); 214 &QtControllerSelectorDialog::CallConfigureInputProfileDialog);
211 215
@@ -276,6 +280,18 @@ void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
276 } 280 }
277} 281}
278 282
283void QtControllerSelectorDialog::CallConfigureMotionTouchDialog() {
284 ConfigureMotionTouch dialog(this, input_subsystem);
285
286 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
287 Qt::WindowSystemMenuHint);
288 dialog.setWindowModality(Qt::WindowModal);
289
290 if (dialog.exec() == QDialog::Accepted) {
291 dialog.ApplyConfiguration();
292 }
293}
294
279void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { 295void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
280 ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get()); 296 ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get());
281 297
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h
index 3518eed56..9b57aea1a 100644
--- a/src/yuzu/applets/controller.h
+++ b/src/yuzu/applets/controller.h
@@ -51,6 +51,9 @@ private:
51 // Initializes the "Configure Vibration" Dialog. 51 // Initializes the "Configure Vibration" Dialog.
52 void CallConfigureVibrationDialog(); 52 void CallConfigureVibrationDialog();
53 53
54 // Initializes the "Configure Motion / Touch" Dialog.
55 void CallConfigureMotionTouchDialog();
56
54 // Initializes the "Create Input Profile" Dialog. 57 // Initializes the "Create Input Profile" Dialog.
55 void CallConfigureInputProfileDialog(); 58 void CallConfigureInputProfileDialog();
56 59
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
index 8ee03ddb3..085688cd4 100644
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/error.cpp
@@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default;
19void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const { 19void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const {
20 callback = std::move(finished); 20 callback = std::move(finished);
21 emit MainWindowDisplayError( 21 emit MainWindowDisplayError(
22 tr("An error has occurred.\nPlease try again or contact the developer of the " 22 tr("Error Code: %1-%2 (0x%3)")
23 "software.\n\nError Code: %1-%2 (0x%3)")
24 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) 23 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
25 .arg(error.description, 4, 10, QChar::fromLatin1('0')) 24 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
26 .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); 25 .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
26 tr("An error has occurred.\nPlease try again or contact the developer of the software."));
27} 27}
28 28
29void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 29void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
@@ -32,13 +32,14 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon
32 32
33 const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); 33 const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
34 emit MainWindowDisplayError( 34 emit MainWindowDisplayError(
35 tr("An error occurred on %1 at %2.\nPlease try again or contact the " 35 tr("Error Code: %1-%2 (0x%3)")
36 "developer of the software.\n\nError Code: %3-%4 (0x%5)")
37 .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
38 .arg(date_time.toString(QStringLiteral("h:mm:ss A")))
39 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) 36 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
40 .arg(error.description, 4, 10, QChar::fromLatin1('0')) 37 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
41 .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); 38 .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
39 tr("An error occurred on %1 at %2.\nPlease try again or contact the developer of the "
40 "software.")
41 .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
42 .arg(date_time.toString(QStringLiteral("h:mm:ss A"))));
42} 43}
43 44
44void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, 45void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text,
@@ -46,10 +47,11 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
46 std::function<void()> finished) const { 47 std::function<void()> finished) const {
47 callback = std::move(finished); 48 callback = std::move(finished);
48 emit MainWindowDisplayError( 49 emit MainWindowDisplayError(
49 tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") 50 tr("Error Code: %1-%2 (0x%3)")
50 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) 51 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
51 .arg(error.description, 4, 10, QChar::fromLatin1('0')) 52 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
52 .arg(error.raw, 8, 16, QChar::fromLatin1('0')) 53 .arg(error.raw, 8, 16, QChar::fromLatin1('0')),
54 tr("An error has occurred.\n\n%1\n\n%2")
53 .arg(QString::fromStdString(dialog_text)) 55 .arg(QString::fromStdString(dialog_text))
54 .arg(QString::fromStdString(fullscreen_text))); 56 .arg(QString::fromStdString(fullscreen_text)));
55} 57}
diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h
index b0932d895..8bd895a32 100644
--- a/src/yuzu/applets/error.h
+++ b/src/yuzu/applets/error.h
@@ -24,7 +24,7 @@ public:
24 std::function<void()> finished) const override; 24 std::function<void()> finished) const override;
25 25
26signals: 26signals:
27 void MainWindowDisplayError(QString error) const; 27 void MainWindowDisplayError(QString error_code, QString error_text) const;
28 28
29private: 29private:
30 void MainWindowFinishedError(); 30 void MainWindowFinishedError();
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp
index ab8cfd8ee..fd3368479 100644
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/software_keyboard.cpp
@@ -1,153 +1,1641 @@
1// Copyright 2018 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <QCursor>
6#include <mutex> 6#include <QKeyEvent>
7#include <QDialogButtonBox> 7#include <QScreen>
8#include <QFont> 8
9#include <QLabel> 9#include "common/logging/log.h"
10#include <QLineEdit> 10#include "common/settings.h"
11#include <QVBoxLayout> 11#include "common/string_util.h"
12#include "core/hle/lock.h" 12#include "core/core.h"
13#include "core/frontend/input_interpreter.h"
14#include "ui_software_keyboard.h"
13#include "yuzu/applets/software_keyboard.h" 15#include "yuzu/applets/software_keyboard.h"
14#include "yuzu/main.h" 16#include "yuzu/main.h"
17#include "yuzu/util/overlay_dialog.h"
18
19namespace {
20
21using namespace Service::AM::Applets;
22
23constexpr float BASE_HEADER_FONT_SIZE = 23.0f;
24constexpr float BASE_SUB_FONT_SIZE = 17.0f;
25constexpr float BASE_EDITOR_FONT_SIZE = 26.0f;
26constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f;
27constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f;
28constexpr float BASE_ICON_BUTTON_SIZE = 36.0f;
29[[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f;
30constexpr float BASE_HEIGHT = 720.0f;
31
32} // Anonymous namespace
33
34QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
35 QWidget* parent, Core::System& system_, bool is_inline_,
36 Core::Frontend::KeyboardInitializeParameters initialize_parameters_)
37 : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_},
38 is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} {
39 ui->setupUi(this);
40
41 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
42 Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
43 setWindowModality(Qt::WindowModal);
44 setAttribute(Qt::WA_DeleteOnClose);
45 setAttribute(Qt::WA_TranslucentBackground);
46
47 keyboard_buttons = {{
48 {{
49 {
50 ui->button_1,
51 ui->button_2,
52 ui->button_3,
53 ui->button_4,
54 ui->button_5,
55 ui->button_6,
56 ui->button_7,
57 ui->button_8,
58 ui->button_9,
59 ui->button_0,
60 ui->button_minus,
61 ui->button_backspace,
62 },
63 {
64 ui->button_q,
65 ui->button_w,
66 ui->button_e,
67 ui->button_r,
68 ui->button_t,
69 ui->button_y,
70 ui->button_u,
71 ui->button_i,
72 ui->button_o,
73 ui->button_p,
74 ui->button_slash,
75 ui->button_return,
76 },
77 {
78 ui->button_a,
79 ui->button_s,
80 ui->button_d,
81 ui->button_f,
82 ui->button_g,
83 ui->button_h,
84 ui->button_j,
85 ui->button_k,
86 ui->button_l,
87 ui->button_colon,
88 ui->button_apostrophe,
89 ui->button_return,
90 },
91 {
92 ui->button_z,
93 ui->button_x,
94 ui->button_c,
95 ui->button_v,
96 ui->button_b,
97 ui->button_n,
98 ui->button_m,
99 ui->button_comma,
100 ui->button_dot,
101 ui->button_question,
102 ui->button_exclamation,
103 ui->button_ok,
104 },
105 {
106 ui->button_shift,
107 ui->button_shift,
108 ui->button_space,
109 ui->button_space,
110 ui->button_space,
111 ui->button_space,
112 ui->button_space,
113 ui->button_space,
114 ui->button_space,
115 ui->button_space,
116 ui->button_space,
117 ui->button_ok,
118 },
119 }},
120 {{
121 {
122 ui->button_hash,
123 ui->button_left_bracket,
124 ui->button_right_bracket,
125 ui->button_dollar,
126 ui->button_percent,
127 ui->button_circumflex,
128 ui->button_ampersand,
129 ui->button_asterisk,
130 ui->button_left_parenthesis,
131 ui->button_right_parenthesis,
132 ui->button_underscore,
133 ui->button_backspace_shift,
134 },
135 {
136 ui->button_q_shift,
137 ui->button_w_shift,
138 ui->button_e_shift,
139 ui->button_r_shift,
140 ui->button_t_shift,
141 ui->button_y_shift,
142 ui->button_u_shift,
143 ui->button_i_shift,
144 ui->button_o_shift,
145 ui->button_p_shift,
146 ui->button_at,
147 ui->button_return_shift,
148 },
149 {
150 ui->button_a_shift,
151 ui->button_s_shift,
152 ui->button_d_shift,
153 ui->button_f_shift,
154 ui->button_g_shift,
155 ui->button_h_shift,
156 ui->button_j_shift,
157 ui->button_k_shift,
158 ui->button_l_shift,
159 ui->button_semicolon,
160 ui->button_quotation,
161 ui->button_return_shift,
162 },
163 {
164 ui->button_z_shift,
165 ui->button_x_shift,
166 ui->button_c_shift,
167 ui->button_v_shift,
168 ui->button_b_shift,
169 ui->button_n_shift,
170 ui->button_m_shift,
171 ui->button_less_than,
172 ui->button_greater_than,
173 ui->button_plus,
174 ui->button_equal,
175 ui->button_ok_shift,
176 },
177 {
178 ui->button_shift_shift,
179 ui->button_shift_shift,
180 ui->button_space_shift,
181 ui->button_space_shift,
182 ui->button_space_shift,
183 ui->button_space_shift,
184 ui->button_space_shift,
185 ui->button_space_shift,
186 ui->button_space_shift,
187 ui->button_space_shift,
188 ui->button_space_shift,
189 ui->button_ok_shift,
190 },
191 }},
192 }};
15 193
16QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( 194 numberpad_buttons = {{
17 Core::Frontend::SoftwareKeyboardParameters parameters) 195 {
18 : parameters(std::move(parameters)) {} 196 ui->button_1_num,
197 ui->button_2_num,
198 ui->button_3_num,
199 ui->button_backspace_num,
200 },
201 {
202 ui->button_4_num,
203 ui->button_5_num,
204 ui->button_6_num,
205 ui->button_ok_num,
206 },
207 {
208 ui->button_7_num,
209 ui->button_8_num,
210 ui->button_9_num,
211 ui->button_ok_num,
212 },
213 {
214 nullptr,
215 ui->button_0_num,
216 nullptr,
217 ui->button_ok_num,
218 },
219 }};
19 220
20QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { 221 all_buttons = {
21 if (input.size() > static_cast<s64>(parameters.max_length)) { 222 ui->button_1,
22 return Invalid; 223 ui->button_2,
224 ui->button_3,
225 ui->button_4,
226 ui->button_5,
227 ui->button_6,
228 ui->button_7,
229 ui->button_8,
230 ui->button_9,
231 ui->button_0,
232 ui->button_minus,
233 ui->button_backspace,
234 ui->button_q,
235 ui->button_w,
236 ui->button_e,
237 ui->button_r,
238 ui->button_t,
239 ui->button_y,
240 ui->button_u,
241 ui->button_i,
242 ui->button_o,
243 ui->button_p,
244 ui->button_slash,
245 ui->button_return,
246 ui->button_a,
247 ui->button_s,
248 ui->button_d,
249 ui->button_f,
250 ui->button_g,
251 ui->button_h,
252 ui->button_j,
253 ui->button_k,
254 ui->button_l,
255 ui->button_colon,
256 ui->button_apostrophe,
257 ui->button_z,
258 ui->button_x,
259 ui->button_c,
260 ui->button_v,
261 ui->button_b,
262 ui->button_n,
263 ui->button_m,
264 ui->button_comma,
265 ui->button_dot,
266 ui->button_question,
267 ui->button_exclamation,
268 ui->button_ok,
269 ui->button_shift,
270 ui->button_space,
271 ui->button_hash,
272 ui->button_left_bracket,
273 ui->button_right_bracket,
274 ui->button_dollar,
275 ui->button_percent,
276 ui->button_circumflex,
277 ui->button_ampersand,
278 ui->button_asterisk,
279 ui->button_left_parenthesis,
280 ui->button_right_parenthesis,
281 ui->button_underscore,
282 ui->button_backspace_shift,
283 ui->button_q_shift,
284 ui->button_w_shift,
285 ui->button_e_shift,
286 ui->button_r_shift,
287 ui->button_t_shift,
288 ui->button_y_shift,
289 ui->button_u_shift,
290 ui->button_i_shift,
291 ui->button_o_shift,
292 ui->button_p_shift,
293 ui->button_at,
294 ui->button_return_shift,
295 ui->button_a_shift,
296 ui->button_s_shift,
297 ui->button_d_shift,
298 ui->button_f_shift,
299 ui->button_g_shift,
300 ui->button_h_shift,
301 ui->button_j_shift,
302 ui->button_k_shift,
303 ui->button_l_shift,
304 ui->button_semicolon,
305 ui->button_quotation,
306 ui->button_z_shift,
307 ui->button_x_shift,
308 ui->button_c_shift,
309 ui->button_v_shift,
310 ui->button_b_shift,
311 ui->button_n_shift,
312 ui->button_m_shift,
313 ui->button_less_than,
314 ui->button_greater_than,
315 ui->button_plus,
316 ui->button_equal,
317 ui->button_ok_shift,
318 ui->button_shift_shift,
319 ui->button_space_shift,
320 ui->button_1_num,
321 ui->button_2_num,
322 ui->button_3_num,
323 ui->button_backspace_num,
324 ui->button_4_num,
325 ui->button_5_num,
326 ui->button_6_num,
327 ui->button_ok_num,
328 ui->button_7_num,
329 ui->button_8_num,
330 ui->button_9_num,
331 ui->button_0_num,
332 };
333
334 SetupMouseHover();
335
336 if (!initialize_parameters.ok_text.empty()) {
337 ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text));
23 } 338 }
24 if (parameters.disable_space && input.contains(QLatin1Char{' '})) { 339
25 return Invalid; 340 ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text));
341 ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text));
342
343 current_text = initialize_parameters.initial_text;
344 cursor_position = initialize_parameters.initial_cursor_position;
345
346 SetTextDrawType();
347
348 for (auto* button : all_buttons) {
349 connect(button, &QPushButton::clicked, this, [this, button](bool) {
350 if (is_inline) {
351 InlineKeyboardButtonClicked(button);
352 } else {
353 NormalKeyboardButtonClicked(button);
354 }
355 });
26 } 356 }
27 if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { 357
28 return Invalid; 358 // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
359 if (system.IsPoweredOn()) {
360 input_interpreter = std::make_unique<InputInterpreter>(system);
29 } 361 }
30 if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { 362}
31 return Invalid; 363
364QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() {
365 StopInputThread();
366}
367
368void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) {
369 if (isVisible()) {
370 return;
32 } 371 }
33 if (parameters.disable_slash && 372
34 (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { 373 MoveAndResizeWindow(pos, size);
35 return Invalid; 374
375 SetKeyboardType();
376 SetPasswordMode();
377 SetControllerImage();
378 DisableKeyboardButtons();
379 SetBackspaceOkEnabled();
380
381 open();
382}
383
384void QtSoftwareKeyboardDialog::ShowTextCheckDialog(
385 Service::AM::Applets::SwkbdTextCheckResult text_check_result,
386 std::u16string text_check_message) {
387 switch (text_check_result) {
388 case SwkbdTextCheckResult::Success:
389 case SwkbdTextCheckResult::Silent:
390 default:
391 break;
392 case SwkbdTextCheckResult::Failure: {
393 StopInputThread();
394
395 OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
396 QString{}, tr("OK"), Qt::AlignCenter);
397 dialog.exec();
398
399 StartInputThread();
400 break;
36 } 401 }
37 if (parameters.disable_number && 402 case SwkbdTextCheckResult::Confirm: {
38 std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { 403 StopInputThread();
39 return Invalid; 404
405 OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message),
406 tr("Cancel"), tr("OK"), Qt::AlignCenter);
407 if (dialog.exec() == QDialog::Accepted) {
408 emit SubmitNormalText(SwkbdResult::Ok, current_text);
409 break;
410 }
411
412 StartInputThread();
413 break;
40 } 414 }
415 }
416}
417
418void QtSoftwareKeyboardDialog::ShowInlineKeyboard(
419 Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) {
420 MoveAndResizeWindow(pos, size);
421
422 ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);"));
423
424 ui->headerOSK->hide();
425 ui->subOSK->hide();
426 ui->inputOSK->hide();
427 ui->charactersOSK->hide();
428 ui->inputBoxOSK->hide();
429 ui->charactersBoxOSK->hide();
430
431 initialize_parameters.max_text_length = appear_parameters.max_text_length;
432 initialize_parameters.min_text_length = appear_parameters.min_text_length;
433 initialize_parameters.type = appear_parameters.type;
434 initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags;
435 initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button;
436 initialize_parameters.enable_return_button = appear_parameters.enable_return_button;
437 initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button;
41 438
42 if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { 439 SetKeyboardType();
43 return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; 440 SetControllerImage();
44 })) { 441 DisableKeyboardButtons();
45 return Invalid; 442 SetBackspaceOkEnabled();
443
444 open();
445}
446
447void QtSoftwareKeyboardDialog::HideInlineKeyboard() {
448 StopInputThread();
449 QDialog::hide();
450}
451
452void QtSoftwareKeyboardDialog::InlineTextChanged(
453 Core::Frontend::InlineTextParameters text_parameters) {
454 current_text = text_parameters.input_text;
455 cursor_position = text_parameters.cursor_position;
456
457 SetBackspaceOkEnabled();
458}
459
460void QtSoftwareKeyboardDialog::ExitKeyboard() {
461 StopInputThread();
462 QDialog::done(QDialog::Accepted);
463}
464
465void QtSoftwareKeyboardDialog::open() {
466 QDialog::open();
467
468 row = 0;
469 column = 0;
470
471 const auto* const curr_button =
472 keyboard_buttons[static_cast<int>(bottom_osk_index)][row][column];
473
474 // This is a workaround for setFocus() randomly not showing focus in the UI
475 QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
476
477 StartInputThread();
478}
479
480void QtSoftwareKeyboardDialog::reject() {
481 // Pressing the ESC key in a dialog calls QDialog::reject().
482 // We will override this behavior to the "Cancel" action on the software keyboard.
483 if (is_inline) {
484 emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
485 } else {
486 emit SubmitNormalText(SwkbdResult::Cancel, current_text);
46 } 487 }
488}
489
490void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
491 if (!is_inline) {
492 QDialog::keyPressEvent(event);
493 return;
494 }
495
496 const auto entered_key = event->key();
47 497
48 return Acceptable; 498 switch (entered_key) {
499 case Qt::Key_Escape:
500 QDialog::keyPressEvent(event);
501 return;
502 case Qt::Key_Backspace:
503 switch (bottom_osk_index) {
504 case BottomOSKIndex::LowerCase:
505 ui->button_backspace->click();
506 break;
507 case BottomOSKIndex::UpperCase:
508 ui->button_backspace_shift->click();
509 break;
510 case BottomOSKIndex::NumberPad:
511 ui->button_backspace_num->click();
512 break;
513 default:
514 break;
515 }
516 return;
517 case Qt::Key_Return:
518 switch (bottom_osk_index) {
519 case BottomOSKIndex::LowerCase:
520 ui->button_ok->click();
521 break;
522 case BottomOSKIndex::UpperCase:
523 ui->button_ok_shift->click();
524 break;
525 case BottomOSKIndex::NumberPad:
526 ui->button_ok_num->click();
527 break;
528 default:
529 break;
530 }
531 return;
532 case Qt::Key_Left:
533 MoveTextCursorDirection(Direction::Left);
534 return;
535 case Qt::Key_Right:
536 MoveTextCursorDirection(Direction::Right);
537 return;
538 default:
539 break;
540 }
541
542 const auto entered_text = event->text();
543
544 if (entered_text.isEmpty()) {
545 return;
546 }
547
548 InlineTextInsertString(entered_text.toStdU16String());
49} 549}
50 550
51QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( 551void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) {
52 QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) 552 QDialog::move(pos);
53 : QDialog(parent), parameters(std::move(parameters_)) { 553 QDialog::resize(size);
54 layout = new QVBoxLayout; 554
55 555 // High DPI
56 header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); 556 const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
57 header_label->setFont({header_label->font().family(), 11, QFont::Bold}); 557
58 if (header_label->text().isEmpty()) 558 RescaleKeyboardElements(size.width(), size.height(), dpi_scale);
59 header_label->setText(tr("Enter text:")); 559}
60 560
61 sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text)); 561void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) {
62 sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(), 562 const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
63 sub_label->font().weight(), true}); 563 const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
64 sub_label->setHidden(parameters.sub_text.empty()); 564 const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
65 565 const auto char_button_font_size =
66 guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text)); 566 BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
67 guide_label->setHidden(parameters.guide_text.empty()); 567 const auto label_button_font_size =
68 568 BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
69 length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length)); 569
70 length_label->setAlignment(Qt::AlignRight); 570 QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal);
71 length_label->setFont({length_label->font().family(), 8}); 571 QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal);
72 572 QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal);
73 line_edit = new QLineEdit; 573 QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal);
74 line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); 574 QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size,
75 line_edit->setMaxLength(static_cast<int>(parameters.max_length)); 575 QFont::Normal);
76 line_edit->setText(QString::fromStdU16String(parameters.initial_text)); 576
77 line_edit->setCursorPosition( 577 ui->label_header->setFont(header_font);
78 parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size())); 578 ui->label_sub->setFont(sub_font);
79 line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); 579 ui->line_edit_osk->setFont(editor_font);
80 580 ui->text_edit_osk->setFont(editor_font);
81 connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) { 581 ui->label_characters->setFont(sub_font);
82 length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); 582 ui->label_characters_box->setFont(sub_font);
83 }); 583
84 584 ui->label_shift->setFont(label_button_font);
85 buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); 585 ui->label_shift_shift->setFont(label_button_font);
86 if (parameters.submit_text.empty()) { 586 ui->label_cancel->setFont(label_button_font);
87 buttons->addButton(QDialogButtonBox::Ok); 587 ui->label_cancel_shift->setFont(label_button_font);
588 ui->label_cancel_num->setFont(label_button_font);
589 ui->label_enter->setFont(label_button_font);
590 ui->label_enter_shift->setFont(label_button_font);
591 ui->label_enter_num->setFont(label_button_font);
592
593 for (auto* button : all_buttons) {
594 if (button == ui->button_return || button == ui->button_return_shift) {
595 button->setFont(label_button_font);
596 continue;
597 }
598
599 if (button == ui->button_space || button == ui->button_space_shift) {
600 button->setFont(label_button_font);
601 continue;
602 }
603
604 if (button == ui->button_shift || button == ui->button_shift_shift) {
605 button->setFont(label_button_font);
606 button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
607 (height / BASE_HEIGHT));
608 continue;
609 }
610
611 if (button == ui->button_backspace || button == ui->button_backspace_shift ||
612 button == ui->button_backspace_num) {
613 button->setFont(label_button_font);
614 button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) *
615 (height / BASE_HEIGHT));
616 continue;
617 }
618
619 if (button == ui->button_ok || button == ui->button_ok_shift ||
620 button == ui->button_ok_num) {
621 button->setFont(label_button_font);
622 continue;
623 }
624
625 button->setFont(char_button_font);
626 }
627}
628
629void QtSoftwareKeyboardDialog::SetKeyboardType() {
630 switch (initialize_parameters.type) {
631 case SwkbdType::Normal:
632 case SwkbdType::Qwerty:
633 case SwkbdType::Unknown3:
634 case SwkbdType::Latin:
635 case SwkbdType::SimplifiedChinese:
636 case SwkbdType::TraditionalChinese:
637 case SwkbdType::Korean:
638 default: {
639 bottom_osk_index = BottomOSKIndex::LowerCase;
640 ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
641
642 ui->verticalLayout_2->setStretch(0, 320);
643 ui->verticalLayout_2->setStretch(1, 400);
644
645 ui->gridLineOSK->setRowStretch(5, 94);
646 ui->gridBoxOSK->setRowStretch(2, 81);
647 break;
648 }
649 case SwkbdType::NumberPad: {
650 bottom_osk_index = BottomOSKIndex::NumberPad;
651 ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
652
653 ui->verticalLayout_2->setStretch(0, 370);
654 ui->verticalLayout_2->setStretch(1, 350);
655
656 ui->gridLineOSK->setRowStretch(5, 144);
657 ui->gridBoxOSK->setRowStretch(2, 131);
658 break;
659 }
660 }
661}
662
663void QtSoftwareKeyboardDialog::SetPasswordMode() {
664 switch (initialize_parameters.password_mode) {
665 case SwkbdPasswordMode::Disabled:
666 default:
667 ui->line_edit_osk->setEchoMode(QLineEdit::Normal);
668 break;
669 case SwkbdPasswordMode::Enabled:
670 ui->line_edit_osk->setEchoMode(QLineEdit::Password);
671 break;
672 }
673}
674
675void QtSoftwareKeyboardDialog::SetTextDrawType() {
676 switch (initialize_parameters.text_draw_type) {
677 case SwkbdTextDrawType::Line:
678 case SwkbdTextDrawType::DownloadCode: {
679 ui->topOSK->setCurrentIndex(0);
680
681 if (initialize_parameters.max_text_length <= 10) {
682 ui->gridLineOSK->setColumnStretch(0, 390);
683 ui->gridLineOSK->setColumnStretch(1, 500);
684 ui->gridLineOSK->setColumnStretch(2, 390);
685 } else {
686 ui->gridLineOSK->setColumnStretch(0, 130);
687 ui->gridLineOSK->setColumnStretch(1, 1020);
688 ui->gridLineOSK->setColumnStretch(2, 130);
689 }
690
691 if (is_inline) {
692 return;
693 }
694
695 connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) {
696 const auto is_valid = ValidateInputText(changed_string);
697
698 const auto text_length = static_cast<u32>(changed_string.length());
699
700 ui->label_characters->setText(QStringLiteral("%1/%2")
701 .arg(text_length)
702 .arg(initialize_parameters.max_text_length));
703
704 ui->button_ok->setEnabled(is_valid);
705 ui->button_ok_shift->setEnabled(is_valid);
706 ui->button_ok_num->setEnabled(is_valid);
707
708 ui->line_edit_osk->setFocus();
709 });
710
711 connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged,
712 [this](int old_cursor_position, int new_cursor_position) {
713 ui->button_backspace->setEnabled(
714 initialize_parameters.enable_backspace_button && new_cursor_position > 0);
715 ui->button_backspace_shift->setEnabled(
716 initialize_parameters.enable_backspace_button && new_cursor_position > 0);
717 ui->button_backspace_num->setEnabled(
718 initialize_parameters.enable_backspace_button && new_cursor_position > 0);
719
720 ui->line_edit_osk->setFocus();
721 });
722
723 connect(ui->line_edit_osk, &QLineEdit::returnPressed, [this] {
724 switch (bottom_osk_index) {
725 case BottomOSKIndex::LowerCase:
726 ui->button_ok->click();
727 break;
728 case BottomOSKIndex::UpperCase:
729 ui->button_ok_shift->click();
730 break;
731 case BottomOSKIndex::NumberPad:
732 ui->button_ok_num->click();
733 break;
734 default:
735 break;
736 }
737 });
738
739 ui->line_edit_osk->setPlaceholderText(
740 QString::fromStdU16String(initialize_parameters.guide_text));
741 ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text));
742 ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length);
743 ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position);
744
745 ui->label_characters->setText(QStringLiteral("%1/%2")
746 .arg(initialize_parameters.initial_text.size())
747 .arg(initialize_parameters.max_text_length));
748 break;
749 }
750 case SwkbdTextDrawType::Box:
751 default: {
752 ui->topOSK->setCurrentIndex(1);
753
754 if (is_inline) {
755 return;
756 }
757
758 connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] {
759 if (static_cast<u32>(ui->text_edit_osk->toPlainText().length()) >
760 initialize_parameters.max_text_length) {
761 auto text_cursor = ui->text_edit_osk->textCursor();
762 ui->text_edit_osk->setTextCursor(text_cursor);
763 text_cursor.deletePreviousChar();
764 }
765
766 const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText());
767
768 const auto text_length = static_cast<u32>(ui->text_edit_osk->toPlainText().length());
769
770 ui->label_characters_box->setText(QStringLiteral("%1/%2")
771 .arg(text_length)
772 .arg(initialize_parameters.max_text_length));
773
774 ui->button_ok->setEnabled(is_valid);
775 ui->button_ok_shift->setEnabled(is_valid);
776 ui->button_ok_num->setEnabled(is_valid);
777
778 ui->text_edit_osk->setFocus();
779 });
780
781 connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] {
782 const auto new_cursor_position = ui->text_edit_osk->textCursor().position();
783
784 ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
785 new_cursor_position > 0);
786 ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
787 new_cursor_position > 0);
788 ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
789 new_cursor_position > 0);
790
791 ui->text_edit_osk->setFocus();
792 });
793
794 ui->text_edit_osk->setPlaceholderText(
795 QString::fromStdU16String(initialize_parameters.guide_text));
796 ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text));
797 ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0
798 ? QTextCursor::Start
799 : QTextCursor::End);
800
801 ui->label_characters_box->setText(QStringLiteral("%1/%2")
802 .arg(initialize_parameters.initial_text.size())
803 .arg(initialize_parameters.max_text_length));
804 break;
805 }
806 }
807}
808
809void QtSoftwareKeyboardDialog::SetControllerImage() {
810 const auto controller_type = Settings::values.players.GetValue()[8].connected
811 ? Settings::values.players.GetValue()[8].controller_type
812 : Settings::values.players.GetValue()[0].controller_type;
813
814 const QString theme = [] {
815 if (QIcon::themeName().contains(QStringLiteral("dark")) ||
816 QIcon::themeName().contains(QStringLiteral("midnight"))) {
817 return QStringLiteral("_dark");
818 } else {
819 return QString{};
820 }
821 }();
822
823 switch (controller_type) {
824 case Settings::ControllerType::ProController:
825 case Settings::ControllerType::GameCube:
826 ui->icon_controller->setStyleSheet(
827 QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
828 ui->icon_controller_shift->setStyleSheet(
829 QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
830 ui->icon_controller_num->setStyleSheet(
831 QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));
832 break;
833 case Settings::ControllerType::DualJoyconDetached:
834 ui->icon_controller->setStyleSheet(
835 QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
836 ui->icon_controller_shift->setStyleSheet(
837 QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
838 ui->icon_controller_num->setStyleSheet(
839 QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme));
840 break;
841 case Settings::ControllerType::LeftJoycon:
842 ui->icon_controller->setStyleSheet(
843 QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
844 .arg(theme));
845 ui->icon_controller_shift->setStyleSheet(
846 QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
847 .arg(theme));
848 ui->icon_controller_num->setStyleSheet(
849 QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);")
850 .arg(theme));
851 break;
852 case Settings::ControllerType::RightJoycon:
853 ui->icon_controller->setStyleSheet(
854 QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
855 .arg(theme));
856 ui->icon_controller_shift->setStyleSheet(
857 QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
858 .arg(theme));
859 ui->icon_controller_num->setStyleSheet(
860 QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);")
861 .arg(theme));
862 break;
863 case Settings::ControllerType::Handheld:
864 ui->icon_controller->setStyleSheet(
865 QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
866 ui->icon_controller_shift->setStyleSheet(
867 QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
868 ui->icon_controller_num->setStyleSheet(
869 QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme));
870 break;
871 default:
872 break;
873 }
874}
875
876void QtSoftwareKeyboardDialog::DisableKeyboardButtons() {
877 switch (bottom_osk_index) {
878 case BottomOSKIndex::LowerCase:
879 case BottomOSKIndex::UpperCase:
880 default: {
881 for (const auto& keys : keyboard_buttons) {
882 for (const auto& rows : keys) {
883 for (auto* button : rows) {
884 if (!button) {
885 continue;
886 }
887
888 button->setEnabled(true);
889 }
890 }
891 }
892
893 const auto& key_disable_flags = initialize_parameters.key_disable_flags;
894
895 ui->button_space->setDisabled(key_disable_flags.space);
896 ui->button_space_shift->setDisabled(key_disable_flags.space);
897
898 ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username);
899
900 ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username);
901
902 ui->button_slash->setDisabled(key_disable_flags.slash);
903
904 ui->button_1->setDisabled(key_disable_flags.numbers);
905 ui->button_2->setDisabled(key_disable_flags.numbers);
906 ui->button_3->setDisabled(key_disable_flags.numbers);
907 ui->button_4->setDisabled(key_disable_flags.numbers);
908 ui->button_5->setDisabled(key_disable_flags.numbers);
909 ui->button_6->setDisabled(key_disable_flags.numbers);
910 ui->button_7->setDisabled(key_disable_flags.numbers);
911 ui->button_8->setDisabled(key_disable_flags.numbers);
912 ui->button_9->setDisabled(key_disable_flags.numbers);
913 ui->button_0->setDisabled(key_disable_flags.numbers);
914
915 ui->button_return->setEnabled(initialize_parameters.enable_return_button);
916 ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button);
917 break;
918 }
919 case BottomOSKIndex::NumberPad: {
920 for (const auto& rows : numberpad_buttons) {
921 for (auto* button : rows) {
922 if (!button) {
923 continue;
924 }
925
926 button->setEnabled(true);
927 }
928 }
929 break;
930 }
931 }
932}
933
934void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() {
935 if (is_inline) {
936 ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length);
937 ui->button_ok_shift->setEnabled(current_text.size() >=
938 initialize_parameters.min_text_length);
939 ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length);
940
941 ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
942 cursor_position > 0);
943 ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
944 cursor_position > 0);
945 ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
946 cursor_position > 0);
88 } else { 947 } else {
89 buttons->addButton(QString::fromStdU16String(parameters.submit_text), 948 const auto text_length = [this] {
90 QDialogButtonBox::AcceptRole); 949 if (ui->topOSK->currentIndex() == 1) {
950 return static_cast<u32>(ui->text_edit_osk->toPlainText().length());
951 } else {
952 return static_cast<u32>(ui->line_edit_osk->text().length());
953 }
954 }();
955
956 const auto normal_cursor_position = [this] {
957 if (ui->topOSK->currentIndex() == 1) {
958 return ui->text_edit_osk->textCursor().position();
959 } else {
960 return ui->line_edit_osk->cursorPosition();
961 }
962 }();
963
964 ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length);
965 ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length);
966 ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length);
967
968 ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button &&
969 normal_cursor_position > 0);
970 ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button &&
971 normal_cursor_position > 0);
972 ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button &&
973 normal_cursor_position > 0);
91 } 974 }
92 connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept);
93 connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject);
94 layout->addWidget(header_label);
95 layout->addWidget(sub_label);
96 layout->addWidget(guide_label);
97 layout->addWidget(length_label);
98 layout->addWidget(line_edit);
99 layout->addWidget(buttons);
100 setLayout(layout);
101 setWindowTitle(tr("Software Keyboard"));
102} 975}
103 976
104QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; 977bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) {
978 const auto& key_disable_flags = initialize_parameters.key_disable_flags;
979
980 const auto input_text_length = static_cast<u32>(input_text.length());
981
982 if (input_text_length < initialize_parameters.min_text_length ||
983 input_text_length > initialize_parameters.max_text_length) {
984 return false;
985 }
986
987 if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) {
988 return false;
989 }
990
991 if ((key_disable_flags.at || key_disable_flags.username) &&
992 input_text.contains(QLatin1Char{'@'})) {
993 return false;
994 }
995
996 if ((key_disable_flags.percent || key_disable_flags.username) &&
997 input_text.contains(QLatin1Char{'%'})) {
998 return false;
999 }
1000
1001 if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) {
1002 return false;
1003 }
1004
1005 if ((key_disable_flags.backslash || key_disable_flags.username) &&
1006 input_text.contains(QLatin1Char('\\'))) {
1007 return false;
1008 }
105 1009
106void QtSoftwareKeyboardDialog::accept() { 1010 if (key_disable_flags.numbers &&
107 text = line_edit->text().toStdU16String(); 1011 std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) {
108 QDialog::accept(); 1012 return false;
1013 }
1014
1015 if (bottom_osk_index == BottomOSKIndex::NumberPad &&
1016 std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) {
1017 return false;
1018 }
1019
1020 return true;
109} 1021}
110 1022
111void QtSoftwareKeyboardDialog::reject() { 1023void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() {
112 text.clear(); 1024 switch (bottom_osk_index) {
113 QDialog::reject(); 1025 case BottomOSKIndex::LowerCase:
1026 bottom_osk_index = BottomOSKIndex::UpperCase;
1027 ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
1028
1029 ui->button_shift_shift->setStyleSheet(
1030 QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);"
1031 "\nbackground-position: left top;"
1032 "\nbackground-repeat: no-repeat;"
1033 "\nbackground-origin: content;"));
1034
1035 ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
1036 ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
1037 break;
1038 case BottomOSKIndex::UpperCase:
1039 if (caps_lock_enabled) {
1040 caps_lock_enabled = false;
1041
1042 ui->button_shift_shift->setStyleSheet(
1043 QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);"
1044 "\nbackground-position: left top;"
1045 "\nbackground-repeat: no-repeat;"
1046 "\nbackground-origin: content;"));
1047
1048 ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
1049 ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
1050
1051 ui->label_shift_shift->setText(QStringLiteral("Caps Lock"));
1052
1053 bottom_osk_index = BottomOSKIndex::LowerCase;
1054 ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index));
1055 } else {
1056 caps_lock_enabled = true;
1057
1058 ui->button_shift_shift->setStyleSheet(
1059 QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_on.png);"
1060 "\nbackground-position: left top;"
1061 "\nbackground-repeat: no-repeat;"
1062 "\nbackground-origin: content;"));
1063
1064 ui->button_shift_shift->setIconSize(ui->button_shift->iconSize());
1065 ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize());
1066
1067 ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off"));
1068 }
1069 break;
1070 case BottomOSKIndex::NumberPad:
1071 default:
1072 break;
1073 }
114} 1074}
115 1075
116std::u16string QtSoftwareKeyboardDialog::GetText() const { 1076void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) {
117 return text; 1077 if (button == ui->button_ampersand) {
1078 if (ui->topOSK->currentIndex() == 1) {
1079 ui->text_edit_osk->insertPlainText(QStringLiteral("&"));
1080 } else {
1081 ui->line_edit_osk->insert(QStringLiteral("&"));
1082 }
1083 return;
1084 }
1085
1086 if (button == ui->button_return || button == ui->button_return_shift) {
1087 if (ui->topOSK->currentIndex() == 1) {
1088 ui->text_edit_osk->insertPlainText(QStringLiteral("\n"));
1089 } else {
1090 ui->line_edit_osk->insert(QStringLiteral("\n"));
1091 }
1092 return;
1093 }
1094
1095 if (button == ui->button_space || button == ui->button_space_shift) {
1096 if (ui->topOSK->currentIndex() == 1) {
1097 ui->text_edit_osk->insertPlainText(QStringLiteral(" "));
1098 } else {
1099 ui->line_edit_osk->insert(QStringLiteral(" "));
1100 }
1101 return;
1102 }
1103
1104 if (button == ui->button_shift || button == ui->button_shift_shift) {
1105 ChangeBottomOSKIndex();
1106 return;
1107 }
1108
1109 if (button == ui->button_backspace || button == ui->button_backspace_shift ||
1110 button == ui->button_backspace_num) {
1111 if (ui->topOSK->currentIndex() == 1) {
1112 auto text_cursor = ui->text_edit_osk->textCursor();
1113 ui->text_edit_osk->setTextCursor(text_cursor);
1114 text_cursor.deletePreviousChar();
1115 } else {
1116 ui->line_edit_osk->backspace();
1117 }
1118 return;
1119 }
1120
1121 if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) {
1122 if (ui->topOSK->currentIndex() == 1) {
1123 emit SubmitNormalText(SwkbdResult::Ok,
1124 ui->text_edit_osk->toPlainText().toStdU16String());
1125 } else {
1126 emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String());
1127 }
1128 return;
1129 }
1130
1131 if (ui->topOSK->currentIndex() == 1) {
1132 ui->text_edit_osk->insertPlainText(button->text());
1133 } else {
1134 ui->line_edit_osk->insert(button->text());
1135 }
1136
1137 // Revert the keyboard to lowercase if the shift key is active.
1138 if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) {
1139 // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
1140 // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
1141 caps_lock_enabled = true;
1142 ChangeBottomOSKIndex();
1143 }
1144}
1145
1146void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) {
1147 if (!button->isEnabled()) {
1148 return;
1149 }
1150
1151 if (button == ui->button_ampersand) {
1152 InlineTextInsertString(u"&");
1153 return;
1154 }
1155
1156 if (button == ui->button_return || button == ui->button_return_shift) {
1157 InlineTextInsertString(u"\n");
1158 return;
1159 }
1160
1161 if (button == ui->button_space || button == ui->button_space_shift) {
1162 InlineTextInsertString(u" ");
1163 return;
1164 }
1165
1166 if (button == ui->button_shift || button == ui->button_shift_shift) {
1167 ChangeBottomOSKIndex();
1168 return;
1169 }
1170
1171 if (button == ui->button_backspace || button == ui->button_backspace_shift ||
1172 button == ui->button_backspace_num) {
1173 if (cursor_position <= 0 || current_text.empty()) {
1174 cursor_position = 0;
1175 return;
1176 }
1177
1178 --cursor_position;
1179
1180 current_text.erase(cursor_position, 1);
1181
1182 SetBackspaceOkEnabled();
1183
1184 emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position);
1185 return;
1186 }
1187
1188 if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) {
1189 emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position);
1190 return;
1191 }
1192
1193 InlineTextInsertString(button->text().toStdU16String());
1194
1195 // Revert the keyboard to lowercase if the shift key is active.
1196 if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) {
1197 // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase
1198 // if bottom_osk_index is UpperCase and caps_lock_enabled is true.
1199 caps_lock_enabled = true;
1200 ChangeBottomOSKIndex();
1201 }
1202}
1203
1204void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) {
1205 if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) {
1206 return;
1207 }
1208
1209 current_text.insert(cursor_position, string);
1210
1211 cursor_position += static_cast<s32>(string.size());
1212
1213 SetBackspaceOkEnabled();
1214
1215 emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position);
1216}
1217
1218void QtSoftwareKeyboardDialog::SetupMouseHover() {
1219 // setFocus() has a bug where continuously changing focus will cause the focus UI to
1220 // mysteriously disappear. A workaround we have found is using the mouse to hover over
1221 // the buttons to act in place of the button focus. As a result, we will have to set
1222 // a blank cursor when hovering over all the buttons and set a no focus policy so the
1223 // buttons do not stay in focus in addition to the mouse hover.
1224 for (auto* button : all_buttons) {
1225 button->setCursor(QCursor(Qt::BlankCursor));
1226 button->setFocusPolicy(Qt::NoFocus);
1227 }
1228}
1229
1230template <HIDButton... T>
1231void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() {
1232 const auto f = [this](HIDButton button) {
1233 if (input_interpreter->IsButtonPressedOnce(button)) {
1234 TranslateButtonPress(button);
1235 }
1236 };
1237
1238 (f(T), ...);
1239}
1240
1241template <HIDButton... T>
1242void QtSoftwareKeyboardDialog::HandleButtonHold() {
1243 const auto f = [this](HIDButton button) {
1244 if (input_interpreter->IsButtonHeld(button)) {
1245 TranslateButtonPress(button);
1246 }
1247 };
1248
1249 (f(T), ...);
1250}
1251
1252void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) {
1253 switch (button) {
1254 case HIDButton::A:
1255 switch (bottom_osk_index) {
1256 case BottomOSKIndex::LowerCase:
1257 case BottomOSKIndex::UpperCase:
1258 keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]->click();
1259 break;
1260 case BottomOSKIndex::NumberPad:
1261 numberpad_buttons[row][column]->click();
1262 break;
1263 default:
1264 break;
1265 }
1266 break;
1267 case HIDButton::B:
1268 switch (bottom_osk_index) {
1269 case BottomOSKIndex::LowerCase:
1270 ui->button_backspace->click();
1271 break;
1272 case BottomOSKIndex::UpperCase:
1273 ui->button_backspace_shift->click();
1274 break;
1275 case BottomOSKIndex::NumberPad:
1276 ui->button_backspace_num->click();
1277 break;
1278 default:
1279 break;
1280 }
1281 break;
1282 case HIDButton::X:
1283 if (is_inline) {
1284 emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
1285 } else {
1286 if (ui->topOSK->currentIndex() == 1) {
1287 emit SubmitNormalText(SwkbdResult::Cancel,
1288 ui->text_edit_osk->toPlainText().toStdU16String());
1289 } else {
1290 emit SubmitNormalText(SwkbdResult::Cancel,
1291 ui->line_edit_osk->text().toStdU16String());
1292 }
1293 }
1294 break;
1295 case HIDButton::Y:
1296 switch (bottom_osk_index) {
1297 case BottomOSKIndex::LowerCase:
1298 ui->button_space->click();
1299 break;
1300 case BottomOSKIndex::UpperCase:
1301 ui->button_space_shift->click();
1302 break;
1303 case BottomOSKIndex::NumberPad:
1304 default:
1305 break;
1306 }
1307 break;
1308 case HIDButton::LStick:
1309 case HIDButton::RStick:
1310 switch (bottom_osk_index) {
1311 case BottomOSKIndex::LowerCase:
1312 ui->button_shift->click();
1313 break;
1314 case BottomOSKIndex::UpperCase:
1315 ui->button_shift_shift->click();
1316 break;
1317 case BottomOSKIndex::NumberPad:
1318 default:
1319 break;
1320 }
1321 break;
1322 case HIDButton::L:
1323 MoveTextCursorDirection(Direction::Left);
1324 break;
1325 case HIDButton::R:
1326 MoveTextCursorDirection(Direction::Right);
1327 break;
1328 case HIDButton::Plus:
1329 switch (bottom_osk_index) {
1330 case BottomOSKIndex::LowerCase:
1331 ui->button_ok->click();
1332 break;
1333 case BottomOSKIndex::UpperCase:
1334 ui->button_ok_shift->click();
1335 break;
1336 case BottomOSKIndex::NumberPad:
1337 ui->button_ok_num->click();
1338 break;
1339 default:
1340 break;
1341 }
1342 break;
1343 case HIDButton::DLeft:
1344 case HIDButton::LStickLeft:
1345 case HIDButton::RStickLeft:
1346 MoveButtonDirection(Direction::Left);
1347 break;
1348 case HIDButton::DUp:
1349 case HIDButton::LStickUp:
1350 case HIDButton::RStickUp:
1351 MoveButtonDirection(Direction::Up);
1352 break;
1353 case HIDButton::DRight:
1354 case HIDButton::LStickRight:
1355 case HIDButton::RStickRight:
1356 MoveButtonDirection(Direction::Right);
1357 break;
1358 case HIDButton::DDown:
1359 case HIDButton::LStickDown:
1360 case HIDButton::RStickDown:
1361 MoveButtonDirection(Direction::Down);
1362 break;
1363 default:
1364 break;
1365 }
1366}
1367
1368void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) {
1369 // Changes the row or column index depending on the direction.
1370 auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) {
1371 switch (direction) {
1372 case Direction::Left:
1373 column = (column + max_columns - 1) % max_columns;
1374 break;
1375 case Direction::Up:
1376 row = (row + max_rows - 1) % max_rows;
1377 break;
1378 case Direction::Right:
1379 column = (column + 1) % max_columns;
1380 break;
1381 case Direction::Down:
1382 row = (row + 1) % max_rows;
1383 break;
1384 default:
1385 break;
1386 }
1387 };
1388
1389 switch (bottom_osk_index) {
1390 case BottomOSKIndex::LowerCase:
1391 case BottomOSKIndex::UpperCase: {
1392 const auto index = static_cast<std::size_t>(bottom_osk_index);
1393
1394 const auto* const prev_button = keyboard_buttons[index][row][column];
1395 move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL);
1396 auto* curr_button = keyboard_buttons[index][row][column];
1397
1398 while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) {
1399 move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL);
1400 curr_button = keyboard_buttons[index][row][column];
1401 }
1402
1403 // This is a workaround for setFocus() randomly not showing focus in the UI
1404 QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
1405 break;
1406 }
1407 case BottomOSKIndex::NumberPad: {
1408 const auto* const prev_button = numberpad_buttons[row][column];
1409 move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD);
1410 auto* curr_button = numberpad_buttons[row][column];
1411
1412 while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) {
1413 move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD);
1414 curr_button = numberpad_buttons[row][column];
1415 }
1416
1417 // This is a workaround for setFocus() randomly not showing focus in the UI
1418 QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center()));
1419 break;
1420 }
1421 default:
1422 break;
1423 }
1424}
1425
1426void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) {
1427 switch (direction) {
1428 case Direction::Left:
1429 if (is_inline) {
1430 if (cursor_position <= 0) {
1431 cursor_position = 0;
1432 } else {
1433 --cursor_position;
1434 emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position);
1435 }
1436 } else {
1437 if (ui->topOSK->currentIndex() == 1) {
1438 ui->text_edit_osk->moveCursor(QTextCursor::Left);
1439 } else {
1440 ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1);
1441 }
1442 }
1443 break;
1444 case Direction::Right:
1445 if (is_inline) {
1446 if (cursor_position >= static_cast<s32>(current_text.size())) {
1447 cursor_position = static_cast<s32>(current_text.size());
1448 } else {
1449 ++cursor_position;
1450 emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position);
1451 }
1452 } else {
1453 if (ui->topOSK->currentIndex() == 1) {
1454 ui->text_edit_osk->moveCursor(QTextCursor::Right);
1455 } else {
1456 ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1);
1457 }
1458 }
1459 break;
1460 default:
1461 break;
1462 }
1463}
1464
1465void QtSoftwareKeyboardDialog::StartInputThread() {
1466 if (input_thread_running) {
1467 return;
1468 }
1469
1470 input_thread_running = true;
1471
1472 input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this);
1473}
1474
1475void QtSoftwareKeyboardDialog::StopInputThread() {
1476 input_thread_running = false;
1477
1478 if (input_thread.joinable()) {
1479 input_thread.join();
1480 }
1481
1482 if (input_interpreter) {
1483 input_interpreter->ResetButtonStates();
1484 }
1485}
1486
1487void QtSoftwareKeyboardDialog::InputThread() {
1488 while (input_thread_running) {
1489 input_interpreter->PollInput();
1490
1491 HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y,
1492 HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R,
1493 HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp,
1494 HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
1495 HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
1496 HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
1497 HIDButton::RStickDown>();
1498
1499 HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp,
1500 HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft,
1501 HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown,
1502 HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight,
1503 HIDButton::RStickDown>();
1504
1505 std::this_thread::sleep_for(std::chrono::milliseconds(50));
1506 }
118} 1507}
119 1508
120QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { 1509QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {
121 connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, 1510 connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window,
122 &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); 1511 &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection);
123 connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, 1512 connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window,
124 &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); 1513 &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection);
125 connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, 1514 connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window,
126 &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); 1515 &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection);
1516 connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window,
1517 &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection);
1518 connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window,
1519 &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection);
1520 connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window,
1521 &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection);
1522 connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window,
1523 &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection);
1524 connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this,
1525 &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection);
1526 connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this,
1527 &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection);
127} 1528}
128 1529
129QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; 1530QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
130 1531
131void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out, 1532void QtSoftwareKeyboard::InitializeKeyboard(
132 Core::Frontend::SoftwareKeyboardParameters parameters) const { 1533 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
133 text_output = std::move(out); 1534 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
134 emit MainWindowGetText(parameters); 1535 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
1536 submit_inline_callback_) {
1537 if (is_inline) {
1538 submit_inline_callback = std::move(submit_inline_callback_);
1539 } else {
1540 submit_normal_callback = std::move(submit_normal_callback_);
1541 }
1542
1543 LOG_INFO(Service_AM,
1544 "\nKeyboardInitializeParameters:"
1545 "\nok_text={}"
1546 "\nheader_text={}"
1547 "\nsub_text={}"
1548 "\nguide_text={}"
1549 "\ninitial_text={}"
1550 "\nmax_text_length={}"
1551 "\nmin_text_length={}"
1552 "\ninitial_cursor_position={}"
1553 "\ntype={}"
1554 "\npassword_mode={}"
1555 "\ntext_draw_type={}"
1556 "\nkey_disable_flags={}"
1557 "\nuse_blur_background={}"
1558 "\nenable_backspace_button={}"
1559 "\nenable_return_button={}"
1560 "\ndisable_cancel_button={}",
1561 Common::UTF16ToUTF8(initialize_parameters.ok_text),
1562 Common::UTF16ToUTF8(initialize_parameters.header_text),
1563 Common::UTF16ToUTF8(initialize_parameters.sub_text),
1564 Common::UTF16ToUTF8(initialize_parameters.guide_text),
1565 Common::UTF16ToUTF8(initialize_parameters.initial_text),
1566 initialize_parameters.max_text_length, initialize_parameters.min_text_length,
1567 initialize_parameters.initial_cursor_position, initialize_parameters.type,
1568 initialize_parameters.password_mode, initialize_parameters.text_draw_type,
1569 initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background,
1570 initialize_parameters.enable_backspace_button,
1571 initialize_parameters.enable_return_button,
1572 initialize_parameters.disable_cancel_button);
1573
1574 emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters));
1575}
1576
1577void QtSoftwareKeyboard::ShowNormalKeyboard() const {
1578 emit MainWindowShowNormalKeyboard();
1579}
1580
1581void QtSoftwareKeyboard::ShowTextCheckDialog(
1582 Service::AM::Applets::SwkbdTextCheckResult text_check_result,
1583 std::u16string text_check_message) const {
1584 emit MainWindowShowTextCheckDialog(text_check_result, text_check_message);
1585}
1586
1587void QtSoftwareKeyboard::ShowInlineKeyboard(
1588 Core::Frontend::InlineAppearParameters appear_parameters) const {
1589 LOG_INFO(Service_AM,
1590 "\nInlineAppearParameters:"
1591 "\nmax_text_length={}"
1592 "\nmin_text_length={}"
1593 "\nkey_top_scale_x={}"
1594 "\nkey_top_scale_y={}"
1595 "\nkey_top_translate_x={}"
1596 "\nkey_top_translate_y={}"
1597 "\ntype={}"
1598 "\nkey_disable_flags={}"
1599 "\nkey_top_as_floating={}"
1600 "\nenable_backspace_button={}"
1601 "\nenable_return_button={}"
1602 "\ndisable_cancel_button={}",
1603 appear_parameters.max_text_length, appear_parameters.min_text_length,
1604 appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y,
1605 appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y,
1606 appear_parameters.type, appear_parameters.key_disable_flags.raw,
1607 appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
1608 appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
1609
1610 emit MainWindowShowInlineKeyboard(std::move(appear_parameters));
1611}
1612
1613void QtSoftwareKeyboard::HideInlineKeyboard() const {
1614 emit MainWindowHideInlineKeyboard();
1615}
1616
1617void QtSoftwareKeyboard::InlineTextChanged(
1618 Core::Frontend::InlineTextParameters text_parameters) const {
1619 LOG_INFO(Service_AM,
1620 "\nInlineTextParameters:"
1621 "\ninput_text={}"
1622 "\ncursor_position={}",
1623 Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
1624
1625 emit MainWindowInlineTextChanged(std::move(text_parameters));
135} 1626}
136 1627
137void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message, 1628void QtSoftwareKeyboard::ExitKeyboard() const {
138 std::function<void()> finished_check_) const { 1629 emit MainWindowExitKeyboard();
139 finished_check = std::move(finished_check_);
140 emit MainWindowTextCheckDialog(error_message);
141} 1630}
142 1631
143void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { 1632void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result,
144 // Acquire the HLE mutex 1633 std::u16string submitted_text) const {
145 std::lock_guard lock{HLE::g_hle_lock}; 1634 submit_normal_callback(result, submitted_text);
146 text_output(std::move(text));
147} 1635}
148 1636
149void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { 1637void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
150 // Acquire the HLE mutex 1638 std::u16string submitted_text,
151 std::lock_guard lock{HLE::g_hle_lock}; 1639 s32 cursor_position) const {
152 finished_check(); 1640 submit_inline_callback(reply_type, submitted_text, cursor_position);
153} 1641}
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h
index 9e1094cce..1a03c098c 100644
--- a/src/yuzu/applets/software_keyboard.h
+++ b/src/yuzu/applets/software_keyboard.h
@@ -1,54 +1,228 @@
1// Copyright 2018 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <atomic>
9#include <memory>
10#include <thread>
11
7#include <QDialog> 12#include <QDialog>
8#include <QValidator> 13#include <QValidator>
14
9#include "core/frontend/applets/software_keyboard.h" 15#include "core/frontend/applets/software_keyboard.h"
10 16
11class GMainWindow; 17enum class HIDButton : u8;
12class QDialogButtonBox;
13class QLabel;
14class QLineEdit;
15class QVBoxLayout;
16class QtSoftwareKeyboard;
17 18
18class QtSoftwareKeyboardValidator final : public QValidator { 19class InputInterpreter;
19public:
20 explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters);
21 State validate(QString& input, int& pos) const override;
22 20
23private: 21namespace Core {
24 Core::Frontend::SoftwareKeyboardParameters parameters; 22class System;
25}; 23}
24
25namespace Ui {
26class QtSoftwareKeyboardDialog;
27}
28
29class GMainWindow;
26 30
27class QtSoftwareKeyboardDialog final : public QDialog { 31class QtSoftwareKeyboardDialog final : public QDialog {
28 Q_OBJECT 32 Q_OBJECT
29 33
30public: 34public:
31 QtSoftwareKeyboardDialog(QWidget* parent, 35 QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_,
32 Core::Frontend::SoftwareKeyboardParameters parameters); 36 Core::Frontend::KeyboardInitializeParameters initialize_parameters_);
33 ~QtSoftwareKeyboardDialog() override; 37 ~QtSoftwareKeyboardDialog() override;
34 38
35 void accept() override; 39 void ShowNormalKeyboard(QPoint pos, QSize size);
40
41 void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
42 std::u16string text_check_message);
43
44 void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos,
45 QSize size);
46
47 void HideInlineKeyboard();
48
49 void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
50
51 void ExitKeyboard();
52
53signals:
54 void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
55 std::u16string submitted_text) const;
56
57 void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
58 std::u16string submitted_text, s32 cursor_position) const;
59
60public slots:
61 void open() override;
36 void reject() override; 62 void reject() override;
37 63
38 std::u16string GetText() const; 64protected:
65 /// We override the keyPressEvent for inputting text into the inline software keyboard.
66 void keyPressEvent(QKeyEvent* event) override;
39 67
40private: 68private:
41 std::u16string text; 69 enum class Direction {
70 Left,
71 Up,
72 Right,
73 Down,
74 };
75
76 enum class BottomOSKIndex {
77 LowerCase,
78 UpperCase,
79 NumberPad,
80 };
81
82 /**
83 * Moves and resizes the window to a specified position and size.
84 *
85 * @param pos Top-left window position
86 * @param size Window size
87 */
88 void MoveAndResizeWindow(QPoint pos, QSize size);
89
90 /**
91 * Rescales all keyboard elements to account for High DPI displays.
92 *
93 * @param width Window width
94 * @param height Window height
95 * @param dpi_scale Display scaling factor
96 */
97 void RescaleKeyboardElements(float width, float height, float dpi_scale);
98
99 /// Sets the keyboard type based on initialize_parameters.
100 void SetKeyboardType();
101
102 /// Sets the password mode based on initialize_parameters.
103 void SetPasswordMode();
104
105 /// Sets the text draw type based on initialize_parameters.
106 void SetTextDrawType();
107
108 /// Sets the controller image at the bottom left of the software keyboard.
109 void SetControllerImage();
110
111 /// Disables buttons based on initialize_parameters.
112 void DisableKeyboardButtons();
113
114 /// Changes whether the backspace or/and ok buttons should be enabled or disabled.
115 void SetBackspaceOkEnabled();
116
117 /**
118 * Validates the input text sent in based on the parameters in initialize_parameters.
119 *
120 * @param input_text Input text
121 *
122 * @returns True if the input text is valid, false otherwise.
123 */
124 bool ValidateInputText(const QString& input_text);
125
126 /// Switches between LowerCase and UpperCase (Shift and Caps Lock)
127 void ChangeBottomOSKIndex();
128
129 /// Processes a keyboard button click from the UI as normal keyboard input.
130 void NormalKeyboardButtonClicked(QPushButton* button);
131
132 /// Processes a keyboard button click from the UI as inline keyboard input.
133 void InlineKeyboardButtonClicked(QPushButton* button);
134
135 /**
136 * Inserts a string of arbitrary length into the current_text at the current cursor position.
137 * This is only used for the inline software keyboard.
138 */
139 void InlineTextInsertString(std::u16string_view string);
42 140
43 QDialogButtonBox* buttons; 141 /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once.
44 QLabel* header_label; 142 void SetupMouseHover();
45 QLabel* sub_label;
46 QLabel* guide_label;
47 QLabel* length_label;
48 QLineEdit* line_edit;
49 QVBoxLayout* layout;
50 143
51 Core::Frontend::SoftwareKeyboardParameters parameters; 144 /**
145 * Handles button presses and converts them into keyboard input.
146 *
147 * @tparam HIDButton The list of buttons that can be converted into keyboard input.
148 */
149 template <HIDButton... T>
150 void HandleButtonPressedOnce();
151
152 /**
153 * Handles button holds and converts them into keyboard input.
154 *
155 * @tparam HIDButton The list of buttons that can be converted into keyboard input.
156 */
157 template <HIDButton... T>
158 void HandleButtonHold();
159
160 /**
161 * Translates a button press to focus or click a keyboard button.
162 *
163 * @param button The button press to process.
164 */
165 void TranslateButtonPress(HIDButton button);
166
167 /**
168 * Moves the focus of a button in a certain direction.
169 *
170 * @param direction The direction to move.
171 */
172 void MoveButtonDirection(Direction direction);
173
174 /**
175 * Moves the text cursor in a certain direction.
176 *
177 * @param direction The direction to move.
178 */
179 void MoveTextCursorDirection(Direction direction);
180
181 void StartInputThread();
182 void StopInputThread();
183
184 /// The thread where input is being polled and processed.
185 void InputThread();
186
187 std::unique_ptr<Ui::QtSoftwareKeyboardDialog> ui;
188
189 Core::System& system;
190
191 // True if it is the inline software keyboard.
192 bool is_inline;
193
194 // Common software keyboard initialize parameters.
195 Core::Frontend::KeyboardInitializeParameters initialize_parameters;
196
197 // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden.
198 std::u16string current_text;
199 s32 cursor_position{0};
200
201 static constexpr std::size_t NUM_ROWS_NORMAL = 5;
202 static constexpr std::size_t NUM_COLUMNS_NORMAL = 12;
203 static constexpr std::size_t NUM_ROWS_NUMPAD = 4;
204 static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4;
205
206 // Stores the normal keyboard layout.
207 std::array<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2>
208 keyboard_buttons;
209 // Stores the numberpad keyboard layout.
210 std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons;
211
212 // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons.
213 std::array<QPushButton*, 110> all_buttons;
214
215 std::size_t row{0};
216 std::size_t column{0};
217
218 BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase};
219 std::atomic<bool> caps_lock_enabled{false};
220
221 std::unique_ptr<InputInterpreter> input_interpreter;
222
223 std::thread input_thread;
224
225 std::atomic<bool> input_thread_running{};
52}; 226};
53 227
54class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { 228class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
@@ -58,19 +232,54 @@ public:
58 explicit QtSoftwareKeyboard(GMainWindow& parent); 232 explicit QtSoftwareKeyboard(GMainWindow& parent);
59 ~QtSoftwareKeyboard() override; 233 ~QtSoftwareKeyboard() override;
60 234
61 void RequestText(std::function<void(std::optional<std::u16string>)> out, 235 void InitializeKeyboard(
62 Core::Frontend::SoftwareKeyboardParameters parameters) const override; 236 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
63 void SendTextCheckDialog(std::u16string error_message, 237 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
64 std::function<void()> finished_check_) const override; 238 submit_normal_callback_,
239 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
240 submit_inline_callback_) override;
241
242 void ShowNormalKeyboard() const override;
243
244 void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
245 std::u16string text_check_message) const override;
246
247 void ShowInlineKeyboard(
248 Core::Frontend::InlineAppearParameters appear_parameters) const override;
249
250 void HideInlineKeyboard() const override;
251
252 void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override;
253
254 void ExitKeyboard() const override;
65 255
66signals: 256signals:
67 void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; 257 void MainWindowInitializeKeyboard(
68 void MainWindowTextCheckDialog(std::u16string error_message) const; 258 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const;
259
260 void MainWindowShowNormalKeyboard() const;
261
262 void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
263 std::u16string text_check_message) const;
264
265 void MainWindowShowInlineKeyboard(
266 Core::Frontend::InlineAppearParameters appear_parameters) const;
267
268 void MainWindowHideInlineKeyboard() const;
269
270 void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const;
271
272 void MainWindowExitKeyboard() const;
69 273
70private: 274private:
71 void MainWindowFinishedText(std::optional<std::u16string> text); 275 void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
72 void MainWindowFinishedCheckDialog(); 276 std::u16string submitted_text) const;
277
278 void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
279 std::u16string submitted_text, s32 cursor_position) const;
73 280
74 mutable std::function<void(std::optional<std::u16string>)> text_output; 281 mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
75 mutable std::function<void()> finished_check; 282 submit_normal_callback;
283 mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
284 submit_inline_callback;
76}; 285};
diff --git a/src/yuzu/applets/software_keyboard.ui b/src/yuzu/applets/software_keyboard.ui
new file mode 100644
index 000000000..b0a1fcde9
--- /dev/null
+++ b/src/yuzu/applets/software_keyboard.ui
@@ -0,0 +1,3503 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>QtSoftwareKeyboardDialog</class>
4 <widget class="QDialog" name="QtSoftwareKeyboardDialog">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>1280</width>
10 <height>720</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Software Keyboard</string>
15 </property>
16 <property name="styleSheet">
17 <string notr="true"/>
18 </property>
19 <layout class="QVBoxLayout" name="verticalLayout">
20 <property name="spacing">
21 <number>0</number>
22 </property>
23 <property name="leftMargin">
24 <number>0</number>
25 </property>
26 <property name="topMargin">
27 <number>0</number>
28 </property>
29 <property name="rightMargin">
30 <number>0</number>
31 </property>
32 <property name="bottomMargin">
33 <number>0</number>
34 </property>
35 <item>
36 <widget class="QWidget" name="mainOSK" native="true">
37 <layout class="QVBoxLayout" name="verticalLayout_2" stretch="320,400">
38 <property name="spacing">
39 <number>0</number>
40 </property>
41 <property name="leftMargin">
42 <number>0</number>
43 </property>
44 <property name="topMargin">
45 <number>0</number>
46 </property>
47 <property name="rightMargin">
48 <number>0</number>
49 </property>
50 <property name="bottomMargin">
51 <number>0</number>
52 </property>
53 <item>
54 <widget class="QStackedWidget" name="topOSK">
55 <property name="currentIndex">
56 <number>0</number>
57 </property>
58 <widget class="QWidget" name="lineOSK">
59 <property name="minimumSize">
60 <size>
61 <width>0</width>
62 <height>100</height>
63 </size>
64 </property>
65 <layout class="QVBoxLayout" name="lineOSKVerticalLayout">
66 <property name="spacing">
67 <number>0</number>
68 </property>
69 <property name="leftMargin">
70 <number>0</number>
71 </property>
72 <property name="topMargin">
73 <number>0</number>
74 </property>
75 <property name="rightMargin">
76 <number>0</number>
77 </property>
78 <property name="bottomMargin">
79 <number>0</number>
80 </property>
81 <item>
82 <layout class="QGridLayout" name="gridLineOSK" rowstretch="40,50,23,48,65,94" columnstretch="130,1020,130">
83 <property name="topMargin">
84 <number>0</number>
85 </property>
86 <property name="spacing">
87 <number>0</number>
88 </property>
89 <item row="4" column="2">
90 <spacer name="horizontalSpacer_3">
91 <property name="orientation">
92 <enum>Qt::Horizontal</enum>
93 </property>
94 <property name="sizeHint" stdset="0">
95 <size>
96 <width>40</width>
97 <height>20</height>
98 </size>
99 </property>
100 </spacer>
101 </item>
102 <item row="4" column="0">
103 <spacer name="horizontalSpacer_4">
104 <property name="orientation">
105 <enum>Qt::Horizontal</enum>
106 </property>
107 <property name="sizeHint" stdset="0">
108 <size>
109 <width>40</width>
110 <height>20</height>
111 </size>
112 </property>
113 </spacer>
114 </item>
115 <item row="5" column="1">
116 <widget class="QWidget" name="charactersOSK" native="true">
117 <layout class="QVBoxLayout" name="verticalLayout_5">
118 <property name="spacing">
119 <number>0</number>
120 </property>
121 <property name="leftMargin">
122 <number>0</number>
123 </property>
124 <property name="topMargin">
125 <number>0</number>
126 </property>
127 <property name="rightMargin">
128 <number>0</number>
129 </property>
130 <property name="bottomMargin">
131 <number>0</number>
132 </property>
133 <item alignment="Qt::AlignRight|Qt::AlignTop">
134 <widget class="QLabel" name="label_characters">
135 <property name="font">
136 <font>
137 <pointsize>17</pointsize>
138 </font>
139 </property>
140 <property name="text">
141 <string notr="true">0/32</string>
142 </property>
143 <property name="alignment">
144 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
145 </property>
146 </widget>
147 </item>
148 </layout>
149 </widget>
150 </item>
151 <item row="3" column="1">
152 <spacer name="verticalSpacer_2">
153 <property name="orientation">
154 <enum>Qt::Vertical</enum>
155 </property>
156 <property name="sizeHint" stdset="0">
157 <size>
158 <width>20</width>
159 <height>40</height>
160 </size>
161 </property>
162 </spacer>
163 </item>
164 <item row="5" column="0">
165 <spacer name="verticalSpacer_3">
166 <property name="orientation">
167 <enum>Qt::Vertical</enum>
168 </property>
169 <property name="sizeHint" stdset="0">
170 <size>
171 <width>20</width>
172 <height>40</height>
173 </size>
174 </property>
175 </spacer>
176 </item>
177 <item row="4" column="1">
178 <widget class="QWidget" name="inputOSK" native="true">
179 <layout class="QVBoxLayout" name="verticalLayout_3">
180 <item>
181 <widget class="QLineEdit" name="line_edit_osk">
182 <property name="font">
183 <font>
184 <pointsize>26</pointsize>
185 <weight>50</weight>
186 <bold>false</bold>
187 </font>
188 </property>
189 <property name="focusPolicy">
190 <enum>Qt::StrongFocus</enum>
191 </property>
192 <property name="text">
193 <string/>
194 </property>
195 <property name="maxLength">
196 <number>32</number>
197 </property>
198 <property name="placeholderText">
199 <string>Enter Text</string>
200 </property>
201 </widget>
202 </item>
203 </layout>
204 </widget>
205 </item>
206 <item row="0" column="1">
207 <spacer name="verticalSpacer_4">
208 <property name="orientation">
209 <enum>Qt::Vertical</enum>
210 </property>
211 <property name="sizeHint" stdset="0">
212 <size>
213 <width>20</width>
214 <height>40</height>
215 </size>
216 </property>
217 </spacer>
218 </item>
219 <item row="1" column="0" colspan="3">
220 <widget class="QWidget" name="headerOSK" native="true">
221 <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="130,1020,130">
222 <property name="spacing">
223 <number>0</number>
224 </property>
225 <property name="leftMargin">
226 <number>0</number>
227 </property>
228 <property name="topMargin">
229 <number>0</number>
230 </property>
231 <property name="rightMargin">
232 <number>0</number>
233 </property>
234 <property name="bottomMargin">
235 <number>0</number>
236 </property>
237 <item>
238 <spacer name="horizontalSpacer_18">
239 <property name="orientation">
240 <enum>Qt::Horizontal</enum>
241 </property>
242 <property name="sizeHint" stdset="0">
243 <size>
244 <width>127</width>
245 <height>20</height>
246 </size>
247 </property>
248 </spacer>
249 </item>
250 <item>
251 <widget class="QLabel" name="label_header">
252 <property name="font">
253 <font>
254 <pointsize>23</pointsize>
255 </font>
256 </property>
257 <property name="text">
258 <string/>
259 </property>
260 </widget>
261 </item>
262 <item>
263 <spacer name="horizontalSpacer_19">
264 <property name="orientation">
265 <enum>Qt::Horizontal</enum>
266 </property>
267 <property name="sizeHint" stdset="0">
268 <size>
269 <width>127</width>
270 <height>20</height>
271 </size>
272 </property>
273 </spacer>
274 </item>
275 </layout>
276 </widget>
277 </item>
278 <item row="2" column="0" colspan="3">
279 <widget class="QWidget" name="subOSK" native="true">
280 <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="130,1020,130">
281 <property name="spacing">
282 <number>0</number>
283 </property>
284 <property name="leftMargin">
285 <number>0</number>
286 </property>
287 <property name="topMargin">
288 <number>0</number>
289 </property>
290 <property name="rightMargin">
291 <number>0</number>
292 </property>
293 <property name="bottomMargin">
294 <number>0</number>
295 </property>
296 <item>
297 <spacer name="horizontalSpacer_16">
298 <property name="orientation">
299 <enum>Qt::Horizontal</enum>
300 </property>
301 <property name="sizeHint" stdset="0">
302 <size>
303 <width>127</width>
304 <height>20</height>
305 </size>
306 </property>
307 </spacer>
308 </item>
309 <item>
310 <widget class="QLabel" name="label_sub">
311 <property name="font">
312 <font>
313 <pointsize>17</pointsize>
314 </font>
315 </property>
316 <property name="text">
317 <string/>
318 </property>
319 </widget>
320 </item>
321 <item>
322 <spacer name="horizontalSpacer_17">
323 <property name="orientation">
324 <enum>Qt::Horizontal</enum>
325 </property>
326 <property name="sizeHint" stdset="0">
327 <size>
328 <width>127</width>
329 <height>20</height>
330 </size>
331 </property>
332 </spacer>
333 </item>
334 </layout>
335 </widget>
336 </item>
337 </layout>
338 </item>
339 </layout>
340 </widget>
341 <widget class="QWidget" name="boxOSK">
342 <layout class="QVBoxLayout" name="boxOSKVerticalLayout">
343 <property name="spacing">
344 <number>0</number>
345 </property>
346 <property name="leftMargin">
347 <number>0</number>
348 </property>
349 <property name="topMargin">
350 <number>0</number>
351 </property>
352 <property name="rightMargin">
353 <number>0</number>
354 </property>
355 <property name="bottomMargin">
356 <number>0</number>
357 </property>
358 <item>
359 <layout class="QGridLayout" name="gridBoxOSK" rowstretch="61,178,81" columnstretch="120,1040,120">
360 <property name="leftMargin">
361 <number>0</number>
362 </property>
363 <property name="topMargin">
364 <number>0</number>
365 </property>
366 <property name="rightMargin">
367 <number>0</number>
368 </property>
369 <property name="bottomMargin">
370 <number>0</number>
371 </property>
372 <property name="spacing">
373 <number>0</number>
374 </property>
375 <item row="0" column="1">
376 <spacer name="verticalSpacer_5">
377 <property name="orientation">
378 <enum>Qt::Vertical</enum>
379 </property>
380 <property name="sizeHint" stdset="0">
381 <size>
382 <width>20</width>
383 <height>40</height>
384 </size>
385 </property>
386 </spacer>
387 </item>
388 <item row="1" column="0">
389 <spacer name="horizontalSpacer_20">
390 <property name="orientation">
391 <enum>Qt::Horizontal</enum>
392 </property>
393 <property name="sizeHint" stdset="0">
394 <size>
395 <width>40</width>
396 <height>20</height>
397 </size>
398 </property>
399 </spacer>
400 </item>
401 <item row="1" column="2">
402 <spacer name="horizontalSpacer_21">
403 <property name="orientation">
404 <enum>Qt::Horizontal</enum>
405 </property>
406 <property name="sizeHint" stdset="0">
407 <size>
408 <width>40</width>
409 <height>20</height>
410 </size>
411 </property>
412 </spacer>
413 </item>
414 <item row="2" column="1" alignment="Qt::AlignRight|Qt::AlignTop">
415 <widget class="QWidget" name="charactersBoxOSK" native="true">
416 <layout class="QVBoxLayout" name="verticalLayout_4">
417 <property name="spacing">
418 <number>0</number>
419 </property>
420 <property name="leftMargin">
421 <number>0</number>
422 </property>
423 <property name="topMargin">
424 <number>0</number>
425 </property>
426 <property name="rightMargin">
427 <number>0</number>
428 </property>
429 <property name="bottomMargin">
430 <number>0</number>
431 </property>
432 <item>
433 <widget class="QLabel" name="label_characters_box">
434 <property name="enabled">
435 <bool>true</bool>
436 </property>
437 <property name="font">
438 <font>
439 <pointsize>17</pointsize>
440 </font>
441 </property>
442 <property name="text">
443 <string notr="true">0/500</string>
444 </property>
445 </widget>
446 </item>
447 </layout>
448 </widget>
449 </item>
450 <item row="1" column="1">
451 <widget class="QWidget" name="inputBoxOSK" native="true">
452 <layout class="QVBoxLayout" name="verticalLayout_6">
453 <property name="spacing">
454 <number>0</number>
455 </property>
456 <property name="leftMargin">
457 <number>14</number>
458 </property>
459 <property name="topMargin">
460 <number>9</number>
461 </property>
462 <property name="rightMargin">
463 <number>14</number>
464 </property>
465 <property name="bottomMargin">
466 <number>9</number>
467 </property>
468 <item>
469 <widget class="QTextEdit" name="text_edit_osk">
470 <property name="font">
471 <font>
472 <pointsize>26</pointsize>
473 </font>
474 </property>
475 <property name="focusPolicy">
476 <enum>Qt::StrongFocus</enum>
477 </property>
478 <property name="html">
479 <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
480&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
481p, li { white-space: pre-wrap; }
482&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:26pt; font-weight:400; font-style:normal;&quot;&gt;
483&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
484 </property>
485 </widget>
486 </item>
487 </layout>
488 </widget>
489 </item>
490 </layout>
491 </item>
492 </layout>
493 </widget>
494 </widget>
495 </item>
496 <item>
497 <widget class="QStackedWidget" name="bottomOSK">
498 <property name="currentIndex">
499 <number>0</number>
500 </property>
501 <widget class="QWidget" name="normalOSK">
502 <layout class="QVBoxLayout" name="normalPageVerticalLayout">
503 <property name="leftMargin">
504 <number>0</number>
505 </property>
506 <property name="topMargin">
507 <number>0</number>
508 </property>
509 <property name="rightMargin">
510 <number>0</number>
511 </property>
512 <property name="bottomMargin">
513 <number>0</number>
514 </property>
515 <item>
516 <layout class="QGridLayout" name="kbOSKnormal" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54">
517 <property name="spacing">
518 <number>0</number>
519 </property>
520 <item row="6" column="1" colspan="12">
521 <widget class="QWidget" name="legendOSK" native="true">
522 <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="70,525,25,12,22,41,25,12,22,41,25,12,47,37,29,12,69,37,29,12,56,8">
523 <property name="spacing">
524 <number>0</number>
525 </property>
526 <property name="leftMargin">
527 <number>2</number>
528 </property>
529 <property name="topMargin">
530 <number>0</number>
531 </property>
532 <property name="rightMargin">
533 <number>0</number>
534 </property>
535 <property name="bottomMargin">
536 <number>0</number>
537 </property>
538 <item>
539 <widget class="QWidget" name="icon_controller" native="true">
540 <property name="styleSheet">
541 <string notr="true"/>
542 </property>
543 </widget>
544 </item>
545 <item>
546 <spacer name="horizontalSpacer_5">
547 <property name="orientation">
548 <enum>Qt::Horizontal</enum>
549 </property>
550 <property name="sizeHint" stdset="0">
551 <size>
552 <width>0</width>
553 <height>20</height>
554 </size>
555 </property>
556 </spacer>
557 </item>
558 <item>
559 <widget class="QWidget" name="button_L" native="true"/>
560 </item>
561 <item>
562 <spacer name="horizontalSpacer_14">
563 <property name="orientation">
564 <enum>Qt::Horizontal</enum>
565 </property>
566 <property name="sizeHint" stdset="0">
567 <size>
568 <width>0</width>
569 <height>20</height>
570 </size>
571 </property>
572 </spacer>
573 </item>
574 <item>
575 <widget class="QWidget" name="arrow_left" native="true"/>
576 </item>
577 <item>
578 <spacer name="horizontalSpacer_13">
579 <property name="orientation">
580 <enum>Qt::Horizontal</enum>
581 </property>
582 <property name="sizeHint" stdset="0">
583 <size>
584 <width>0</width>
585 <height>20</height>
586 </size>
587 </property>
588 </spacer>
589 </item>
590 <item>
591 <widget class="QWidget" name="button_R" native="true"/>
592 </item>
593 <item>
594 <spacer name="horizontalSpacer_12">
595 <property name="orientation">
596 <enum>Qt::Horizontal</enum>
597 </property>
598 <property name="sizeHint" stdset="0">
599 <size>
600 <width>0</width>
601 <height>20</height>
602 </size>
603 </property>
604 </spacer>
605 </item>
606 <item>
607 <widget class="QWidget" name="arrow_right" native="true"/>
608 </item>
609 <item>
610 <spacer name="horizontalSpacer_11">
611 <property name="orientation">
612 <enum>Qt::Horizontal</enum>
613 </property>
614 <property name="sizeHint" stdset="0">
615 <size>
616 <width>0</width>
617 <height>20</height>
618 </size>
619 </property>
620 </spacer>
621 </item>
622 <item>
623 <widget class="QWidget" name="button_press_stick" native="true"/>
624 </item>
625 <item>
626 <spacer name="horizontalSpacer_10">
627 <property name="orientation">
628 <enum>Qt::Horizontal</enum>
629 </property>
630 <property name="sizeHint" stdset="0">
631 <size>
632 <width>0</width>
633 <height>20</height>
634 </size>
635 </property>
636 </spacer>
637 </item>
638 <item>
639 <widget class="QLabel" name="label_shift">
640 <property name="font">
641 <font>
642 <pointsize>18</pointsize>
643 </font>
644 </property>
645 <property name="text">
646 <string notr="true">Shift</string>
647 </property>
648 </widget>
649 </item>
650 <item>
651 <spacer name="horizontalSpacer_15">
652 <property name="orientation">
653 <enum>Qt::Horizontal</enum>
654 </property>
655 <property name="sizeHint" stdset="0">
656 <size>
657 <width>0</width>
658 <height>20</height>
659 </size>
660 </property>
661 </spacer>
662 </item>
663 <item>
664 <widget class="QWidget" name="button_X" native="true"/>
665 </item>
666 <item>
667 <spacer name="horizontalSpacer_9">
668 <property name="orientation">
669 <enum>Qt::Horizontal</enum>
670 </property>
671 <property name="sizeHint" stdset="0">
672 <size>
673 <width>0</width>
674 <height>20</height>
675 </size>
676 </property>
677 </spacer>
678 </item>
679 <item>
680 <widget class="QLabel" name="label_cancel">
681 <property name="font">
682 <font>
683 <pointsize>18</pointsize>
684 </font>
685 </property>
686 <property name="text">
687 <string notr="true">Cancel</string>
688 </property>
689 </widget>
690 </item>
691 <item>
692 <spacer name="horizontalSpacer_8">
693 <property name="orientation">
694 <enum>Qt::Horizontal</enum>
695 </property>
696 <property name="sizeHint" stdset="0">
697 <size>
698 <width>0</width>
699 <height>20</height>
700 </size>
701 </property>
702 </spacer>
703 </item>
704 <item>
705 <widget class="QWidget" name="button_A" native="true"/>
706 </item>
707 <item>
708 <spacer name="horizontalSpacer_7">
709 <property name="orientation">
710 <enum>Qt::Horizontal</enum>
711 </property>
712 <property name="sizeHint" stdset="0">
713 <size>
714 <width>0</width>
715 <height>20</height>
716 </size>
717 </property>
718 </spacer>
719 </item>
720 <item>
721 <widget class="QLabel" name="label_enter">
722 <property name="font">
723 <font>
724 <pointsize>18</pointsize>
725 </font>
726 </property>
727 <property name="text">
728 <string notr="true">Enter</string>
729 </property>
730 </widget>
731 </item>
732 <item>
733 <spacer name="horizontalSpacer_6">
734 <property name="orientation">
735 <enum>Qt::Horizontal</enum>
736 </property>
737 <property name="sizeHint" stdset="0">
738 <size>
739 <width>0</width>
740 <height>20</height>
741 </size>
742 </property>
743 </spacer>
744 </item>
745 </layout>
746 </widget>
747 </item>
748 <item row="1" column="11">
749 <widget class="QPushButton" name="button_minus">
750 <property name="sizePolicy">
751 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
752 <horstretch>1</horstretch>
753 <verstretch>1</verstretch>
754 </sizepolicy>
755 </property>
756 <property name="font">
757 <font>
758 <pointsize>28</pointsize>
759 </font>
760 </property>
761 <property name="text">
762 <string notr="true">-</string>
763 </property>
764 </widget>
765 </item>
766 <item row="3" column="11">
767 <widget class="QPushButton" name="button_apostrophe">
768 <property name="sizePolicy">
769 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
770 <horstretch>1</horstretch>
771 <verstretch>1</verstretch>
772 </sizepolicy>
773 </property>
774 <property name="font">
775 <font>
776 <pointsize>28</pointsize>
777 </font>
778 </property>
779 <property name="text">
780 <string notr="true">'</string>
781 </property>
782 </widget>
783 </item>
784 <item row="2" column="11">
785 <widget class="QPushButton" name="button_slash">
786 <property name="sizePolicy">
787 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
788 <horstretch>1</horstretch>
789 <verstretch>1</verstretch>
790 </sizepolicy>
791 </property>
792 <property name="font">
793 <font>
794 <pointsize>28</pointsize>
795 </font>
796 </property>
797 <property name="text">
798 <string notr="true">/</string>
799 </property>
800 </widget>
801 </item>
802 <item row="4" column="11">
803 <widget class="QPushButton" name="button_exclamation">
804 <property name="sizePolicy">
805 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
806 <horstretch>1</horstretch>
807 <verstretch>1</verstretch>
808 </sizepolicy>
809 </property>
810 <property name="font">
811 <font>
812 <pointsize>28</pointsize>
813 </font>
814 </property>
815 <property name="text">
816 <string notr="true">!</string>
817 </property>
818 </widget>
819 </item>
820 <item row="1" column="7">
821 <widget class="QPushButton" name="button_7">
822 <property name="sizePolicy">
823 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
824 <horstretch>1</horstretch>
825 <verstretch>1</verstretch>
826 </sizepolicy>
827 </property>
828 <property name="font">
829 <font>
830 <pointsize>28</pointsize>
831 </font>
832 </property>
833 <property name="text">
834 <string notr="true">7</string>
835 </property>
836 </widget>
837 </item>
838 <item row="1" column="8">
839 <widget class="QPushButton" name="button_8">
840 <property name="sizePolicy">
841 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
842 <horstretch>1</horstretch>
843 <verstretch>1</verstretch>
844 </sizepolicy>
845 </property>
846 <property name="font">
847 <font>
848 <pointsize>28</pointsize>
849 </font>
850 </property>
851 <property name="text">
852 <string notr="true">8</string>
853 </property>
854 </widget>
855 </item>
856 <item row="1" column="10">
857 <widget class="QPushButton" name="button_0">
858 <property name="sizePolicy">
859 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
860 <horstretch>1</horstretch>
861 <verstretch>1</verstretch>
862 </sizepolicy>
863 </property>
864 <property name="font">
865 <font>
866 <pointsize>28</pointsize>
867 </font>
868 </property>
869 <property name="text">
870 <string notr="true">0</string>
871 </property>
872 </widget>
873 </item>
874 <item row="1" column="9">
875 <widget class="QPushButton" name="button_9">
876 <property name="sizePolicy">
877 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
878 <horstretch>1</horstretch>
879 <verstretch>1</verstretch>
880 </sizepolicy>
881 </property>
882 <property name="font">
883 <font>
884 <pointsize>28</pointsize>
885 </font>
886 </property>
887 <property name="text">
888 <string notr="true">9</string>
889 </property>
890 </widget>
891 </item>
892 <item row="2" column="2">
893 <widget class="QPushButton" name="button_w">
894 <property name="sizePolicy">
895 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
896 <horstretch>1</horstretch>
897 <verstretch>1</verstretch>
898 </sizepolicy>
899 </property>
900 <property name="font">
901 <font>
902 <pointsize>28</pointsize>
903 </font>
904 </property>
905 <property name="text">
906 <string notr="true">w</string>
907 </property>
908 </widget>
909 </item>
910 <item row="2" column="4">
911 <widget class="QPushButton" name="button_r">
912 <property name="sizePolicy">
913 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
914 <horstretch>1</horstretch>
915 <verstretch>1</verstretch>
916 </sizepolicy>
917 </property>
918 <property name="font">
919 <font>
920 <pointsize>28</pointsize>
921 </font>
922 </property>
923 <property name="text">
924 <string notr="true">r</string>
925 </property>
926 </widget>
927 </item>
928 <item row="2" column="3">
929 <widget class="QPushButton" name="button_e">
930 <property name="sizePolicy">
931 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
932 <horstretch>1</horstretch>
933 <verstretch>1</verstretch>
934 </sizepolicy>
935 </property>
936 <property name="font">
937 <font>
938 <pointsize>28</pointsize>
939 </font>
940 </property>
941 <property name="text">
942 <string notr="true">e</string>
943 </property>
944 </widget>
945 </item>
946 <item row="2" column="1">
947 <widget class="QPushButton" name="button_q">
948 <property name="sizePolicy">
949 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
950 <horstretch>1</horstretch>
951 <verstretch>1</verstretch>
952 </sizepolicy>
953 </property>
954 <property name="font">
955 <font>
956 <pointsize>28</pointsize>
957 </font>
958 </property>
959 <property name="text">
960 <string notr="true">q</string>
961 </property>
962 </widget>
963 </item>
964 <item row="2" column="7">
965 <widget class="QPushButton" name="button_u">
966 <property name="sizePolicy">
967 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
968 <horstretch>1</horstretch>
969 <verstretch>1</verstretch>
970 </sizepolicy>
971 </property>
972 <property name="font">
973 <font>
974 <pointsize>28</pointsize>
975 </font>
976 </property>
977 <property name="text">
978 <string notr="true">u</string>
979 </property>
980 </widget>
981 </item>
982 <item row="2" column="6">
983 <widget class="QPushButton" name="button_y">
984 <property name="sizePolicy">
985 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
986 <horstretch>1</horstretch>
987 <verstretch>1</verstretch>
988 </sizepolicy>
989 </property>
990 <property name="font">
991 <font>
992 <pointsize>28</pointsize>
993 </font>
994 </property>
995 <property name="text">
996 <string notr="true">y</string>
997 </property>
998 </widget>
999 </item>
1000 <item row="2" column="5">
1001 <widget class="QPushButton" name="button_t">
1002 <property name="sizePolicy">
1003 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1004 <horstretch>1</horstretch>
1005 <verstretch>1</verstretch>
1006 </sizepolicy>
1007 </property>
1008 <property name="font">
1009 <font>
1010 <pointsize>28</pointsize>
1011 </font>
1012 </property>
1013 <property name="text">
1014 <string notr="true">t</string>
1015 </property>
1016 </widget>
1017 </item>
1018 <item row="2" column="9">
1019 <widget class="QPushButton" name="button_o">
1020 <property name="sizePolicy">
1021 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1022 <horstretch>1</horstretch>
1023 <verstretch>1</verstretch>
1024 </sizepolicy>
1025 </property>
1026 <property name="font">
1027 <font>
1028 <pointsize>28</pointsize>
1029 </font>
1030 </property>
1031 <property name="text">
1032 <string notr="true">o</string>
1033 </property>
1034 </widget>
1035 </item>
1036 <item row="2" column="10">
1037 <widget class="QPushButton" name="button_p">
1038 <property name="sizePolicy">
1039 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1040 <horstretch>1</horstretch>
1041 <verstretch>1</verstretch>
1042 </sizepolicy>
1043 </property>
1044 <property name="font">
1045 <font>
1046 <pointsize>28</pointsize>
1047 </font>
1048 </property>
1049 <property name="text">
1050 <string notr="true">p</string>
1051 </property>
1052 </widget>
1053 </item>
1054 <item row="2" column="8">
1055 <widget class="QPushButton" name="button_i">
1056 <property name="sizePolicy">
1057 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1058 <horstretch>1</horstretch>
1059 <verstretch>1</verstretch>
1060 </sizepolicy>
1061 </property>
1062 <property name="font">
1063 <font>
1064 <pointsize>28</pointsize>
1065 </font>
1066 </property>
1067 <property name="text">
1068 <string notr="true">i</string>
1069 </property>
1070 </widget>
1071 </item>
1072 <item row="3" column="1">
1073 <widget class="QPushButton" name="button_a">
1074 <property name="sizePolicy">
1075 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1076 <horstretch>1</horstretch>
1077 <verstretch>1</verstretch>
1078 </sizepolicy>
1079 </property>
1080 <property name="font">
1081 <font>
1082 <pointsize>28</pointsize>
1083 </font>
1084 </property>
1085 <property name="text">
1086 <string notr="true">a</string>
1087 </property>
1088 </widget>
1089 </item>
1090 <item row="3" column="2">
1091 <widget class="QPushButton" name="button_s">
1092 <property name="sizePolicy">
1093 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1094 <horstretch>1</horstretch>
1095 <verstretch>1</verstretch>
1096 </sizepolicy>
1097 </property>
1098 <property name="font">
1099 <font>
1100 <pointsize>28</pointsize>
1101 </font>
1102 </property>
1103 <property name="text">
1104 <string notr="true">s</string>
1105 </property>
1106 </widget>
1107 </item>
1108 <item row="3" column="3">
1109 <widget class="QPushButton" name="button_d">
1110 <property name="sizePolicy">
1111 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1112 <horstretch>1</horstretch>
1113 <verstretch>1</verstretch>
1114 </sizepolicy>
1115 </property>
1116 <property name="font">
1117 <font>
1118 <pointsize>28</pointsize>
1119 </font>
1120 </property>
1121 <property name="text">
1122 <string notr="true">d</string>
1123 </property>
1124 </widget>
1125 </item>
1126 <item row="3" column="4">
1127 <widget class="QPushButton" name="button_f">
1128 <property name="sizePolicy">
1129 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1130 <horstretch>1</horstretch>
1131 <verstretch>1</verstretch>
1132 </sizepolicy>
1133 </property>
1134 <property name="font">
1135 <font>
1136 <pointsize>28</pointsize>
1137 </font>
1138 </property>
1139 <property name="text">
1140 <string notr="true">f</string>
1141 </property>
1142 </widget>
1143 </item>
1144 <item row="3" column="6">
1145 <widget class="QPushButton" name="button_h">
1146 <property name="sizePolicy">
1147 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1148 <horstretch>1</horstretch>
1149 <verstretch>1</verstretch>
1150 </sizepolicy>
1151 </property>
1152 <property name="font">
1153 <font>
1154 <pointsize>28</pointsize>
1155 </font>
1156 </property>
1157 <property name="text">
1158 <string notr="true">h</string>
1159 </property>
1160 </widget>
1161 </item>
1162 <item row="3" column="7">
1163 <widget class="QPushButton" name="button_j">
1164 <property name="sizePolicy">
1165 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1166 <horstretch>1</horstretch>
1167 <verstretch>1</verstretch>
1168 </sizepolicy>
1169 </property>
1170 <property name="font">
1171 <font>
1172 <pointsize>28</pointsize>
1173 </font>
1174 </property>
1175 <property name="text">
1176 <string notr="true">j</string>
1177 </property>
1178 </widget>
1179 </item>
1180 <item row="3" column="5">
1181 <widget class="QPushButton" name="button_g">
1182 <property name="sizePolicy">
1183 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1184 <horstretch>1</horstretch>
1185 <verstretch>1</verstretch>
1186 </sizepolicy>
1187 </property>
1188 <property name="font">
1189 <font>
1190 <pointsize>28</pointsize>
1191 </font>
1192 </property>
1193 <property name="text">
1194 <string notr="true">g</string>
1195 </property>
1196 </widget>
1197 </item>
1198 <item row="3" column="8">
1199 <widget class="QPushButton" name="button_k">
1200 <property name="sizePolicy">
1201 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1202 <horstretch>1</horstretch>
1203 <verstretch>1</verstretch>
1204 </sizepolicy>
1205 </property>
1206 <property name="font">
1207 <font>
1208 <pointsize>28</pointsize>
1209 </font>
1210 </property>
1211 <property name="text">
1212 <string notr="true">k</string>
1213 </property>
1214 </widget>
1215 </item>
1216 <item row="3" column="9">
1217 <widget class="QPushButton" name="button_l">
1218 <property name="sizePolicy">
1219 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1220 <horstretch>1</horstretch>
1221 <verstretch>1</verstretch>
1222 </sizepolicy>
1223 </property>
1224 <property name="font">
1225 <font>
1226 <pointsize>28</pointsize>
1227 </font>
1228 </property>
1229 <property name="text">
1230 <string notr="true">l</string>
1231 </property>
1232 </widget>
1233 </item>
1234 <item row="3" column="10">
1235 <widget class="QPushButton" name="button_colon">
1236 <property name="sizePolicy">
1237 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1238 <horstretch>1</horstretch>
1239 <verstretch>1</verstretch>
1240 </sizepolicy>
1241 </property>
1242 <property name="font">
1243 <font>
1244 <pointsize>28</pointsize>
1245 </font>
1246 </property>
1247 <property name="text">
1248 <string notr="true">:</string>
1249 </property>
1250 </widget>
1251 </item>
1252 <item row="2" column="12" rowspan="2">
1253 <widget class="QPushButton" name="button_return">
1254 <property name="sizePolicy">
1255 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1256 <horstretch>1</horstretch>
1257 <verstretch>1</verstretch>
1258 </sizepolicy>
1259 </property>
1260 <property name="font">
1261 <font>
1262 <pointsize>18</pointsize>
1263 </font>
1264 </property>
1265 <property name="text">
1266 <string notr="true">Return</string>
1267 </property>
1268 </widget>
1269 </item>
1270 <item row="4" column="12" rowspan="2">
1271 <widget class="QPushButton" name="button_ok">
1272 <property name="sizePolicy">
1273 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1274 <horstretch>1</horstretch>
1275 <verstretch>1</verstretch>
1276 </sizepolicy>
1277 </property>
1278 <property name="font">
1279 <font>
1280 <pointsize>18</pointsize>
1281 </font>
1282 </property>
1283 <property name="text">
1284 <string notr="true">OK</string>
1285 </property>
1286 </widget>
1287 </item>
1288 <item row="4" column="1">
1289 <widget class="QPushButton" name="button_z">
1290 <property name="sizePolicy">
1291 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1292 <horstretch>1</horstretch>
1293 <verstretch>1</verstretch>
1294 </sizepolicy>
1295 </property>
1296 <property name="font">
1297 <font>
1298 <pointsize>28</pointsize>
1299 </font>
1300 </property>
1301 <property name="text">
1302 <string notr="true">z</string>
1303 </property>
1304 </widget>
1305 </item>
1306 <item row="4" column="3">
1307 <widget class="QPushButton" name="button_c">
1308 <property name="sizePolicy">
1309 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1310 <horstretch>1</horstretch>
1311 <verstretch>1</verstretch>
1312 </sizepolicy>
1313 </property>
1314 <property name="font">
1315 <font>
1316 <pointsize>28</pointsize>
1317 </font>
1318 </property>
1319 <property name="text">
1320 <string notr="true">c</string>
1321 </property>
1322 </widget>
1323 </item>
1324 <item row="4" column="2">
1325 <widget class="QPushButton" name="button_x">
1326 <property name="sizePolicy">
1327 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1328 <horstretch>1</horstretch>
1329 <verstretch>1</verstretch>
1330 </sizepolicy>
1331 </property>
1332 <property name="font">
1333 <font>
1334 <pointsize>28</pointsize>
1335 </font>
1336 </property>
1337 <property name="text">
1338 <string notr="true">x</string>
1339 </property>
1340 </widget>
1341 </item>
1342 <item row="4" column="4">
1343 <widget class="QPushButton" name="button_v">
1344 <property name="sizePolicy">
1345 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1346 <horstretch>1</horstretch>
1347 <verstretch>1</verstretch>
1348 </sizepolicy>
1349 </property>
1350 <property name="font">
1351 <font>
1352 <pointsize>28</pointsize>
1353 </font>
1354 </property>
1355 <property name="text">
1356 <string notr="true">v</string>
1357 </property>
1358 </widget>
1359 </item>
1360 <item row="4" column="7">
1361 <widget class="QPushButton" name="button_m">
1362 <property name="sizePolicy">
1363 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1364 <horstretch>1</horstretch>
1365 <verstretch>1</verstretch>
1366 </sizepolicy>
1367 </property>
1368 <property name="font">
1369 <font>
1370 <pointsize>28</pointsize>
1371 </font>
1372 </property>
1373 <property name="text">
1374 <string notr="true">m</string>
1375 </property>
1376 </widget>
1377 </item>
1378 <item row="4" column="8">
1379 <widget class="QPushButton" name="button_comma">
1380 <property name="sizePolicy">
1381 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1382 <horstretch>1</horstretch>
1383 <verstretch>1</verstretch>
1384 </sizepolicy>
1385 </property>
1386 <property name="font">
1387 <font>
1388 <pointsize>28</pointsize>
1389 </font>
1390 </property>
1391 <property name="text">
1392 <string notr="true">,</string>
1393 </property>
1394 </widget>
1395 </item>
1396 <item row="4" column="6">
1397 <widget class="QPushButton" name="button_n">
1398 <property name="sizePolicy">
1399 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1400 <horstretch>1</horstretch>
1401 <verstretch>1</verstretch>
1402 </sizepolicy>
1403 </property>
1404 <property name="font">
1405 <font>
1406 <pointsize>28</pointsize>
1407 </font>
1408 </property>
1409 <property name="text">
1410 <string notr="true">n</string>
1411 </property>
1412 </widget>
1413 </item>
1414 <item row="4" column="5">
1415 <widget class="QPushButton" name="button_b">
1416 <property name="sizePolicy">
1417 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1418 <horstretch>1</horstretch>
1419 <verstretch>1</verstretch>
1420 </sizepolicy>
1421 </property>
1422 <property name="font">
1423 <font>
1424 <pointsize>28</pointsize>
1425 </font>
1426 </property>
1427 <property name="text">
1428 <string notr="true">b</string>
1429 </property>
1430 </widget>
1431 </item>
1432 <item row="5" column="1" colspan="2">
1433 <widget class="QPushButton" name="button_shift">
1434 <property name="sizePolicy">
1435 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1436 <horstretch>1</horstretch>
1437 <verstretch>1</verstretch>
1438 </sizepolicy>
1439 </property>
1440 <property name="font">
1441 <font>
1442 <pointsize>18</pointsize>
1443 </font>
1444 </property>
1445 <property name="text">
1446 <string notr="true"/>
1447 </property>
1448 <property name="checkable">
1449 <bool>true</bool>
1450 </property>
1451 <property name="checked">
1452 <bool>false</bool>
1453 </property>
1454 </widget>
1455 </item>
1456 <item row="4" column="10">
1457 <widget class="QPushButton" name="button_question">
1458 <property name="sizePolicy">
1459 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1460 <horstretch>1</horstretch>
1461 <verstretch>1</verstretch>
1462 </sizepolicy>
1463 </property>
1464 <property name="font">
1465 <font>
1466 <pointsize>28</pointsize>
1467 </font>
1468 </property>
1469 <property name="text">
1470 <string notr="true">?</string>
1471 </property>
1472 </widget>
1473 </item>
1474 <item row="4" column="9">
1475 <widget class="QPushButton" name="button_dot">
1476 <property name="sizePolicy">
1477 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1478 <horstretch>1</horstretch>
1479 <verstretch>1</verstretch>
1480 </sizepolicy>
1481 </property>
1482 <property name="font">
1483 <font>
1484 <pointsize>28</pointsize>
1485 </font>
1486 </property>
1487 <property name="text">
1488 <string notr="true">.</string>
1489 </property>
1490 </widget>
1491 </item>
1492 <item row="1" column="1">
1493 <widget class="QPushButton" name="button_1">
1494 <property name="sizePolicy">
1495 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1496 <horstretch>1</horstretch>
1497 <verstretch>1</verstretch>
1498 </sizepolicy>
1499 </property>
1500 <property name="font">
1501 <font>
1502 <pointsize>28</pointsize>
1503 </font>
1504 </property>
1505 <property name="text">
1506 <string notr="true">1</string>
1507 </property>
1508 </widget>
1509 </item>
1510 <item row="1" column="3">
1511 <widget class="QPushButton" name="button_3">
1512 <property name="sizePolicy">
1513 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1514 <horstretch>1</horstretch>
1515 <verstretch>1</verstretch>
1516 </sizepolicy>
1517 </property>
1518 <property name="font">
1519 <font>
1520 <pointsize>28</pointsize>
1521 </font>
1522 </property>
1523 <property name="text">
1524 <string notr="true">3</string>
1525 </property>
1526 </widget>
1527 </item>
1528 <item row="1" column="4">
1529 <widget class="QPushButton" name="button_4">
1530 <property name="sizePolicy">
1531 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1532 <horstretch>1</horstretch>
1533 <verstretch>1</verstretch>
1534 </sizepolicy>
1535 </property>
1536 <property name="font">
1537 <font>
1538 <pointsize>28</pointsize>
1539 </font>
1540 </property>
1541 <property name="text">
1542 <string notr="true">4</string>
1543 </property>
1544 </widget>
1545 </item>
1546 <item row="1" column="2">
1547 <widget class="QPushButton" name="button_2">
1548 <property name="sizePolicy">
1549 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1550 <horstretch>1</horstretch>
1551 <verstretch>1</verstretch>
1552 </sizepolicy>
1553 </property>
1554 <property name="font">
1555 <font>
1556 <pointsize>28</pointsize>
1557 </font>
1558 </property>
1559 <property name="text">
1560 <string notr="true">2</string>
1561 </property>
1562 </widget>
1563 </item>
1564 <item row="1" column="6">
1565 <widget class="QPushButton" name="button_6">
1566 <property name="sizePolicy">
1567 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1568 <horstretch>1</horstretch>
1569 <verstretch>1</verstretch>
1570 </sizepolicy>
1571 </property>
1572 <property name="font">
1573 <font>
1574 <pointsize>28</pointsize>
1575 </font>
1576 </property>
1577 <property name="text">
1578 <string notr="true">6</string>
1579 </property>
1580 </widget>
1581 </item>
1582 <item row="1" column="5">
1583 <widget class="QPushButton" name="button_5">
1584 <property name="sizePolicy">
1585 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1586 <horstretch>1</horstretch>
1587 <verstretch>1</verstretch>
1588 </sizepolicy>
1589 </property>
1590 <property name="font">
1591 <font>
1592 <pointsize>28</pointsize>
1593 </font>
1594 </property>
1595 <property name="text">
1596 <string notr="true">5</string>
1597 </property>
1598 </widget>
1599 </item>
1600 <item row="5" column="3" colspan="9">
1601 <widget class="QPushButton" name="button_space">
1602 <property name="sizePolicy">
1603 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1604 <horstretch>1</horstretch>
1605 <verstretch>1</verstretch>
1606 </sizepolicy>
1607 </property>
1608 <property name="font">
1609 <font>
1610 <pointsize>18</pointsize>
1611 </font>
1612 </property>
1613 <property name="text">
1614 <string notr="true">Space</string>
1615 </property>
1616 </widget>
1617 </item>
1618 <item row="1" column="12">
1619 <widget class="QPushButton" name="button_backspace">
1620 <property name="sizePolicy">
1621 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1622 <horstretch>1</horstretch>
1623 <verstretch>1</verstretch>
1624 </sizepolicy>
1625 </property>
1626 <property name="font">
1627 <font>
1628 <pointsize>18</pointsize>
1629 </font>
1630 </property>
1631 <property name="text">
1632 <string notr="true"/>
1633 </property>
1634 </widget>
1635 </item>
1636 <item row="1" column="0">
1637 <spacer name="horizontalSpacer">
1638 <property name="orientation">
1639 <enum>Qt::Horizontal</enum>
1640 </property>
1641 <property name="sizeHint" stdset="0">
1642 <size>
1643 <width>40</width>
1644 <height>20</height>
1645 </size>
1646 </property>
1647 </spacer>
1648 </item>
1649 <item row="0" column="1">
1650 <spacer name="verticalSpacer">
1651 <property name="orientation">
1652 <enum>Qt::Vertical</enum>
1653 </property>
1654 <property name="sizeHint" stdset="0">
1655 <size>
1656 <width>20</width>
1657 <height>0</height>
1658 </size>
1659 </property>
1660 </spacer>
1661 </item>
1662 <item row="1" column="13">
1663 <spacer name="horizontalSpacer_2">
1664 <property name="orientation">
1665 <enum>Qt::Horizontal</enum>
1666 </property>
1667 <property name="sizeHint" stdset="0">
1668 <size>
1669 <width>40</width>
1670 <height>20</height>
1671 </size>
1672 </property>
1673 </spacer>
1674 </item>
1675 </layout>
1676 </item>
1677 </layout>
1678 </widget>
1679 <widget class="QWidget" name="shiftOSK">
1680 <layout class="QVBoxLayout" name="shiftPageVerticalLayout">
1681 <property name="leftMargin">
1682 <number>0</number>
1683 </property>
1684 <property name="topMargin">
1685 <number>0</number>
1686 </property>
1687 <property name="rightMargin">
1688 <number>0</number>
1689 </property>
1690 <property name="bottomMargin">
1691 <number>0</number>
1692 </property>
1693 <item>
1694 <layout class="QGridLayout" name="kbOSKshift" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54">
1695 <property name="spacing">
1696 <number>0</number>
1697 </property>
1698 <item row="6" column="1" colspan="12">
1699 <widget class="QWidget" name="legendOSKshift" native="true">
1700 <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="70,464,25,12,22,41,25,12,22,41,25,12,95,37,29,12,69,37,29,12,56,8">
1701 <property name="spacing">
1702 <number>0</number>
1703 </property>
1704 <property name="leftMargin">
1705 <number>2</number>
1706 </property>
1707 <property name="topMargin">
1708 <number>0</number>
1709 </property>
1710 <property name="rightMargin">
1711 <number>0</number>
1712 </property>
1713 <property name="bottomMargin">
1714 <number>0</number>
1715 </property>
1716 <item>
1717 <widget class="QWidget" name="icon_controller_shift" native="true">
1718 <property name="styleSheet">
1719 <string notr="true"/>
1720 </property>
1721 </widget>
1722 </item>
1723 <item>
1724 <spacer name="horizontalSpacer_22">
1725 <property name="orientation">
1726 <enum>Qt::Horizontal</enum>
1727 </property>
1728 <property name="sizeHint" stdset="0">
1729 <size>
1730 <width>0</width>
1731 <height>20</height>
1732 </size>
1733 </property>
1734 </spacer>
1735 </item>
1736 <item>
1737 <widget class="QWidget" name="button_L_shift" native="true"/>
1738 </item>
1739 <item>
1740 <spacer name="horizontalSpacer_23">
1741 <property name="orientation">
1742 <enum>Qt::Horizontal</enum>
1743 </property>
1744 <property name="sizeHint" stdset="0">
1745 <size>
1746 <width>0</width>
1747 <height>20</height>
1748 </size>
1749 </property>
1750 </spacer>
1751 </item>
1752 <item>
1753 <widget class="QWidget" name="arrow_left_shift" native="true"/>
1754 </item>
1755 <item>
1756 <spacer name="horizontalSpacer_24">
1757 <property name="orientation">
1758 <enum>Qt::Horizontal</enum>
1759 </property>
1760 <property name="sizeHint" stdset="0">
1761 <size>
1762 <width>0</width>
1763 <height>20</height>
1764 </size>
1765 </property>
1766 </spacer>
1767 </item>
1768 <item>
1769 <widget class="QWidget" name="button_R_shift" native="true"/>
1770 </item>
1771 <item>
1772 <spacer name="horizontalSpacer_25">
1773 <property name="orientation">
1774 <enum>Qt::Horizontal</enum>
1775 </property>
1776 <property name="sizeHint" stdset="0">
1777 <size>
1778 <width>0</width>
1779 <height>20</height>
1780 </size>
1781 </property>
1782 </spacer>
1783 </item>
1784 <item>
1785 <widget class="QWidget" name="arrow_right_shift" native="true"/>
1786 </item>
1787 <item>
1788 <spacer name="horizontalSpacer_26">
1789 <property name="orientation">
1790 <enum>Qt::Horizontal</enum>
1791 </property>
1792 <property name="sizeHint" stdset="0">
1793 <size>
1794 <width>0</width>
1795 <height>20</height>
1796 </size>
1797 </property>
1798 </spacer>
1799 </item>
1800 <item>
1801 <widget class="QWidget" name="button_press_stick_shift" native="true"/>
1802 </item>
1803 <item>
1804 <spacer name="horizontalSpacer_27">
1805 <property name="orientation">
1806 <enum>Qt::Horizontal</enum>
1807 </property>
1808 <property name="sizeHint" stdset="0">
1809 <size>
1810 <width>0</width>
1811 <height>20</height>
1812 </size>
1813 </property>
1814 </spacer>
1815 </item>
1816 <item>
1817 <widget class="QLabel" name="label_shift_shift">
1818 <property name="font">
1819 <font>
1820 <pointsize>18</pointsize>
1821 </font>
1822 </property>
1823 <property name="text">
1824 <string notr="true">Caps Lock</string>
1825 </property>
1826 </widget>
1827 </item>
1828 <item>
1829 <spacer name="horizontalSpacer_28">
1830 <property name="orientation">
1831 <enum>Qt::Horizontal</enum>
1832 </property>
1833 <property name="sizeHint" stdset="0">
1834 <size>
1835 <width>0</width>
1836 <height>20</height>
1837 </size>
1838 </property>
1839 </spacer>
1840 </item>
1841 <item>
1842 <widget class="QWidget" name="button_X_shift" native="true"/>
1843 </item>
1844 <item>
1845 <spacer name="horizontalSpacer_29">
1846 <property name="orientation">
1847 <enum>Qt::Horizontal</enum>
1848 </property>
1849 <property name="sizeHint" stdset="0">
1850 <size>
1851 <width>0</width>
1852 <height>20</height>
1853 </size>
1854 </property>
1855 </spacer>
1856 </item>
1857 <item>
1858 <widget class="QLabel" name="label_cancel_shift">
1859 <property name="font">
1860 <font>
1861 <pointsize>18</pointsize>
1862 </font>
1863 </property>
1864 <property name="text">
1865 <string notr="true">Cancel</string>
1866 </property>
1867 </widget>
1868 </item>
1869 <item>
1870 <spacer name="horizontalSpacer_30">
1871 <property name="orientation">
1872 <enum>Qt::Horizontal</enum>
1873 </property>
1874 <property name="sizeHint" stdset="0">
1875 <size>
1876 <width>0</width>
1877 <height>20</height>
1878 </size>
1879 </property>
1880 </spacer>
1881 </item>
1882 <item>
1883 <widget class="QWidget" name="button_A_shift" native="true"/>
1884 </item>
1885 <item>
1886 <spacer name="horizontalSpacer_31">
1887 <property name="orientation">
1888 <enum>Qt::Horizontal</enum>
1889 </property>
1890 <property name="sizeHint" stdset="0">
1891 <size>
1892 <width>0</width>
1893 <height>20</height>
1894 </size>
1895 </property>
1896 </spacer>
1897 </item>
1898 <item>
1899 <widget class="QLabel" name="label_enter_shift">
1900 <property name="font">
1901 <font>
1902 <pointsize>18</pointsize>
1903 </font>
1904 </property>
1905 <property name="text">
1906 <string notr="true">Enter</string>
1907 </property>
1908 </widget>
1909 </item>
1910 <item>
1911 <spacer name="horizontalSpacer_32">
1912 <property name="orientation">
1913 <enum>Qt::Horizontal</enum>
1914 </property>
1915 <property name="sizeHint" stdset="0">
1916 <size>
1917 <width>0</width>
1918 <height>20</height>
1919 </size>
1920 </property>
1921 </spacer>
1922 </item>
1923 </layout>
1924 </widget>
1925 </item>
1926 <item row="1" column="11">
1927 <widget class="QPushButton" name="button_underscore">
1928 <property name="sizePolicy">
1929 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1930 <horstretch>1</horstretch>
1931 <verstretch>1</verstretch>
1932 </sizepolicy>
1933 </property>
1934 <property name="font">
1935 <font>
1936 <pointsize>28</pointsize>
1937 </font>
1938 </property>
1939 <property name="text">
1940 <string notr="true">_</string>
1941 </property>
1942 </widget>
1943 </item>
1944 <item row="3" column="11">
1945 <widget class="QPushButton" name="button_quotation">
1946 <property name="sizePolicy">
1947 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1948 <horstretch>1</horstretch>
1949 <verstretch>1</verstretch>
1950 </sizepolicy>
1951 </property>
1952 <property name="font">
1953 <font>
1954 <pointsize>28</pointsize>
1955 </font>
1956 </property>
1957 <property name="text">
1958 <string notr="true">&quot;</string>
1959 </property>
1960 </widget>
1961 </item>
1962 <item row="2" column="11">
1963 <widget class="QPushButton" name="button_at">
1964 <property name="sizePolicy">
1965 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1966 <horstretch>1</horstretch>
1967 <verstretch>1</verstretch>
1968 </sizepolicy>
1969 </property>
1970 <property name="font">
1971 <font>
1972 <pointsize>28</pointsize>
1973 </font>
1974 </property>
1975 <property name="text">
1976 <string notr="true">@</string>
1977 </property>
1978 </widget>
1979 </item>
1980 <item row="4" column="11">
1981 <widget class="QPushButton" name="button_equal">
1982 <property name="sizePolicy">
1983 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1984 <horstretch>1</horstretch>
1985 <verstretch>1</verstretch>
1986 </sizepolicy>
1987 </property>
1988 <property name="font">
1989 <font>
1990 <pointsize>28</pointsize>
1991 </font>
1992 </property>
1993 <property name="text">
1994 <string notr="true">=</string>
1995 </property>
1996 </widget>
1997 </item>
1998 <item row="1" column="7">
1999 <widget class="QPushButton" name="button_ampersand">
2000 <property name="sizePolicy">
2001 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2002 <horstretch>1</horstretch>
2003 <verstretch>1</verstretch>
2004 </sizepolicy>
2005 </property>
2006 <property name="font">
2007 <font>
2008 <pointsize>28</pointsize>
2009 </font>
2010 </property>
2011 <property name="text">
2012 <string notr="true">&amp;&amp;</string>
2013 </property>
2014 </widget>
2015 </item>
2016 <item row="1" column="8">
2017 <widget class="QPushButton" name="button_asterisk">
2018 <property name="sizePolicy">
2019 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2020 <horstretch>1</horstretch>
2021 <verstretch>1</verstretch>
2022 </sizepolicy>
2023 </property>
2024 <property name="font">
2025 <font>
2026 <pointsize>28</pointsize>
2027 </font>
2028 </property>
2029 <property name="text">
2030 <string notr="true">*</string>
2031 </property>
2032 </widget>
2033 </item>
2034 <item row="1" column="10">
2035 <widget class="QPushButton" name="button_right_parenthesis">
2036 <property name="sizePolicy">
2037 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2038 <horstretch>1</horstretch>
2039 <verstretch>1</verstretch>
2040 </sizepolicy>
2041 </property>
2042 <property name="font">
2043 <font>
2044 <pointsize>28</pointsize>
2045 </font>
2046 </property>
2047 <property name="text">
2048 <string notr="true">)</string>
2049 </property>
2050 </widget>
2051 </item>
2052 <item row="1" column="9">
2053 <widget class="QPushButton" name="button_left_parenthesis">
2054 <property name="sizePolicy">
2055 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2056 <horstretch>1</horstretch>
2057 <verstretch>1</verstretch>
2058 </sizepolicy>
2059 </property>
2060 <property name="font">
2061 <font>
2062 <pointsize>28</pointsize>
2063 </font>
2064 </property>
2065 <property name="text">
2066 <string notr="true">(</string>
2067 </property>
2068 </widget>
2069 </item>
2070 <item row="2" column="2">
2071 <widget class="QPushButton" name="button_w_shift">
2072 <property name="sizePolicy">
2073 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2074 <horstretch>1</horstretch>
2075 <verstretch>1</verstretch>
2076 </sizepolicy>
2077 </property>
2078 <property name="font">
2079 <font>
2080 <pointsize>28</pointsize>
2081 </font>
2082 </property>
2083 <property name="text">
2084 <string notr="true">W</string>
2085 </property>
2086 </widget>
2087 </item>
2088 <item row="2" column="4">
2089 <widget class="QPushButton" name="button_r_shift">
2090 <property name="sizePolicy">
2091 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2092 <horstretch>1</horstretch>
2093 <verstretch>1</verstretch>
2094 </sizepolicy>
2095 </property>
2096 <property name="font">
2097 <font>
2098 <pointsize>28</pointsize>
2099 </font>
2100 </property>
2101 <property name="text">
2102 <string notr="true">R</string>
2103 </property>
2104 </widget>
2105 </item>
2106 <item row="2" column="3">
2107 <widget class="QPushButton" name="button_e_shift">
2108 <property name="sizePolicy">
2109 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2110 <horstretch>1</horstretch>
2111 <verstretch>1</verstretch>
2112 </sizepolicy>
2113 </property>
2114 <property name="font">
2115 <font>
2116 <pointsize>28</pointsize>
2117 </font>
2118 </property>
2119 <property name="text">
2120 <string notr="true">E</string>
2121 </property>
2122 </widget>
2123 </item>
2124 <item row="2" column="1">
2125 <widget class="QPushButton" name="button_q_shift">
2126 <property name="sizePolicy">
2127 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2128 <horstretch>1</horstretch>
2129 <verstretch>1</verstretch>
2130 </sizepolicy>
2131 </property>
2132 <property name="font">
2133 <font>
2134 <pointsize>28</pointsize>
2135 </font>
2136 </property>
2137 <property name="text">
2138 <string notr="true">Q</string>
2139 </property>
2140 </widget>
2141 </item>
2142 <item row="2" column="7">
2143 <widget class="QPushButton" name="button_u_shift">
2144 <property name="sizePolicy">
2145 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2146 <horstretch>1</horstretch>
2147 <verstretch>1</verstretch>
2148 </sizepolicy>
2149 </property>
2150 <property name="font">
2151 <font>
2152 <pointsize>28</pointsize>
2153 </font>
2154 </property>
2155 <property name="text">
2156 <string notr="true">U</string>
2157 </property>
2158 </widget>
2159 </item>
2160 <item row="2" column="6">
2161 <widget class="QPushButton" name="button_y_shift">
2162 <property name="sizePolicy">
2163 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2164 <horstretch>1</horstretch>
2165 <verstretch>1</verstretch>
2166 </sizepolicy>
2167 </property>
2168 <property name="font">
2169 <font>
2170 <pointsize>28</pointsize>
2171 </font>
2172 </property>
2173 <property name="text">
2174 <string notr="true">Y</string>
2175 </property>
2176 </widget>
2177 </item>
2178 <item row="2" column="5">
2179 <widget class="QPushButton" name="button_t_shift">
2180 <property name="sizePolicy">
2181 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2182 <horstretch>1</horstretch>
2183 <verstretch>1</verstretch>
2184 </sizepolicy>
2185 </property>
2186 <property name="font">
2187 <font>
2188 <pointsize>28</pointsize>
2189 </font>
2190 </property>
2191 <property name="text">
2192 <string notr="true">T</string>
2193 </property>
2194 </widget>
2195 </item>
2196 <item row="2" column="9">
2197 <widget class="QPushButton" name="button_o_shift">
2198 <property name="sizePolicy">
2199 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2200 <horstretch>1</horstretch>
2201 <verstretch>1</verstretch>
2202 </sizepolicy>
2203 </property>
2204 <property name="font">
2205 <font>
2206 <pointsize>28</pointsize>
2207 </font>
2208 </property>
2209 <property name="text">
2210 <string notr="true">O</string>
2211 </property>
2212 </widget>
2213 </item>
2214 <item row="2" column="10">
2215 <widget class="QPushButton" name="button_p_shift">
2216 <property name="sizePolicy">
2217 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2218 <horstretch>1</horstretch>
2219 <verstretch>1</verstretch>
2220 </sizepolicy>
2221 </property>
2222 <property name="font">
2223 <font>
2224 <pointsize>28</pointsize>
2225 </font>
2226 </property>
2227 <property name="text">
2228 <string notr="true">P</string>
2229 </property>
2230 </widget>
2231 </item>
2232 <item row="2" column="8">
2233 <widget class="QPushButton" name="button_i_shift">
2234 <property name="sizePolicy">
2235 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2236 <horstretch>1</horstretch>
2237 <verstretch>1</verstretch>
2238 </sizepolicy>
2239 </property>
2240 <property name="font">
2241 <font>
2242 <pointsize>28</pointsize>
2243 </font>
2244 </property>
2245 <property name="text">
2246 <string notr="true">I</string>
2247 </property>
2248 </widget>
2249 </item>
2250 <item row="3" column="1">
2251 <widget class="QPushButton" name="button_a_shift">
2252 <property name="sizePolicy">
2253 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2254 <horstretch>1</horstretch>
2255 <verstretch>1</verstretch>
2256 </sizepolicy>
2257 </property>
2258 <property name="font">
2259 <font>
2260 <pointsize>28</pointsize>
2261 </font>
2262 </property>
2263 <property name="text">
2264 <string notr="true">A</string>
2265 </property>
2266 </widget>
2267 </item>
2268 <item row="3" column="2">
2269 <widget class="QPushButton" name="button_s_shift">
2270 <property name="sizePolicy">
2271 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2272 <horstretch>1</horstretch>
2273 <verstretch>1</verstretch>
2274 </sizepolicy>
2275 </property>
2276 <property name="font">
2277 <font>
2278 <pointsize>28</pointsize>
2279 </font>
2280 </property>
2281 <property name="text">
2282 <string notr="true">S</string>
2283 </property>
2284 </widget>
2285 </item>
2286 <item row="3" column="3">
2287 <widget class="QPushButton" name="button_d_shift">
2288 <property name="sizePolicy">
2289 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2290 <horstretch>1</horstretch>
2291 <verstretch>1</verstretch>
2292 </sizepolicy>
2293 </property>
2294 <property name="font">
2295 <font>
2296 <pointsize>28</pointsize>
2297 </font>
2298 </property>
2299 <property name="text">
2300 <string notr="true">D</string>
2301 </property>
2302 </widget>
2303 </item>
2304 <item row="3" column="4">
2305 <widget class="QPushButton" name="button_f_shift">
2306 <property name="sizePolicy">
2307 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2308 <horstretch>1</horstretch>
2309 <verstretch>1</verstretch>
2310 </sizepolicy>
2311 </property>
2312 <property name="font">
2313 <font>
2314 <pointsize>28</pointsize>
2315 </font>
2316 </property>
2317 <property name="text">
2318 <string notr="true">F</string>
2319 </property>
2320 </widget>
2321 </item>
2322 <item row="3" column="6">
2323 <widget class="QPushButton" name="button_h_shift">
2324 <property name="sizePolicy">
2325 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2326 <horstretch>1</horstretch>
2327 <verstretch>1</verstretch>
2328 </sizepolicy>
2329 </property>
2330 <property name="font">
2331 <font>
2332 <pointsize>28</pointsize>
2333 </font>
2334 </property>
2335 <property name="text">
2336 <string notr="true">H</string>
2337 </property>
2338 </widget>
2339 </item>
2340 <item row="3" column="7">
2341 <widget class="QPushButton" name="button_j_shift">
2342 <property name="sizePolicy">
2343 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2344 <horstretch>1</horstretch>
2345 <verstretch>1</verstretch>
2346 </sizepolicy>
2347 </property>
2348 <property name="font">
2349 <font>
2350 <pointsize>28</pointsize>
2351 </font>
2352 </property>
2353 <property name="text">
2354 <string notr="true">J</string>
2355 </property>
2356 </widget>
2357 </item>
2358 <item row="3" column="5">
2359 <widget class="QPushButton" name="button_g_shift">
2360 <property name="sizePolicy">
2361 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2362 <horstretch>1</horstretch>
2363 <verstretch>1</verstretch>
2364 </sizepolicy>
2365 </property>
2366 <property name="font">
2367 <font>
2368 <pointsize>28</pointsize>
2369 </font>
2370 </property>
2371 <property name="text">
2372 <string notr="true">G</string>
2373 </property>
2374 </widget>
2375 </item>
2376 <item row="3" column="8">
2377 <widget class="QPushButton" name="button_k_shift">
2378 <property name="sizePolicy">
2379 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2380 <horstretch>1</horstretch>
2381 <verstretch>1</verstretch>
2382 </sizepolicy>
2383 </property>
2384 <property name="font">
2385 <font>
2386 <pointsize>28</pointsize>
2387 </font>
2388 </property>
2389 <property name="text">
2390 <string notr="true">K</string>
2391 </property>
2392 </widget>
2393 </item>
2394 <item row="3" column="9">
2395 <widget class="QPushButton" name="button_l_shift">
2396 <property name="sizePolicy">
2397 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2398 <horstretch>1</horstretch>
2399 <verstretch>1</verstretch>
2400 </sizepolicy>
2401 </property>
2402 <property name="font">
2403 <font>
2404 <pointsize>28</pointsize>
2405 </font>
2406 </property>
2407 <property name="text">
2408 <string notr="true">L</string>
2409 </property>
2410 </widget>
2411 </item>
2412 <item row="3" column="10">
2413 <widget class="QPushButton" name="button_semicolon">
2414 <property name="sizePolicy">
2415 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2416 <horstretch>1</horstretch>
2417 <verstretch>1</verstretch>
2418 </sizepolicy>
2419 </property>
2420 <property name="font">
2421 <font>
2422 <pointsize>28</pointsize>
2423 </font>
2424 </property>
2425 <property name="text">
2426 <string notr="true">;</string>
2427 </property>
2428 </widget>
2429 </item>
2430 <item row="2" column="12" rowspan="2">
2431 <widget class="QPushButton" name="button_return_shift">
2432 <property name="sizePolicy">
2433 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2434 <horstretch>1</horstretch>
2435 <verstretch>1</verstretch>
2436 </sizepolicy>
2437 </property>
2438 <property name="font">
2439 <font>
2440 <pointsize>18</pointsize>
2441 </font>
2442 </property>
2443 <property name="text">
2444 <string notr="true">Return</string>
2445 </property>
2446 </widget>
2447 </item>
2448 <item row="4" column="12" rowspan="2">
2449 <widget class="QPushButton" name="button_ok_shift">
2450 <property name="sizePolicy">
2451 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2452 <horstretch>1</horstretch>
2453 <verstretch>1</verstretch>
2454 </sizepolicy>
2455 </property>
2456 <property name="font">
2457 <font>
2458 <pointsize>18</pointsize>
2459 </font>
2460 </property>
2461 <property name="text">
2462 <string notr="true">OK</string>
2463 </property>
2464 </widget>
2465 </item>
2466 <item row="4" column="1">
2467 <widget class="QPushButton" name="button_z_shift">
2468 <property name="sizePolicy">
2469 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2470 <horstretch>1</horstretch>
2471 <verstretch>1</verstretch>
2472 </sizepolicy>
2473 </property>
2474 <property name="font">
2475 <font>
2476 <pointsize>28</pointsize>
2477 </font>
2478 </property>
2479 <property name="text">
2480 <string notr="true">Z</string>
2481 </property>
2482 </widget>
2483 </item>
2484 <item row="4" column="3">
2485 <widget class="QPushButton" name="button_c_shift">
2486 <property name="sizePolicy">
2487 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2488 <horstretch>1</horstretch>
2489 <verstretch>1</verstretch>
2490 </sizepolicy>
2491 </property>
2492 <property name="font">
2493 <font>
2494 <pointsize>28</pointsize>
2495 </font>
2496 </property>
2497 <property name="text">
2498 <string notr="true">C</string>
2499 </property>
2500 </widget>
2501 </item>
2502 <item row="4" column="2">
2503 <widget class="QPushButton" name="button_x_shift">
2504 <property name="sizePolicy">
2505 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2506 <horstretch>1</horstretch>
2507 <verstretch>1</verstretch>
2508 </sizepolicy>
2509 </property>
2510 <property name="font">
2511 <font>
2512 <pointsize>28</pointsize>
2513 </font>
2514 </property>
2515 <property name="text">
2516 <string notr="true">X</string>
2517 </property>
2518 </widget>
2519 </item>
2520 <item row="4" column="4">
2521 <widget class="QPushButton" name="button_v_shift">
2522 <property name="sizePolicy">
2523 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2524 <horstretch>1</horstretch>
2525 <verstretch>1</verstretch>
2526 </sizepolicy>
2527 </property>
2528 <property name="font">
2529 <font>
2530 <pointsize>28</pointsize>
2531 </font>
2532 </property>
2533 <property name="text">
2534 <string notr="true">V</string>
2535 </property>
2536 </widget>
2537 </item>
2538 <item row="4" column="7">
2539 <widget class="QPushButton" name="button_m_shift">
2540 <property name="sizePolicy">
2541 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2542 <horstretch>1</horstretch>
2543 <verstretch>1</verstretch>
2544 </sizepolicy>
2545 </property>
2546 <property name="font">
2547 <font>
2548 <pointsize>28</pointsize>
2549 </font>
2550 </property>
2551 <property name="text">
2552 <string notr="true">M</string>
2553 </property>
2554 </widget>
2555 </item>
2556 <item row="4" column="8">
2557 <widget class="QPushButton" name="button_less_than">
2558 <property name="sizePolicy">
2559 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2560 <horstretch>1</horstretch>
2561 <verstretch>1</verstretch>
2562 </sizepolicy>
2563 </property>
2564 <property name="font">
2565 <font>
2566 <pointsize>28</pointsize>
2567 </font>
2568 </property>
2569 <property name="text">
2570 <string notr="true">&lt;</string>
2571 </property>
2572 </widget>
2573 </item>
2574 <item row="4" column="6">
2575 <widget class="QPushButton" name="button_n_shift">
2576 <property name="sizePolicy">
2577 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2578 <horstretch>1</horstretch>
2579 <verstretch>1</verstretch>
2580 </sizepolicy>
2581 </property>
2582 <property name="font">
2583 <font>
2584 <pointsize>28</pointsize>
2585 </font>
2586 </property>
2587 <property name="text">
2588 <string notr="true">N</string>
2589 </property>
2590 </widget>
2591 </item>
2592 <item row="4" column="5">
2593 <widget class="QPushButton" name="button_b_shift">
2594 <property name="sizePolicy">
2595 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2596 <horstretch>1</horstretch>
2597 <verstretch>1</verstretch>
2598 </sizepolicy>
2599 </property>
2600 <property name="font">
2601 <font>
2602 <pointsize>28</pointsize>
2603 </font>
2604 </property>
2605 <property name="text">
2606 <string notr="true">B</string>
2607 </property>
2608 </widget>
2609 </item>
2610 <item row="5" column="1" colspan="2">
2611 <widget class="QPushButton" name="button_shift_shift">
2612 <property name="sizePolicy">
2613 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2614 <horstretch>1</horstretch>
2615 <verstretch>1</verstretch>
2616 </sizepolicy>
2617 </property>
2618 <property name="font">
2619 <font>
2620 <pointsize>18</pointsize>
2621 </font>
2622 </property>
2623 <property name="text">
2624 <string notr="true"/>
2625 </property>
2626 <property name="checkable">
2627 <bool>true</bool>
2628 </property>
2629 <property name="checked">
2630 <bool>false</bool>
2631 </property>
2632 </widget>
2633 </item>
2634 <item row="4" column="10">
2635 <widget class="QPushButton" name="button_plus">
2636 <property name="sizePolicy">
2637 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2638 <horstretch>1</horstretch>
2639 <verstretch>1</verstretch>
2640 </sizepolicy>
2641 </property>
2642 <property name="font">
2643 <font>
2644 <pointsize>28</pointsize>
2645 </font>
2646 </property>
2647 <property name="text">
2648 <string notr="true">+</string>
2649 </property>
2650 </widget>
2651 </item>
2652 <item row="4" column="9">
2653 <widget class="QPushButton" name="button_greater_than">
2654 <property name="sizePolicy">
2655 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2656 <horstretch>1</horstretch>
2657 <verstretch>1</verstretch>
2658 </sizepolicy>
2659 </property>
2660 <property name="font">
2661 <font>
2662 <pointsize>28</pointsize>
2663 </font>
2664 </property>
2665 <property name="text">
2666 <string notr="true">&gt;</string>
2667 </property>
2668 </widget>
2669 </item>
2670 <item row="1" column="1">
2671 <widget class="QPushButton" name="button_hash">
2672 <property name="sizePolicy">
2673 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2674 <horstretch>1</horstretch>
2675 <verstretch>1</verstretch>
2676 </sizepolicy>
2677 </property>
2678 <property name="font">
2679 <font>
2680 <pointsize>28</pointsize>
2681 </font>
2682 </property>
2683 <property name="text">
2684 <string notr="true">#</string>
2685 </property>
2686 </widget>
2687 </item>
2688 <item row="1" column="3">
2689 <widget class="QPushButton" name="button_right_bracket">
2690 <property name="sizePolicy">
2691 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2692 <horstretch>1</horstretch>
2693 <verstretch>1</verstretch>
2694 </sizepolicy>
2695 </property>
2696 <property name="font">
2697 <font>
2698 <pointsize>28</pointsize>
2699 </font>
2700 </property>
2701 <property name="text">
2702 <string notr="true">]</string>
2703 </property>
2704 </widget>
2705 </item>
2706 <item row="1" column="4">
2707 <widget class="QPushButton" name="button_dollar">
2708 <property name="sizePolicy">
2709 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2710 <horstretch>1</horstretch>
2711 <verstretch>1</verstretch>
2712 </sizepolicy>
2713 </property>
2714 <property name="font">
2715 <font>
2716 <pointsize>28</pointsize>
2717 </font>
2718 </property>
2719 <property name="text">
2720 <string notr="true">$</string>
2721 </property>
2722 </widget>
2723 </item>
2724 <item row="1" column="2">
2725 <widget class="QPushButton" name="button_left_bracket">
2726 <property name="sizePolicy">
2727 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2728 <horstretch>1</horstretch>
2729 <verstretch>1</verstretch>
2730 </sizepolicy>
2731 </property>
2732 <property name="font">
2733 <font>
2734 <pointsize>28</pointsize>
2735 </font>
2736 </property>
2737 <property name="text">
2738 <string notr="true">[</string>
2739 </property>
2740 </widget>
2741 </item>
2742 <item row="1" column="6">
2743 <widget class="QPushButton" name="button_circumflex">
2744 <property name="sizePolicy">
2745 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2746 <horstretch>1</horstretch>
2747 <verstretch>1</verstretch>
2748 </sizepolicy>
2749 </property>
2750 <property name="font">
2751 <font>
2752 <pointsize>28</pointsize>
2753 </font>
2754 </property>
2755 <property name="text">
2756 <string notr="true">^</string>
2757 </property>
2758 </widget>
2759 </item>
2760 <item row="1" column="5">
2761 <widget class="QPushButton" name="button_percent">
2762 <property name="sizePolicy">
2763 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2764 <horstretch>1</horstretch>
2765 <verstretch>1</verstretch>
2766 </sizepolicy>
2767 </property>
2768 <property name="font">
2769 <font>
2770 <pointsize>28</pointsize>
2771 </font>
2772 </property>
2773 <property name="text">
2774 <string notr="true">%</string>
2775 </property>
2776 </widget>
2777 </item>
2778 <item row="5" column="3" colspan="9">
2779 <widget class="QPushButton" name="button_space_shift">
2780 <property name="sizePolicy">
2781 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2782 <horstretch>1</horstretch>
2783 <verstretch>1</verstretch>
2784 </sizepolicy>
2785 </property>
2786 <property name="font">
2787 <font>
2788 <pointsize>18</pointsize>
2789 </font>
2790 </property>
2791 <property name="text">
2792 <string notr="true">Space</string>
2793 </property>
2794 </widget>
2795 </item>
2796 <item row="1" column="12">
2797 <widget class="QPushButton" name="button_backspace_shift">
2798 <property name="sizePolicy">
2799 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2800 <horstretch>1</horstretch>
2801 <verstretch>1</verstretch>
2802 </sizepolicy>
2803 </property>
2804 <property name="font">
2805 <font>
2806 <pointsize>18</pointsize>
2807 </font>
2808 </property>
2809 <property name="text">
2810 <string notr="true"/>
2811 </property>
2812 </widget>
2813 </item>
2814 <item row="1" column="0">
2815 <spacer name="horizontalSpacer_33">
2816 <property name="orientation">
2817 <enum>Qt::Horizontal</enum>
2818 </property>
2819 <property name="sizeHint" stdset="0">
2820 <size>
2821 <width>40</width>
2822 <height>20</height>
2823 </size>
2824 </property>
2825 </spacer>
2826 </item>
2827 <item row="0" column="1">
2828 <spacer name="verticalSpacer_6">
2829 <property name="orientation">
2830 <enum>Qt::Vertical</enum>
2831 </property>
2832 <property name="sizeHint" stdset="0">
2833 <size>
2834 <width>20</width>
2835 <height>0</height>
2836 </size>
2837 </property>
2838 </spacer>
2839 </item>
2840 <item row="1" column="13">
2841 <spacer name="horizontalSpacer_34">
2842 <property name="orientation">
2843 <enum>Qt::Horizontal</enum>
2844 </property>
2845 <property name="sizeHint" stdset="0">
2846 <size>
2847 <width>40</width>
2848 <height>20</height>
2849 </size>
2850 </property>
2851 </spacer>
2852 </item>
2853 </layout>
2854 </item>
2855 </layout>
2856 </widget>
2857 <widget class="QWidget" name="numOSK">
2858 <layout class="QVBoxLayout" name="graphicsTabVerticalLayout">
2859 <property name="leftMargin">
2860 <number>0</number>
2861 </property>
2862 <property name="topMargin">
2863 <number>0</number>
2864 </property>
2865 <property name="rightMargin">
2866 <number>0</number>
2867 </property>
2868 <property name="bottomMargin">
2869 <number>0</number>
2870 </property>
2871 <item>
2872 <layout class="QGridLayout" name="kbOSKnum" rowstretch="18,63,63,63,63,10,70" columnstretch="54,307,186,186,186,120,187,54">
2873 <property name="leftMargin">
2874 <number>0</number>
2875 </property>
2876 <property name="rightMargin">
2877 <number>0</number>
2878 </property>
2879 <property name="spacing">
2880 <number>0</number>
2881 </property>
2882 <item row="1" column="5">
2883 <widget class="QPushButton" name="button_backspace_num">
2884 <property name="sizePolicy">
2885 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
2886 <horstretch>1</horstretch>
2887 <verstretch>1</verstretch>
2888 </sizepolicy>
2889 </property>
2890 <property name="font">
2891 <font>
2892 <pointsize>18</pointsize>
2893 </font>
2894 </property>
2895 <property name="text">
2896 <string notr="true"/>
2897 </property>
2898 </widget>
2899 </item>
2900 <item row="1" column="6">
2901 <spacer name="horizontalSpacer_35">
2902 <property name="orientation">
2903 <enum>Qt::Horizontal</enum>
2904 </property>
2905 <property name="sizeHint" stdset="0">
2906 <size>
2907 <width>40</width>
2908 <height>20</height>
2909 </size>
2910 </property>
2911 </spacer>
2912 </item>
2913 <item row="1" column="1">
2914 <spacer name="horizontalSpacer_36">
2915 <property name="orientation">
2916 <enum>Qt::Horizontal</enum>
2917 </property>
2918 <property name="sizeHint" stdset="0">
2919 <size>
2920 <width>40</width>
2921 <height>20</height>
2922 </size>
2923 </property>
2924 </spacer>
2925 </item>
2926 <item row="0" column="2">
2927 <spacer name="verticalSpacer_7">
2928 <property name="orientation">
2929 <enum>Qt::Vertical</enum>
2930 </property>
2931 <property name="sizeHint" stdset="0">
2932 <size>
2933 <width>20</width>
2934 <height>0</height>
2935 </size>
2936 </property>
2937 </spacer>
2938 </item>
2939 <item row="6" column="1" colspan="6">
2940 <widget class="QWidget" name="legendOSKnum" native="true">
2941 <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="25,70,601,25,12,22,41,25,12,22,41,29,12,69,37,29,12,56,30">
2942 <property name="spacing">
2943 <number>0</number>
2944 </property>
2945 <property name="leftMargin">
2946 <number>0</number>
2947 </property>
2948 <property name="topMargin">
2949 <number>0</number>
2950 </property>
2951 <property name="rightMargin">
2952 <number>0</number>
2953 </property>
2954 <property name="bottomMargin">
2955 <number>0</number>
2956 </property>
2957 <item>
2958 <spacer name="horizontalSpacer_48">
2959 <property name="orientation">
2960 <enum>Qt::Horizontal</enum>
2961 </property>
2962 <property name="sizeHint" stdset="0">
2963 <size>
2964 <width>40</width>
2965 <height>20</height>
2966 </size>
2967 </property>
2968 </spacer>
2969 </item>
2970 <item>
2971 <widget class="QWidget" name="icon_controller_num" native="true">
2972 <property name="styleSheet">
2973 <string notr="true"/>
2974 </property>
2975 </widget>
2976 </item>
2977 <item>
2978 <spacer name="horizontalSpacer_38">
2979 <property name="orientation">
2980 <enum>Qt::Horizontal</enum>
2981 </property>
2982 <property name="sizeHint" stdset="0">
2983 <size>
2984 <width>0</width>
2985 <height>20</height>
2986 </size>
2987 </property>
2988 </spacer>
2989 </item>
2990 <item>
2991 <widget class="QWidget" name="button_L_num" native="true"/>
2992 </item>
2993 <item>
2994 <spacer name="horizontalSpacer_39">
2995 <property name="orientation">
2996 <enum>Qt::Horizontal</enum>
2997 </property>
2998 <property name="sizeHint" stdset="0">
2999 <size>
3000 <width>0</width>
3001 <height>20</height>
3002 </size>
3003 </property>
3004 </spacer>
3005 </item>
3006 <item>
3007 <widget class="QWidget" name="arrow_left_num" native="true"/>
3008 </item>
3009 <item>
3010 <spacer name="horizontalSpacer_40">
3011 <property name="orientation">
3012 <enum>Qt::Horizontal</enum>
3013 </property>
3014 <property name="sizeHint" stdset="0">
3015 <size>
3016 <width>0</width>
3017 <height>20</height>
3018 </size>
3019 </property>
3020 </spacer>
3021 </item>
3022 <item>
3023 <widget class="QWidget" name="button_R_num" native="true"/>
3024 </item>
3025 <item>
3026 <spacer name="horizontalSpacer_41">
3027 <property name="orientation">
3028 <enum>Qt::Horizontal</enum>
3029 </property>
3030 <property name="sizeHint" stdset="0">
3031 <size>
3032 <width>0</width>
3033 <height>20</height>
3034 </size>
3035 </property>
3036 </spacer>
3037 </item>
3038 <item>
3039 <widget class="QWidget" name="arrow_right_num" native="true"/>
3040 </item>
3041 <item>
3042 <spacer name="horizontalSpacer_42">
3043 <property name="orientation">
3044 <enum>Qt::Horizontal</enum>
3045 </property>
3046 <property name="sizeHint" stdset="0">
3047 <size>
3048 <width>0</width>
3049 <height>20</height>
3050 </size>
3051 </property>
3052 </spacer>
3053 </item>
3054 <item>
3055 <widget class="QWidget" name="button_X_num" native="true"/>
3056 </item>
3057 <item>
3058 <spacer name="horizontalSpacer_43">
3059 <property name="orientation">
3060 <enum>Qt::Horizontal</enum>
3061 </property>
3062 <property name="sizeHint" stdset="0">
3063 <size>
3064 <width>0</width>
3065 <height>20</height>
3066 </size>
3067 </property>
3068 </spacer>
3069 </item>
3070 <item>
3071 <widget class="QLabel" name="label_cancel_num">
3072 <property name="font">
3073 <font>
3074 <pointsize>18</pointsize>
3075 </font>
3076 </property>
3077 <property name="text">
3078 <string notr="true">Cancel</string>
3079 </property>
3080 </widget>
3081 </item>
3082 <item>
3083 <spacer name="horizontalSpacer_44">
3084 <property name="orientation">
3085 <enum>Qt::Horizontal</enum>
3086 </property>
3087 <property name="sizeHint" stdset="0">
3088 <size>
3089 <width>0</width>
3090 <height>20</height>
3091 </size>
3092 </property>
3093 </spacer>
3094 </item>
3095 <item>
3096 <widget class="QWidget" name="button_A_num" native="true"/>
3097 </item>
3098 <item>
3099 <spacer name="horizontalSpacer_45">
3100 <property name="orientation">
3101 <enum>Qt::Horizontal</enum>
3102 </property>
3103 <property name="sizeHint" stdset="0">
3104 <size>
3105 <width>0</width>
3106 <height>20</height>
3107 </size>
3108 </property>
3109 </spacer>
3110 </item>
3111 <item>
3112 <widget class="QLabel" name="label_enter_num">
3113 <property name="font">
3114 <font>
3115 <pointsize>18</pointsize>
3116 </font>
3117 </property>
3118 <property name="text">
3119 <string notr="true">Enter</string>
3120 </property>
3121 </widget>
3122 </item>
3123 <item>
3124 <spacer name="horizontalSpacer_46">
3125 <property name="orientation">
3126 <enum>Qt::Horizontal</enum>
3127 </property>
3128 <property name="sizeHint" stdset="0">
3129 <size>
3130 <width>0</width>
3131 <height>20</height>
3132 </size>
3133 </property>
3134 </spacer>
3135 </item>
3136 </layout>
3137 </widget>
3138 </item>
3139 <item row="2" column="4">
3140 <widget class="QPushButton" name="button_6_num">
3141 <property name="sizePolicy">
3142 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3143 <horstretch>1</horstretch>
3144 <verstretch>1</verstretch>
3145 </sizepolicy>
3146 </property>
3147 <property name="font">
3148 <font>
3149 <pointsize>28</pointsize>
3150 </font>
3151 </property>
3152 <property name="text">
3153 <string notr="true">6</string>
3154 </property>
3155 </widget>
3156 </item>
3157 <item row="2" column="2">
3158 <widget class="QPushButton" name="button_4_num">
3159 <property name="sizePolicy">
3160 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3161 <horstretch>1</horstretch>
3162 <verstretch>1</verstretch>
3163 </sizepolicy>
3164 </property>
3165 <property name="font">
3166 <font>
3167 <pointsize>28</pointsize>
3168 </font>
3169 </property>
3170 <property name="text">
3171 <string notr="true">4</string>
3172 </property>
3173 </widget>
3174 </item>
3175 <item row="3" column="4">
3176 <widget class="QPushButton" name="button_9_num">
3177 <property name="sizePolicy">
3178 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3179 <horstretch>1</horstretch>
3180 <verstretch>1</verstretch>
3181 </sizepolicy>
3182 </property>
3183 <property name="font">
3184 <font>
3185 <pointsize>28</pointsize>
3186 </font>
3187 </property>
3188 <property name="text">
3189 <string notr="true">9</string>
3190 </property>
3191 </widget>
3192 </item>
3193 <item row="2" column="3">
3194 <widget class="QPushButton" name="button_5_num">
3195 <property name="sizePolicy">
3196 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3197 <horstretch>1</horstretch>
3198 <verstretch>1</verstretch>
3199 </sizepolicy>
3200 </property>
3201 <property name="font">
3202 <font>
3203 <pointsize>28</pointsize>
3204 </font>
3205 </property>
3206 <property name="text">
3207 <string notr="true">5</string>
3208 </property>
3209 </widget>
3210 </item>
3211 <item row="2" column="5" rowspan="3">
3212 <widget class="QPushButton" name="button_ok_num">
3213 <property name="sizePolicy">
3214 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3215 <horstretch>1</horstretch>
3216 <verstretch>1</verstretch>
3217 </sizepolicy>
3218 </property>
3219 <property name="font">
3220 <font>
3221 <pointsize>18</pointsize>
3222 </font>
3223 </property>
3224 <property name="text">
3225 <string notr="true">OK</string>
3226 </property>
3227 </widget>
3228 </item>
3229 <item row="3" column="2">
3230 <widget class="QPushButton" name="button_7_num">
3231 <property name="sizePolicy">
3232 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3233 <horstretch>1</horstretch>
3234 <verstretch>1</verstretch>
3235 </sizepolicy>
3236 </property>
3237 <property name="font">
3238 <font>
3239 <pointsize>28</pointsize>
3240 </font>
3241 </property>
3242 <property name="text">
3243 <string notr="true">7</string>
3244 </property>
3245 </widget>
3246 </item>
3247 <item row="3" column="3">
3248 <widget class="QPushButton" name="button_8_num">
3249 <property name="sizePolicy">
3250 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3251 <horstretch>1</horstretch>
3252 <verstretch>1</verstretch>
3253 </sizepolicy>
3254 </property>
3255 <property name="font">
3256 <font>
3257 <pointsize>28</pointsize>
3258 </font>
3259 </property>
3260 <property name="text">
3261 <string notr="true">8</string>
3262 </property>
3263 </widget>
3264 </item>
3265 <item row="1" column="3">
3266 <widget class="QPushButton" name="button_2_num">
3267 <property name="sizePolicy">
3268 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3269 <horstretch>1</horstretch>
3270 <verstretch>1</verstretch>
3271 </sizepolicy>
3272 </property>
3273 <property name="font">
3274 <font>
3275 <pointsize>28</pointsize>
3276 </font>
3277 </property>
3278 <property name="text">
3279 <string notr="true">2</string>
3280 </property>
3281 </widget>
3282 </item>
3283 <item row="1" column="2">
3284 <widget class="QPushButton" name="button_1_num">
3285 <property name="sizePolicy">
3286 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3287 <horstretch>1</horstretch>
3288 <verstretch>1</verstretch>
3289 </sizepolicy>
3290 </property>
3291 <property name="font">
3292 <font>
3293 <pointsize>28</pointsize>
3294 </font>
3295 </property>
3296 <property name="text">
3297 <string notr="true">1</string>
3298 </property>
3299 </widget>
3300 </item>
3301 <item row="4" column="3">
3302 <widget class="QPushButton" name="button_0_num">
3303 <property name="sizePolicy">
3304 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3305 <horstretch>1</horstretch>
3306 <verstretch>1</verstretch>
3307 </sizepolicy>
3308 </property>
3309 <property name="font">
3310 <font>
3311 <pointsize>28</pointsize>
3312 </font>
3313 </property>
3314 <property name="text">
3315 <string notr="true">0</string>
3316 </property>
3317 </widget>
3318 </item>
3319 <item row="1" column="4">
3320 <widget class="QPushButton" name="button_3_num">
3321 <property name="sizePolicy">
3322 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
3323 <horstretch>1</horstretch>
3324 <verstretch>1</verstretch>
3325 </sizepolicy>
3326 </property>
3327 <property name="font">
3328 <font>
3329 <pointsize>28</pointsize>
3330 </font>
3331 </property>
3332 <property name="text">
3333 <string notr="true">3</string>
3334 </property>
3335 </widget>
3336 </item>
3337 <item row="1" column="0">
3338 <spacer name="horizontalSpacer_37">
3339 <property name="orientation">
3340 <enum>Qt::Horizontal</enum>
3341 </property>
3342 <property name="sizeHint" stdset="0">
3343 <size>
3344 <width>40</width>
3345 <height>20</height>
3346 </size>
3347 </property>
3348 </spacer>
3349 </item>
3350 <item row="1" column="7">
3351 <spacer name="horizontalSpacer_47">
3352 <property name="orientation">
3353 <enum>Qt::Horizontal</enum>
3354 </property>
3355 <property name="sizeHint" stdset="0">
3356 <size>
3357 <width>40</width>
3358 <height>20</height>
3359 </size>
3360 </property>
3361 </spacer>
3362 </item>
3363 <item row="5" column="3">
3364 <spacer name="verticalSpacer_8">
3365 <property name="orientation">
3366 <enum>Qt::Vertical</enum>
3367 </property>
3368 <property name="sizeHint" stdset="0">
3369 <size>
3370 <width>20</width>
3371 <height>0</height>
3372 </size>
3373 </property>
3374 </spacer>
3375 </item>
3376 </layout>
3377 </item>
3378 </layout>
3379 </widget>
3380 </widget>
3381 </item>
3382 </layout>
3383 </widget>
3384 </item>
3385 </layout>
3386 </widget>
3387 <tabstops>
3388 <tabstop>button_1</tabstop>
3389 <tabstop>button_2</tabstop>
3390 <tabstop>button_3</tabstop>
3391 <tabstop>button_4</tabstop>
3392 <tabstop>button_5</tabstop>
3393 <tabstop>button_6</tabstop>
3394 <tabstop>button_7</tabstop>
3395 <tabstop>button_8</tabstop>
3396 <tabstop>button_9</tabstop>
3397 <tabstop>button_0</tabstop>
3398 <tabstop>button_minus</tabstop>
3399 <tabstop>button_backspace</tabstop>
3400 <tabstop>button_q</tabstop>
3401 <tabstop>button_w</tabstop>
3402 <tabstop>button_e</tabstop>
3403 <tabstop>button_r</tabstop>
3404 <tabstop>button_t</tabstop>
3405 <tabstop>button_y</tabstop>
3406 <tabstop>button_u</tabstop>
3407 <tabstop>button_i</tabstop>
3408 <tabstop>button_o</tabstop>
3409 <tabstop>button_p</tabstop>
3410 <tabstop>button_slash</tabstop>
3411 <tabstop>button_return</tabstop>
3412 <tabstop>button_a</tabstop>
3413 <tabstop>button_s</tabstop>
3414 <tabstop>button_d</tabstop>
3415 <tabstop>button_f</tabstop>
3416 <tabstop>button_g</tabstop>
3417 <tabstop>button_h</tabstop>
3418 <tabstop>button_j</tabstop>
3419 <tabstop>button_k</tabstop>
3420 <tabstop>button_l</tabstop>
3421 <tabstop>button_colon</tabstop>
3422 <tabstop>button_apostrophe</tabstop>
3423 <tabstop>button_z</tabstop>
3424 <tabstop>button_x</tabstop>
3425 <tabstop>button_c</tabstop>
3426 <tabstop>button_v</tabstop>
3427 <tabstop>button_b</tabstop>
3428 <tabstop>button_n</tabstop>
3429 <tabstop>button_m</tabstop>
3430 <tabstop>button_comma</tabstop>
3431 <tabstop>button_dot</tabstop>
3432 <tabstop>button_question</tabstop>
3433 <tabstop>button_exclamation</tabstop>
3434 <tabstop>button_ok</tabstop>
3435 <tabstop>button_shift</tabstop>
3436 <tabstop>button_space</tabstop>
3437 <tabstop>button_hash</tabstop>
3438 <tabstop>button_left_bracket</tabstop>
3439 <tabstop>button_right_bracket</tabstop>
3440 <tabstop>button_dollar</tabstop>
3441 <tabstop>button_percent</tabstop>
3442 <tabstop>button_circumflex</tabstop>
3443 <tabstop>button_ampersand</tabstop>
3444 <tabstop>button_asterisk</tabstop>
3445 <tabstop>button_left_parenthesis</tabstop>
3446 <tabstop>button_right_parenthesis</tabstop>
3447 <tabstop>button_underscore</tabstop>
3448 <tabstop>button_backspace_shift</tabstop>
3449 <tabstop>button_q_shift</tabstop>
3450 <tabstop>button_w_shift</tabstop>
3451 <tabstop>button_e_shift</tabstop>
3452 <tabstop>button_r_shift</tabstop>
3453 <tabstop>button_t_shift</tabstop>
3454 <tabstop>button_y_shift</tabstop>
3455 <tabstop>button_u_shift</tabstop>
3456 <tabstop>button_i_shift</tabstop>
3457 <tabstop>button_o_shift</tabstop>
3458 <tabstop>button_p_shift</tabstop>
3459 <tabstop>button_at</tabstop>
3460 <tabstop>button_return_shift</tabstop>
3461 <tabstop>button_a_shift</tabstop>
3462 <tabstop>button_s_shift</tabstop>
3463 <tabstop>button_d_shift</tabstop>
3464 <tabstop>button_f_shift</tabstop>
3465 <tabstop>button_g_shift</tabstop>
3466 <tabstop>button_h_shift</tabstop>
3467 <tabstop>button_j_shift</tabstop>
3468 <tabstop>button_k_shift</tabstop>
3469 <tabstop>button_l_shift</tabstop>
3470 <tabstop>button_semicolon</tabstop>
3471 <tabstop>button_quotation</tabstop>
3472 <tabstop>button_z_shift</tabstop>
3473 <tabstop>button_x_shift</tabstop>
3474 <tabstop>button_c_shift</tabstop>
3475 <tabstop>button_v_shift</tabstop>
3476 <tabstop>button_b_shift</tabstop>
3477 <tabstop>button_n_shift</tabstop>
3478 <tabstop>button_m_shift</tabstop>
3479 <tabstop>button_less_than</tabstop>
3480 <tabstop>button_greater_than</tabstop>
3481 <tabstop>button_plus</tabstop>
3482 <tabstop>button_equal</tabstop>
3483 <tabstop>button_ok_shift</tabstop>
3484 <tabstop>button_shift_shift</tabstop>
3485 <tabstop>button_space_shift</tabstop>
3486 <tabstop>button_1_num</tabstop>
3487 <tabstop>button_2_num</tabstop>
3488 <tabstop>button_3_num</tabstop>
3489 <tabstop>button_backspace_num</tabstop>
3490 <tabstop>button_4_num</tabstop>
3491 <tabstop>button_5_num</tabstop>
3492 <tabstop>button_6_num</tabstop>
3493 <tabstop>button_ok_num</tabstop>
3494 <tabstop>button_7_num</tabstop>
3495 <tabstop>button_8_num</tabstop>
3496 <tabstop>button_9_num</tabstop>
3497 <tabstop>button_0_num</tabstop>
3498 </tabstops>
3499 <resources>
3500 <include location="../../../dist/icons/overlay/overlay.qrc"/>
3501 </resources>
3502 <connections/>
3503</ui>
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 15c09e0ad..9c7daeac7 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -29,10 +29,10 @@
29#include "common/microprofile.h" 29#include "common/microprofile.h"
30#include "common/scm_rev.h" 30#include "common/scm_rev.h"
31#include "common/scope_exit.h" 31#include "common/scope_exit.h"
32#include "common/settings.h"
32#include "core/core.h" 33#include "core/core.h"
33#include "core/frontend/framebuffer_layout.h" 34#include "core/frontend/framebuffer_layout.h"
34#include "core/hle/kernel/process.h" 35#include "core/hle/kernel/process.h"
35#include "core/settings.h"
36#include "input_common/keyboard.h" 36#include "input_common/keyboard.h"
37#include "input_common/main.h" 37#include "input_common/main.h"
38#include "input_common/mouse/mouse_input.h" 38#include "input_common/mouse/mouse_input.h"
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 1bac57bb2..851246233 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -641,6 +641,9 @@ void Config::ReadDebuggingValues() {
641 ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); 641 ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool();
642 Settings::values.extended_logging = 642 Settings::values.extended_logging =
643 ReadSetting(QStringLiteral("extended_logging"), false).toBool(); 643 ReadSetting(QStringLiteral("extended_logging"), false).toBool();
644 Settings::values.use_debug_asserts =
645 ReadSetting(QStringLiteral("use_debug_asserts"), false).toBool();
646 Settings::values.use_auto_stub = ReadSetting(QStringLiteral("use_auto_stub"), false).toBool();
644 647
645 qt_config->endGroup(); 648 qt_config->endGroup();
646} 649}
@@ -770,6 +773,13 @@ void Config::ReadRendererValues() {
770 ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); 773 ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0);
771 ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); 774 ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false);
772 ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); 775 ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0);
776#ifdef _WIN32
777 ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 0);
778#else
779 // *nix platforms may have issues with the borderless windowed fullscreen mode.
780 // Default to exclusive fullscreen on these platforms for now.
781 ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 1);
782#endif
773 ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); 783 ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0);
774 ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); 784 ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0);
775 ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); 785 ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true);
@@ -1230,6 +1240,7 @@ void Config::SaveDebuggingValues() {
1230 WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); 1240 WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
1231 WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); 1241 WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
1232 WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); 1242 WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false);
1243 WriteSetting(QStringLiteral("use_debug_asserts"), Settings::values.use_debug_asserts, false);
1233 WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false); 1244 WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false);
1234 1245
1235 qt_config->endGroup(); 1246 qt_config->endGroup();
@@ -1333,6 +1344,13 @@ void Config::SaveRendererValues() {
1333 Settings::values.renderer_backend.UsingGlobal(), 0); 1344 Settings::values.renderer_backend.UsingGlobal(), 0);
1334 WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); 1345 WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false);
1335 WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); 1346 WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0);
1347#ifdef _WIN32
1348 WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 0);
1349#else
1350 // *nix platforms may have issues with the borderless windowed fullscreen mode.
1351 // Default to exclusive fullscreen on these platforms for now.
1352 WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 1);
1353#endif
1336 WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); 1354 WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0);
1337 WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); 1355 WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0);
1338 WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); 1356 WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true);
@@ -1584,7 +1602,7 @@ void Config::Reload() {
1584 ReadValues(); 1602 ReadValues();
1585 // To apply default value changes 1603 // To apply default value changes
1586 SaveValues(); 1604 SaveValues();
1587 Settings::Apply(Core::System::GetInstance()); 1605 Core::System::GetInstance().ApplySettings();
1588} 1606}
1589 1607
1590void Config::Save() { 1608void Config::Save() {
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 949c4eb13..5a2c026b3 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -9,7 +9,7 @@
9#include <string> 9#include <string>
10#include <QMetaType> 10#include <QMetaType>
11#include <QVariant> 11#include <QVariant>
12#include "core/settings.h" 12#include "common/settings.h"
13#include "yuzu/uisettings.h" 13#include "yuzu/uisettings.h"
14 14
15class QSettings; 15class QSettings;
@@ -131,6 +131,6 @@ private:
131 bool global; 131 bool global;
132}; 132};
133 133
134// These metatype declarations cannot be in core/settings.h because core is devoid of QT 134// These metatype declarations cannot be in common/settings.h because core is devoid of QT
135Q_DECLARE_METATYPE(Settings::RendererBackend); 135Q_DECLARE_METATYPE(Settings::RendererBackend);
136Q_DECLARE_METATYPE(Settings::GPUAccuracy); 136Q_DECLARE_METATYPE(Settings::GPUAccuracy);
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 18482795c..89be4a62d 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -6,7 +6,7 @@
6#include <QComboBox> 6#include <QComboBox>
7#include <QObject> 7#include <QObject>
8#include <QString> 8#include <QString>
9#include "core/settings.h" 9#include "common/settings.h"
10#include "yuzu/configuration/configuration_shared.h" 10#include "yuzu/configuration/configuration_shared.h"
11#include "yuzu/configuration/configure_per_game.h" 11#include "yuzu/configuration/configure_per_game.h"
12 12
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 312b9e549..5b344cdbd 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -7,7 +7,7 @@
7#include <QCheckBox> 7#include <QCheckBox>
8#include <QComboBox> 8#include <QComboBox>
9#include <QString> 9#include <QString>
10#include "core/settings.h" 10#include "common/settings.h"
11 11
12namespace ConfigurationShared { 12namespace ConfigurationShared {
13 13
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index db9518798..f9507e228 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -8,8 +8,8 @@
8 8
9#include "audio_core/sink.h" 9#include "audio_core/sink.h"
10#include "audio_core/sink_details.h" 10#include "audio_core/sink_details.h"
11#include "common/settings.h"
11#include "core/core.h" 12#include "core/core.h"
12#include "core/settings.h"
13#include "ui_configure_audio.h" 13#include "ui_configure_audio.h"
14#include "yuzu/configuration/configuration_shared.h" 14#include "yuzu/configuration/configuration_shared.h"
15#include "yuzu/configuration/configure_audio.h" 15#include "yuzu/configuration/configure_audio.h"
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index d055cbd60..4f99bc80f 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -7,8 +7,8 @@
7 7
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/settings.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/settings.h"
12#include "ui_configure_cpu.h" 12#include "ui_configure_cpu.h"
13#include "yuzu/configuration/configure_cpu.h" 13#include "yuzu/configuration/configure_cpu.h"
14 14
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index 3c5683d81..ef77b2e7e 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -6,7 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9#include "core/settings.h" 9#include "common/settings.h"
10 10
11namespace Ui { 11namespace Ui {
12class ConfigureCpu; 12class ConfigureCpu;
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp
index 3385b2cf6..c925c023c 100644
--- a/src/yuzu/configuration/configure_cpu_debug.cpp
+++ b/src/yuzu/configuration/configure_cpu_debug.cpp
@@ -6,8 +6,8 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/settings.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/settings.h"
11#include "ui_configure_cpu_debug.h" 11#include "ui_configure_cpu_debug.h"
12#include "yuzu/configuration/configure_cpu_debug.h" 12#include "yuzu/configuration/configure_cpu_debug.h"
13 13
diff --git a/src/yuzu/configuration/configure_cpu_debug.h b/src/yuzu/configuration/configure_cpu_debug.h
index c9941ef3b..10de55099 100644
--- a/src/yuzu/configuration/configure_cpu_debug.h
+++ b/src/yuzu/configuration/configure_cpu_debug.h
@@ -6,7 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9#include "core/settings.h" 9#include "common/settings.h"
10 10
11namespace Ui { 11namespace Ui {
12class ConfigureCpuDebug; 12class ConfigureCpuDebug;
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 121873f95..6730eb356 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -7,8 +7,8 @@
7#include "common/file_util.h" 7#include "common/file_util.h"
8#include "common/logging/backend.h" 8#include "common/logging/backend.h"
9#include "common/logging/filter.h" 9#include "common/logging/filter.h"
10#include "common/settings.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/settings.h"
12#include "ui_configure_debug.h" 12#include "ui_configure_debug.h"
13#include "yuzu/configuration/configure_debug.h" 13#include "yuzu/configuration/configure_debug.h"
14#include "yuzu/debugger/console.h" 14#include "yuzu/debugger/console.h"
@@ -34,6 +34,8 @@ void ConfigureDebug::SetConfiguration() {
34 ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); 34 ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
35 ui->reporting_services->setChecked(Settings::values.reporting_services); 35 ui->reporting_services->setChecked(Settings::values.reporting_services);
36 ui->quest_flag->setChecked(Settings::values.quest_flag); 36 ui->quest_flag->setChecked(Settings::values.quest_flag);
37 ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts);
38 ui->use_auto_stub->setChecked(Settings::values.use_auto_stub);
37 ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 39 ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn());
38 ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); 40 ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug);
39 ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 41 ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
@@ -47,13 +49,15 @@ void ConfigureDebug::ApplyConfiguration() {
47 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); 49 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
48 Settings::values.reporting_services = ui->reporting_services->isChecked(); 50 Settings::values.reporting_services = ui->reporting_services->isChecked();
49 Settings::values.quest_flag = ui->quest_flag->isChecked(); 51 Settings::values.quest_flag = ui->quest_flag->isChecked();
52 Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
53 Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
50 Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); 54 Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
51 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); 55 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
52 Settings::values.extended_logging = ui->extended_logging->isChecked(); 56 Settings::values.extended_logging = ui->extended_logging->isChecked();
53 Debugger::ToggleConsole(); 57 Debugger::ToggleConsole();
54 Log::Filter filter; 58 Common::Log::Filter filter;
55 filter.ParseFilterString(Settings::values.log_filter); 59 filter.ParseFilterString(Settings::values.log_filter);
56 Log::SetGlobalFilter(filter); 60 Common::Log::SetGlobalFilter(filter);
57} 61}
58 62
59void ConfigureDebug::changeEvent(QEvent* event) { 63void ConfigureDebug::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 9186aa732..d812858b6 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -185,6 +185,35 @@
185 </property> 185 </property>
186 </widget> 186 </widget>
187 </item> 187 </item>
188 <item>
189 <widget class="QCheckBox" name="use_debug_asserts">
190 <property name="text">
191 <string>Enable Debug Asserts</string>
192 </property>
193 </widget>
194 </item>
195 <item>
196 <widget class="QCheckBox" name="use_auto_stub">
197 <property name="text">
198 <string>Enable Auto-Stub</string>
199 </property>
200 </widget>
201 </item>
202 <item>
203 <widget class="QLabel" name="label_3">
204 <property name="font">
205 <font>
206 <italic>true</italic>
207 </font>
208 </property>
209 <property name="text">
210 <string>This will be reset automatically when yuzu closes.</string>
211 </property>
212 <property name="indent">
213 <number>20</number>
214 </property>
215 </widget>
216 </item>
188 </layout> 217 </layout>
189 </widget> 218 </widget>
190 </item> 219 </item>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index d6b17a28d..3ad40d2b3 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -5,8 +5,8 @@
5#include <QHash> 5#include <QHash>
6#include <QListWidgetItem> 6#include <QListWidgetItem>
7#include <QSignalBlocker> 7#include <QSignalBlocker>
8#include "common/settings.h"
8#include "core/core.h" 9#include "core/core.h"
9#include "core/settings.h"
10#include "ui_configure.h" 10#include "ui_configure.h"
11#include "yuzu/configuration/config.h" 11#include "yuzu/configuration/config.h"
12#include "yuzu/configuration/configure_dialog.h" 12#include "yuzu/configuration/configure_dialog.h"
@@ -55,7 +55,7 @@ void ConfigureDialog::ApplyConfiguration() {
55 ui->debugTab->ApplyConfiguration(); 55 ui->debugTab->ApplyConfiguration();
56 ui->webTab->ApplyConfiguration(); 56 ui->webTab->ApplyConfiguration();
57 ui->serviceTab->ApplyConfiguration(); 57 ui->serviceTab->ApplyConfiguration();
58 Settings::Apply(Core::System::GetInstance()); 58 Core::System::GetInstance().ApplySettings();
59 Settings::LogSettings(); 59 Settings::LogSettings();
60} 60}
61 61
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp
index 58f644af4..006eda4b0 100644
--- a/src/yuzu/configuration/configure_filesystem.cpp
+++ b/src/yuzu/configuration/configure_filesystem.cpp
@@ -6,7 +6,7 @@
6#include <QMessageBox> 6#include <QMessageBox>
7#include "common/common_paths.h" 7#include "common/common_paths.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "core/settings.h" 9#include "common/settings.h"
10#include "ui_configure_filesystem.h" 10#include "ui_configure_filesystem.h"
11#include "yuzu/configuration/configure_filesystem.h" 11#include "yuzu/configuration/configure_filesystem.h"
12#include "yuzu/uisettings.h" 12#include "yuzu/uisettings.h"
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index d4d29d422..2fa88dcec 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -4,8 +4,8 @@
4 4
5#include <QCheckBox> 5#include <QCheckBox>
6#include <QSpinBox> 6#include <QSpinBox>
7#include "common/settings.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/settings.h"
9#include "ui_configure_general.h" 9#include "ui_configure_general.h"
10#include "yuzu/configuration/configuration_shared.h" 10#include "yuzu/configuration/configuration_shared.h"
11#include "yuzu/configuration/configure_general.h" 11#include "yuzu/configuration/configure_general.h"
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 9ff32aec4..0a7536617 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -11,8 +11,8 @@
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/settings.h"
14#include "core/core.h" 15#include "core/core.h"
15#include "core/settings.h"
16#include "ui_configure_graphics.h" 16#include "ui_configure_graphics.h"
17#include "video_core/vulkan_common/vulkan_instance.h" 17#include "video_core/vulkan_common/vulkan_instance.h"
18#include "video_core/vulkan_common/vulkan_library.h" 18#include "video_core/vulkan_common/vulkan_library.h"
@@ -77,18 +77,25 @@ void ConfigureGraphics::SetConfiguration() {
77 77
78 if (Settings::IsConfiguringGlobal()) { 78 if (Settings::IsConfiguringGlobal()) {
79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); 79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
80 ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue());
80 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); 81 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
81 } else { 82 } else {
82 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); 83 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
83 ConfigurationShared::SetHighlight(ui->api_layout, 84 ConfigurationShared::SetHighlight(ui->api_layout,
84 !Settings::values.renderer_backend.UsingGlobal()); 85 !Settings::values.renderer_backend.UsingGlobal());
86
87 ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox,
88 &Settings::values.fullscreen_mode);
89 ConfigurationShared::SetHighlight(ui->fullscreen_mode_label,
90 !Settings::values.fullscreen_mode.UsingGlobal());
91
85 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, 92 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
86 &Settings::values.aspect_ratio); 93 &Settings::values.aspect_ratio);
94 ConfigurationShared::SetHighlight(ui->ar_label,
95 !Settings::values.aspect_ratio.UsingGlobal());
87 96
88 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); 97 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
89 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); 98 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
90 ConfigurationShared::SetHighlight(ui->ar_label,
91 !Settings::values.aspect_ratio.UsingGlobal());
92 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); 99 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal());
93 } 100 }
94 101
@@ -107,6 +114,9 @@ void ConfigureGraphics::ApplyConfiguration() {
107 if (Settings::values.vulkan_device.UsingGlobal()) { 114 if (Settings::values.vulkan_device.UsingGlobal()) {
108 Settings::values.vulkan_device.SetValue(vulkan_device); 115 Settings::values.vulkan_device.SetValue(vulkan_device);
109 } 116 }
117 if (Settings::values.fullscreen_mode.UsingGlobal()) {
118 Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex());
119 }
110 if (Settings::values.aspect_ratio.UsingGlobal()) { 120 if (Settings::values.aspect_ratio.UsingGlobal()) {
111 Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); 121 Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex());
112 } 122 }
@@ -140,6 +150,8 @@ void ConfigureGraphics::ApplyConfiguration() {
140 } 150 }
141 } 151 }
142 152
153 ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode,
154 ui->fullscreen_mode_combobox);
143 ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, 155 ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
144 ui->aspect_ratio_combobox); 156 ui->aspect_ratio_combobox);
145 157
@@ -227,7 +239,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {
227 vulkan_devices.clear(); 239 vulkan_devices.clear();
228 vulkan_devices.reserve(physical_devices.size()); 240 vulkan_devices.reserve(physical_devices.size());
229 for (const VkPhysicalDevice device : physical_devices) { 241 for (const VkPhysicalDevice device : physical_devices) {
230 const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; 242 const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
231 vulkan_devices.push_back(QString::fromStdString(name)); 243 vulkan_devices.push_back(QString::fromStdString(name));
232 } 244 }
233 245
@@ -253,6 +265,7 @@ void ConfigureGraphics::SetupPerGameUI() {
253 if (Settings::IsConfiguringGlobal()) { 265 if (Settings::IsConfiguringGlobal()) {
254 ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); 266 ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal());
255 ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal()); 267 ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal());
268 ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal());
256 ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); 269 ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal());
257 ui->use_asynchronous_gpu_emulation->setEnabled( 270 ui->use_asynchronous_gpu_emulation->setEnabled(
258 Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); 271 Settings::values.use_asynchronous_gpu_emulation.UsingGlobal());
@@ -278,6 +291,8 @@ void ConfigureGraphics::SetupPerGameUI() {
278 291
279 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, 292 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label,
280 Settings::values.aspect_ratio.GetValue(true)); 293 Settings::values.aspect_ratio.GetValue(true));
294 ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label,
295 Settings::values.fullscreen_mode.GetValue(true));
281 ConfigurationShared::InsertGlobalItem( 296 ConfigurationShared::InsertGlobalItem(
282 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); 297 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
283} 298}
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 1fefc88eb..c162048a2 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -8,7 +8,7 @@
8#include <vector> 8#include <vector>
9#include <QString> 9#include <QString>
10#include <QWidget> 10#include <QWidget>
11#include "core/settings.h" 11#include "common/settings.h"
12 12
13namespace ConfigurationShared { 13namespace ConfigurationShared {
14enum class CheckState; 14enum class CheckState;
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 58486eb1e..ab0bd4d77 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -105,8 +105,47 @@
105 </widget> 105 </widget>
106 </item> 106 </item>
107 <item> 107 <item>
108 <widget class="QWidget" name="fullscreen_mode_layout" native="true">
109 <layout class="QHBoxLayout" name="horizontalLayout_1">
110 <property name="leftMargin">
111 <number>0</number>
112 </property>
113 <property name="topMargin">
114 <number>0</number>
115 </property>
116 <property name="rightMargin">
117 <number>0</number>
118 </property>
119 <property name="bottomMargin">
120 <number>0</number>
121 </property>
122 <item>
123 <widget class="QLabel" name="fullscreen_mode_label">
124 <property name="text">
125 <string>Fullscreen Mode:</string>
126 </property>
127 </widget>
128 </item>
129 <item>
130 <widget class="QComboBox" name="fullscreen_mode_combobox">
131 <item>
132 <property name="text">
133 <string>Borderless Windowed</string>
134 </property>
135 </item>
136 <item>
137 <property name="text">
138 <string>Exclusive Fullscreen</string>
139 </property>
140 </item>
141 </widget>
142 </item>
143 </layout>
144 </widget>
145 </item>
146 <item>
108 <widget class="QWidget" name="aspect_ratio_layout" native="true"> 147 <widget class="QWidget" name="aspect_ratio_layout" native="true">
109 <layout class="QHBoxLayout" name="horizontalLayout_6"> 148 <layout class="QHBoxLayout" name="horizontalLayout_2">
110 <property name="leftMargin"> 149 <property name="leftMargin">
111 <number>0</number> 150 <number>0</number>
112 </property> 151 </property>
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 383c7bac8..c67609b0e 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
5#include "core/core.h" 6#include "core/core.h"
6#include "core/settings.h"
7#include "ui_configure_graphics_advanced.h" 7#include "ui_configure_graphics_advanced.h"
8#include "yuzu/configuration/configuration_shared.h" 8#include "yuzu/configuration/configuration_shared.h"
9#include "yuzu/configuration/configure_graphics_advanced.h" 9#include "yuzu/configuration/configure_graphics_advanced.h"
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index cbee51a5e..ed76fe18e 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -5,7 +5,7 @@
5#include <QMenu> 5#include <QMenu>
6#include <QMessageBox> 6#include <QMessageBox>
7#include <QStandardItemModel> 7#include <QStandardItemModel>
8#include "core/settings.h" 8#include "common/settings.h"
9#include "ui_configure_hotkeys.h" 9#include "ui_configure_hotkeys.h"
10#include "yuzu/configuration/config.h" 10#include "yuzu/configuration/config.h"
11#include "yuzu/configuration/configure_hotkeys.h" 11#include "yuzu/configuration/configure_hotkeys.h"
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index a1a0eb676..d8d3b83dc 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -3,8 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QColorDialog> 5#include <QColorDialog>
6#include "common/settings.h"
6#include "core/core.h" 7#include "core/core.h"
7#include "core/settings.h"
8#include "ui_configure_input_advanced.h" 8#include "ui_configure_input_advanced.h"
9#include "yuzu/configuration/configure_input_advanced.h" 9#include "yuzu/configuration/configure_input_advanced.h"
10 10
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index efe953fbc..c7d101682 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -14,7 +14,7 @@
14#include <QWidget> 14#include <QWidget>
15 15
16#include "common/param_package.h" 16#include "common/param_package.h"
17#include "core/settings.h" 17#include "common/settings.h"
18#include "ui_configure_input.h" 18#include "ui_configure_input.h"
19 19
20class QCheckBox; 20class QCheckBox;
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 91c3343f1..51bb84eb6 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -7,8 +7,8 @@
7#include <array> 7#include <array>
8#include <QFrame> 8#include <QFrame>
9#include <QPointer> 9#include <QPointer>
10#include "common/settings.h"
10#include "core/frontend/input.h" 11#include "core/frontend/input.h"
11#include "core/settings.h"
12 12
13class QLabel; 13class QLabel;
14 14
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index 52fdf7265..6a5d625df 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -14,7 +14,7 @@
14#include <QVBoxLayout> 14#include <QVBoxLayout>
15 15
16#include "common/logging/log.h" 16#include "common/logging/log.h"
17#include "core/settings.h" 17#include "common/settings.h"
18#include "input_common/main.h" 18#include "input_common/main.h"
19#include "input_common/udp/client.h" 19#include "input_common/udp/client.h"
20#include "input_common/udp/udp.h" 20#include "input_common/udp/udp.h"
@@ -23,8 +23,7 @@
23#include "yuzu/configuration/configure_touch_from_button.h" 23#include "yuzu/configuration/configure_touch_from_button.h"
24 24
25CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, 25CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
26 const std::string& host, u16 port, 26 const std::string& host, u16 port)
27 u8 pad_index)
28 : QDialog(parent) { 27 : QDialog(parent) {
29 layout = new QVBoxLayout; 28 layout = new QVBoxLayout;
30 status_label = new QLabel(tr("Communicating with the server...")); 29 status_label = new QLabel(tr("Communicating with the server..."));
@@ -41,7 +40,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
41 40
42 using namespace InputCommon::CemuhookUDP; 41 using namespace InputCommon::CemuhookUDP;
43 job = std::make_unique<CalibrationConfigurationJob>( 42 job = std::make_unique<CalibrationConfigurationJob>(
44 host, port, pad_index, 43 host, port,
45 [this](CalibrationConfigurationJob::Status status) { 44 [this](CalibrationConfigurationJob::Status status) {
46 QString text; 45 QString text;
47 switch (status) { 46 switch (status) {
@@ -217,7 +216,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
217 ui->udp_test->setText(tr("Testing")); 216 ui->udp_test->setText(tr("Testing"));
218 udp_test_in_progress = true; 217 udp_test_in_progress = true;
219 InputCommon::CemuhookUDP::TestCommunication( 218 InputCommon::CemuhookUDP::TestCommunication(
220 ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0, 219 ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),
221 [this] { 220 [this] {
222 LOG_INFO(Frontend, "UDP input test success"); 221 LOG_INFO(Frontend, "UDP input test success");
223 QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); 222 QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
@@ -232,7 +231,7 @@ void ConfigureMotionTouch::OnConfigureTouchCalibration() {
232 ui->touch_calibration_config->setEnabled(false); 231 ui->touch_calibration_config->setEnabled(false);
233 ui->touch_calibration_config->setText(tr("Configuring")); 232 ui->touch_calibration_config->setText(tr("Configuring"));
234 CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), 233 CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(),
235 static_cast<u16>(ui->udp_port->text().toUInt()), 0); 234 static_cast<u16>(ui->udp_port->text().toUInt()));
236 dialog.exec(); 235 dialog.exec();
237 if (dialog.completed) { 236 if (dialog.completed) {
238 min_x = dialog.min_x; 237 min_x = dialog.min_x;
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h
index d76bc8154..8b707d2ff 100644
--- a/src/yuzu/configuration/configure_motion_touch.h
+++ b/src/yuzu/configuration/configure_motion_touch.h
@@ -29,8 +29,7 @@ class ConfigureMotionTouch;
29class CalibrationConfigurationDialog : public QDialog { 29class CalibrationConfigurationDialog : public QDialog {
30 Q_OBJECT 30 Q_OBJECT
31public: 31public:
32 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port, 32 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port);
33 u8 pad_index);
34 ~CalibrationConfigurationDialog() override; 33 ~CalibrationConfigurationDialog() override;
35 34
36private: 35private:
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index f598513df..bd91ebc42 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -57,7 +57,7 @@ void ConfigurePerGame::ApplyConfiguration() {
57 ui->graphicsAdvancedTab->ApplyConfiguration(); 57 ui->graphicsAdvancedTab->ApplyConfiguration();
58 ui->audioTab->ApplyConfiguration(); 58 ui->audioTab->ApplyConfiguration();
59 59
60 Settings::Apply(Core::System::GetInstance()); 60 Core::System::GetInstance().ApplySettings();
61 Settings::LogSettings(); 61 Settings::LogSettings();
62 62
63 game_config->Save(); 63 game_config->Save();
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 51647a028..d61b5e29b 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -13,10 +13,10 @@
13#include <QVBoxLayout> 13#include <QVBoxLayout>
14#include "common/assert.h" 14#include "common/assert.h"
15#include "common/file_util.h" 15#include "common/file_util.h"
16#include "common/settings.h"
16#include "common/string_util.h" 17#include "common/string_util.h"
17#include "core/core.h" 18#include "core/core.h"
18#include "core/hle/service/acc/profile_manager.h" 19#include "core/hle/service/acc/profile_manager.h"
19#include "core/settings.h"
20#include "ui_configure_profile_manager.h" 20#include "ui_configure_profile_manager.h"
21#include "yuzu/configuration/configure_profile_manager.h" 21#include "yuzu/configuration/configure_profile_manager.h"
22#include "yuzu/util/limitable_input_dialog.h" 22#include "yuzu/util/limitable_input_dialog.h"
@@ -180,7 +180,7 @@ void ConfigureProfileManager::ApplyConfiguration() {
180 return; 180 return;
181 } 181 }
182 182
183 Settings::Apply(Core::System::GetInstance()); 183 Core::System::GetInstance().ApplySettings();
184} 184}
185 185
186void ConfigureProfileManager::SelectUser(const QModelIndex& index) { 186void ConfigureProfileManager::SelectUser(const QModelIndex& index) {
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp
index b580cfff2..6d954a67f 100644
--- a/src/yuzu/configuration/configure_service.cpp
+++ b/src/yuzu/configuration/configure_service.cpp
@@ -4,8 +4,8 @@
4 4
5#include <QGraphicsItem> 5#include <QGraphicsItem>
6#include <QtConcurrent/QtConcurrent> 6#include <QtConcurrent/QtConcurrent>
7#include "common/settings.h"
7#include "core/hle/service/bcat/backend/boxcat.h" 8#include "core/hle/service/bcat/backend/boxcat.h"
8#include "core/settings.h"
9#include "ui_configure_service.h" 9#include "ui_configure_service.h"
10#include "yuzu/configuration/configure_service.h" 10#include "yuzu/configuration/configure_service.h"
11 11
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 6cf2032da..268ed44c3 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -11,9 +11,9 @@
11#include <QMessageBox> 11#include <QMessageBox>
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/file_util.h" 13#include "common/file_util.h"
14#include "common/settings.h"
14#include "core/core.h" 15#include "core/core.h"
15#include "core/hle/service/time/time.h" 16#include "core/hle/service/time/time.h"
16#include "core/settings.h"
17#include "ui_configure_system.h" 17#include "ui_configure_system.h"
18#include "yuzu/configuration/configuration_shared.h" 18#include "yuzu/configuration/configuration_shared.h"
19#include "yuzu/configuration/configure_system.h" 19#include "yuzu/configuration/configure_system.h"
@@ -199,7 +199,7 @@ void ConfigureSystem::ApplyConfiguration() {
199 } 199 }
200 } 200 }
201 201
202 Settings::Apply(system); 202 system.ApplySettings();
203} 203}
204 204
205void ConfigureSystem::RefreshConsoleID() { 205void ConfigureSystem::RefreshConsoleID() {
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index 15557e4b8..40129f228 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -10,8 +10,8 @@
10#include <QStandardItemModel> 10#include <QStandardItemModel>
11#include <QTimer> 11#include <QTimer>
12#include "common/param_package.h" 12#include "common/param_package.h"
13#include "common/settings.h"
13#include "core/frontend/framebuffer_layout.h" 14#include "core/frontend/framebuffer_layout.h"
14#include "core/settings.h"
15#include "input_common/main.h" 15#include "input_common/main.h"
16#include "ui_configure_touch_from_button.h" 16#include "ui_configure_touch_from_button.h"
17#include "yuzu/configuration/configure_touch_from_button.h" 17#include "yuzu/configuration/configure_touch_from_button.h"
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index aed876008..f35c89e04 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -9,8 +9,8 @@
9#include <QDirIterator> 9#include <QDirIterator>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/file_util.h" 11#include "common/file_util.h"
12#include "common/settings.h"
12#include "core/core.h" 13#include "core/core.h"
13#include "core/settings.h"
14#include "ui_configure_ui.h" 14#include "ui_configure_ui.h"
15#include "yuzu/configuration/configure_ui.h" 15#include "yuzu/configuration/configure_ui.h"
16#include "yuzu/uisettings.h" 16#include "yuzu/uisettings.h"
@@ -85,7 +85,7 @@ void ConfigureUi::ApplyConfiguration() {
85 UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); 85 UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked();
86 Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, 86 Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir,
87 ui->screenshot_path_edit->text().toStdString()); 87 ui->screenshot_path_edit->text().toStdString());
88 Settings::Apply(Core::System::GetInstance()); 88 Core::System::GetInstance().ApplySettings();
89} 89}
90 90
91void ConfigureUi::RequestGameListUpdate() { 91void ConfigureUi::RequestGameListUpdate() {
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index 7dcb2c5b9..9d92c4949 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -8,7 +8,7 @@
8#include <fmt/format.h> 8#include <fmt/format.h>
9 9
10#include "common/param_package.h" 10#include "common/param_package.h"
11#include "core/settings.h" 11#include "common/settings.h"
12#include "ui_configure_vibration.h" 12#include "ui_configure_vibration.h"
13#include "yuzu/configuration/configure_vibration.h" 13#include "yuzu/configuration/configure_vibration.h"
14 14
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 8637f5b3c..f3f3b54d6 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -5,7 +5,7 @@
5#include <QIcon> 5#include <QIcon>
6#include <QMessageBox> 6#include <QMessageBox>
7#include <QtConcurrent/QtConcurrentRun> 7#include <QtConcurrent/QtConcurrentRun>
8#include "core/settings.h" 8#include "common/settings.h"
9#include "core/telemetry_session.h" 9#include "core/telemetry_session.h"
10#include "ui_configure_web.h" 10#include "ui_configure_web.h"
11#include "yuzu/configuration/configure_web.h" 11#include "yuzu/configuration/configure_web.h"
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp
index 207ff4d58..c11a326ac 100644
--- a/src/yuzu/debugger/console.cpp
+++ b/src/yuzu/debugger/console.cpp
@@ -29,13 +29,13 @@ void ToggleConsole() {
29 freopen_s(&temp, "CONIN$", "r", stdin); 29 freopen_s(&temp, "CONIN$", "r", stdin);
30 freopen_s(&temp, "CONOUT$", "w", stdout); 30 freopen_s(&temp, "CONOUT$", "w", stdout);
31 freopen_s(&temp, "CONOUT$", "w", stderr); 31 freopen_s(&temp, "CONOUT$", "w", stderr);
32 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); 32 Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
33 } 33 }
34 } else { 34 } else {
35 if (FreeConsole()) { 35 if (FreeConsole()) {
36 // In order to close the console, we have to also detach the streams on it. 36 // In order to close the console, we have to also detach the streams on it.
37 // Just redirect them to NUL if there is no console window 37 // Just redirect them to NUL if there is no console window
38 Log::RemoveBackend(Log::ColorConsoleBackend::Name()); 38 Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
39 freopen_s(&temp, "NUL", "r", stdin); 39 freopen_s(&temp, "NUL", "r", stdin);
40 freopen_s(&temp, "NUL", "w", stdout); 40 freopen_s(&temp, "NUL", "w", stdout);
41 freopen_s(&temp, "NUL", "w", stderr); 41 freopen_s(&temp, "NUL", "w", stderr);
@@ -43,9 +43,9 @@ void ToggleConsole() {
43 } 43 }
44#else 44#else
45 if (UISettings::values.show_console) { 45 if (UISettings::values.show_console) {
46 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); 46 Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
47 } else { 47 } else {
48 Log::RemoveBackend(Log::ColorConsoleBackend::Name()); 48 Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
49 } 49 }
50#endif 50#endif
51} 51}
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 2731d948d..7186eac76 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -5,7 +5,7 @@
5#include <QAction> 5#include <QAction>
6#include <QLayout> 6#include <QLayout>
7#include <QString> 7#include <QString>
8#include "core/settings.h" 8#include "common/settings.h"
9#include "yuzu/configuration/configure_input_player_widget.h" 9#include "yuzu/configuration/configure_input_player_widget.h"
10#include "yuzu/debugger/controller.h" 10#include "yuzu/debugger/controller.h"
11 11
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 24bfa4d34..5f6cdc0c6 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -79,6 +79,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
79#ifdef ARCHITECTURE_x86_64 79#ifdef ARCHITECTURE_x86_64
80#include "common/x64/cpu_detect.h" 80#include "common/x64/cpu_detect.h"
81#endif 81#endif
82#include "common/settings.h"
82#include "common/telemetry.h" 83#include "common/telemetry.h"
83#include "core/core.h" 84#include "core/core.h"
84#include "core/crypto/key_manager.h" 85#include "core/crypto/key_manager.h"
@@ -98,9 +99,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
98#include "core/hle/service/sm/sm.h" 99#include "core/hle/service/sm/sm.h"
99#include "core/loader/loader.h" 100#include "core/loader/loader.h"
100#include "core/perf_stats.h" 101#include "core/perf_stats.h"
101#include "core/settings.h"
102#include "core/telemetry_session.h" 102#include "core/telemetry_session.h"
103#include "input_common/main.h" 103#include "input_common/main.h"
104#include "util/overlay_dialog.h"
104#include "video_core/gpu.h" 105#include "video_core/gpu.h"
105#include "video_core/shader_notify.h" 106#include "video_core/shader_notify.h"
106#include "yuzu/about_dialog.h" 107#include "yuzu/about_dialog.h"
@@ -164,19 +165,21 @@ void GMainWindow::ShowTelemetryCallout() {
164 "<br/><br/>Would you like to share your usage data with us?"); 165 "<br/><br/>Would you like to share your usage data with us?");
165 if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { 166 if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) {
166 Settings::values.enable_telemetry = false; 167 Settings::values.enable_telemetry = false;
167 Settings::Apply(Core::System::GetInstance()); 168 Core::System::GetInstance().ApplySettings();
168 } 169 }
169} 170}
170 171
171const int GMainWindow::max_recent_files_item; 172const int GMainWindow::max_recent_files_item;
172 173
173static void InitializeLogging() { 174static void InitializeLogging() {
175 using namespace Common;
176
174 Log::Filter log_filter; 177 Log::Filter log_filter;
175 log_filter.ParseFilterString(Settings::values.log_filter); 178 log_filter.ParseFilterString(Settings::values.log_filter);
176 Log::SetGlobalFilter(log_filter); 179 Log::SetGlobalFilter(log_filter);
177 180
178 const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); 181 const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir);
179 Common::FS::CreateFullPath(log_dir); 182 FS::CreateFullPath(log_dir);
180 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); 183 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
181#ifdef _WIN32 184#ifdef _WIN32
182 Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); 185 Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
@@ -225,6 +228,8 @@ GMainWindow::GMainWindow()
225 SetDiscordEnabled(UISettings::values.enable_discord_presence); 228 SetDiscordEnabled(UISettings::values.enable_discord_presence);
226 discord_rpc->Update(); 229 discord_rpc->Update();
227 230
231 RegisterMetaTypes();
232
228 InitializeWidgets(); 233 InitializeWidgets();
229 InitializeDebugWidgets(); 234 InitializeDebugWidgets();
230 InitializeRecentFileMenuActions(); 235 InitializeRecentFileMenuActions();
@@ -320,6 +325,34 @@ GMainWindow::GMainWindow()
320 continue; 325 continue;
321 } 326 }
322 327
328 // Launch game with a specific user
329 if (args[i] == QStringLiteral("-u")) {
330 if (i >= args.size() - 1) {
331 continue;
332 }
333
334 if (args[i + 1].startsWith(QChar::fromLatin1('-'))) {
335 continue;
336 }
337
338 bool argument_ok;
339 const std::size_t selected_user = args[++i].toUInt(&argument_ok);
340
341 if (!argument_ok) {
342 LOG_ERROR(Frontend, "Invalid user argument");
343 continue;
344 }
345
346 const Service::Account::ProfileManager manager;
347 if (!manager.UserExistsIndex(selected_user)) {
348 LOG_ERROR(Frontend, "Selected user doesn't exist");
349 continue;
350 }
351
352 Settings::values.current_user = selected_user;
353 continue;
354 }
355
323 // Launch game at path 356 // Launch game at path
324 if (args[i] == QStringLiteral("-g")) { 357 if (args[i] == QStringLiteral("-g")) {
325 if (i >= args.size() - 1) { 358 if (i >= args.size() - 1) {
@@ -345,6 +378,55 @@ GMainWindow::~GMainWindow() {
345 delete render_window; 378 delete render_window;
346} 379}
347 380
381void GMainWindow::RegisterMetaTypes() {
382 // Register integral and floating point types
383 qRegisterMetaType<u8>("u8");
384 qRegisterMetaType<u16>("u16");
385 qRegisterMetaType<u32>("u32");
386 qRegisterMetaType<u64>("u64");
387 qRegisterMetaType<u128>("u128");
388 qRegisterMetaType<s8>("s8");
389 qRegisterMetaType<s16>("s16");
390 qRegisterMetaType<s32>("s32");
391 qRegisterMetaType<s64>("s64");
392 qRegisterMetaType<f32>("f32");
393 qRegisterMetaType<f64>("f64");
394
395 // Register string types
396 qRegisterMetaType<std::string>("std::string");
397 qRegisterMetaType<std::wstring>("std::wstring");
398 qRegisterMetaType<std::u8string>("std::u8string");
399 qRegisterMetaType<std::u16string>("std::u16string");
400 qRegisterMetaType<std::u32string>("std::u32string");
401 qRegisterMetaType<std::string_view>("std::string_view");
402 qRegisterMetaType<std::wstring_view>("std::wstring_view");
403 qRegisterMetaType<std::u8string_view>("std::u8string_view");
404 qRegisterMetaType<std::u16string_view>("std::u16string_view");
405 qRegisterMetaType<std::u32string_view>("std::u32string_view");
406
407 // Register applet types
408
409 // Controller Applet
410 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
411
412 // Software Keyboard Applet
413 qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
414 "Core::Frontend::KeyboardInitializeParameters");
415 qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
416 "Core::Frontend::InlineAppearParameters");
417 qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
418 qRegisterMetaType<Service::AM::Applets::SwkbdResult>("Service::AM::Applets::SwkbdResult");
419 qRegisterMetaType<Service::AM::Applets::SwkbdTextCheckResult>(
420 "Service::AM::Applets::SwkbdTextCheckResult");
421 qRegisterMetaType<Service::AM::Applets::SwkbdReplyType>("Service::AM::Applets::SwkbdReplyType");
422
423 // Web Browser Applet
424 qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
425
426 // Register loader types
427 qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
428}
429
348void GMainWindow::ControllerSelectorReconfigureControllers( 430void GMainWindow::ControllerSelectorReconfigureControllers(
349 const Core::Frontend::ControllerParameters& parameters) { 431 const Core::Frontend::ControllerParameters& parameters) {
350 QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); 432 QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
@@ -357,7 +439,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
357 emit ControllerSelectorReconfigureFinished(); 439 emit ControllerSelectorReconfigureFinished();
358 440
359 // Don't forget to apply settings. 441 // Don't forget to apply settings.
360 Settings::Apply(Core::System::GetInstance()); 442 Core::System::GetInstance().ApplySettings();
361 config->Save(); 443 config->Save();
362 444
363 UpdateStatusButtons(); 445 UpdateStatusButtons();
@@ -384,25 +466,112 @@ void GMainWindow::ProfileSelectorSelectProfile() {
384 emit ProfileSelectorFinishedSelection(uuid); 466 emit ProfileSelectorFinishedSelection(uuid);
385} 467}
386 468
387void GMainWindow::SoftwareKeyboardGetText( 469void GMainWindow::SoftwareKeyboardInitialize(
388 const Core::Frontend::SoftwareKeyboardParameters& parameters) { 470 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
389 QtSoftwareKeyboardDialog dialog(this, parameters); 471 if (software_keyboard) {
390 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | 472 LOG_ERROR(Frontend, "The software keyboard is already initialized!");
391 Qt::WindowTitleHint | Qt::WindowSystemMenuHint | 473 return;
392 Qt::WindowCloseButtonHint); 474 }
393 dialog.setWindowModality(Qt::WindowModal);
394 475
395 if (dialog.exec() == QDialog::Rejected) { 476 software_keyboard = new QtSoftwareKeyboardDialog(render_window, Core::System::GetInstance(),
396 emit SoftwareKeyboardFinishedText(std::nullopt); 477 is_inline, std::move(initialize_parameters));
478
479 if (is_inline) {
480 connect(
481 software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this,
482 [this](Service::AM::Applets::SwkbdReplyType reply_type, std::u16string submitted_text,
483 s32 cursor_position) {
484 emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position);
485 },
486 Qt::QueuedConnection);
487 } else {
488 connect(
489 software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this,
490 [this](Service::AM::Applets::SwkbdResult result, std::u16string submitted_text) {
491 emit SoftwareKeyboardSubmitNormalText(result, submitted_text);
492 },
493 Qt::QueuedConnection);
494 }
495}
496
497void GMainWindow::SoftwareKeyboardShowNormal() {
498 if (!software_keyboard) {
499 LOG_ERROR(Frontend, "The software keyboard is not initialized!");
500 return;
501 }
502
503 const auto& layout = render_window->GetFramebufferLayout();
504
505 const auto x = layout.screen.left;
506 const auto y = layout.screen.top;
507 const auto w = layout.screen.GetWidth();
508 const auto h = layout.screen.GetHeight();
509
510 software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h));
511}
512
513void GMainWindow::SoftwareKeyboardShowTextCheck(
514 Service::AM::Applets::SwkbdTextCheckResult text_check_result,
515 std::u16string text_check_message) {
516 if (!software_keyboard) {
517 LOG_ERROR(Frontend, "The software keyboard is not initialized!");
397 return; 518 return;
398 } 519 }
399 520
400 emit SoftwareKeyboardFinishedText(dialog.GetText()); 521 software_keyboard->ShowTextCheckDialog(text_check_result, text_check_message);
401} 522}
402 523
403void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { 524void GMainWindow::SoftwareKeyboardShowInline(
404 QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); 525 Core::Frontend::InlineAppearParameters appear_parameters) {
405 emit SoftwareKeyboardFinishedCheckDialog(); 526 if (!software_keyboard) {
527 LOG_ERROR(Frontend, "The software keyboard is not initialized!");
528 return;
529 }
530
531 const auto& layout = render_window->GetFramebufferLayout();
532
533 const auto x =
534 static_cast<int>(layout.screen.left + (0.5f * layout.screen.GetWidth() *
535 ((2.0f * appear_parameters.key_top_translate_x) +
536 (1.0f - appear_parameters.key_top_scale_x))));
537 const auto y =
538 static_cast<int>(layout.screen.top + (layout.screen.GetHeight() *
539 ((2.0f * appear_parameters.key_top_translate_y) +
540 (1.0f - appear_parameters.key_top_scale_y))));
541 const auto w = static_cast<int>(layout.screen.GetWidth() * appear_parameters.key_top_scale_x);
542 const auto h = static_cast<int>(layout.screen.GetHeight() * appear_parameters.key_top_scale_y);
543
544 software_keyboard->ShowInlineKeyboard(std::move(appear_parameters),
545 render_window->mapToGlobal(QPoint(x, y)), QSize(w, h));
546}
547
548void GMainWindow::SoftwareKeyboardHideInline() {
549 if (!software_keyboard) {
550 LOG_ERROR(Frontend, "The software keyboard is not initialized!");
551 return;
552 }
553
554 software_keyboard->HideInlineKeyboard();
555}
556
557void GMainWindow::SoftwareKeyboardInlineTextChanged(
558 Core::Frontend::InlineTextParameters text_parameters) {
559 if (!software_keyboard) {
560 LOG_ERROR(Frontend, "The software keyboard is not initialized!");
561 return;
562 }
563
564 software_keyboard->InlineTextChanged(std::move(text_parameters));
565}
566
567void GMainWindow::SoftwareKeyboardExit() {
568 if (!software_keyboard) {
569 return;
570 }
571
572 software_keyboard->ExitKeyboard();
573
574 software_keyboard = nullptr;
406} 575}
407 576
408void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, 577void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
@@ -622,7 +791,7 @@ void GMainWindow::InitializeWidgets() {
622 Settings::values.use_asynchronous_gpu_emulation.SetValue( 791 Settings::values.use_asynchronous_gpu_emulation.SetValue(
623 !Settings::values.use_asynchronous_gpu_emulation.GetValue()); 792 !Settings::values.use_asynchronous_gpu_emulation.GetValue());
624 async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); 793 async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue());
625 Settings::Apply(Core::System::GetInstance()); 794 Core::System::GetInstance().ApplySettings();
626 }); 795 });
627 async_status_button->setText(tr("ASYNC")); 796 async_status_button->setText(tr("ASYNC"));
628 async_status_button->setCheckable(true); 797 async_status_button->setCheckable(true);
@@ -638,7 +807,7 @@ void GMainWindow::InitializeWidgets() {
638 } 807 }
639 Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); 808 Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue());
640 multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); 809 multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue());
641 Settings::Apply(Core::System::GetInstance()); 810 Core::System::GetInstance().ApplySettings();
642 }); 811 });
643 multicore_status_button->setText(tr("MULTICORE")); 812 multicore_status_button->setText(tr("MULTICORE"));
644 multicore_status_button->setCheckable(true); 813 multicore_status_button->setCheckable(true);
@@ -669,7 +838,7 @@ void GMainWindow::InitializeWidgets() {
669 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); 838 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL);
670 } 839 }
671 840
672 Settings::Apply(Core::System::GetInstance()); 841 Core::System::GetInstance().ApplySettings();
673 }); 842 });
674 statusBar()->insertPermanentWidget(0, renderer_status_button); 843 statusBar()->insertPermanentWidget(0, renderer_status_button);
675 844
@@ -948,6 +1117,10 @@ void GMainWindow::ConnectWidgetEvents() {
948 connect(this, &GMainWindow::EmulationStopping, render_window, 1117 connect(this, &GMainWindow::EmulationStopping, render_window,
949 &GRenderWindow::OnEmulationStopping); 1118 &GRenderWindow::OnEmulationStopping);
950 1119
1120 // Software Keyboard Applet
1121 connect(this, &GMainWindow::EmulationStarting, this, &GMainWindow::SoftwareKeyboardExit);
1122 connect(this, &GMainWindow::EmulationStopping, this, &GMainWindow::SoftwareKeyboardExit);
1123
951 connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar); 1124 connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
952} 1125}
953 1126
@@ -2157,15 +2330,6 @@ void GMainWindow::OnStartGame() {
2157 2330
2158 emu_thread->SetRunning(true); 2331 emu_thread->SetRunning(true);
2159 2332
2160 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
2161 qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>(
2162 "Core::Frontend::SoftwareKeyboardParameters");
2163 qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
2164 qRegisterMetaType<std::string>("std::string");
2165 qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>");
2166 qRegisterMetaType<std::string_view>("std::string_view");
2167 qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
2168
2169 connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); 2333 connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
2170 2334
2171 ui.action_Start->setEnabled(false); 2335 ui.action_Start->setEnabled(false);
@@ -2214,8 +2378,11 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
2214 BootGame(last_filename_booted, program_index); 2378 BootGame(last_filename_booted, program_index);
2215} 2379}
2216 2380
2217void GMainWindow::ErrorDisplayDisplayError(QString body) { 2381void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
2218 QMessageBox::critical(this, tr("Error Display"), body); 2382 OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
2383 QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
2384 dialog.exec();
2385
2219 emit ErrorDisplayFinished(); 2386 emit ErrorDisplayFinished();
2220} 2387}
2221 2388
@@ -2267,24 +2434,66 @@ void GMainWindow::ToggleFullscreen() {
2267void GMainWindow::ShowFullscreen() { 2434void GMainWindow::ShowFullscreen() {
2268 if (ui.action_Single_Window_Mode->isChecked()) { 2435 if (ui.action_Single_Window_Mode->isChecked()) {
2269 UISettings::values.geometry = saveGeometry(); 2436 UISettings::values.geometry = saveGeometry();
2437
2270 ui.menubar->hide(); 2438 ui.menubar->hide();
2271 statusBar()->hide(); 2439 statusBar()->hide();
2272 showFullScreen(); 2440
2441 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2442 showFullScreen();
2443 return;
2444 }
2445
2446 hide();
2447 setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2448 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2449 setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2450 screen_geometry.height() + 1);
2451 raise();
2452 showNormal();
2273 } else { 2453 } else {
2274 UISettings::values.renderwindow_geometry = render_window->saveGeometry(); 2454 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
2275 render_window->showFullScreen(); 2455
2456 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2457 render_window->showFullScreen();
2458 return;
2459 }
2460
2461 render_window->hide();
2462 render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2463 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2464 render_window->setGeometry(screen_geometry.x(), screen_geometry.y(),
2465 screen_geometry.width(), screen_geometry.height() + 1);
2466 render_window->raise();
2467 render_window->showNormal();
2276 } 2468 }
2277} 2469}
2278 2470
2279void GMainWindow::HideFullscreen() { 2471void GMainWindow::HideFullscreen() {
2280 if (ui.action_Single_Window_Mode->isChecked()) { 2472 if (ui.action_Single_Window_Mode->isChecked()) {
2473 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2474 showNormal();
2475 restoreGeometry(UISettings::values.geometry);
2476 } else {
2477 hide();
2478 setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
2479 restoreGeometry(UISettings::values.geometry);
2480 raise();
2481 show();
2482 }
2483
2281 statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); 2484 statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked());
2282 ui.menubar->show(); 2485 ui.menubar->show();
2283 showNormal();
2284 restoreGeometry(UISettings::values.geometry);
2285 } else { 2486 } else {
2286 render_window->showNormal(); 2487 if (Settings::values.fullscreen_mode.GetValue() == 1) {
2287 render_window->restoreGeometry(UISettings::values.renderwindow_geometry); 2488 render_window->showNormal();
2489 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
2490 } else {
2491 render_window->hide();
2492 render_window->setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
2493 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
2494 render_window->raise();
2495 render_window->show();
2496 }
2288 } 2497 }
2289} 2498}
2290 2499
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 04d37d4ae..7f1e50a5b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -37,9 +37,13 @@ enum class GameListRemoveTarget;
37enum class InstalledEntryType; 37enum class InstalledEntryType;
38class GameListPlaceholder; 38class GameListPlaceholder;
39 39
40class QtSoftwareKeyboardDialog;
41
40namespace Core::Frontend { 42namespace Core::Frontend {
41struct ControllerParameters; 43struct ControllerParameters;
42struct SoftwareKeyboardParameters; 44struct InlineAppearParameters;
45struct InlineTextParameters;
46struct KeyboardInitializeParameters;
43} // namespace Core::Frontend 47} // namespace Core::Frontend
44 48
45namespace DiscordRPC { 49namespace DiscordRPC {
@@ -57,8 +61,11 @@ class InputSubsystem;
57} 61}
58 62
59namespace Service::AM::Applets { 63namespace Service::AM::Applets {
64enum class SwkbdResult : u32;
65enum class SwkbdTextCheckResult : u32;
66enum class SwkbdReplyType : u32;
60enum class WebExitReason : u32; 67enum class WebExitReason : u32;
61} 68} // namespace Service::AM::Applets
62 69
63enum class EmulatedDirectoryTarget { 70enum class EmulatedDirectoryTarget {
64 NAND, 71 NAND,
@@ -128,8 +135,10 @@ signals:
128 135
129 void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); 136 void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
130 137
131 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); 138 void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result,
132 void SoftwareKeyboardFinishedCheckDialog(); 139 std::u16string submitted_text);
140 void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
141 std::u16string submitted_text, s32 cursor_position);
133 142
134 void WebBrowserExtractOfflineRomFS(); 143 void WebBrowserExtractOfflineRomFS();
135 void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); 144 void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url);
@@ -139,15 +148,24 @@ public slots:
139 void OnExecuteProgram(std::size_t program_index); 148 void OnExecuteProgram(std::size_t program_index);
140 void ControllerSelectorReconfigureControllers( 149 void ControllerSelectorReconfigureControllers(
141 const Core::Frontend::ControllerParameters& parameters); 150 const Core::Frontend::ControllerParameters& parameters);
142 void ErrorDisplayDisplayError(QString body); 151 void SoftwareKeyboardInitialize(
152 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters);
153 void SoftwareKeyboardShowNormal();
154 void SoftwareKeyboardShowTextCheck(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
155 std::u16string text_check_message);
156 void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters);
157 void SoftwareKeyboardHideInline();
158 void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
159 void SoftwareKeyboardExit();
160 void ErrorDisplayDisplayError(QString error_code, QString error_text);
143 void ProfileSelectorSelectProfile(); 161 void ProfileSelectorSelectProfile();
144 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
145 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
146 void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, 162 void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
147 bool is_local); 163 bool is_local);
148 void OnAppFocusStateChanged(Qt::ApplicationState state); 164 void OnAppFocusStateChanged(Qt::ApplicationState state);
149 165
150private: 166private:
167 void RegisterMetaTypes();
168
151 void InitializeWidgets(); 169 void InitializeWidgets();
152 void InitializeDebugWidgets(); 170 void InitializeDebugWidgets();
153 void InitializeRecentFileMenuActions(); 171 void InitializeRecentFileMenuActions();
@@ -334,6 +352,9 @@ private:
334 // Disables the web applet for the rest of the emulated session 352 // Disables the web applet for the rest of the emulated session
335 bool disable_web_applet{}; 353 bool disable_web_applet{};
336 354
355 // Applets
356 QtSoftwareKeyboardDialog* software_keyboard = nullptr;
357
337protected: 358protected:
338 void dropEvent(QDropEvent* event) override; 359 void dropEvent(QDropEvent* event) override;
339 void dragEnterEvent(QDragEnterEvent* event) override; 360 void dragEnterEvent(QDragEnterEvent* event) override;
diff --git a/src/yuzu/util/overlay_dialog.cpp b/src/yuzu/util/overlay_dialog.cpp
new file mode 100644
index 000000000..95b148545
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.cpp
@@ -0,0 +1,249 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QKeyEvent>
6#include <QScreen>
7
8#include "core/core.h"
9#include "core/frontend/input_interpreter.h"
10#include "ui_overlay_dialog.h"
11#include "yuzu/util/overlay_dialog.h"
12
13namespace {
14
15constexpr float BASE_TITLE_FONT_SIZE = 14.0f;
16constexpr float BASE_FONT_SIZE = 18.0f;
17constexpr float BASE_WIDTH = 1280.0f;
18constexpr float BASE_HEIGHT = 720.0f;
19
20} // Anonymous namespace
21
22OverlayDialog::OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
23 const QString& body_text, const QString& left_button_text,
24 const QString& right_button_text, Qt::Alignment alignment,
25 bool use_rich_text_)
26 : QDialog(parent), ui{std::make_unique<Ui::OverlayDialog>()}, use_rich_text{use_rich_text_} {
27 ui->setupUi(this);
28
29 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint |
30 Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint);
31 setWindowModality(Qt::WindowModal);
32 setAttribute(Qt::WA_TranslucentBackground);
33
34 if (use_rich_text) {
35 InitializeRichTextDialog(title_text, body_text, left_button_text, right_button_text,
36 alignment);
37 } else {
38 InitializeRegularTextDialog(title_text, body_text, left_button_text, right_button_text,
39 alignment);
40 }
41
42 MoveAndResizeWindow();
43
44 // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend
45 if (system.IsPoweredOn()) {
46 input_interpreter = std::make_unique<InputInterpreter>(system);
47
48 StartInputThread();
49 }
50}
51
52OverlayDialog::~OverlayDialog() {
53 StopInputThread();
54}
55
56void OverlayDialog::InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
57 const QString& left_button_text,
58 const QString& right_button_text,
59 Qt::Alignment alignment) {
60 ui->stackedDialog->setCurrentIndex(0);
61
62 ui->label_title->setText(title_text);
63 ui->label_dialog->setText(body_text);
64 ui->button_cancel->setText(left_button_text);
65 ui->button_ok_label->setText(right_button_text);
66
67 ui->label_dialog->setAlignment(alignment);
68
69 if (title_text.isEmpty()) {
70 ui->label_title->hide();
71 ui->verticalLayout_2->setStretch(0, 0);
72 ui->verticalLayout_2->setStretch(1, 219);
73 ui->verticalLayout_2->setStretch(2, 82);
74 }
75
76 if (left_button_text.isEmpty()) {
77 ui->button_cancel->hide();
78 ui->button_cancel->setEnabled(false);
79 }
80
81 if (right_button_text.isEmpty()) {
82 ui->button_ok_label->hide();
83 ui->button_ok_label->setEnabled(false);
84 }
85
86 connect(
87 ui->button_cancel, &QPushButton::clicked, this,
88 [this](bool) {
89 StopInputThread();
90 QDialog::reject();
91 },
92 Qt::QueuedConnection);
93 connect(
94 ui->button_ok_label, &QPushButton::clicked, this,
95 [this](bool) {
96 StopInputThread();
97 QDialog::accept();
98 },
99 Qt::QueuedConnection);
100}
101
102void OverlayDialog::InitializeRichTextDialog(const QString& title_text, const QString& body_text,
103 const QString& left_button_text,
104 const QString& right_button_text,
105 Qt::Alignment alignment) {
106 ui->stackedDialog->setCurrentIndex(1);
107
108 ui->label_title_rich->setText(title_text);
109 ui->text_browser_dialog->setText(body_text);
110 ui->button_cancel_rich->setText(left_button_text);
111 ui->button_ok_rich->setText(right_button_text);
112
113 // TODO (Morph/Rei): Replace this with something that works better
114 ui->text_browser_dialog->setAlignment(alignment);
115
116 if (title_text.isEmpty()) {
117 ui->label_title_rich->hide();
118 ui->verticalLayout_3->setStretch(0, 0);
119 ui->verticalLayout_3->setStretch(1, 438);
120 ui->verticalLayout_3->setStretch(2, 82);
121 }
122
123 if (left_button_text.isEmpty()) {
124 ui->button_cancel_rich->hide();
125 ui->button_cancel_rich->setEnabled(false);
126 }
127
128 if (right_button_text.isEmpty()) {
129 ui->button_ok_rich->hide();
130 ui->button_ok_rich->setEnabled(false);
131 }
132
133 connect(
134 ui->button_cancel_rich, &QPushButton::clicked, this,
135 [this](bool) {
136 StopInputThread();
137 QDialog::reject();
138 },
139 Qt::QueuedConnection);
140 connect(
141 ui->button_ok_rich, &QPushButton::clicked, this,
142 [this](bool) {
143 StopInputThread();
144 QDialog::accept();
145 },
146 Qt::QueuedConnection);
147}
148
149void OverlayDialog::MoveAndResizeWindow() {
150 const auto pos = parentWidget()->mapToGlobal(parentWidget()->rect().topLeft());
151 const auto width = static_cast<float>(parentWidget()->width());
152 const auto height = static_cast<float>(parentWidget()->height());
153
154 // High DPI
155 const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f;
156
157 const auto title_text_font_size = BASE_TITLE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
158 const auto body_text_font_size =
159 BASE_FONT_SIZE * (((width / BASE_WIDTH) + (height / BASE_HEIGHT)) / 2.0f) / dpi_scale;
160 const auto button_text_font_size = BASE_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale;
161
162 QFont title_text_font(QStringLiteral("MS Shell Dlg 2"), title_text_font_size, QFont::Normal);
163 QFont body_text_font(QStringLiteral("MS Shell Dlg 2"), body_text_font_size, QFont::Normal);
164 QFont button_text_font(QStringLiteral("MS Shell Dlg 2"), button_text_font_size, QFont::Normal);
165
166 if (use_rich_text) {
167 ui->label_title_rich->setFont(title_text_font);
168 ui->text_browser_dialog->setFont(body_text_font);
169 ui->button_cancel_rich->setFont(button_text_font);
170 ui->button_ok_rich->setFont(button_text_font);
171 } else {
172 ui->label_title->setFont(title_text_font);
173 ui->label_dialog->setFont(body_text_font);
174 ui->button_cancel->setFont(button_text_font);
175 ui->button_ok_label->setFont(button_text_font);
176 }
177
178 QDialog::move(pos);
179 QDialog::resize(width, height);
180}
181
182template <HIDButton... T>
183void OverlayDialog::HandleButtonPressedOnce() {
184 const auto f = [this](HIDButton button) {
185 if (input_interpreter->IsButtonPressedOnce(button)) {
186 TranslateButtonPress(button);
187 }
188 };
189
190 (f(T), ...);
191}
192
193void OverlayDialog::TranslateButtonPress(HIDButton button) {
194 QPushButton* left_button = use_rich_text ? ui->button_cancel_rich : ui->button_cancel;
195 QPushButton* right_button = use_rich_text ? ui->button_ok_rich : ui->button_ok_label;
196
197 // TODO (Morph): Handle QTextBrowser text scrolling
198 // TODO (Morph): focusPrevious/NextChild() doesn't work well with the rich text dialog, fix it
199
200 switch (button) {
201 case HIDButton::A:
202 case HIDButton::B:
203 if (left_button->hasFocus()) {
204 left_button->click();
205 } else if (right_button->hasFocus()) {
206 right_button->click();
207 }
208 break;
209 case HIDButton::DLeft:
210 case HIDButton::LStickLeft:
211 focusPreviousChild();
212 break;
213 case HIDButton::DRight:
214 case HIDButton::LStickRight:
215 focusNextChild();
216 break;
217 default:
218 break;
219 }
220}
221
222void OverlayDialog::StartInputThread() {
223 if (input_thread_running) {
224 return;
225 }
226
227 input_thread_running = true;
228
229 input_thread = std::thread(&OverlayDialog::InputThread, this);
230}
231
232void OverlayDialog::StopInputThread() {
233 input_thread_running = false;
234
235 if (input_thread.joinable()) {
236 input_thread.join();
237 }
238}
239
240void OverlayDialog::InputThread() {
241 while (input_thread_running) {
242 input_interpreter->PollInput();
243
244 HandleButtonPressedOnce<HIDButton::A, HIDButton::B, HIDButton::DLeft, HIDButton::DRight,
245 HIDButton::LStickLeft, HIDButton::LStickRight>();
246
247 std::this_thread::sleep_for(std::chrono::milliseconds(50));
248 }
249}
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h
new file mode 100644
index 000000000..e8c388bd0
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.h
@@ -0,0 +1,107 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <atomic>
9#include <memory>
10#include <thread>
11
12#include <QDialog>
13
14#include "common/common_types.h"
15
16enum class HIDButton : u8;
17
18class InputInterpreter;
19
20namespace Core {
21class System;
22}
23
24namespace Ui {
25class OverlayDialog;
26}
27
28/**
29 * An OverlayDialog is an interactive dialog that accepts controller input (while a game is running)
30 * This dialog attempts to replicate the look and feel of the Nintendo Switch's overlay dialogs and
31 * provide some extra features such as embedding HTML/Rich Text content in a QTextBrowser.
32 * The OverlayDialog provides 2 modes: one to embed regular text into a QLabel and another to embed
33 * HTML/Rich Text content into a QTextBrowser.
34 */
35class OverlayDialog final : public QDialog {
36 Q_OBJECT
37
38public:
39 explicit OverlayDialog(QWidget* parent, Core::System& system, const QString& title_text,
40 const QString& body_text, const QString& left_button_text,
41 const QString& right_button_text,
42 Qt::Alignment alignment = Qt::AlignCenter, bool use_rich_text_ = false);
43 ~OverlayDialog() override;
44
45private:
46 /**
47 * Initializes a text dialog with a QLabel storing text.
48 * Only use this for short text as the dialog buttons would be squashed with longer text.
49 *
50 * @param title_text Title text to be displayed
51 * @param body_text Main text to be displayed
52 * @param left_button_text Left button text. If empty, the button is hidden and disabled
53 * @param right_button_text Right button text. If empty, the button is hidden and disabled
54 * @param alignment Main text alignment
55 */
56 void InitializeRegularTextDialog(const QString& title_text, const QString& body_text,
57 const QString& left_button_text,
58 const QString& right_button_text, Qt::Alignment alignment);
59
60 /**
61 * Initializes a text dialog with a QTextBrowser storing text.
62 * This is ideal for longer text or rich text content. A scrollbar is shown for longer text.
63 *
64 * @param title_text Title text to be displayed
65 * @param body_text Main text to be displayed
66 * @param left_button_text Left button text. If empty, the button is hidden and disabled
67 * @param right_button_text Right button text. If empty, the button is hidden and disabled
68 * @param alignment Main text alignment
69 */
70 void InitializeRichTextDialog(const QString& title_text, const QString& body_text,
71 const QString& left_button_text, const QString& right_button_text,
72 Qt::Alignment alignment);
73
74 /// Moves and resizes the dialog to be fully overlayed on top of the parent window.
75 void MoveAndResizeWindow();
76
77 /**
78 * Handles button presses and converts them into keyboard input.
79 *
80 * @tparam HIDButton The list of buttons that can be converted into keyboard input.
81 */
82 template <HIDButton... T>
83 void HandleButtonPressedOnce();
84
85 /**
86 * Translates a button press to focus or click either the left or right buttons.
87 *
88 * @param button The button press to process.
89 */
90 void TranslateButtonPress(HIDButton button);
91
92 void StartInputThread();
93 void StopInputThread();
94
95 /// The thread where input is being polled and processed.
96 void InputThread();
97
98 std::unique_ptr<Ui::OverlayDialog> ui;
99
100 bool use_rich_text;
101
102 std::unique_ptr<InputInterpreter> input_interpreter;
103
104 std::thread input_thread;
105
106 std::atomic<bool> input_thread_running{};
107};
diff --git a/src/yuzu/util/overlay_dialog.ui b/src/yuzu/util/overlay_dialog.ui
new file mode 100644
index 000000000..278e2f219
--- /dev/null
+++ b/src/yuzu/util/overlay_dialog.ui
@@ -0,0 +1,404 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>OverlayDialog</class>
4 <widget class="QDialog" name="OverlayDialog">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>1280</width>
10 <height>720</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Dialog</string>
15 </property>
16 <property name="styleSheet">
17 <string notr="true"/>
18 </property>
19 <layout class="QVBoxLayout" name="verticalLayout">
20 <property name="spacing">
21 <number>0</number>
22 </property>
23 <property name="leftMargin">
24 <number>0</number>
25 </property>
26 <property name="topMargin">
27 <number>0</number>
28 </property>
29 <property name="rightMargin">
30 <number>0</number>
31 </property>
32 <property name="bottomMargin">
33 <number>0</number>
34 </property>
35 <item>
36 <widget class="QStackedWidget" name="stackedDialog">
37 <property name="currentIndex">
38 <number>0</number>
39 </property>
40 <widget class="QWidget" name="lineDialog">
41 <layout class="QGridLayout" name="lineDialogGridLayout" rowstretch="210,300,210" columnstretch="250,780,250">
42 <property name="leftMargin">
43 <number>0</number>
44 </property>
45 <property name="topMargin">
46 <number>0</number>
47 </property>
48 <property name="rightMargin">
49 <number>0</number>
50 </property>
51 <property name="bottomMargin">
52 <number>0</number>
53 </property>
54 <property name="spacing">
55 <number>0</number>
56 </property>
57 <item row="1" column="1">
58 <widget class="QWidget" name="contentDialog" native="true">
59 <layout class="QVBoxLayout" name="verticalLayout_2" stretch="70,149,82">
60 <property name="spacing">
61 <number>0</number>
62 </property>
63 <property name="leftMargin">
64 <number>0</number>
65 </property>
66 <property name="topMargin">
67 <number>0</number>
68 </property>
69 <property name="rightMargin">
70 <number>0</number>
71 </property>
72 <property name="bottomMargin">
73 <number>0</number>
74 </property>
75 <item>
76 <widget class="QLabel" name="label_title">
77 <property name="font">
78 <font>
79 <pointsize>14</pointsize>
80 </font>
81 </property>
82 <property name="alignment">
83 <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
84 </property>
85 </widget>
86 </item>
87 <item>
88 <widget class="QLabel" name="label_dialog">
89 <property name="font">
90 <font>
91 <pointsize>18</pointsize>
92 </font>
93 </property>
94 <property name="alignment">
95 <set>Qt::AlignCenter</set>
96 </property>
97 <property name="wordWrap">
98 <bool>true</bool>
99 </property>
100 </widget>
101 </item>
102 <item>
103 <widget class="QWidget" name="buttonsDialog" native="true">
104 <layout class="QHBoxLayout" name="horizontalLayout">
105 <property name="spacing">
106 <number>0</number>
107 </property>
108 <property name="leftMargin">
109 <number>0</number>
110 </property>
111 <property name="topMargin">
112 <number>0</number>
113 </property>
114 <property name="rightMargin">
115 <number>0</number>
116 </property>
117 <property name="bottomMargin">
118 <number>0</number>
119 </property>
120 <item>
121 <widget class="QPushButton" name="button_cancel">
122 <property name="sizePolicy">
123 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
124 <horstretch>0</horstretch>
125 <verstretch>0</verstretch>
126 </sizepolicy>
127 </property>
128 <property name="font">
129 <font>
130 <pointsize>18</pointsize>
131 </font>
132 </property>
133 <property name="text">
134 <string>Cancel</string>
135 </property>
136 </widget>
137 </item>
138 <item>
139 <widget class="QPushButton" name="button_ok_label">
140 <property name="sizePolicy">
141 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
142 <horstretch>0</horstretch>
143 <verstretch>0</verstretch>
144 </sizepolicy>
145 </property>
146 <property name="font">
147 <font>
148 <pointsize>18</pointsize>
149 </font>
150 </property>
151 <property name="text">
152 <string>OK</string>
153 </property>
154 </widget>
155 </item>
156 </layout>
157 </widget>
158 </item>
159 </layout>
160 </widget>
161 </item>
162 <item row="0" column="1">
163 <spacer name="verticalSpacer">
164 <property name="orientation">
165 <enum>Qt::Vertical</enum>
166 </property>
167 <property name="sizeHint" stdset="0">
168 <size>
169 <width>20</width>
170 <height>40</height>
171 </size>
172 </property>
173 </spacer>
174 </item>
175 <item row="1" column="0">
176 <spacer name="horizontalSpacer">
177 <property name="orientation">
178 <enum>Qt::Horizontal</enum>
179 </property>
180 <property name="sizeHint" stdset="0">
181 <size>
182 <width>40</width>
183 <height>20</height>
184 </size>
185 </property>
186 </spacer>
187 </item>
188 <item row="2" column="1">
189 <spacer name="verticalSpacer_2">
190 <property name="orientation">
191 <enum>Qt::Vertical</enum>
192 </property>
193 <property name="sizeHint" stdset="0">
194 <size>
195 <width>20</width>
196 <height>40</height>
197 </size>
198 </property>
199 </spacer>
200 </item>
201 <item row="1" column="2">
202 <spacer name="horizontalSpacer_2">
203 <property name="orientation">
204 <enum>Qt::Horizontal</enum>
205 </property>
206 <property name="sizeHint" stdset="0">
207 <size>
208 <width>40</width>
209 <height>20</height>
210 </size>
211 </property>
212 </spacer>
213 </item>
214 </layout>
215 </widget>
216 <widget class="QWidget" name="richDialog">
217 <layout class="QGridLayout" name="richDialogGridLayout" rowstretch="100,520,100" columnstretch="165,950,165">
218 <property name="leftMargin">
219 <number>0</number>
220 </property>
221 <property name="topMargin">
222 <number>0</number>
223 </property>
224 <property name="rightMargin">
225 <number>0</number>
226 </property>
227 <property name="bottomMargin">
228 <number>0</number>
229 </property>
230 <property name="spacing">
231 <number>0</number>
232 </property>
233 <item row="1" column="0">
234 <spacer name="horizontalSpacer_3">
235 <property name="orientation">
236 <enum>Qt::Horizontal</enum>
237 </property>
238 <property name="sizeHint" stdset="0">
239 <size>
240 <width>40</width>
241 <height>20</height>
242 </size>
243 </property>
244 </spacer>
245 </item>
246 <item row="2" column="1">
247 <spacer name="verticalSpacer_4">
248 <property name="orientation">
249 <enum>Qt::Vertical</enum>
250 </property>
251 <property name="sizeHint" stdset="0">
252 <size>
253 <width>20</width>
254 <height>40</height>
255 </size>
256 </property>
257 </spacer>
258 </item>
259 <item row="0" column="1">
260 <spacer name="verticalSpacer_3">
261 <property name="orientation">
262 <enum>Qt::Vertical</enum>
263 </property>
264 <property name="sizeHint" stdset="0">
265 <size>
266 <width>20</width>
267 <height>40</height>
268 </size>
269 </property>
270 </spacer>
271 </item>
272 <item row="1" column="1">
273 <widget class="QWidget" name="contentRichDialog" native="true">
274 <layout class="QVBoxLayout" name="verticalLayout_3" stretch="70,368,82">
275 <property name="spacing">
276 <number>0</number>
277 </property>
278 <property name="leftMargin">
279 <number>0</number>
280 </property>
281 <property name="topMargin">
282 <number>0</number>
283 </property>
284 <property name="rightMargin">
285 <number>0</number>
286 </property>
287 <property name="bottomMargin">
288 <number>0</number>
289 </property>
290 <item>
291 <widget class="QLabel" name="label_title_rich">
292 <property name="font">
293 <font>
294 <pointsize>14</pointsize>
295 </font>
296 </property>
297 <property name="text">
298 <string/>
299 </property>
300 <property name="alignment">
301 <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
302 </property>
303 </widget>
304 </item>
305 <item>
306 <widget class="QTextBrowser" name="text_browser_dialog">
307 <property name="font">
308 <font>
309 <pointsize>18</pointsize>
310 </font>
311 </property>
312 <property name="html">
313 <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
314&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
315p, li { white-space: pre-wrap; }
316&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:400; font-style:normal;&quot;&gt;
317&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
318 </property>
319 </widget>
320 </item>
321 <item>
322 <widget class="QWidget" name="buttonsRichDialog" native="true">
323 <layout class="QHBoxLayout" name="horizontalLayout_2">
324 <property name="spacing">
325 <number>0</number>
326 </property>
327 <property name="leftMargin">
328 <number>0</number>
329 </property>
330 <property name="topMargin">
331 <number>0</number>
332 </property>
333 <property name="rightMargin">
334 <number>0</number>
335 </property>
336 <property name="bottomMargin">
337 <number>0</number>
338 </property>
339 <item>
340 <widget class="QPushButton" name="button_cancel_rich">
341 <property name="sizePolicy">
342 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
343 <horstretch>0</horstretch>
344 <verstretch>0</verstretch>
345 </sizepolicy>
346 </property>
347 <property name="font">
348 <font>
349 <pointsize>18</pointsize>
350 </font>
351 </property>
352 <property name="text">
353 <string>Cancel</string>
354 </property>
355 </widget>
356 </item>
357 <item>
358 <widget class="QPushButton" name="button_ok_rich">
359 <property name="sizePolicy">
360 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
361 <horstretch>0</horstretch>
362 <verstretch>0</verstretch>
363 </sizepolicy>
364 </property>
365 <property name="font">
366 <font>
367 <pointsize>18</pointsize>
368 </font>
369 </property>
370 <property name="text">
371 <string>OK</string>
372 </property>
373 </widget>
374 </item>
375 </layout>
376 </widget>
377 </item>
378 </layout>
379 </widget>
380 </item>
381 <item row="1" column="2">
382 <spacer name="horizontalSpacer_4">
383 <property name="orientation">
384 <enum>Qt::Horizontal</enum>
385 </property>
386 <property name="sizeHint" stdset="0">
387 <size>
388 <width>40</width>
389 <height>20</height>
390 </size>
391 </property>
392 </spacer>
393 </item>
394 </layout>
395 </widget>
396 </widget>
397 </item>
398 </layout>
399 </widget>
400 <resources>
401 <include location="../../../dist/icons/overlay/overlay.qrc"/>
402 </resources>
403 <connections/>
404</ui>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 43877fc98..2f984d1b8 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -9,8 +9,8 @@
9#include "common/file_util.h" 9#include "common/file_util.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/param_package.h" 11#include "common/param_package.h"
12#include "common/settings.h"
12#include "core/hle/service/acc/profile_manager.h" 13#include "core/hle/service/acc/profile_manager.h"
13#include "core/settings.h"
14#include "input_common/main.h" 14#include "input_common/main.h"
15#include "input_common/udp/client.h" 15#include "input_common/udp/client.h"
16#include "yuzu_cmd/config.h" 16#include "yuzu_cmd/config.h"
@@ -428,6 +428,10 @@ void Config::ReadValues() {
428 Settings::values.reporting_services = 428 Settings::values.reporting_services =
429 sdl2_config->GetBoolean("Debugging", "reporting_services", false); 429 sdl2_config->GetBoolean("Debugging", "reporting_services", false);
430 Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false); 430 Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false);
431 Settings::values.use_debug_asserts =
432 sdl2_config->GetBoolean("Debugging", "use_debug_asserts", false);
433 Settings::values.use_auto_stub = sdl2_config->GetBoolean("Debugging", "use_auto_stub", false);
434
431 Settings::values.disable_macro_jit = 435 Settings::values.disable_macro_jit =
432 sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false); 436 sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false);
433 437
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 3ee0e037d..4ce8e08e4 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -325,6 +325,12 @@ dump_nso=false
325# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode 325# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode
326# false: Retail/Normal Mode (default), true: Kiosk Mode 326# false: Retail/Normal Mode (default), true: Kiosk Mode
327quest_flag = 327quest_flag =
328# Determines whether debug asserts should be enabled, which will throw an exception on asserts.
329# false: Disabled (default), true: Enabled
330use_debug_asserts =
331# Determines whether unimplemented HLE service calls should be automatically stubbed.
332# false: Disabled (default), true: Enabled
333use_auto_stub =
328# Enables/Disables the macro JIT compiler 334# Enables/Disables the macro JIT compiler
329disable_macro_jit=false 335disable_macro_jit=false
330 336
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index a02485c14..a765fa7b3 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -12,9 +12,9 @@
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/scm_rev.h" 14#include "common/scm_rev.h"
15#include "common/settings.h"
15#include "common/string_util.h" 16#include "common/string_util.h"
16#include "core/core.h" 17#include "core/core.h"
17#include "core/settings.h"
18#include "input_common/keyboard.h" 18#include "input_common/keyboard.h"
19#include "input_common/main.h" 19#include "input_common/main.h"
20#include "video_core/renderer_base.h" 20#include "video_core/renderer_base.h"
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index 6f9b00461..dfd53e285 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -11,7 +11,7 @@
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/scm_rev.h" 13#include "common/scm_rev.h"
14#include "core/settings.h" 14#include "common/settings.h"
15#include "video_core/renderer_vulkan/renderer_vulkan.h" 15#include "video_core/renderer_vulkan/renderer_vulkan.h"
16#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" 16#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
17 17
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 982c41785..4871ac3bb 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -20,6 +20,7 @@
20#include "common/nvidia_flags.h" 20#include "common/nvidia_flags.h"
21#include "common/scm_rev.h" 21#include "common/scm_rev.h"
22#include "common/scope_exit.h" 22#include "common/scope_exit.h"
23#include "common/settings.h"
23#include "common/string_util.h" 24#include "common/string_util.h"
24#include "common/telemetry.h" 25#include "common/telemetry.h"
25#include "core/core.h" 26#include "core/core.h"
@@ -29,7 +30,6 @@
29#include "core/hle/kernel/process.h" 30#include "core/hle/kernel/process.h"
30#include "core/hle/service/filesystem/filesystem.h" 31#include "core/hle/service/filesystem/filesystem.h"
31#include "core/loader/loader.h" 32#include "core/loader/loader.h"
32#include "core/settings.h"
33#include "core/telemetry_session.h" 33#include "core/telemetry_session.h"
34#include "input_common/main.h" 34#include "input_common/main.h"
35#include "video_core/renderer_base.h" 35#include "video_core/renderer_base.h"
@@ -74,14 +74,16 @@ static void PrintVersion() {
74} 74}
75 75
76static void InitializeLogging() { 76static void InitializeLogging() {
77 using namespace Common;
78
77 Log::Filter log_filter(Log::Level::Debug); 79 Log::Filter log_filter(Log::Level::Debug);
78 log_filter.ParseFilterString(Settings::values.log_filter); 80 log_filter.ParseFilterString(Settings::values.log_filter);
79 Log::SetGlobalFilter(log_filter); 81 Log::SetGlobalFilter(log_filter);
80 82
81 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); 83 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
82 84
83 const std::string& log_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir); 85 const std::string& log_dir = FS::GetUserPath(FS::UserPath::LogDir);
84 Common::FS::CreateFullPath(log_dir); 86 FS::CreateFullPath(log_dir);
85 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); 87 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
86#ifdef _WIN32 88#ifdef _WIN32
87 Log::AddBackend(std::make_unique<Log::DebuggerBackend>()); 89 Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
@@ -164,7 +166,7 @@ int main(int argc, char** argv) {
164 InputCommon::InputSubsystem input_subsystem; 166 InputCommon::InputSubsystem input_subsystem;
165 167
166 // Apply the command line arguments 168 // Apply the command line arguments
167 Settings::Apply(system); 169 system.ApplySettings();
168 170
169 std::unique_ptr<EmuWindow_SDL2> emu_window; 171 std::unique_ptr<EmuWindow_SDL2> emu_window;
170 switch (Settings::values.renderer_backend.GetValue()) { 172 switch (Settings::values.renderer_backend.GetValue()) {