summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.codespellrc2
-rw-r--r--.github/workflows/verify.yml3
-rw-r--r--dist/72-yuzu-input.rules19
m---------externals/vcpkg0
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddGameFolderDialogFragment.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt28
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt8
-rw-r--r--src/android/app/src/main/jni/native.cpp7
-rw-r--r--src/android/app/src/main/jni/native.h1
-rw-r--r--src/common/host_memory.cpp38
-rw-r--r--src/common/host_memory.h2
-rw-r--r--src/common/settings.cpp8
-rw-r--r--src/common/settings.h14
-rw-r--r--src/core/CMakeLists.txt26
-rw-r--r--src/core/arm/arm_interface.cpp217
-rw-r--r--src/core/arm/arm_interface.h221
-rw-r--r--src/core/arm/debug.cpp354
-rw-r--r--src/core/arm/debug.h35
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp325
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h92
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp340
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h77
-rw-r--r--src/core/arm/dynarmic/dynarmic_cp15.cpp4
-rw-r--r--src/core/arm/dynarmic/dynarmic_cp15.h8
-rw-r--r--src/core/arm/dynarmic/dynarmic_exclusive_monitor.h8
-rw-r--r--src/core/arm/nce/arm_nce.cpp255
-rw-r--r--src/core/arm/nce/arm_nce.h70
-rw-r--r--src/core/arm/nce/arm_nce.s80
-rw-r--r--src/core/arm/nce/guest_context.h8
-rw-r--r--src/core/arm/nce/patcher.cpp2
-rw-r--r--src/core/core.cpp39
-rw-r--r--src/core/core.h29
-rw-r--r--src/core/cpu_manager.cpp8
-rw-r--r--src/core/debugger/gdbstub.cpp243
-rw-r--r--src/core/debugger/gdbstub_arch.cpp72
-rw-r--r--src/core/debugger/gdbstub_arch.h1
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.cpp134
-rw-r--r--src/core/file_sys/fsmitm_romfsbuild.h6
-rw-r--r--src/core/file_sys/romfs.cpp83
-rw-r--r--src/core/file_sys/savedata_factory.cpp6
-rw-r--r--src/core/file_sys/savedata_factory.h4
-rw-r--r--src/core/file_sys/vfs_concat.cpp4
-rw-r--r--src/core/file_sys/vfs_concat.h2
-rw-r--r--src/core/file_sys/vfs_layered.cpp21
-rw-r--r--src/core/hid/input_interpreter.cpp3
-rw-r--r--src/core/hle/kernel/k_client_port.cpp69
-rw-r--r--src/core/hle/kernel/k_client_port.h2
-rw-r--r--src/core/hle/kernel/k_client_session.cpp24
-rw-r--r--src/core/hle/kernel/k_client_session.h18
-rw-r--r--src/core/hle/kernel/k_light_client_session.cpp31
-rw-r--r--src/core/hle/kernel/k_light_client_session.h39
-rw-r--r--src/core/hle/kernel/k_light_server_session.cpp247
-rw-r--r--src/core/hle/kernel/k_light_server_session.h49
-rw-r--r--src/core/hle/kernel/k_light_session.cpp81
-rw-r--r--src/core/hle/kernel/k_light_session.h86
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp32
-rw-r--r--src/core/hle/kernel/k_port.cpp9
-rw-r--r--src/core/hle/kernel/k_port.h2
-rw-r--r--src/core/hle/kernel/k_process.cpp40
-rw-r--r--src/core/hle/kernel/k_process.h9
-rw-r--r--src/core/hle/kernel/k_process_page_table.h4
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp16
-rw-r--r--src/core/hle/kernel/k_server_port.cpp56
-rw-r--r--src/core/hle/kernel/k_server_port.h5
-rw-r--r--src/core/hle/kernel/k_server_session.cpp8
-rw-r--r--src/core/hle/kernel/k_session.h4
-rw-r--r--src/core/hle/kernel/k_thread.cpp80
-rw-r--r--src/core/hle/kernel/k_thread.h36
-rw-r--r--src/core/hle/kernel/kernel.cpp47
-rw-r--r--src/core/hle/kernel/kernel.h13
-rw-r--r--src/core/hle/kernel/physical_core.cpp251
-rw-r--r--src/core/hle/kernel/physical_core.h57
-rw-r--r--src/core/hle/kernel/svc.cpp2955
-rw-r--r--src/core/hle/kernel/svc.h14
-rw-r--r--src/core/hle/kernel/svc/svc_exception.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp296
-rw-r--r--src/core/hle/kernel/svc/svc_light_ipc.cpp60
-rw-r--r--src/core/hle/kernel/svc/svc_port.cpp71
-rw-r--r--src/core/hle/kernel/svc/svc_secure_monitor_call.cpp22
-rw-r--r--src/core/hle/kernel/svc/svc_session.cpp40
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp50
-rw-r--r--src/core/hle/kernel/svc_generator.py59
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp8
-rw-r--r--src/core/hle/service/hid/controllers/applet_resource.cpp313
-rw-r--r--src/core/hle/service/hid/controllers/applet_resource.h98
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.cpp21
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.h19
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h3
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp23
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h48
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp36
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h90
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp23
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h33
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h16
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp28
-rw-r--r--src/core/hle/service/hid/controllers/npad.h314
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp3
-rw-r--r--src/core/hle/service/hid/controllers/palma.h3
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_format.h240
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_holder.cpp53
-rw-r--r--src/core/hle/service/hid/controllers/shared_memory_holder.h44
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.cpp25
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.h18
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp24
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h32
-rw-r--r--src/core/hle/service/hid/controllers/types/debug_pad_types.h31
-rw-r--r--src/core/hle/service/hid/controllers/types/gesture_types.h77
-rw-r--r--src/core/hle/service/hid/controllers/types/keyboard_types.h20
-rw-r--r--src/core/hle/service/hid/controllers/types/mouse_types.h8
-rw-r--r--src/core/hle/service/hid/controllers/types/npad_types.h254
-rw-r--r--src/core/hle/service/hid/controllers/types/touch_types.h90
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp39
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h112
-rw-r--r--src/core/hle/service/hid/errors.h8
-rw-r--r--src/core/hle/service/hid/hid.cpp8
-rw-r--r--src/core/hle/service/hid/hid_server.cpp32
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp139
-rw-r--r--src/core/hle/service/hid/hid_system_server.h6
-rw-r--r--src/core/hle/service/hid/resource_manager.cpp160
-rw-r--r--src/core/hle/service/hid/resource_manager.h44
-rw-r--r--src/core/hle/service/hle_ipc.cpp15
-rw-r--r--src/core/hle/service/hle_ipc.h15
-rw-r--r--src/core/hle/service/jit/jit.cpp6
-rw-r--r--src/core/hle/service/ldr/ldr.cpp634
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp1
-rw-r--r--src/core/hle/service/ro/ro.cpp709
-rw-r--r--src/core/hle/service/ro/ro.h14
-rw-r--r--src/core/hle/service/ro/ro_nro_utils.cpp185
-rw-r--r--src/core/hle/service/ro/ro_nro_utils.h26
-rw-r--r--src/core/hle/service/ro/ro_results.h24
-rw-r--r--src/core/hle/service/ro/ro_types.h181
-rw-r--r--src/core/hle/service/server_manager.cpp32
-rw-r--r--src/core/hle/service/server_manager.h14
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/hle/service/sm/sm.cpp33
-rw-r--r--src/core/hle/service/sm/sm.h14
-rw-r--r--src/core/hle/service/ssl/ssl.cpp6
-rw-r--r--src/core/memory.cpp10
-rw-r--r--src/core/memory.h2
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/core/reporter.cpp32
-rw-r--r--src/tests/video_core/memory_tracker.cpp6
-rw-r--r--src/video_core/buffer_cache/word_manager.h2
-rw-r--r--src/video_core/host1x/ffmpeg/ffmpeg.cpp7
-rw-r--r--src/video_core/rasterizer_accelerated.cpp99
-rw-r--r--src/video_core/rasterizer_accelerated.h29
-rw-r--r--src/video_core/rasterizer_interface.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp9
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h1
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp32
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h7
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h21
-rw-r--r--src/video_core/shader_cache.cpp4
-rw-r--r--src/video_core/texture_cache/texture_cache.h45
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h3
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp14
-rw-r--r--src/yuzu/applets/qt_profile_select.h15
-rw-r--r--src/yuzu/configuration/configure_debug.ui2
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp36
-rw-r--r--src/yuzu/configuration/configure_profile_manager.h5
-rw-r--r--src/yuzu/debugger/wait_tree.cpp8
-rw-r--r--src/yuzu/main.cpp19
-rw-r--r--src/yuzu/multiplayer/lobby.cpp11
-rw-r--r--src/yuzu/multiplayer/lobby.h5
-rw-r--r--src/yuzu/play_time_manager.cpp21
-rw-r--r--src/yuzu/play_time_manager.h12
-rw-r--r--vcpkg.json4
178 files changed, 7461 insertions, 5347 deletions
diff --git a/.codespellrc b/.codespellrc
index d1f998449..1874359d3 100644
--- a/.codespellrc
+++ b/.codespellrc
@@ -3,4 +3,4 @@
[codespell]
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
-ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nce,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink
+ignore-words-list = aci,allright,ba,canonicalizations,deques,fpr,froms,hda,inout,lod,masia,nam,nax,nce,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml
index ea1302b2f..c073f3f3f 100644
--- a/.github/workflows/verify.yml
+++ b/.github/workflows/verify.yml
@@ -79,7 +79,8 @@ jobs:
fetch-depth: 0
- name: Install dependencies
run: |
- brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd
+ # workaround for https://github.com/actions/setup-python/issues/577
+ brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd || brew link --overwrite python@3.12
- name: Build
run: |
mkdir build
diff --git a/dist/72-yuzu-input.rules b/dist/72-yuzu-input.rules
new file mode 100644
index 000000000..d64f8b28d
--- /dev/null
+++ b/dist/72-yuzu-input.rules
@@ -0,0 +1,19 @@
+# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Allow systemd-logind to manage user access to hidraw with this file
+# On most systems, this file should be installed to /etc/udev/rules.d/72-yuzu-input.rules
+# Consult your distro if this is not the case
+
+# Switch Pro Controller (USB/Bluetooth)
+KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", MODE="0660", TAG+="uaccess"
+KERNEL=="hidraw*", KERNELS=="*057e:2009*", MODE="0660", TAG+="uaccess"
+
+# Joy-Con L (Bluetooth)
+KERNEL=="hidraw*", KERNELS=="*057e:2006*", MODE="0660", TAG+="uaccess"
+
+# Joy-Con R (Bluetooth)
+KERNEL=="hidraw*", KERNELS=="*057e:2007*", MODE="0660", TAG+="uaccess"
+
+# Joy-Con Charging Grip (USB)
+KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="200e", MODE="0660", TAG+="uaccess"
diff --git a/externals/vcpkg b/externals/vcpkg
-Subproject ef2eef17340f3fbd679327d286fad06dd6e838e
+Subproject a42af01b72c28a8e1d7b48107b33e4f286a55ef
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddGameFolderDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddGameFolderDialogFragment.kt
index dec2b7cf1..9fab88248 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddGameFolderDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddGameFolderDialogFragment.kt
@@ -14,8 +14,10 @@ import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.DialogAddFolderBinding
import org.yuzu.yuzu_emu.model.GameDir
import org.yuzu.yuzu_emu.model.GamesViewModel
+import org.yuzu.yuzu_emu.model.HomeViewModel
class AddGameFolderDialogFragment : DialogFragment() {
+ private val homeViewModel: HomeViewModel by activityViewModels()
private val gamesViewModel: GamesViewModel by activityViewModels()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@@ -30,6 +32,7 @@ class AddGameFolderDialogFragment : DialogFragment() {
.setTitle(R.string.add_game_folder)
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
val newGameDir = GameDir(folderUriString!!, binding.deepScanSwitch.isChecked)
+ homeViewModel.setGamesDirSelected(true)
gamesViewModel.addFolder(newGameDir)
}
.setNegativeButton(android.R.string.cancel, null)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt
index c4277735d..eb5edaa10 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt
@@ -4,6 +4,7 @@
package org.yuzu.yuzu_emu.fragments
import android.Manifest
+import android.annotation.SuppressLint
import android.content.Intent
import android.os.Build
import android.os.Bundle
@@ -75,6 +76,8 @@ class SetupFragment : Fragment() {
return binding.root
}
+ // This is using the correct scope, lint is just acting up
+ @SuppressLint("UnsafeRepeatOnLifecycleDetector")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
mainActivity = requireActivity() as MainActivity
@@ -206,12 +209,24 @@ class SetupFragment : Fragment() {
)
}
- viewLifecycleOwner.lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- homeViewModel.shouldPageForward.collect {
- if (it) {
- pageForward()
- homeViewModel.setShouldPageForward(false)
+ viewLifecycleOwner.lifecycleScope.apply {
+ launch {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ homeViewModel.shouldPageForward.collect {
+ if (it) {
+ pageForward()
+ homeViewModel.setShouldPageForward(false)
+ }
+ }
+ }
+ }
+ launch {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ homeViewModel.gamesDirSelected.collect {
+ if (it) {
+ gamesDirCallback.onStepCompleted()
+ homeViewModel.setGamesDirSelected(false)
+ }
}
}
}
@@ -339,7 +354,6 @@ class SetupFragment : Fragment() {
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
if (result != null) {
mainActivity.processGamesDir(result)
- gamesDirCallback.onStepCompleted()
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
index 752d98c10..fd925235b 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
@@ -133,7 +133,7 @@ class GamesViewModel : ViewModel() {
viewModelScope.launch {
withContext(Dispatchers.IO) {
NativeConfig.addGameDir(gameDir)
- getGameDirs()
+ getGameDirs(true)
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt
index 251b5a667..07e65b028 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt
@@ -6,6 +6,7 @@ package org.yuzu.yuzu_emu.model
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
class HomeViewModel : ViewModel() {
val navigationVisible: StateFlow<Pair<Boolean, Boolean>> get() = _navigationVisible
@@ -17,6 +18,9 @@ class HomeViewModel : ViewModel() {
val shouldPageForward: StateFlow<Boolean> get() = _shouldPageForward
private val _shouldPageForward = MutableStateFlow(false)
+ private val _gamesDirSelected = MutableStateFlow(false)
+ val gamesDirSelected get() = _gamesDirSelected.asStateFlow()
+
var navigatedToSetup = false
fun setNavigationVisibility(visible: Boolean, animated: Boolean) {
@@ -36,4 +40,8 @@ class HomeViewModel : ViewModel() {
fun setShouldPageForward(pageForward: Boolean) {
_shouldPageForward.value = pageForward
}
+
+ fun setGamesDirSelected(selected: Boolean) {
+ _gamesDirSelected.value = selected
+ }
}
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 3d795b57f..e5d3158c8 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -291,9 +291,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
// Initialize filesystem.
ConfigureFilesystemProvider(filepath);
- // Initialize account manager
- m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
-
// Load the ROM.
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
if (m_load_result != Core::SystemResultStatus::Success) {
@@ -736,8 +733,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory(
Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read);
- Service::Account::ProfileManager manager;
- const auto user_id = manager.GetUser(static_cast<std::size_t>(0));
+ const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser(
+ static_cast<std::size_t>(0));
ASSERT(user_id);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index 78ef96802..f1457bd1f 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -73,7 +73,6 @@ private:
std::atomic<bool> m_is_running = false;
std::atomic<bool> m_is_paused = false;
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
- std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
// GPU driver parameters
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 4bfc64f2d..e540375b8 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -11,10 +11,6 @@
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
-#ifdef ANDROID
-#include <android/sharedmem.h>
-#endif
-
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -193,6 +189,11 @@ public:
}
}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+ // TODO: This does not seem to be possible on Windows.
+ return false;
+ }
+
void EnableDirectMappedAddress() {
// TODO
UNREACHABLE();
@@ -442,9 +443,7 @@ public:
}
// Backing memory initialization
-#ifdef ANDROID
- fd = ASharedMemory_create("HostMemory", backing_size);
-#elif defined(__FreeBSD__) && __FreeBSD__ < 13
+#if defined(__FreeBSD__) && __FreeBSD__ < 13
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
fd = shm_open(SHM_ANON, O_RDWR, 0600);
#else
@@ -455,7 +454,6 @@ public:
throw std::bad_alloc{};
}
-#ifndef ANDROID
// Defined to extend the file with zeros
int ret = ftruncate(fd, backing_size);
if (ret != 0) {
@@ -463,7 +461,6 @@ public:
strerror(errno));
throw std::bad_alloc{};
}
-#endif
backing_base = static_cast<u8*>(
mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@@ -552,6 +549,19 @@ public:
ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+#ifdef __linux__
+ // Set MADV_REMOVE on backing map to destroy it instantly.
+ // This also deletes the area from the backing file.
+ int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
+ ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
+
+ return true;
+#else
+ return false;
+#endif
+ }
+
void EnableDirectMappedAddress() {
virtual_base = nullptr;
}
@@ -623,6 +633,10 @@ public:
void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+ return false;
+ }
+
void EnableDirectMappedAddress() {}
u8* backing_base{nullptr};
@@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w
impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);
}
+void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
+ if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) {
+ std::memset(backing_base + physical_offset, fill_value, length);
+ }
+}
+
void HostMemory::EnableDirectMappedAddress() {
if (impl) {
impl->EnableDirectMappedAddress();
diff --git a/src/common/host_memory.h b/src/common/host_memory.h
index cebfacab2..747c5850c 100644
--- a/src/common/host_memory.h
+++ b/src/common/host_memory.h
@@ -48,6 +48,8 @@ public:
void EnableDirectMappedAddress();
+ void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value);
+
[[nodiscard]] u8* BackingBasePointer() noexcept {
return backing_base;
}
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 4666bd0a0..88f509ba7 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -160,12 +160,16 @@ static bool is_nce_enabled = false;
void SetNceEnabled(bool is_39bit) {
const bool is_nce_selected = values.cpu_backend.GetValue() == CpuBackend::Nce;
- is_nce_enabled = IsFastmemEnabled() && is_nce_selected && is_39bit;
- if (is_nce_selected && !is_nce_enabled) {
+ if (is_nce_selected && !IsFastmemEnabled()) {
+ LOG_WARNING(Common, "Fastmem is required to natively execute code in a performant manner, "
+ "falling back to Dynarmic");
+ }
+ if (is_nce_selected && !is_39bit) {
LOG_WARNING(
Common,
"Program does not utilize 39-bit address space, unable to natively execute code");
}
+ is_nce_enabled = IsFastmemEnabled() && is_nce_selected && is_39bit;
}
bool IsNceEnabled() {
diff --git a/src/common/settings.h b/src/common/settings.h
index 98341ad96..7dc18fffe 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -180,14 +180,20 @@ struct Values {
&use_speed_limit};
// Cpu
- SwitchableSetting<CpuBackend, true> cpu_backend{
- linkage, CpuBackend::Dynarmic, CpuBackend::Dynarmic,
+ SwitchableSetting<CpuBackend, true> cpu_backend{linkage,
#ifdef HAS_NCE
- CpuBackend::Nce,
+ CpuBackend::Nce,
#else
CpuBackend::Dynarmic,
#endif
- "cpu_backend", Category::Cpu};
+ CpuBackend::Dynarmic,
+#ifdef HAS_NCE
+ CpuBackend::Nce,
+#else
+ CpuBackend::Dynarmic,
+#endif
+ "cpu_backend",
+ Category::Cpu};
SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
"cpu_accuracy", Category::Cpu};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 85583941c..dced37079 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -4,6 +4,8 @@
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
+ arm/debug.cpp
+ arm/debug.h
arm/exclusive_monitor.cpp
arm/exclusive_monitor.h
arm/symbols.cpp
@@ -249,10 +251,16 @@ add_library(core STATIC
hle/kernel/k_hardware_timer.h
hle/kernel/k_interrupt_manager.cpp
hle/kernel/k_interrupt_manager.h
+ hle/kernel/k_light_client_session.cpp
+ hle/kernel/k_light_client_session.h
hle/kernel/k_light_condition_variable.cpp
hle/kernel/k_light_condition_variable.h
hle/kernel/k_light_lock.cpp
hle/kernel/k_light_lock.h
+ hle/kernel/k_light_server_session.cpp
+ hle/kernel/k_light_server_session.h
+ hle/kernel/k_light_session.cpp
+ hle/kernel/k_light_session.h
hle/kernel/k_memory_block.h
hle/kernel/k_memory_block_manager.cpp
hle/kernel/k_memory_block_manager.h
@@ -541,6 +549,13 @@ add_library(core STATIC
hle/service/hid/xcd.cpp
hle/service/hid/xcd.h
hle/service/hid/errors.h
+ hle/service/hid/controllers/types/debug_pad_types.h
+ hle/service/hid/controllers/types/keyboard_types.h
+ hle/service/hid/controllers/types/mouse_types.h
+ hle/service/hid/controllers/types/npad_types.h
+ hle/service/hid/controllers/types/touch_types.h
+ hle/service/hid/controllers/applet_resource.cpp
+ hle/service/hid/controllers/applet_resource.h
hle/service/hid/controllers/console_six_axis.cpp
hle/service/hid/controllers/console_six_axis.h
hle/service/hid/controllers/controller_base.cpp
@@ -559,14 +574,15 @@ add_library(core STATIC
hle/service/hid/controllers/palma.h
hle/service/hid/controllers/seven_six_axis.cpp
hle/service/hid/controllers/seven_six_axis.h
+ hle/service/hid/controllers/shared_memory_format.h
+ hle/service/hid/controllers/shared_memory_holder.cpp
+ hle/service/hid/controllers/shared_memory_holder.h
hle/service/hid/controllers/six_axis.cpp
hle/service/hid/controllers/six_axis.h
hle/service/hid/controllers/stubbed.cpp
hle/service/hid/controllers/stubbed.h
hle/service/hid/controllers/touchscreen.cpp
hle/service/hid/controllers/touchscreen.h
- hle/service/hid/controllers/xpad.cpp
- hle/service/hid/controllers/xpad.h
hle/service/hid/hidbus/hidbus_base.cpp
hle/service/hid/hidbus/hidbus_base.h
hle/service/hid/hidbus/ringcon.cpp
@@ -762,6 +778,12 @@ add_library(core STATIC
hle/service/kernel_helpers.h
hle/service/mutex.cpp
hle/service/mutex.h
+ hle/service/ro/ro_nro_utils.cpp
+ hle/service/ro/ro_nro_utils.h
+ hle/service/ro/ro_results.h
+ hle/service/ro/ro_types.h
+ hle/service/ro/ro.cpp
+ hle/service/ro/ro.h
hle/service/server_manager.cpp
hle/service/server_manager.h
hle/service/service.cpp
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index d231bf89c..698c9c8ad 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -1,231 +1,32 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <map>
-#include <optional>
-
-#include "common/bit_field.h"
-#include "common/common_types.h"
-#include "common/demangle.h"
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
-#include "core/arm/symbols.h"
+#include "core/arm/debug.h"
#include "core/core.h"
-#include "core/debugger/debugger.h"
#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/svc.h"
-#include "core/loader/loader.h"
-#include "core/memory.h"
namespace Core {
-constexpr u64 SEGMENT_BASE = 0x7100000000ull;
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
- Core::System& system, const ARM_Interface::ThreadContext32& ctx) {
- std::vector<BacktraceEntry> out;
- auto& memory = system.ApplicationMemory();
-
- const auto& reg = ctx.cpu_registers;
- u32 pc = reg[15], lr = reg[14], fp = reg[11];
- out.push_back({"", 0, pc, 0, ""});
-
- // fp (= r11) points to the last frame record.
- // Frame records are two words long:
- // fp+0 : pointer to previous frame record
- // fp+4 : value of lr for frame
- for (size_t i = 0; i < 256; i++) {
- out.push_back({"", 0, lr, 0, ""});
- if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) {
- break;
- }
- lr = memory.Read32(fp + 4);
- fp = memory.Read32(fp);
- }
-
- SymbolicateBacktrace(system, out);
-
- return out;
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
- Core::System& system, const ARM_Interface::ThreadContext64& ctx) {
- std::vector<BacktraceEntry> out;
- auto& memory = system.ApplicationMemory();
-
- const auto& reg = ctx.cpu_registers;
- u64 pc = ctx.pc, lr = reg[30], fp = reg[29];
-
- out.push_back({"", 0, pc, 0, ""});
-
- // fp (= x29) points to the previous frame record.
- // Frame records are two words long:
- // fp+0 : pointer to previous frame record
- // fp+8 : value of lr for frame
- for (size_t i = 0; i < 256; i++) {
- out.push_back({"", 0, lr, 0, ""});
- if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) {
- break;
- }
- lr = memory.Read64(fp + 8);
- fp = memory.Read64(fp);
- }
-
- SymbolicateBacktrace(system, out);
-
- return out;
-}
-
-void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out) {
- std::map<VAddr, std::string> modules;
- auto& loader{system.GetAppLoader()};
- if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
- return;
- }
-
- std::map<std::string, Symbols::Symbols> symbols;
- for (const auto& module : modules) {
- symbols.insert_or_assign(module.second,
- Symbols::GetSymbols(module.first, system.ApplicationMemory(),
- system.ApplicationProcess()->Is64Bit()));
- }
-
- for (auto& entry : out) {
- VAddr base = 0;
- for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
- const auto& module{*iter};
- if (entry.original_address >= module.first) {
- entry.module = module.second;
- base = module.first;
- break;
- }
- }
-
- entry.offset = entry.original_address - base;
- entry.address = SEGMENT_BASE + entry.offset;
-
- if (entry.module.empty()) {
- entry.module = "unknown";
- }
-
- const auto symbol_set = symbols.find(entry.module);
- if (symbol_set != symbols.end()) {
- const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset);
- if (symbol) {
- entry.name = Common::DemangleSymbol(*symbol);
- }
- }
- }
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
- if (GetArchitecture() == Architecture::Aarch64) {
- ThreadContext64 ctx;
- SaveContext(ctx);
- return GetBacktraceFromContext(system, ctx);
- } else {
- ThreadContext32 ctx;
- SaveContext(ctx);
- return GetBacktraceFromContext(system, ctx);
- }
-}
+void ArmInterface::LogBacktrace(const Kernel::KProcess* process) const {
+ Kernel::Svc::ThreadContext ctx;
+ this->GetContext(ctx);
-void ARM_Interface::LogBacktrace() const {
- const VAddr sp = GetSP();
- const VAddr pc = GetPC();
- LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
+ LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", ctx.sp, ctx.pc);
LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
"Offset", "Symbol");
LOG_ERROR(Core_ARM, "");
- const auto backtrace = GetBacktrace();
+ const auto backtrace = GetBacktraceFromContext(process, ctx);
for (const auto& entry : backtrace) {
LOG_ERROR(Core_ARM, "{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
entry.original_address, entry.offset, entry.name);
}
}
-void ARM_Interface::Run() {
- using Kernel::StepState;
- using Kernel::SuspendType;
-
- while (true) {
- Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())};
- HaltReason hr{};
-
- // If the thread is scheduled for termination, exit the thread.
- if (current_thread->HasDpc()) {
- if (current_thread->IsTerminationRequested()) {
- current_thread->Exit();
- UNREACHABLE();
- }
- }
-
- // Notify the debugger and go to sleep if a step was performed
- // and this thread has been scheduled again.
- if (current_thread->GetStepState() == StepState::StepPerformed) {
- system.GetDebugger().NotifyThreadStopped(current_thread);
- current_thread->RequestSuspend(SuspendType::Debug);
- break;
- }
-
- // Otherwise, run the thread.
- system.EnterCPUProfile();
- if (current_thread->GetStepState() == StepState::StepPending) {
- hr = StepJit();
-
- if (True(hr & HaltReason::StepThread)) {
- current_thread->SetStepState(StepState::StepPerformed);
- }
- } else {
- hr = RunJit();
- }
- system.ExitCPUProfile();
-
- // Notify the debugger and go to sleep if a breakpoint was hit,
- // or if the thread is unable to continue for any reason.
- if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) {
- if (!True(hr & HaltReason::PrefetchAbort)) {
- RewindBreakpointInstruction();
- }
- if (system.DebuggerEnabled()) {
- system.GetDebugger().NotifyThreadStopped(current_thread);
- } else {
- LogBacktrace();
- }
- current_thread->RequestSuspend(SuspendType::Debug);
- break;
- }
-
- // Notify the debugger and go to sleep if a watchpoint was hit.
- if (True(hr & HaltReason::DataAbort)) {
- if (system.DebuggerEnabled()) {
- system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint());
- } else {
- LogBacktrace();
- }
- current_thread->RequestSuspend(SuspendType::Debug);
- break;
- }
-
- // Handle syscalls and scheduling (this may change the current thread/core)
- if (True(hr & HaltReason::SupervisorCall)) {
- Kernel::Svc::Call(system, GetSvcNumber());
- break;
- }
- if (True(hr & HaltReason::BreakLoop) || !uses_wall_clock) {
- break;
- }
- }
-}
-
-void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
- watchpoints = wp;
-}
-
-const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
+const Kernel::DebugWatchpoint* ArmInterface::MatchingWatchpoint(
u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const {
- if (!watchpoints) {
+ if (!m_watchpoints) {
return nullptr;
}
@@ -233,7 +34,7 @@ const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
const u64 end_address{addr + size};
for (size_t i = 0; i < Core::Hardware::NUM_WATCHPOINTS; i++) {
- const auto& watch{(*watchpoints)[i]};
+ const auto& watch{(*m_watchpoints)[i]};
if (end_address <= GetInteger(watch.start_address)) {
continue;
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index a9d9ac09d..806c7c9e9 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -12,20 +12,20 @@
#include "common/common_types.h"
#include "core/hardware_properties.h"
+#include "core/hle/kernel/svc_types.h"
+
namespace Common {
struct PageTable;
}
namespace Kernel {
-enum class VMAPermission : u8;
enum class DebugWatchpointType : u8;
struct DebugWatchpoint;
+class KThread;
+class KProcess;
} // namespace Kernel
namespace Core {
-class System;
-class CPUInterruptHandler;
-
using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
// NOTE: these values match the HaltReason enum in Dynarmic
@@ -40,197 +40,74 @@ enum class HaltReason : u64 {
DECLARE_ENUM_FLAG_OPERATORS(HaltReason);
enum class Architecture {
- Aarch32,
- Aarch64,
+ AArch64,
+ AArch32,
};
/// Generic ARMv8 CPU interface
-class ARM_Interface {
+class ArmInterface {
public:
- YUZU_NON_COPYABLE(ARM_Interface);
- YUZU_NON_MOVEABLE(ARM_Interface);
-
- explicit ARM_Interface(System& system_, bool uses_wall_clock_)
- : system{system_}, uses_wall_clock{uses_wall_clock_} {}
- virtual ~ARM_Interface() = default;
-
- struct ThreadContext32 {
- std::array<u32, 16> cpu_registers{};
- std::array<u32, 64> extension_registers{};
- u32 cpsr{};
- u32 fpscr{};
- u32 fpexc{};
- u32 tpidr{};
- };
- // Internally within the kernel, it expects the AArch32 version of the
- // thread context to be 344 bytes in size.
- static_assert(sizeof(ThreadContext32) == 0x150);
-
- struct ThreadContext64 {
- std::array<u64, 31> cpu_registers{};
- u64 sp{};
- u64 pc{};
- u32 pstate{};
- std::array<u8, 4> padding{};
- std::array<u128, 32> vector_registers{};
- u32 fpcr{};
- u32 fpsr{};
- u64 tpidr{};
- };
- // Internally within the kernel, it expects the AArch64 version of the
- // thread context to be 800 bytes in size.
- static_assert(sizeof(ThreadContext64) == 0x320);
-
- /// Perform any backend-specific initialization.
+ YUZU_NON_COPYABLE(ArmInterface);
+ YUZU_NON_MOVEABLE(ArmInterface);
+
+ explicit ArmInterface(bool uses_wall_clock) : m_uses_wall_clock{uses_wall_clock} {}
+ virtual ~ArmInterface() = default;
+
+ // Perform any backend-specific initialization.
virtual void Initialize() {}
- /// Runs the CPU until an event happens
- void Run();
+ // Runs the CPU until an event happens.
+ virtual HaltReason RunThread(Kernel::KThread* thread) = 0;
- /// Clear all instruction cache
+ // Runs the CPU for one instruction or until an event happens.
+ virtual HaltReason StepThread(Kernel::KThread* thread) = 0;
+
+ // Admits a backend-specific mechanism to lock the thread context.
+ virtual void LockThread(Kernel::KThread* thread) {}
+ virtual void UnlockThread(Kernel::KThread* thread) {}
+
+ // Clear the entire instruction cache for this CPU.
virtual void ClearInstructionCache() = 0;
- /**
- * Clear instruction cache range
- * @param addr Start address of the cache range to clear
- * @param size Size of the cache range to clear, starting at addr
- */
+ // Clear a range of the instruction cache for this CPU.
virtual void InvalidateCacheRange(u64 addr, std::size_t size) = 0;
- /**
- * Notifies CPU emulation that the current page table has changed.
- * @param new_page_table The new page table.
- * @param new_address_space_size_in_bits The new usable size of the address space in bits.
- * This can be either 32, 36, or 39 on official software.
- */
- virtual void PageTableChanged(Common::PageTable& new_page_table,
- std::size_t new_address_space_size_in_bits) = 0;
-
- /**
- * Set the Program Counter to an address
- * @param addr Address to set PC to
- */
- virtual void SetPC(u64 addr) = 0;
-
- /*
- * Get the current Program Counter
- * @return Returns current PC
- */
- virtual u64 GetPC() const = 0;
-
- /**
- * Get the current Stack Pointer
- * @return Returns current SP
- */
- virtual u64 GetSP() const = 0;
-
- /**
- * Get an ARM register
- * @param index Register index
- * @return Returns the value in the register
- */
- virtual u64 GetReg(int index) const = 0;
-
- /**
- * Set an ARM register
- * @param index Register index
- * @param value Value to set register to
- */
- virtual void SetReg(int index, u64 value) = 0;
-
- /**
- * Gets the value of a specified vector register.
- *
- * @param index The index of the vector register.
- * @return the value within the vector register.
- */
- virtual u128 GetVectorReg(int index) const = 0;
-
- /**
- * Sets a given value into a vector register.
- *
- * @param index The index of the vector register.
- * @param value The new value to place in the register.
- */
- virtual void SetVectorReg(int index, u128 value) = 0;
-
- /**
- * Get the current PSTATE register
- * @return Returns the value of the PSTATE register
- */
- virtual u32 GetPSTATE() const = 0;
-
- /**
- * Set the current PSTATE register
- * @param pstate Value to set PSTATE to
- */
- virtual void SetPSTATE(u32 pstate) = 0;
-
- virtual u64 GetTlsAddress() const = 0;
-
- virtual void SetTlsAddress(u64 address) = 0;
-
- /**
- * Gets the value within the TPIDR_EL0 (read/write software thread ID) register.
- *
- * @return the value within the register.
- */
- virtual u64 GetTPIDR_EL0() const = 0;
-
- /**
- * Sets a new value within the TPIDR_EL0 (read/write software thread ID) register.
- *
- * @param value The new value to place in the register.
- */
- virtual void SetTPIDR_EL0(u64 value) = 0;
-
+ // Get the current architecture.
+ // This returns AArch64 when PSTATE.nRW == 0 and AArch32 when PSTATE.nRW == 1.
virtual Architecture GetArchitecture() const = 0;
- virtual void SaveContext(ThreadContext32& ctx) const = 0;
- virtual void SaveContext(ThreadContext64& ctx) const = 0;
- virtual void LoadContext(const ThreadContext32& ctx) = 0;
- virtual void LoadContext(const ThreadContext64& ctx) = 0;
- void LoadWatchpointArray(const WatchpointArray* wp);
- /// Clears the exclusive monitor's state.
- virtual void ClearExclusiveState() = 0;
+ // Context accessors.
+ // These should not be called if the CPU is running.
+ virtual void GetContext(Kernel::Svc::ThreadContext& ctx) const = 0;
+ virtual void SetContext(const Kernel::Svc::ThreadContext& ctx) = 0;
+ virtual void SetTpidrroEl0(u64 value) = 0;
- /// Signal an interrupt and ask the core to halt as soon as possible.
- virtual void SignalInterrupt() = 0;
+ virtual void GetSvcArguments(std::span<uint64_t, 8> args) const = 0;
+ virtual void SetSvcArguments(std::span<const uint64_t, 8> args) = 0;
+ virtual u32 GetSvcNumber() const = 0;
- /// Clear a previous interrupt.
- virtual void ClearInterrupt() = 0;
+ void SetWatchpointArray(const WatchpointArray* watchpoints) {
+ m_watchpoints = watchpoints;
+ }
- struct BacktraceEntry {
- std::string module;
- u64 address;
- u64 original_address;
- u64 offset;
- std::string name;
- };
+ // Signal an interrupt for execution to halt as soon as possible.
+ // It is safe to call this if the CPU is not running.
+ virtual void SignalInterrupt(Kernel::KThread* thread) = 0;
- static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
- const ThreadContext32& ctx);
- static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
- const ThreadContext64& ctx);
+ // Stack trace generation.
+ void LogBacktrace(const Kernel::KProcess* process) const;
- std::vector<BacktraceEntry> GetBacktrace() const;
- void LogBacktrace() const;
+ // Debug functionality.
+ virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0;
+ virtual void RewindBreakpointInstruction() = 0;
protected:
- /// System context that this ARM interface is running under.
- System& system;
- const WatchpointArray* watchpoints;
- bool uses_wall_clock;
-
- static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out);
const Kernel::DebugWatchpoint* MatchingWatchpoint(
u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const;
- virtual HaltReason RunJit() = 0;
- virtual HaltReason StepJit() = 0;
- virtual u32 GetSvcNumber() const = 0;
- virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0;
- virtual void RewindBreakpointInstruction() = 0;
+protected:
+ const WatchpointArray* m_watchpoints{};
+ bool m_uses_wall_clock{};
};
} // namespace Core
diff --git a/src/core/arm/debug.cpp b/src/core/arm/debug.cpp
new file mode 100644
index 000000000..af1c34bc3
--- /dev/null
+++ b/src/core/arm/debug.cpp
@@ -0,0 +1,354 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/demangle.h"
+#include "core/arm/debug.h"
+#include "core/arm/symbols.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/memory.h"
+
+namespace Core {
+
+namespace {
+
+std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory,
+ const Kernel::KThread& thread) {
+ // Read thread type from TLS
+ const VAddr tls_thread_type{memory.Read64(thread.GetTlsAddress() + 0x1f8)};
+ const VAddr argument_thread_type{thread.GetArgument()};
+
+ if (argument_thread_type && tls_thread_type != argument_thread_type) {
+ // Probably not created by nnsdk, no name available.
+ return std::nullopt;
+ }
+
+ if (!tls_thread_type) {
+ return std::nullopt;
+ }
+
+ const u16 version{memory.Read16(tls_thread_type + 0x46)};
+ VAddr name_pointer{};
+ if (version == 1) {
+ name_pointer = memory.Read64(tls_thread_type + 0x1a0);
+ } else {
+ name_pointer = memory.Read64(tls_thread_type + 0x1a8);
+ }
+
+ if (!name_pointer) {
+ // No name provided.
+ return std::nullopt;
+ }
+
+ return memory.ReadCString(name_pointer, 256);
+}
+
+std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory,
+ const Kernel::KThread& thread) {
+ // Read thread type from TLS
+ const VAddr tls_thread_type{memory.Read32(thread.GetTlsAddress() + 0x1fc)};
+ const VAddr argument_thread_type{thread.GetArgument()};
+
+ if (argument_thread_type && tls_thread_type != argument_thread_type) {
+ // Probably not created by nnsdk, no name available.
+ return std::nullopt;
+ }
+
+ if (!tls_thread_type) {
+ return std::nullopt;
+ }
+
+ const u16 version{memory.Read16(tls_thread_type + 0x26)};
+ VAddr name_pointer{};
+ if (version == 1) {
+ name_pointer = memory.Read32(tls_thread_type + 0xe4);
+ } else {
+ name_pointer = memory.Read32(tls_thread_type + 0xe8);
+ }
+
+ if (!name_pointer) {
+ // No name provided.
+ return std::nullopt;
+ }
+
+ return memory.ReadCString(name_pointer, 256);
+}
+
+constexpr std::array<u64, 2> SegmentBases{
+ 0x60000000ULL,
+ 0x7100000000ULL,
+};
+
+void SymbolicateBacktrace(const Kernel::KProcess* process, std::vector<BacktraceEntry>& out) {
+ auto modules = FindModules(process);
+
+ const bool is_64 = process->Is64Bit();
+
+ std::map<std::string, Symbols::Symbols> symbols;
+ for (const auto& module : modules) {
+ symbols.insert_or_assign(module.second,
+ Symbols::GetSymbols(module.first, process->GetMemory(), is_64));
+ }
+
+ for (auto& entry : out) {
+ VAddr base = 0;
+ for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) {
+ const auto& module{*iter};
+ if (entry.original_address >= module.first) {
+ entry.module = module.second;
+ base = module.first;
+ break;
+ }
+ }
+
+ entry.offset = entry.original_address - base;
+ entry.address = SegmentBases[is_64] + entry.offset;
+
+ if (entry.module.empty()) {
+ entry.module = "unknown";
+ }
+
+ const auto symbol_set = symbols.find(entry.module);
+ if (symbol_set != symbols.end()) {
+ const auto symbol = Symbols::GetSymbolName(symbol_set->second, entry.offset);
+ if (symbol) {
+ entry.name = Common::DemangleSymbol(*symbol);
+ }
+ }
+ }
+}
+
+std::vector<BacktraceEntry> GetAArch64Backtrace(const Kernel::KProcess* process,
+ const Kernel::Svc::ThreadContext& ctx) {
+ std::vector<BacktraceEntry> out;
+ auto& memory = process->GetMemory();
+ auto pc = ctx.pc, lr = ctx.lr, fp = ctx.fp;
+
+ out.push_back({"", 0, pc, 0, ""});
+
+ // fp (= x29) points to the previous frame record.
+ // Frame records are two words long:
+ // fp+0 : pointer to previous frame record
+ // fp+8 : value of lr for frame
+ for (size_t i = 0; i < 256; i++) {
+ out.push_back({"", 0, lr, 0, ""});
+ if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) {
+ break;
+ }
+ lr = memory.Read64(fp + 8);
+ fp = memory.Read64(fp);
+ }
+
+ SymbolicateBacktrace(process, out);
+
+ return out;
+}
+
+std::vector<BacktraceEntry> GetAArch32Backtrace(const Kernel::KProcess* process,
+ const Kernel::Svc::ThreadContext& ctx) {
+ std::vector<BacktraceEntry> out;
+ auto& memory = process->GetMemory();
+ auto pc = ctx.pc, lr = ctx.lr, fp = ctx.fp;
+
+ out.push_back({"", 0, pc, 0, ""});
+
+ // fp (= r11) points to the last frame record.
+ // Frame records are two words long:
+ // fp+0 : pointer to previous frame record
+ // fp+4 : value of lr for frame
+ for (size_t i = 0; i < 256; i++) {
+ out.push_back({"", 0, lr, 0, ""});
+ if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) {
+ break;
+ }
+ lr = memory.Read32(fp + 4);
+ fp = memory.Read32(fp);
+ }
+
+ SymbolicateBacktrace(process, out);
+
+ return out;
+}
+
+} // namespace
+
+std::optional<std::string> GetThreadName(const Kernel::KThread* thread) {
+ const auto* process = thread->GetOwnerProcess();
+ if (process->Is64Bit()) {
+ return GetNameFromThreadType64(process->GetMemory(), *thread);
+ } else {
+ return GetNameFromThreadType32(process->GetMemory(), *thread);
+ }
+}
+
+std::string_view GetThreadWaitReason(const Kernel::KThread* thread) {
+ switch (thread->GetWaitReasonForDebugging()) {
+ case Kernel::ThreadWaitReasonForDebugging::Sleep:
+ return "Sleep";
+ case Kernel::ThreadWaitReasonForDebugging::IPC:
+ return "IPC";
+ case Kernel::ThreadWaitReasonForDebugging::Synchronization:
+ return "Synchronization";
+ case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
+ return "ConditionVar";
+ case Kernel::ThreadWaitReasonForDebugging::Arbitration:
+ return "Arbitration";
+ case Kernel::ThreadWaitReasonForDebugging::Suspended:
+ return "Suspended";
+ default:
+ return "Unknown";
+ }
+}
+
+std::string GetThreadState(const Kernel::KThread* thread) {
+ switch (thread->GetState()) {
+ case Kernel::ThreadState::Initialized:
+ return "Initialized";
+ case Kernel::ThreadState::Waiting:
+ return fmt::format("Waiting ({})", GetThreadWaitReason(thread));
+ case Kernel::ThreadState::Runnable:
+ return "Runnable";
+ case Kernel::ThreadState::Terminated:
+ return "Terminated";
+ default:
+ return "Unknown";
+ }
+}
+
+Kernel::KProcessAddress GetModuleEnd(const Kernel::KProcess* process,
+ Kernel::KProcessAddress base) {
+ Kernel::KMemoryInfo mem_info;
+ Kernel::Svc::MemoryInfo svc_mem_info;
+ Kernel::Svc::PageInfo page_info;
+ VAddr cur_addr{GetInteger(base)};
+ auto& page_table = process->GetPageTable();
+
+ // Expect: r-x Code (.text)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
+ return cur_addr - 1;
+ }
+
+ // Expect: r-- Code (.rodata)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
+ return cur_addr - 1;
+ }
+
+ // Expect: rw- CodeData (.data)
+ R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ svc_mem_info = mem_info.GetSvcMemoryInfo();
+ cur_addr = svc_mem_info.base_address + svc_mem_info.size;
+ return cur_addr - 1;
+}
+
+Loader::AppLoader::Modules FindModules(const Kernel::KProcess* process) {
+ Loader::AppLoader::Modules modules;
+
+ auto& page_table = process->GetPageTable();
+ auto& memory = process->GetMemory();
+ VAddr cur_addr = 0;
+
+ // Look for executable sections in Code or AliasCode regions.
+ while (true) {
+ Kernel::KMemoryInfo mem_info{};
+ Kernel::Svc::PageInfo page_info{};
+ R_ASSERT(
+ page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
+ auto svc_mem_info = mem_info.GetSvcMemoryInfo();
+
+ if (svc_mem_info.permission == Kernel::Svc::MemoryPermission::ReadExecute &&
+ (svc_mem_info.state == Kernel::Svc::MemoryState::Code ||
+ svc_mem_info.state == Kernel::Svc::MemoryState::AliasCode)) {
+ // Try to read the module name from its path.
+ constexpr s32 PathLengthMax = 0x200;
+ struct {
+ u32 zero;
+ s32 path_length;
+ std::array<char, PathLengthMax> path;
+ } module_path;
+
+ if (memory.ReadBlock(svc_mem_info.base_address + svc_mem_info.size, &module_path,
+ sizeof(module_path))) {
+ if (module_path.zero == 0 && module_path.path_length > 0) {
+ // Truncate module name.
+ module_path.path[PathLengthMax - 1] = '\0';
+
+ // Ignore leading directories.
+ char* path_pointer = module_path.path.data();
+ char* path_end =
+ path_pointer + std::min(PathLengthMax, module_path.path_length);
+
+ for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) &&
+ module_path.path[i] != '\0';
+ i++) {
+ if (module_path.path[i] == '/' || module_path.path[i] == '\\') {
+ path_pointer = module_path.path.data() + i + 1;
+ }
+ }
+
+ // Insert output.
+ modules.emplace(svc_mem_info.base_address,
+ std::string_view(path_pointer, path_end));
+ }
+ }
+ }
+
+ // Check if we're done.
+ const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
+ if (next_address <= cur_addr) {
+ break;
+ }
+
+ cur_addr = next_address;
+ }
+
+ return modules;
+}
+
+Kernel::KProcessAddress FindMainModuleEntrypoint(const Kernel::KProcess* process) {
+ // Do we have any loaded executable sections?
+ auto modules = FindModules(process);
+
+ if (modules.size() >= 2) {
+ // If we have two or more, the first one is rtld and the second is main.
+ return std::next(modules.begin())->first;
+ } else if (!modules.empty()) {
+ // If we only have one, this is the main module.
+ return modules.begin()->first;
+ }
+
+ // As a last resort, use the start of the code region.
+ return GetInteger(process->GetPageTable().GetCodeRegionStart());
+}
+
+void InvalidateInstructionCacheRange(const Kernel::KProcess* process, u64 address, u64 size) {
+ for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ auto* interface = process->GetArmInterface(i);
+ if (interface) {
+ interface->InvalidateCacheRange(address, size);
+ }
+ }
+}
+
+std::vector<BacktraceEntry> GetBacktraceFromContext(const Kernel::KProcess* process,
+ const Kernel::Svc::ThreadContext& ctx) {
+ if (process->Is64Bit()) {
+ return GetAArch64Backtrace(process, ctx);
+ } else {
+ return GetAArch32Backtrace(process, ctx);
+ }
+}
+
+std::vector<BacktraceEntry> GetBacktrace(const Kernel::KThread* thread) {
+ Kernel::Svc::ThreadContext ctx = thread->GetContext();
+ return GetBacktraceFromContext(thread->GetOwnerProcess(), ctx);
+}
+
+} // namespace Core
diff --git a/src/core/arm/debug.h b/src/core/arm/debug.h
new file mode 100644
index 000000000..c542633db
--- /dev/null
+++ b/src/core/arm/debug.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <optional>
+
+#include "core/hle/kernel/k_thread.h"
+#include "core/loader/loader.h"
+
+namespace Core {
+
+std::optional<std::string> GetThreadName(const Kernel::KThread* thread);
+std::string_view GetThreadWaitReason(const Kernel::KThread* thread);
+std::string GetThreadState(const Kernel::KThread* thread);
+
+Loader::AppLoader::Modules FindModules(const Kernel::KProcess* process);
+Kernel::KProcessAddress GetModuleEnd(const Kernel::KProcess* process, Kernel::KProcessAddress base);
+Kernel::KProcessAddress FindMainModuleEntrypoint(const Kernel::KProcess* process);
+
+void InvalidateInstructionCacheRange(const Kernel::KProcess* process, u64 address, u64 size);
+
+struct BacktraceEntry {
+ std::string module;
+ u64 address;
+ u64 original_address;
+ u64 offset;
+ std::string name;
+};
+
+std::vector<BacktraceEntry> GetBacktraceFromContext(const Kernel::KProcess* process,
+ const Kernel::Svc::ThreadContext& ctx);
+std::vector<BacktraceEntry> GetBacktrace(const Kernel::KThread* thread);
+
+} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 44a297cdc..f34865e26 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -1,25 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cinttypes>
-#include <memory>
-#include <dynarmic/interface/A32/a32.h>
-#include <dynarmic/interface/A32/config.h>
-#include "common/assert.h"
-#include "common/literals.h"
-#include "common/logging/log.h"
-#include "common/page_table.h"
#include "common/settings.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
#include "core/arm/dynarmic/dynarmic_cp15.h"
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
-#include "core/core.h"
#include "core/core_timing.h"
-#include "core/debugger/debugger.h"
#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/svc.h"
-#include "core/memory.h"
namespace Core {
@@ -27,78 +15,78 @@ using namespace Common::Literals;
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public:
- explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
- : parent{parent_}, memory(parent.system.ApplicationMemory()),
- debugger_enabled{parent.system.DebuggerEnabled()},
- check_memory_access{debugger_enabled ||
- !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
+ explicit DynarmicCallbacks32(ArmDynarmic32& parent, const Kernel::KProcess* process)
+ : m_parent{parent}, m_memory(process->GetMemory()),
+ m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
+ m_check_memory_access{m_debugger_enabled ||
+ !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
u8 MemoryRead8(u32 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
- return memory.Read8(vaddr);
+ return m_memory.Read8(vaddr);
}
u16 MemoryRead16(u32 vaddr) override {
CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read);
- return memory.Read16(vaddr);
+ return m_memory.Read16(vaddr);
}
u32 MemoryRead32(u32 vaddr) override {
CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read);
- return memory.Read32(vaddr);
+ return m_memory.Read32(vaddr);
}
u64 MemoryRead64(u32 vaddr) override {
CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
- return memory.Read64(vaddr);
+ return m_memory.Read64(vaddr);
}
std::optional<u32> MemoryReadCode(u32 vaddr) override {
- if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
+ if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
return std::nullopt;
}
- return memory.Read32(vaddr);
+ return m_memory.Read32(vaddr);
}
void MemoryWrite8(u32 vaddr, u8 value) override {
if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) {
- memory.Write8(vaddr, value);
+ m_memory.Write8(vaddr, value);
}
}
void MemoryWrite16(u32 vaddr, u16 value) override {
if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) {
- memory.Write16(vaddr, value);
+ m_memory.Write16(vaddr, value);
}
}
void MemoryWrite32(u32 vaddr, u32 value) override {
if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) {
- memory.Write32(vaddr, value);
+ m_memory.Write32(vaddr, value);
}
}
void MemoryWrite64(u32 vaddr, u64 value) override {
if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) {
- memory.Write64(vaddr, value);
+ m_memory.Write64(vaddr, value);
}
}
bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override {
return CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive8(vaddr, value, expected);
+ m_memory.WriteExclusive8(vaddr, value, expected);
}
bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override {
return CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive16(vaddr, value, expected);
+ m_memory.WriteExclusive16(vaddr, value, expected);
}
bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override {
return CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive32(vaddr, value, expected);
+ m_memory.WriteExclusive32(vaddr, value, expected);
}
bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override {
return CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive64(vaddr, value, expected);
+ m_memory.WriteExclusive64(vaddr, value, expected);
}
void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
- parent.LogBacktrace();
+ m_parent.LogBacktrace(m_process);
LOG_ERROR(Core_ARM,
"Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
- num_instructions, memory.Read32(pc));
+ num_instructions, m_memory.Read32(pc));
}
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
@@ -108,73 +96,64 @@ public:
ReturnException(pc, PrefetchAbort);
return;
default:
- if (debugger_enabled) {
+ if (m_debugger_enabled) {
ReturnException(pc, InstructionBreakpoint);
return;
}
- parent.LogBacktrace();
+ m_parent.LogBacktrace(m_process);
LOG_CRITICAL(Core_ARM,
"ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
- exception, pc, memory.Read32(pc), parent.IsInThumbMode());
+ exception, pc, m_memory.Read32(pc), m_parent.IsInThumbMode());
}
}
void CallSVC(u32 swi) override {
- parent.svc_swi = swi;
- parent.jit.load()->HaltExecution(SupervisorCall);
+ m_parent.m_svc_swi = swi;
+ m_parent.m_jit->HaltExecution(SupervisorCall);
}
void AddTicks(u64 ticks) override {
- if (parent.uses_wall_clock) {
- return;
- }
+ ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
// rough approximation of the amount of executed ticks in the system, it may be thrown off
// if not all cores are doing a similar amount of work. Instead of doing this, we should
// device a way so that timing is consistent across all cores without increasing the ticks 4
// times.
- u64 amortized_ticks =
- (ticks - num_interpreted_instructions) / Core::Hardware::NUM_CPU_CORES;
+ u64 amortized_ticks = ticks / Core::Hardware::NUM_CPU_CORES;
// Always execute at least one tick.
amortized_ticks = std::max<u64>(amortized_ticks, 1);
- parent.system.CoreTiming().AddTicks(amortized_ticks);
- num_interpreted_instructions = 0;
+ m_parent.m_system.CoreTiming().AddTicks(amortized_ticks);
}
u64 GetTicksRemaining() override {
- if (parent.uses_wall_clock) {
- if (!IsInterrupted()) {
- return minimum_run_cycles;
- }
- return 0U;
- }
+ ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
- return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
+ return std::max<s64>(m_parent.m_system.CoreTiming().GetDowncount(), 0);
}
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type) {
- if (!check_memory_access) {
+ if (!m_check_memory_access) {
return true;
}
- if (!memory.IsValidVirtualAddressRange(addr, size)) {
+ if (!m_memory.IsValidVirtualAddressRange(addr, size)) {
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
addr);
- parent.jit.load()->HaltExecution(PrefetchAbort);
+ m_parent.m_jit->HaltExecution(PrefetchAbort);
return false;
}
- if (!debugger_enabled) {
+ if (!m_debugger_enabled) {
return true;
}
- const auto match{parent.MatchingWatchpoint(addr, size, type)};
+ const auto match{m_parent.MatchingWatchpoint(addr, size, type)};
if (match) {
- parent.halted_watchpoint = match;
- parent.jit.load()->HaltExecution(DataAbort);
+ m_parent.m_halted_watchpoint = match;
+ m_parent.m_jit->HaltExecution(DataAbort);
return false;
}
@@ -182,32 +161,31 @@ public:
}
void ReturnException(u32 pc, Dynarmic::HaltReason hr) {
- parent.SaveContext(parent.breakpoint_context);
- parent.breakpoint_context.cpu_registers[15] = pc;
- parent.jit.load()->HaltExecution(hr);
- }
-
- bool IsInterrupted() {
- return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
+ m_parent.GetContext(m_parent.m_breakpoint_context);
+ m_parent.m_breakpoint_context.pc = pc;
+ m_parent.m_breakpoint_context.r[15] = pc;
+ m_parent.m_jit->HaltExecution(hr);
}
- ARM_Dynarmic_32& parent;
- Core::Memory::Memory& memory;
- std::size_t num_interpreted_instructions{};
- const bool debugger_enabled{};
- const bool check_memory_access{};
- static constexpr u64 minimum_run_cycles = 10000U;
+ ArmDynarmic32& m_parent;
+ Core::Memory::Memory& m_memory;
+ const Kernel::KProcess* m_process{};
+ const bool m_debugger_enabled{};
+ const bool m_check_memory_access{};
+ static constexpr u64 MinimumRunCycles = 10000U;
};
-std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* page_table) const {
+std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* page_table) const {
Dynarmic::A32::UserConfig config;
- config.callbacks = cb.get();
- config.coprocessors[15] = cp15;
+ config.callbacks = m_cb.get();
+ config.coprocessors[15] = m_cp15;
config.define_unpredictable_behaviour = true;
- static constexpr std::size_t YUZU_PAGEBITS = 12;
- static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - YUZU_PAGEBITS);
+
if (page_table) {
- config.page_table = reinterpret_cast<std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>*>(
+ constexpr size_t PageBits = 12;
+ constexpr size_t NumPageTableEntries = 1 << (32 - PageBits);
+
+ config.page_table = reinterpret_cast<std::array<std::uint8_t*, NumPageTableEntries>*>(
page_table->pointers.data());
config.absolute_offset_page_table = true;
config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS;
@@ -221,12 +199,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
}
// Multi-process state
- config.processor_id = core_index;
- config.global_monitor = &exclusive_monitor.monitor;
+ config.processor_id = m_core_index;
+ config.global_monitor = &m_exclusive_monitor.monitor;
// Timing
- config.wall_clock_cntpct = uses_wall_clock;
- config.enable_cycle_counting = true;
+ config.wall_clock_cntpct = m_uses_wall_clock;
+ config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size
#ifdef ARCHITECTURE_arm64
@@ -236,7 +214,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
#endif
// Allow memory fault handling to work
- if (system.DebuggerEnabled()) {
+ if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true;
}
@@ -325,137 +303,140 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
return std::make_unique<Dynarmic::A32::Jit>(config);
}
-HaltReason ARM_Dynarmic_32::RunJit() {
- return TranslateHaltReason(jit.load()->Run());
+static std::pair<u32, u32> FpscrToFpsrFpcr(u32 fpscr) {
+ // FPSCR bits [31:27] are mapped to FPSR[31:27].
+ // FPSCR bit [7] is mapped to FPSR[7].
+ // FPSCR bits [4:0] are mapped to FPSR[4:0].
+ const u32 nzcv = fpscr & 0xf8000000;
+ const u32 idc = fpscr & 0x80;
+ const u32 fiq = fpscr & 0x1f;
+ const u32 fpsr = nzcv | idc | fiq;
+
+ // FPSCR bits [26:15] are mapped to FPCR[26:15].
+ // FPSCR bits [12:8] are mapped to FPCR[12:8].
+ const u32 round = fpscr & 0x7ff8000;
+ const u32 trap = fpscr & 0x1f00;
+ const u32 fpcr = round | trap;
+
+ return {fpsr, fpcr};
}
-HaltReason ARM_Dynarmic_32::StepJit() {
- return TranslateHaltReason(jit.load()->Step());
+static u32 FpsrFpcrToFpscr(u64 fpsr, u64 fpcr) {
+ auto [s, c] = FpscrToFpsrFpcr(static_cast<u32>(fpsr | fpcr));
+ return s | c;
}
-u32 ARM_Dynarmic_32::GetSvcNumber() const {
- return svc_swi;
+bool ArmDynarmic32::IsInThumbMode() const {
+ return (m_jit->Cpsr() & 0x20) != 0;
}
-const Kernel::DebugWatchpoint* ARM_Dynarmic_32::HaltedWatchpoint() const {
- return halted_watchpoint;
+HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
+ m_jit->ClearExclusiveState();
+ return TranslateHaltReason(m_jit->Run());
}
-void ARM_Dynarmic_32::RewindBreakpointInstruction() {
- LoadContext(breakpoint_context);
+HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
+ m_jit->ClearExclusiveState();
+ return TranslateHaltReason(m_jit->Step());
}
-ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
- DynarmicExclusiveMonitor& exclusive_monitor_,
- std::size_t core_index_)
- : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
- cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
- exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
+u32 ArmDynarmic32::GetSvcNumber() const {
+ return m_svc_swi;
+}
-ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
+void ArmDynarmic32::GetSvcArguments(std::span<uint64_t, 8> args) const {
+ Dynarmic::A32::Jit& j = *m_jit;
+ auto& gpr = j.Regs();
-void ARM_Dynarmic_32::SetPC(u64 pc) {
- jit.load()->Regs()[15] = static_cast<u32>(pc);
+ for (size_t i = 0; i < 8; i++) {
+ args[i] = gpr[i];
+ }
}
-u64 ARM_Dynarmic_32::GetPC() const {
- return jit.load()->Regs()[15];
-}
+void ArmDynarmic32::SetSvcArguments(std::span<const uint64_t, 8> args) {
+ Dynarmic::A32::Jit& j = *m_jit;
+ auto& gpr = j.Regs();
-u64 ARM_Dynarmic_32::GetSP() const {
- return jit.load()->Regs()[13];
+ for (size_t i = 0; i < 8; i++) {
+ gpr[i] = static_cast<u32>(args[i]);
+ }
}
-u64 ARM_Dynarmic_32::GetReg(int index) const {
- return jit.load()->Regs()[index];
+const Kernel::DebugWatchpoint* ArmDynarmic32::HaltedWatchpoint() const {
+ return m_halted_watchpoint;
}
-void ARM_Dynarmic_32::SetReg(int index, u64 value) {
- jit.load()->Regs()[index] = static_cast<u32>(value);
+void ArmDynarmic32::RewindBreakpointInstruction() {
+ this->SetContext(m_breakpoint_context);
}
-u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
- return {};
+ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, const Kernel::KProcess* process,
+ DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index)
+ : ArmInterface{uses_wall_clock}, m_system{system}, m_exclusive_monitor{exclusive_monitor},
+ m_cb(std::make_unique<DynarmicCallbacks32>(*this, process)),
+ m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
+ auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
+ m_jit = MakeJit(&page_table_impl);
}
-void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {}
+ArmDynarmic32::~ArmDynarmic32() = default;
-u32 ARM_Dynarmic_32::GetPSTATE() const {
- return jit.load()->Cpsr();
+void ArmDynarmic32::SetTpidrroEl0(u64 value) {
+ m_cp15->uro = static_cast<u32>(value);
}
-void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {
- jit.load()->SetCpsr(cpsr);
-}
+void ArmDynarmic32::GetContext(Kernel::Svc::ThreadContext& ctx) const {
+ Dynarmic::A32::Jit& j = *m_jit;
+ auto& gpr = j.Regs();
+ auto& fpr = j.ExtRegs();
-u64 ARM_Dynarmic_32::GetTlsAddress() const {
- return cp15->uro;
-}
+ for (size_t i = 0; i < 16; i++) {
+ ctx.r[i] = gpr[i];
+ }
-void ARM_Dynarmic_32::SetTlsAddress(u64 address) {
- cp15->uro = static_cast<u32>(address);
-}
+ ctx.fp = gpr[11];
+ ctx.sp = gpr[13];
+ ctx.lr = gpr[14];
+ ctx.pc = gpr[15];
+ ctx.pstate = j.Cpsr();
-u64 ARM_Dynarmic_32::GetTPIDR_EL0() const {
- return cp15->uprw;
-}
+ static_assert(sizeof(fpr) <= sizeof(ctx.v));
+ std::memcpy(ctx.v.data(), &fpr, sizeof(fpr));
-void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
- cp15->uprw = static_cast<u32>(value);
+ auto [fpsr, fpcr] = FpscrToFpsrFpcr(j.Fpscr());
+ ctx.fpcr = fpcr;
+ ctx.fpsr = fpsr;
+ ctx.tpidr = m_cp15->uprw;
}
-void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) const {
- Dynarmic::A32::Jit* j = jit.load();
- ctx.cpu_registers = j->Regs();
- ctx.extension_registers = j->ExtRegs();
- ctx.cpsr = j->Cpsr();
- ctx.fpscr = j->Fpscr();
-}
+void ArmDynarmic32::SetContext(const Kernel::Svc::ThreadContext& ctx) {
+ Dynarmic::A32::Jit& j = *m_jit;
+ auto& gpr = j.Regs();
+ auto& fpr = j.ExtRegs();
-void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
- Dynarmic::A32::Jit* j = jit.load();
- j->Regs() = ctx.cpu_registers;
- j->ExtRegs() = ctx.extension_registers;
- j->SetCpsr(ctx.cpsr);
- j->SetFpscr(ctx.fpscr);
-}
+ for (size_t i = 0; i < 16; i++) {
+ gpr[i] = static_cast<u32>(ctx.r[i]);
+ }
-void ARM_Dynarmic_32::SignalInterrupt() {
- jit.load()->HaltExecution(BreakLoop);
-}
+ j.SetCpsr(ctx.pstate);
-void ARM_Dynarmic_32::ClearInterrupt() {
- jit.load()->ClearHalt(BreakLoop);
-}
+ static_assert(sizeof(fpr) <= sizeof(ctx.v));
+ std::memcpy(&fpr, ctx.v.data(), sizeof(fpr));
-void ARM_Dynarmic_32::ClearInstructionCache() {
- jit.load()->ClearCache();
+ j.SetFpscr(FpsrFpcrToFpscr(ctx.fpsr, ctx.fpcr));
+ m_cp15->uprw = static_cast<u32>(ctx.tpidr);
}
-void ARM_Dynarmic_32::InvalidateCacheRange(u64 addr, std::size_t size) {
- jit.load()->InvalidateCacheRange(static_cast<u32>(addr), size);
+void ArmDynarmic32::SignalInterrupt(Kernel::KThread* thread) {
+ m_jit->HaltExecution(BreakLoop);
}
-void ARM_Dynarmic_32::ClearExclusiveState() {
- jit.load()->ClearExclusiveState();
+void ArmDynarmic32::ClearInstructionCache() {
+ m_jit->ClearCache();
}
-void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
- std::size_t new_address_space_size_in_bits) {
- ThreadContext32 ctx{};
- SaveContext(ctx);
-
- auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
- auto iter = jit_cache.find(key);
- if (iter != jit_cache.end()) {
- jit.store(iter->second.get());
- LoadContext(ctx);
- return;
- }
- std::shared_ptr new_jit = MakeJit(&page_table);
- jit.store(new_jit.get());
- LoadContext(ctx);
- jit_cache.emplace(key, std::move(new_jit));
+void ArmDynarmic32::InvalidateCacheRange(u64 addr, std::size_t size) {
+ m_jit->InvalidateCacheRange(static_cast<u32>(addr), size);
}
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 92fb3f836..185ac7cbf 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -3,14 +3,8 @@
#pragma once
-#include <atomic>
-#include <memory>
-#include <unordered_map>
-
#include <dynarmic/interface/A32/a32.h>
-#include <dynarmic/interface/A64/a64.h>
-#include "common/common_types.h"
-#include "common/hash.h"
+
#include "core/arm/arm_interface.h"
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
@@ -20,89 +14,63 @@ class Memory;
namespace Core {
-class CPUInterruptHandler;
class DynarmicCallbacks32;
class DynarmicCP15;
-class DynarmicExclusiveMonitor;
class System;
-class ARM_Dynarmic_32 final : public ARM_Interface {
+class ArmDynarmic32 final : public ArmInterface {
public:
- ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
- DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
- ~ARM_Dynarmic_32() override;
-
- void SetPC(u64 pc) override;
- u64 GetPC() const override;
- u64 GetSP() const override;
- u64 GetReg(int index) const override;
- void SetReg(int index, u64 value) override;
- u128 GetVectorReg(int index) const override;
- void SetVectorReg(int index, u128 value) override;
- u32 GetPSTATE() const override;
- void SetPSTATE(u32 pstate) override;
- u64 GetTlsAddress() const override;
- void SetTlsAddress(u64 address) override;
- void SetTPIDR_EL0(u64 value) override;
- u64 GetTPIDR_EL0() const override;
-
- bool IsInThumbMode() const {
- return (GetPSTATE() & 0x20) != 0;
- }
+ ArmDynarmic32(System& system, bool uses_wall_clock, const Kernel::KProcess* process,
+ DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index);
+ ~ArmDynarmic32() override;
Architecture GetArchitecture() const override {
- return Architecture::Aarch32;
+ return Architecture::AArch32;
}
- void SaveContext(ThreadContext32& ctx) const override;
- void SaveContext(ThreadContext64& ctx) const override {}
- void LoadContext(const ThreadContext32& ctx) override;
- void LoadContext(const ThreadContext64& ctx) override {}
- void SignalInterrupt() override;
- void ClearInterrupt() override;
- void ClearExclusiveState() override;
+ bool IsInThumbMode() const;
+
+ HaltReason RunThread(Kernel::KThread* thread) override;
+ HaltReason StepThread(Kernel::KThread* thread) override;
+
+ void GetContext(Kernel::Svc::ThreadContext& ctx) const override;
+ void SetContext(const Kernel::Svc::ThreadContext& ctx) override;
+ void SetTpidrroEl0(u64 value) override;
+
+ void GetSvcArguments(std::span<uint64_t, 8> args) const override;
+ void SetSvcArguments(std::span<const uint64_t, 8> args) override;
+ u32 GetSvcNumber() const override;
+ void SignalInterrupt(Kernel::KThread* thread) override;
void ClearInstructionCache() override;
void InvalidateCacheRange(u64 addr, std::size_t size) override;
- void PageTableChanged(Common::PageTable& new_page_table,
- std::size_t new_address_space_size_in_bits) override;
protected:
- HaltReason RunJit() override;
- HaltReason StepJit() override;
- u32 GetSvcNumber() const override;
const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
void RewindBreakpointInstruction() override;
private:
- std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
-
- static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc);
-
- using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
- using JitCacheType =
- std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;
+ System& m_system;
+ DynarmicExclusiveMonitor& m_exclusive_monitor;
+private:
friend class DynarmicCallbacks32;
friend class DynarmicCP15;
- std::unique_ptr<DynarmicCallbacks32> cb;
- JitCacheType jit_cache;
- std::shared_ptr<DynarmicCP15> cp15;
- std::size_t core_index;
- DynarmicExclusiveMonitor& exclusive_monitor;
+ std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
- std::shared_ptr<Dynarmic::A32::Jit> null_jit;
+ std::unique_ptr<DynarmicCallbacks32> m_cb{};
+ std::shared_ptr<DynarmicCP15> m_cp15{};
+ std::size_t m_core_index{};
- // A raw pointer here is fine; we never delete Jit instances.
- std::atomic<Dynarmic::A32::Jit*> jit;
+ std::shared_ptr<Dynarmic::A32::Jit> m_jit{};
// SVC callback
- u32 svc_swi{};
+ u32 m_svc_swi{};
// Watchpoint info
- const Kernel::DebugWatchpoint* halted_watchpoint;
- ThreadContext32 breakpoint_context;
+ const Kernel::DebugWatchpoint* m_halted_watchpoint{};
+ Kernel::Svc::ThreadContext m_breakpoint_context{};
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 2e3674b6d..dff14756e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -1,25 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cinttypes>
-#include <memory>
-#include <dynarmic/interface/A64/a64.h>
-#include <dynarmic/interface/A64/config.h>
-#include "common/assert.h"
-#include "common/literals.h"
-#include "common/logging/log.h"
-#include "common/page_table.h"
#include "common/settings.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
-#include "core/core.h"
#include "core/core_timing.h"
-#include "core/debugger/debugger.h"
-#include "core/hardware_properties.h"
#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/svc.h"
-#include "core/memory.h"
namespace Core {
@@ -28,92 +15,92 @@ using namespace Common::Literals;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public:
- explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
- : parent{parent_}, memory(parent.system.ApplicationMemory()),
- debugger_enabled{parent.system.DebuggerEnabled()},
- check_memory_access{debugger_enabled ||
- !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
+ explicit DynarmicCallbacks64(ArmDynarmic64& parent, const Kernel::KProcess* process)
+ : m_parent{parent}, m_memory(process->GetMemory()),
+ m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
+ m_check_memory_access{m_debugger_enabled ||
+ !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
u8 MemoryRead8(u64 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
- return memory.Read8(vaddr);
+ return m_memory.Read8(vaddr);
}
u16 MemoryRead16(u64 vaddr) override {
CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read);
- return memory.Read16(vaddr);
+ return m_memory.Read16(vaddr);
}
u32 MemoryRead32(u64 vaddr) override {
CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read);
- return memory.Read32(vaddr);
+ return m_memory.Read32(vaddr);
}
u64 MemoryRead64(u64 vaddr) override {
CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
- return memory.Read64(vaddr);
+ return m_memory.Read64(vaddr);
}
Vector MemoryRead128(u64 vaddr) override {
CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read);
- return {memory.Read64(vaddr), memory.Read64(vaddr + 8)};
+ return {m_memory.Read64(vaddr), m_memory.Read64(vaddr + 8)};
}
std::optional<u32> MemoryReadCode(u64 vaddr) override {
- if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
+ if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
return std::nullopt;
}
- return memory.Read32(vaddr);
+ return m_memory.Read32(vaddr);
}
void MemoryWrite8(u64 vaddr, u8 value) override {
if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) {
- memory.Write8(vaddr, value);
+ m_memory.Write8(vaddr, value);
}
}
void MemoryWrite16(u64 vaddr, u16 value) override {
if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) {
- memory.Write16(vaddr, value);
+ m_memory.Write16(vaddr, value);
}
}
void MemoryWrite32(u64 vaddr, u32 value) override {
if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) {
- memory.Write32(vaddr, value);
+ m_memory.Write32(vaddr, value);
}
}
void MemoryWrite64(u64 vaddr, u64 value) override {
if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) {
- memory.Write64(vaddr, value);
+ m_memory.Write64(vaddr, value);
}
}
void MemoryWrite128(u64 vaddr, Vector value) override {
if (CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Write)) {
- memory.Write64(vaddr, value[0]);
- memory.Write64(vaddr + 8, value[1]);
+ m_memory.Write64(vaddr, value[0]);
+ m_memory.Write64(vaddr + 8, value[1]);
}
}
bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override {
return CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive8(vaddr, value, expected);
+ m_memory.WriteExclusive8(vaddr, value, expected);
}
bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override {
return CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive16(vaddr, value, expected);
+ m_memory.WriteExclusive16(vaddr, value, expected);
}
bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override {
return CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive32(vaddr, value, expected);
+ m_memory.WriteExclusive32(vaddr, value, expected);
}
bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override {
return CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive64(vaddr, value, expected);
+ m_memory.WriteExclusive64(vaddr, value, expected);
}
bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override {
return CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Write) &&
- memory.WriteExclusive128(vaddr, value, expected);
+ m_memory.WriteExclusive128(vaddr, value, expected);
}
void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
- parent.LogBacktrace();
+ m_parent.LogBacktrace(m_process);
LOG_ERROR(Core_ARM,
"Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
- num_instructions, memory.Read32(pc));
+ num_instructions, m_memory.Read32(pc));
ReturnException(pc, PrefetchAbort);
}
@@ -124,11 +111,11 @@ public:
static constexpr u64 ICACHE_LINE_SIZE = 64;
const u64 cache_line_start = value & ~(ICACHE_LINE_SIZE - 1);
- parent.system.InvalidateCpuInstructionCacheRange(cache_line_start, ICACHE_LINE_SIZE);
+ m_parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE);
break;
}
case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU:
- parent.system.InvalidateCpuInstructionCaches();
+ m_parent.ClearInstructionCache();
break;
case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable:
default:
@@ -136,7 +123,7 @@ public:
break;
}
- parent.jit.load()->HaltExecution(Dynarmic::HaltReason::CacheInvalidation);
+ m_parent.m_jit->HaltExecution(Dynarmic::HaltReason::CacheInvalidation);
}
void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -152,26 +139,24 @@ public:
ReturnException(pc, PrefetchAbort);
return;
default:
- if (debugger_enabled) {
+ if (m_debugger_enabled) {
ReturnException(pc, InstructionBreakpoint);
return;
}
- parent.LogBacktrace();
+ m_parent.LogBacktrace(m_process);
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
- static_cast<std::size_t>(exception), pc, memory.Read32(pc));
+ static_cast<std::size_t>(exception), pc, m_memory.Read32(pc));
}
}
- void CallSVC(u32 swi) override {
- parent.svc_swi = swi;
- parent.jit.load()->HaltExecution(SupervisorCall);
+ void CallSVC(u32 svc) override {
+ m_parent.m_svc = svc;
+ m_parent.m_jit->HaltExecution(SupervisorCall);
}
void AddTicks(u64 ticks) override {
- if (parent.uses_wall_clock) {
- return;
- }
+ ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
// rough approximation of the amount of executed ticks in the system, it may be thrown off
@@ -182,44 +167,39 @@ public:
// Always execute at least one tick.
amortized_ticks = std::max<u64>(amortized_ticks, 1);
- parent.system.CoreTiming().AddTicks(amortized_ticks);
+ m_parent.m_system.CoreTiming().AddTicks(amortized_ticks);
}
u64 GetTicksRemaining() override {
- if (parent.uses_wall_clock) {
- if (!IsInterrupted()) {
- return minimum_run_cycles;
- }
- return 0U;
- }
+ ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
- return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
+ return std::max<s64>(m_parent.m_system.CoreTiming().GetDowncount(), 0);
}
u64 GetCNTPCT() override {
- return parent.system.CoreTiming().GetClockTicks();
+ return m_parent.m_system.CoreTiming().GetClockTicks();
}
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type) {
- if (!check_memory_access) {
+ if (!m_check_memory_access) {
return true;
}
- if (!memory.IsValidVirtualAddressRange(addr, size)) {
+ if (!m_memory.IsValidVirtualAddressRange(addr, size)) {
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
addr);
- parent.jit.load()->HaltExecution(PrefetchAbort);
+ m_parent.m_jit->HaltExecution(PrefetchAbort);
return false;
}
- if (!debugger_enabled) {
+ if (!m_debugger_enabled) {
return true;
}
- const auto match{parent.MatchingWatchpoint(addr, size, type)};
+ const auto match{m_parent.MatchingWatchpoint(addr, size, type)};
if (match) {
- parent.halted_watchpoint = match;
- parent.jit.load()->HaltExecution(DataAbort);
+ m_parent.m_halted_watchpoint = match;
+ m_parent.m_jit->HaltExecution(DataAbort);
return false;
}
@@ -227,30 +207,27 @@ public:
}
void ReturnException(u64 pc, Dynarmic::HaltReason hr) {
- parent.SaveContext(parent.breakpoint_context);
- parent.breakpoint_context.pc = pc;
- parent.jit.load()->HaltExecution(hr);
+ m_parent.GetContext(m_parent.m_breakpoint_context);
+ m_parent.m_breakpoint_context.pc = pc;
+ m_parent.m_jit->HaltExecution(hr);
}
- bool IsInterrupted() {
- return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
- }
-
- ARM_Dynarmic_64& parent;
- Core::Memory::Memory& memory;
- u64 tpidrro_el0 = 0;
- u64 tpidr_el0 = 0;
- const bool debugger_enabled{};
- const bool check_memory_access{};
- static constexpr u64 minimum_run_cycles = 10000U;
+ ArmDynarmic64& m_parent;
+ Core::Memory::Memory& m_memory;
+ u64 m_tpidrro_el0{};
+ u64 m_tpidr_el0{};
+ const Kernel::KProcess* m_process{};
+ const bool m_debugger_enabled{};
+ const bool m_check_memory_access{};
+ static constexpr u64 MinimumRunCycles = 10000U;
};
-std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* page_table,
- std::size_t address_space_bits) const {
+std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* page_table,
+ std::size_t address_space_bits) const {
Dynarmic::A64::UserConfig config;
// Callbacks
- config.callbacks = cb.get();
+ config.callbacks = m_cb.get();
// Memory
if (page_table) {
@@ -271,12 +248,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
}
// Multi-process state
- config.processor_id = core_index;
- config.global_monitor = &exclusive_monitor.monitor;
+ config.processor_id = m_core_index;
+ config.global_monitor = &m_exclusive_monitor.monitor;
// System registers
- config.tpidrro_el0 = &cb->tpidrro_el0;
- config.tpidr_el0 = &cb->tpidr_el0;
+ config.tpidrro_el0 = &m_cb->m_tpidrro_el0;
+ config.tpidr_el0 = &m_cb->m_tpidr_el0;
config.dczid_el0 = 4;
config.ctr_el0 = 0x8444c004;
config.cntfrq_el0 = Hardware::CNTFREQ;
@@ -285,8 +262,8 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
config.define_unpredictable_behaviour = true;
// Timing
- config.wall_clock_cntpct = uses_wall_clock;
- config.enable_cycle_counting = true;
+ config.wall_clock_cntpct = m_uses_wall_clock;
+ config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size
#ifdef ARCHITECTURE_arm64
@@ -296,7 +273,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
#endif
// Allow memory fault handling to work
- if (system.DebuggerEnabled()) {
+ if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true;
}
@@ -384,147 +361,112 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
return std::make_shared<Dynarmic::A64::Jit>(config);
}
-HaltReason ARM_Dynarmic_64::RunJit() {
- return TranslateHaltReason(jit.load()->Run());
-}
-
-HaltReason ARM_Dynarmic_64::StepJit() {
- return TranslateHaltReason(jit.load()->Step());
-}
-
-u32 ARM_Dynarmic_64::GetSvcNumber() const {
- return svc_swi;
-}
-
-const Kernel::DebugWatchpoint* ARM_Dynarmic_64::HaltedWatchpoint() const {
- return halted_watchpoint;
-}
-
-void ARM_Dynarmic_64::RewindBreakpointInstruction() {
- LoadContext(breakpoint_context);
-}
-
-ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
- DynarmicExclusiveMonitor& exclusive_monitor_,
- std::size_t core_index_)
- : ARM_Interface{system_, uses_wall_clock_},
- cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
- exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
-
-ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
-
-void ARM_Dynarmic_64::SetPC(u64 pc) {
- jit.load()->SetPC(pc);
-}
-
-u64 ARM_Dynarmic_64::GetPC() const {
- return jit.load()->GetPC();
+HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
+ m_jit->ClearExclusiveState();
+ return TranslateHaltReason(m_jit->Run());
}
-u64 ARM_Dynarmic_64::GetSP() const {
- return jit.load()->GetSP();
+HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
+ m_jit->ClearExclusiveState();
+ return TranslateHaltReason(m_jit->Step());
}
-u64 ARM_Dynarmic_64::GetReg(int index) const {
- return jit.load()->GetRegister(index);
+u32 ArmDynarmic64::GetSvcNumber() const {
+ return m_svc;
}
-void ARM_Dynarmic_64::SetReg(int index, u64 value) {
- jit.load()->SetRegister(index, value);
-}
+void ArmDynarmic64::GetSvcArguments(std::span<uint64_t, 8> args) const {
+ Dynarmic::A64::Jit& j = *m_jit;
-u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
- return jit.load()->GetVector(index);
+ for (size_t i = 0; i < 8; i++) {
+ args[i] = j.GetRegister(i);
+ }
}
-void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
- jit.load()->SetVector(index, value);
-}
+void ArmDynarmic64::SetSvcArguments(std::span<const uint64_t, 8> args) {
+ Dynarmic::A64::Jit& j = *m_jit;
-u32 ARM_Dynarmic_64::GetPSTATE() const {
- return jit.load()->GetPstate();
+ for (size_t i = 0; i < 8; i++) {
+ j.SetRegister(i, args[i]);
+ }
}
-void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
- jit.load()->SetPstate(pstate);
+const Kernel::DebugWatchpoint* ArmDynarmic64::HaltedWatchpoint() const {
+ return m_halted_watchpoint;
}
-u64 ARM_Dynarmic_64::GetTlsAddress() const {
- return cb->tpidrro_el0;
+void ArmDynarmic64::RewindBreakpointInstruction() {
+ this->SetContext(m_breakpoint_context);
}
-void ARM_Dynarmic_64::SetTlsAddress(u64 address) {
- cb->tpidrro_el0 = address;
+ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, const Kernel::KProcess* process,
+ DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index)
+ : ArmInterface{uses_wall_clock}, m_system{system}, m_exclusive_monitor{exclusive_monitor},
+ m_cb(std::make_unique<DynarmicCallbacks64>(*this, process)), m_core_index{core_index} {
+ auto& page_table = process->GetPageTable().GetBasePageTable();
+ auto& page_table_impl = page_table.GetImpl();
+ m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
}
-u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
- return cb->tpidr_el0;
-}
+ArmDynarmic64::~ArmDynarmic64() = default;
-void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
- cb->tpidr_el0 = value;
+void ArmDynarmic64::SetTpidrroEl0(u64 value) {
+ m_cb->m_tpidrro_el0 = value;
}
-void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) const {
- Dynarmic::A64::Jit* j = jit.load();
- ctx.cpu_registers = j->GetRegisters();
- ctx.sp = j->GetSP();
- ctx.pc = j->GetPC();
- ctx.pstate = j->GetPstate();
- ctx.vector_registers = j->GetVectors();
- ctx.fpcr = j->GetFpcr();
- ctx.fpsr = j->GetFpsr();
- ctx.tpidr = cb->tpidr_el0;
-}
+void ArmDynarmic64::GetContext(Kernel::Svc::ThreadContext& ctx) const {
+ Dynarmic::A64::Jit& j = *m_jit;
+ auto gpr = j.GetRegisters();
+ auto fpr = j.GetVectors();
-void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
- Dynarmic::A64::Jit* j = jit.load();
- j->SetRegisters(ctx.cpu_registers);
- j->SetSP(ctx.sp);
- j->SetPC(ctx.pc);
- j->SetPstate(ctx.pstate);
- j->SetVectors(ctx.vector_registers);
- j->SetFpcr(ctx.fpcr);
- j->SetFpsr(ctx.fpsr);
- SetTPIDR_EL0(ctx.tpidr);
+ // TODO: this is inconvenient
+ for (size_t i = 0; i < 29; i++) {
+ ctx.r[i] = gpr[i];
+ }
+ ctx.fp = gpr[29];
+ ctx.lr = gpr[30];
+
+ ctx.sp = j.GetSP();
+ ctx.pc = j.GetPC();
+ ctx.pstate = j.GetPstate();
+ ctx.v = fpr;
+ ctx.fpcr = j.GetFpcr();
+ ctx.fpsr = j.GetFpsr();
+ ctx.tpidr = m_cb->m_tpidr_el0;
}
-void ARM_Dynarmic_64::SignalInterrupt() {
- jit.load()->HaltExecution(BreakLoop);
-}
+void ArmDynarmic64::SetContext(const Kernel::Svc::ThreadContext& ctx) {
+ Dynarmic::A64::Jit& j = *m_jit;
-void ARM_Dynarmic_64::ClearInterrupt() {
- jit.load()->ClearHalt(BreakLoop);
-}
+ // TODO: this is inconvenient
+ std::array<u64, 31> gpr;
-void ARM_Dynarmic_64::ClearInstructionCache() {
- jit.load()->ClearCache();
+ for (size_t i = 0; i < 29; i++) {
+ gpr[i] = ctx.r[i];
+ }
+ gpr[29] = ctx.fp;
+ gpr[30] = ctx.lr;
+
+ j.SetRegisters(gpr);
+ j.SetSP(ctx.sp);
+ j.SetPC(ctx.pc);
+ j.SetPstate(ctx.pstate);
+ j.SetVectors(ctx.v);
+ j.SetFpcr(ctx.fpcr);
+ j.SetFpsr(ctx.fpsr);
+ m_cb->m_tpidr_el0 = ctx.tpidr;
}
-void ARM_Dynarmic_64::InvalidateCacheRange(u64 addr, std::size_t size) {
- jit.load()->InvalidateCacheRange(addr, size);
+void ArmDynarmic64::SignalInterrupt(Kernel::KThread* thread) {
+ m_jit->HaltExecution(BreakLoop);
}
-void ARM_Dynarmic_64::ClearExclusiveState() {
- jit.load()->ClearExclusiveState();
+void ArmDynarmic64::ClearInstructionCache() {
+ m_jit->ClearCache();
}
-void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
- std::size_t new_address_space_size_in_bits) {
- ThreadContext64 ctx{};
- SaveContext(ctx);
-
- auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
- auto iter = jit_cache.find(key);
- if (iter != jit_cache.end()) {
- jit.store(iter->second.get());
- LoadContext(ctx);
- return;
- }
- std::shared_ptr new_jit = MakeJit(&page_table, new_address_space_size_in_bits);
- jit.store(new_jit.get());
- LoadContext(ctx);
- jit_cache.emplace(key, std::move(new_jit));
+void ArmDynarmic64::InvalidateCacheRange(u64 addr, std::size_t size) {
+ m_jit->InvalidateCacheRange(addr, size);
}
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 2b88a08e2..4f3dd026f 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -23,76 +23,55 @@ class DynarmicCallbacks64;
class DynarmicExclusiveMonitor;
class System;
-class ARM_Dynarmic_64 final : public ARM_Interface {
+class ArmDynarmic64 final : public ArmInterface {
public:
- ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
- DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
- ~ARM_Dynarmic_64() override;
-
- void SetPC(u64 pc) override;
- u64 GetPC() const override;
- u64 GetSP() const override;
- u64 GetReg(int index) const override;
- void SetReg(int index, u64 value) override;
- u128 GetVectorReg(int index) const override;
- void SetVectorReg(int index, u128 value) override;
- u32 GetPSTATE() const override;
- void SetPSTATE(u32 pstate) override;
- u64 GetTlsAddress() const override;
- void SetTlsAddress(u64 address) override;
- void SetTPIDR_EL0(u64 value) override;
- u64 GetTPIDR_EL0() const override;
+ ArmDynarmic64(System& system, bool uses_wall_clock, const Kernel::KProcess* process,
+ DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index);
+ ~ArmDynarmic64() override;
Architecture GetArchitecture() const override {
- return Architecture::Aarch64;
+ return Architecture::AArch64;
}
- void SaveContext(ThreadContext32& ctx) const override {}
- void SaveContext(ThreadContext64& ctx) const override;
- void LoadContext(const ThreadContext32& ctx) override {}
- void LoadContext(const ThreadContext64& ctx) override;
- void SignalInterrupt() override;
- void ClearInterrupt() override;
- void ClearExclusiveState() override;
+ HaltReason RunThread(Kernel::KThread* thread) override;
+ HaltReason StepThread(Kernel::KThread* thread) override;
+ void GetContext(Kernel::Svc::ThreadContext& ctx) const override;
+ void SetContext(const Kernel::Svc::ThreadContext& ctx) override;
+ void SetTpidrroEl0(u64 value) override;
+
+ void GetSvcArguments(std::span<uint64_t, 8> args) const override;
+ void SetSvcArguments(std::span<const uint64_t, 8> args) override;
+ u32 GetSvcNumber() const override;
+
+ void SignalInterrupt(Kernel::KThread* thread) override;
void ClearInstructionCache() override;
void InvalidateCacheRange(u64 addr, std::size_t size) override;
- void PageTableChanged(Common::PageTable& new_page_table,
- std::size_t new_address_space_size_in_bits) override;
protected:
- HaltReason RunJit() override;
- HaltReason StepJit() override;
- u32 GetSvcNumber() const override;
const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
void RewindBreakpointInstruction() override;
private:
- std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
- std::size_t address_space_bits) const;
-
- using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
- using JitCacheType =
- std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
+ System& m_system;
+ DynarmicExclusiveMonitor& m_exclusive_monitor;
+private:
friend class DynarmicCallbacks64;
- std::unique_ptr<DynarmicCallbacks64> cb;
- JitCacheType jit_cache;
-
- std::size_t core_index;
- DynarmicExclusiveMonitor& exclusive_monitor;
- std::shared_ptr<Dynarmic::A64::Jit> null_jit;
+ std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
+ std::size_t address_space_bits) const;
+ std::unique_ptr<DynarmicCallbacks64> m_cb{};
+ std::size_t m_core_index{};
- // A raw pointer here is fine; we never delete Jit instances.
- std::atomic<Dynarmic::A64::Jit*> jit;
+ std::shared_ptr<Dynarmic::A64::Jit> m_jit{};
// SVC callback
- u32 svc_swi{};
+ u32 m_svc{};
- // Breakpoint info
- const Kernel::DebugWatchpoint* halted_watchpoint;
- ThreadContext64 breakpoint_context;
+ // Watchpoint info
+ const Kernel::DebugWatchpoint* m_halted_watchpoint{};
+ Kernel::Svc::ThreadContext m_breakpoint_context{};
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/dynarmic_cp15.cpp b/src/core/arm/dynarmic/dynarmic_cp15.cpp
index 92c548db0..f3eee0d42 100644
--- a/src/core/arm/dynarmic/dynarmic_cp15.cpp
+++ b/src/core/arm/dynarmic/dynarmic_cp15.cpp
@@ -124,8 +124,8 @@ CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc
if (!two && opc == 0 && CRm == CoprocReg::C14) {
// CNTPCT
const auto callback = [](void* arg, u32, u32) -> u64 {
- const auto& parent_arg = *static_cast<ARM_Dynarmic_32*>(arg);
- return parent_arg.system.CoreTiming().GetClockTicks();
+ const auto& parent_arg = *static_cast<ArmDynarmic32*>(arg);
+ return parent_arg.m_system.CoreTiming().GetClockTicks();
};
return Callback{callback, &parent};
}
diff --git a/src/core/arm/dynarmic/dynarmic_cp15.h b/src/core/arm/dynarmic/dynarmic_cp15.h
index d90b3e568..f3d96b0d8 100644
--- a/src/core/arm/dynarmic/dynarmic_cp15.h
+++ b/src/core/arm/dynarmic/dynarmic_cp15.h
@@ -10,13 +10,13 @@
namespace Core {
-class ARM_Dynarmic_32;
+class ArmDynarmic32;
class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
public:
using CoprocReg = Dynarmic::A32::CoprocReg;
- explicit DynarmicCP15(ARM_Dynarmic_32& parent_) : parent{parent_} {}
+ explicit DynarmicCP15(ArmDynarmic32& parent_) : parent{parent_} {}
std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
CoprocReg CRn, CoprocReg CRm,
@@ -32,11 +32,11 @@ public:
std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
std::optional<u8> option) override;
- ARM_Dynarmic_32& parent;
+ ArmDynarmic32& parent;
u32 uprw = 0;
u32 uro = 0;
- friend class ARM_Dynarmic_32;
+ friend class ArmDynarmic32;
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
index fbfcd8d95..c4f22ec89 100644
--- a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
@@ -14,8 +14,8 @@ class Memory;
namespace Core {
-class ARM_Dynarmic_32;
-class ARM_Dynarmic_64;
+class ArmDynarmic32;
+class ArmDynarmic64;
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
public:
@@ -36,8 +36,8 @@ public:
bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;
private:
- friend class ARM_Dynarmic_32;
- friend class ARM_Dynarmic_64;
+ friend class ArmDynarmic32;
+ friend class ArmDynarmic64;
Dynarmic::ExclusiveMonitor monitor;
Core::Memory::Memory& memory;
};
diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp
index f7bdafd39..b42a32a0b 100644
--- a/src/core/arm/nce/arm_nce.cpp
+++ b/src/core/arm/nce/arm_nce.cpp
@@ -6,6 +6,7 @@
#include "common/signal_chain.h"
#include "core/arm/nce/arm_nce.h"
+#include "core/arm/nce/guest_context.h"
#include "core/arm/nce/patcher.h"
#include "core/core.h"
#include "core/memory.h"
@@ -38,7 +39,7 @@ fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
} // namespace
-void* ARM_NCE::RestoreGuestContext(void* raw_context) {
+void* ArmNce::RestoreGuestContext(void* raw_context) {
// Retrieve the host context.
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
@@ -71,7 +72,7 @@ void* ARM_NCE::RestoreGuestContext(void* raw_context) {
return tpidr;
}
-void ARM_NCE::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) {
+void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) {
// Retrieve the host context.
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
@@ -103,7 +104,7 @@ void ARM_NCE::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) {
host_ctx.regs[0] = guest_ctx->esr_el1.exchange(0);
}
-bool ARM_NCE::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
+bool ArmNce::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) {
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
auto* info = static_cast<siginfo_t*>(raw_info);
@@ -134,7 +135,7 @@ bool ARM_NCE::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* ra
// - If we lose the race, then SignalInterrupt will send us a signal we are masking,
// and it will do nothing when it is unmasked, as we have already left guest code.
// - If we win the race, then SignalInterrupt will wait for us to unlock first.
- auto& thread_params = guest_ctx->parent->running_thread->GetNativeExecutionParameters();
+ auto& thread_params = guest_ctx->parent->m_running_thread->GetNativeExecutionParameters();
thread_params.lock.store(SpinLockLocked);
// Return to host.
@@ -142,97 +143,93 @@ bool ARM_NCE::HandleGuestFault(GuestContext* guest_ctx, void* raw_info, void* ra
return false;
}
-void ARM_NCE::HandleHostFault(int sig, void* raw_info, void* raw_context) {
+void ArmNce::HandleHostFault(int sig, void* raw_info, void* raw_context) {
return g_orig_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context);
}
-HaltReason ARM_NCE::RunJit() {
- // Get the thread parameters.
- // TODO: pass the current thread down from ::Run
- auto* thread = Kernel::GetCurrentThreadPointer(system.Kernel());
+void ArmNce::LockThread(Kernel::KThread* thread) {
auto* thread_params = &thread->GetNativeExecutionParameters();
+ LockThreadParameters(thread_params);
+}
- {
- // Lock our core context.
- std::scoped_lock lk{lock};
-
- // We should not be running.
- ASSERT(running_thread == nullptr);
-
- // Check if we need to run. If we have already been halted, we are done.
- u64 halt = guest_ctx.esr_el1.exchange(0);
- if (halt != 0) {
- return static_cast<HaltReason>(halt);
- }
-
- // Mark that we are running.
- running_thread = thread;
+void ArmNce::UnlockThread(Kernel::KThread* thread) {
+ auto* thread_params = &thread->GetNativeExecutionParameters();
+ UnlockThreadParameters(thread_params);
+}
- // Acquire the lock on the thread parameters.
- // This allows us to force synchronization with SignalInterrupt.
- LockThreadParameters(thread_params);
+HaltReason ArmNce::RunThread(Kernel::KThread* thread) {
+ // Check if we're already interrupted.
+ // If we are, we can just return immediately.
+ HaltReason hr = static_cast<HaltReason>(m_guest_ctx.esr_el1.exchange(0));
+ if (True(hr)) {
+ return hr;
}
+ // Get the thread context.
+ auto* thread_params = &thread->GetNativeExecutionParameters();
+ auto* process = thread->GetOwnerProcess();
+
// Assign current members.
- guest_ctx.parent = this;
- thread_params->native_context = &guest_ctx;
- thread_params->tpidr_el0 = guest_ctx.tpidr_el0;
- thread_params->tpidrro_el0 = guest_ctx.tpidrro_el0;
+ m_running_thread = thread;
+ m_guest_ctx.parent = this;
+ thread_params->native_context = &m_guest_ctx;
+ thread_params->tpidr_el0 = m_guest_ctx.tpidr_el0;
+ thread_params->tpidrro_el0 = m_guest_ctx.tpidrro_el0;
thread_params->is_running = true;
- HaltReason halt{};
-
// TODO: finding and creating the post handler needs to be locked
// to deal with dynamic loading of NROs.
- const auto& post_handlers = system.ApplicationProcess()->GetPostHandlers();
- if (auto it = post_handlers.find(guest_ctx.pc); it != post_handlers.end()) {
- halt = ReturnToRunCodeByTrampoline(thread_params, &guest_ctx, it->second);
+ const auto& post_handlers = process->GetPostHandlers();
+ if (auto it = post_handlers.find(m_guest_ctx.pc); it != post_handlers.end()) {
+ hr = ReturnToRunCodeByTrampoline(thread_params, &m_guest_ctx, it->second);
} else {
- halt = ReturnToRunCodeByExceptionLevelChange(thread_id, thread_params);
+ hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params);
}
// Unload members.
// The thread does not change, so we can persist the old reference.
- guest_ctx.tpidr_el0 = thread_params->tpidr_el0;
+ m_running_thread = nullptr;
+ m_guest_ctx.tpidr_el0 = thread_params->tpidr_el0;
thread_params->native_context = nullptr;
thread_params->is_running = false;
- // Unlock the thread parameters.
- UnlockThreadParameters(thread_params);
-
- {
- // Lock the core context.
- std::scoped_lock lk{lock};
-
- // On exit, we no longer have an active thread.
- running_thread = nullptr;
- }
-
// Return the halt reason.
- return halt;
+ return hr;
}
-HaltReason ARM_NCE::StepJit() {
+HaltReason ArmNce::StepThread(Kernel::KThread* thread) {
return HaltReason::StepThread;
}
-u32 ARM_NCE::GetSvcNumber() const {
- return guest_ctx.svc_swi;
+u32 ArmNce::GetSvcNumber() const {
+ return m_guest_ctx.svc;
+}
+
+void ArmNce::GetSvcArguments(std::span<uint64_t, 8> args) const {
+ for (size_t i = 0; i < 8; i++) {
+ args[i] = m_guest_ctx.cpu_registers[i];
+ }
+}
+
+void ArmNce::SetSvcArguments(std::span<const uint64_t, 8> args) {
+ for (size_t i = 0; i < 8; i++) {
+ m_guest_ctx.cpu_registers[i] = args[i];
+ }
}
-ARM_NCE::ARM_NCE(System& system_, bool uses_wall_clock_, std::size_t core_index_)
- : ARM_Interface{system_, uses_wall_clock_}, core_index{core_index_} {
- guest_ctx.system = &system_;
+ArmNce::ArmNce(System& system, bool uses_wall_clock, std::size_t core_index)
+ : ArmInterface{uses_wall_clock}, m_system{system}, m_core_index{core_index} {
+ m_guest_ctx.system = &m_system;
}
-ARM_NCE::~ARM_NCE() = default;
+ArmNce::~ArmNce() = default;
-void ARM_NCE::Initialize() {
- thread_id = gettid();
+void ArmNce::Initialize() {
+ m_thread_id = gettid();
// Setup our signals
- static std::once_flag flag;
- std::call_once(flag, [] {
+ static std::once_flag signals;
+ std::call_once(signals, [] {
using HandlerType = decltype(sigaction::sa_sigaction);
sigset_t signal_mask;
@@ -244,7 +241,7 @@ void ARM_NCE::Initialize() {
struct sigaction return_to_run_code_action {};
return_to_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
return_to_run_code_action.sa_sigaction = reinterpret_cast<HandlerType>(
- &ARM_NCE::ReturnToRunCodeByExceptionLevelChangeSignalHandler);
+ &ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler);
return_to_run_code_action.sa_mask = signal_mask;
Common::SigAction(ReturnToRunCodeByExceptionLevelChangeSignal, &return_to_run_code_action,
nullptr);
@@ -252,14 +249,13 @@ void ARM_NCE::Initialize() {
struct sigaction break_from_run_code_action {};
break_from_run_code_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
break_from_run_code_action.sa_sigaction =
- reinterpret_cast<HandlerType>(&ARM_NCE::BreakFromRunCodeSignalHandler);
+ reinterpret_cast<HandlerType>(&ArmNce::BreakFromRunCodeSignalHandler);
break_from_run_code_action.sa_mask = signal_mask;
Common::SigAction(BreakFromRunCodeSignal, &break_from_run_code_action, nullptr);
struct sigaction fault_action {};
fault_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
- fault_action.sa_sigaction =
- reinterpret_cast<HandlerType>(&ARM_NCE::GuestFaultSignalHandler);
+ fault_action.sa_sigaction = reinterpret_cast<HandlerType>(&ArmNce::GuestFaultSignalHandler);
fault_action.sa_mask = signal_mask;
Common::SigAction(GuestFaultSignal, &fault_action, &g_orig_action);
@@ -272,111 +268,59 @@ void ARM_NCE::Initialize() {
});
}
-void ARM_NCE::SetPC(u64 pc) {
- guest_ctx.pc = pc;
+void ArmNce::SetTpidrroEl0(u64 value) {
+ m_guest_ctx.tpidrro_el0 = value;
}
-u64 ARM_NCE::GetPC() const {
- return guest_ctx.pc;
-}
-
-u64 ARM_NCE::GetSP() const {
- return guest_ctx.sp;
-}
-
-u64 ARM_NCE::GetReg(int index) const {
- return guest_ctx.cpu_registers[index];
-}
-
-void ARM_NCE::SetReg(int index, u64 value) {
- guest_ctx.cpu_registers[index] = value;
-}
-
-u128 ARM_NCE::GetVectorReg(int index) const {
- return guest_ctx.vector_registers[index];
-}
-
-void ARM_NCE::SetVectorReg(int index, u128 value) {
- guest_ctx.vector_registers[index] = value;
-}
-
-u32 ARM_NCE::GetPSTATE() const {
- return guest_ctx.pstate;
-}
-
-void ARM_NCE::SetPSTATE(u32 pstate) {
- guest_ctx.pstate = pstate;
-}
-
-u64 ARM_NCE::GetTlsAddress() const {
- return guest_ctx.tpidrro_el0;
-}
-
-void ARM_NCE::SetTlsAddress(u64 address) {
- guest_ctx.tpidrro_el0 = address;
-}
-
-u64 ARM_NCE::GetTPIDR_EL0() const {
- return guest_ctx.tpidr_el0;
-}
-
-void ARM_NCE::SetTPIDR_EL0(u64 value) {
- guest_ctx.tpidr_el0 = value;
-}
-
-void ARM_NCE::SaveContext(ThreadContext64& ctx) const {
- ctx.cpu_registers = guest_ctx.cpu_registers;
- ctx.sp = guest_ctx.sp;
- ctx.pc = guest_ctx.pc;
- ctx.pstate = guest_ctx.pstate;
- ctx.vector_registers = guest_ctx.vector_registers;
- ctx.fpcr = guest_ctx.fpcr;
- ctx.fpsr = guest_ctx.fpsr;
- ctx.tpidr = guest_ctx.tpidr_el0;
+void ArmNce::GetContext(Kernel::Svc::ThreadContext& ctx) const {
+ for (size_t i = 0; i < 29; i++) {
+ ctx.r[i] = m_guest_ctx.cpu_registers[i];
+ }
+ ctx.fp = m_guest_ctx.cpu_registers[29];
+ ctx.lr = m_guest_ctx.cpu_registers[30];
+ ctx.sp = m_guest_ctx.sp;
+ ctx.pc = m_guest_ctx.pc;
+ ctx.pstate = m_guest_ctx.pstate;
+ ctx.v = m_guest_ctx.vector_registers;
+ ctx.fpcr = m_guest_ctx.fpcr;
+ ctx.fpsr = m_guest_ctx.fpsr;
+ ctx.tpidr = m_guest_ctx.tpidr_el0;
}
-void ARM_NCE::LoadContext(const ThreadContext64& ctx) {
- guest_ctx.cpu_registers = ctx.cpu_registers;
- guest_ctx.sp = ctx.sp;
- guest_ctx.pc = ctx.pc;
- guest_ctx.pstate = ctx.pstate;
- guest_ctx.vector_registers = ctx.vector_registers;
- guest_ctx.fpcr = ctx.fpcr;
- guest_ctx.fpsr = ctx.fpsr;
- guest_ctx.tpidr_el0 = ctx.tpidr;
+void ArmNce::SetContext(const Kernel::Svc::ThreadContext& ctx) {
+ for (size_t i = 0; i < 29; i++) {
+ m_guest_ctx.cpu_registers[i] = ctx.r[i];
+ }
+ m_guest_ctx.cpu_registers[29] = ctx.fp;
+ m_guest_ctx.cpu_registers[30] = ctx.lr;
+ m_guest_ctx.sp = ctx.sp;
+ m_guest_ctx.pc = ctx.pc;
+ m_guest_ctx.pstate = ctx.pstate;
+ m_guest_ctx.vector_registers = ctx.v;
+ m_guest_ctx.fpcr = ctx.fpcr;
+ m_guest_ctx.fpsr = ctx.fpsr;
+ m_guest_ctx.tpidr_el0 = ctx.tpidr;
}
-void ARM_NCE::SignalInterrupt() {
- // Lock core context.
- std::scoped_lock lk{lock};
-
+void ArmNce::SignalInterrupt(Kernel::KThread* thread) {
// Add break loop condition.
- guest_ctx.esr_el1.fetch_or(static_cast<u64>(HaltReason::BreakLoop));
-
- // If there is no thread running, we are done.
- if (running_thread == nullptr) {
- return;
- }
+ m_guest_ctx.esr_el1.fetch_or(static_cast<u64>(HaltReason::BreakLoop));
// Lock the thread context.
- auto* params = &running_thread->GetNativeExecutionParameters();
+ auto* params = &thread->GetNativeExecutionParameters();
LockThreadParameters(params);
if (params->is_running) {
// We should signal to the running thread.
// The running thread will unlock the thread context.
- syscall(SYS_tkill, thread_id, BreakFromRunCodeSignal);
+ syscall(SYS_tkill, m_thread_id, BreakFromRunCodeSignal);
} else {
// If the thread is no longer running, we have nothing to do.
UnlockThreadParameters(params);
}
}
-void ARM_NCE::ClearInterrupt() {
- guest_ctx.esr_el1 = {};
-}
-
-void ARM_NCE::ClearInstructionCache() {
+void ArmNce::ClearInstructionCache() {
// TODO: This is not possible to implement correctly on Linux because
// we do not have any access to ic iallu.
@@ -384,17 +328,8 @@ void ARM_NCE::ClearInstructionCache() {
std::atomic_thread_fence(std::memory_order_seq_cst);
}
-void ARM_NCE::InvalidateCacheRange(u64 addr, std::size_t size) {
+void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) {
this->ClearInstructionCache();
}
-void ARM_NCE::ClearExclusiveState() {
- // No-op.
-}
-
-void ARM_NCE::PageTableChanged(Common::PageTable& page_table,
- std::size_t new_address_space_size_in_bits) {
- // No-op. Page table is never used.
-}
-
} // namespace Core
diff --git a/src/core/arm/nce/arm_nce.h b/src/core/arm/nce/arm_nce.h
index 5fbd6dbf3..f55c10d1d 100644
--- a/src/core/arm/nce/arm_nce.h
+++ b/src/core/arm/nce/arm_nce.h
@@ -3,11 +3,7 @@
#pragma once
-#include <atomic>
-#include <memory>
-#include <span>
-#include <unordered_map>
-#include <vector>
+#include <mutex>
#include "core/arm/arm_interface.h"
#include "core/arm/nce/guest_context.h"
@@ -20,51 +16,36 @@ namespace Core {
class System;
-class ARM_NCE final : public ARM_Interface {
+class ArmNce final : public ArmInterface {
public:
- ARM_NCE(System& system_, bool uses_wall_clock_, std::size_t core_index_);
-
- ~ARM_NCE() override;
+ ArmNce(System& system, bool uses_wall_clock, std::size_t core_index);
+ ~ArmNce() override;
void Initialize() override;
- void SetPC(u64 pc) override;
- u64 GetPC() const override;
- u64 GetSP() const override;
- u64 GetReg(int index) const override;
- void SetReg(int index, u64 value) override;
- u128 GetVectorReg(int index) const override;
- void SetVectorReg(int index, u128 value) override;
-
- u32 GetPSTATE() const override;
- void SetPSTATE(u32 pstate) override;
- u64 GetTlsAddress() const override;
- void SetTlsAddress(u64 address) override;
- void SetTPIDR_EL0(u64 value) override;
- u64 GetTPIDR_EL0() const override;
Architecture GetArchitecture() const override {
- return Architecture::Aarch64;
+ return Architecture::AArch64;
}
- void SaveContext(ThreadContext32& ctx) const override {}
- void SaveContext(ThreadContext64& ctx) const override;
- void LoadContext(const ThreadContext32& ctx) override {}
- void LoadContext(const ThreadContext64& ctx) override;
+ HaltReason RunThread(Kernel::KThread* thread) override;
+ HaltReason StepThread(Kernel::KThread* thread) override;
+
+ void GetContext(Kernel::Svc::ThreadContext& ctx) const override;
+ void SetContext(const Kernel::Svc::ThreadContext& ctx) override;
+ void SetTpidrroEl0(u64 value) override;
- void SignalInterrupt() override;
- void ClearInterrupt() override;
- void ClearExclusiveState() override;
+ void GetSvcArguments(std::span<uint64_t, 8> args) const override;
+ void SetSvcArguments(std::span<const uint64_t, 8> args) override;
+ u32 GetSvcNumber() const override;
+
+ void SignalInterrupt(Kernel::KThread* thread) override;
void ClearInstructionCache() override;
void InvalidateCacheRange(u64 addr, std::size_t size) override;
- void PageTableChanged(Common::PageTable& new_page_table,
- std::size_t new_address_space_size_in_bits) override;
-
-protected:
- HaltReason RunJit() override;
- HaltReason StepJit() override;
- u32 GetSvcNumber() const override;
+ void LockThread(Kernel::KThread* thread) override;
+ void UnlockThread(Kernel::KThread* thread) override;
+protected:
const Kernel::DebugWatchpoint* HaltedWatchpoint() const override {
return nullptr;
}
@@ -93,16 +74,15 @@ private:
static void HandleHostFault(int sig, void* info, void* raw_context);
public:
+ Core::System& m_system;
+
// Members set on initialization.
- std::size_t core_index{};
- pid_t thread_id{-1};
+ std::size_t m_core_index{};
+ pid_t m_thread_id{-1};
// Core context.
- GuestContext guest_ctx;
-
- // Thread and invalidation info.
- std::mutex lock;
- Kernel::KThread* running_thread{};
+ GuestContext m_guest_ctx{};
+ Kernel::KThread* m_running_thread{};
};
} // namespace Core
diff --git a/src/core/arm/nce/arm_nce.s b/src/core/arm/nce/arm_nce.s
index b98e09f31..4aeda4740 100644
--- a/src/core/arm/nce/arm_nce.s
+++ b/src/core/arm/nce/arm_nce.s
@@ -8,11 +8,11 @@
movk reg, #(((val) >> 0x10) & 0xFFFF), lsl #16
-/* static HaltReason Core::ARM_NCE::ReturnToRunCodeByTrampoline(void* tpidr, Core::GuestContext* ctx, u64 trampoline_addr) */
-.section .text._ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, "ax", %progbits
-.global _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm
-.type _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, %function
-_ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
+/* static HaltReason Core::ArmNce::ReturnToRunCodeByTrampoline(void* tpidr, Core::GuestContext* ctx, u64 trampoline_addr) */
+.section .text._ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, "ax", %progbits
+.global _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm
+.type _ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, %function
+_ZN4Core6ArmNce27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
/* Back up host sp to x3. */
/* Back up host tpidr_el0 to x4. */
mov x3, sp
@@ -49,11 +49,11 @@ _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
br x2
-/* static HaltReason Core::ARM_NCE::ReturnToRunCodeByExceptionLevelChange(int tid, void* tpidr) */
-.section .text._ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv, "ax", %progbits
-.global _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv
-.type _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv, %function
-_ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv:
+/* static HaltReason Core::ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void* tpidr) */
+.section .text._ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv, "ax", %progbits
+.global _ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv
+.type _ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv, %function
+_ZN4Core6ArmNce37ReturnToRunCodeByExceptionLevelChangeEiPv:
/* This jumps to the signal handler, which will restore the entire context. */
/* On entry, x0 = thread id, which is already in the right place. */
@@ -71,17 +71,17 @@ _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv:
brk #1000
-/* static void Core::ARM_NCE::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context) */
-.section .text._ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, "ax", %progbits
-.global _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
-.type _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, %function
-_ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
+/* static void Core::ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context) */
+.section .text._ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, "ax", %progbits
+.global _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
+.type _ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, %function
+_ZN4Core6ArmNce50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
stp x29, x30, [sp, #-0x10]!
mov x29, sp
/* Call the context restorer with the raw context. */
mov x0, x2
- bl _ZN4Core7ARM_NCE19RestoreGuestContextEPv
+ bl _ZN4Core6ArmNce19RestoreGuestContextEPv
/* Save the old value of tpidr_el0. */
mrs x8, tpidr_el0
@@ -92,18 +92,18 @@ _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
msr tpidr_el0, x0
/* Unlock the context. */
- bl _ZN4Core7ARM_NCE22UnlockThreadParametersEPv
+ bl _ZN4Core6ArmNce22UnlockThreadParametersEPv
/* Returning from here will enter the guest. */
ldp x29, x30, [sp], #0x10
ret
-/* static void Core::ARM_NCE::BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context) */
-.section .text._ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_, "ax", %progbits
-.global _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_
-.type _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_, %function
-_ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_:
+/* static void Core::ArmNce::BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context) */
+.section .text._ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_, "ax", %progbits
+.global _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_
+.type _ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_, %function
+_ZN4Core6ArmNce29BreakFromRunCodeSignalHandlerEiPvS1_:
/* Check to see if we have the correct TLS magic. */
mrs x8, tpidr_el0
ldr w9, [x8, #(TpidrEl0TlsMagic)]
@@ -121,7 +121,7 @@ _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_:
/* Tail call the restorer. */
mov x1, x2
- b _ZN4Core7ARM_NCE16SaveGuestContextEPNS_12GuestContextEPv
+ b _ZN4Core6ArmNce16SaveGuestContextEPNS_12GuestContextEPv
/* Returning from here will enter host code. */
@@ -130,11 +130,11 @@ _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_:
ret
-/* static void Core::ARM_NCE::GuestFaultSignalHandler(int sig, void* info, void* raw_context) */
-.section .text._ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_, "ax", %progbits
-.global _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_
-.type _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_, %function
-_ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_:
+/* static void Core::ArmNce::GuestFaultSignalHandler(int sig, void* info, void* raw_context) */
+.section .text._ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_, "ax", %progbits
+.global _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_
+.type _ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_, %function
+_ZN4Core6ArmNce23GuestFaultSignalHandlerEiPvS1_:
/* Check to see if we have the correct TLS magic. */
mrs x8, tpidr_el0
ldr w9, [x8, #(TpidrEl0TlsMagic)]
@@ -146,7 +146,7 @@ _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_:
/* Incorrect TLS magic, so this is a host fault. */
/* Tail call the handler. */
- b _ZN4Core7ARM_NCE15HandleHostFaultEiPvS1_
+ b _ZN4Core6ArmNce15HandleHostFaultEiPvS1_
1:
/* Correct TLS magic, so this is a guest fault. */
@@ -163,7 +163,7 @@ _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_:
msr tpidr_el0, x3
/* Call the handler. */
- bl _ZN4Core7ARM_NCE16HandleGuestFaultEPNS_12GuestContextEPvS3_
+ bl _ZN4Core6ArmNce16HandleGuestFaultEPNS_12GuestContextEPvS3_
/* If the handler returned false, we want to preserve the host tpidr_el0. */
cbz x0, 2f
@@ -177,11 +177,11 @@ _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_:
ret
-/* static void Core::ARM_NCE::LockThreadParameters(void* tpidr) */
-.section .text._ZN4Core7ARM_NCE20LockThreadParametersEPv, "ax", %progbits
-.global _ZN4Core7ARM_NCE20LockThreadParametersEPv
-.type _ZN4Core7ARM_NCE20LockThreadParametersEPv, %function
-_ZN4Core7ARM_NCE20LockThreadParametersEPv:
+/* static void Core::ArmNce::LockThreadParameters(void* tpidr) */
+.section .text._ZN4Core6ArmNce20LockThreadParametersEPv, "ax", %progbits
+.global _ZN4Core6ArmNce20LockThreadParametersEPv
+.type _ZN4Core6ArmNce20LockThreadParametersEPv, %function
+_ZN4Core6ArmNce20LockThreadParametersEPv:
/* Offset to lock member. */
add x0, x0, #(TpidrEl0Lock)
@@ -205,11 +205,11 @@ _ZN4Core7ARM_NCE20LockThreadParametersEPv:
ret
-/* static void Core::ARM_NCE::UnlockThreadParameters(void* tpidr) */
-.section .text._ZN4Core7ARM_NCE22UnlockThreadParametersEPv, "ax", %progbits
-.global _ZN4Core7ARM_NCE22UnlockThreadParametersEPv
-.type _ZN4Core7ARM_NCE22UnlockThreadParametersEPv, %function
-_ZN4Core7ARM_NCE22UnlockThreadParametersEPv:
+/* static void Core::ArmNce::UnlockThreadParameters(void* tpidr) */
+.section .text._ZN4Core6ArmNce22UnlockThreadParametersEPv, "ax", %progbits
+.global _ZN4Core6ArmNce22UnlockThreadParametersEPv
+.type _ZN4Core6ArmNce22UnlockThreadParametersEPv, %function
+_ZN4Core6ArmNce22UnlockThreadParametersEPv:
/* Offset to lock member. */
add x0, x0, #(TpidrEl0Lock)
diff --git a/src/core/arm/nce/guest_context.h b/src/core/arm/nce/guest_context.h
index 0767a0337..a7eadccce 100644
--- a/src/core/arm/nce/guest_context.h
+++ b/src/core/arm/nce/guest_context.h
@@ -3,6 +3,8 @@
#pragma once
+#include <atomic>
+
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
@@ -10,7 +12,7 @@
namespace Core {
-class ARM_NCE;
+class ArmNce;
class System;
struct HostContext {
@@ -33,9 +35,9 @@ struct GuestContext {
u64 tpidr_el0{};
std::atomic<u64> esr_el1{};
u32 nzcv{};
- u32 svc_swi{};
+ u32 svc{};
System* system{};
- ARM_NCE* parent{};
+ ArmNce* parent{};
};
// Verify assembly offsets.
diff --git a/src/core/arm/nce/patcher.cpp b/src/core/arm/nce/patcher.cpp
index bdaa3af49..47a7a8880 100644
--- a/src/core/arm/nce/patcher.cpp
+++ b/src/core/arm/nce/patcher.cpp
@@ -280,7 +280,7 @@ void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) {
// Store SVC number to execute when we return
c.MOV(X2, svc_id);
- c.STR(W2, X1, offsetof(GuestContext, svc_swi));
+ c.STR(W2, X1, offsetof(GuestContext, svc));
// We are calling a SVC. Clear esr_el1 and return it.
static_assert(std::is_same_v<std::underlying_type_t<HaltReason>, u64>);
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 14d6c8c27..b14f74976 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -36,6 +36,7 @@
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
+#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/filesystem/filesystem.h"
@@ -130,8 +131,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{},
- cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system},
- gpu_dirty_memory_write_manager{} {
+ cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{},
+ time_manager{system}, gpu_dirty_memory_write_manager{} {
memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager);
}
@@ -323,7 +324,6 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
- kernel.InitializeCores();
// Initialize cheat engine
if (cheat_engine) {
@@ -533,6 +533,7 @@ struct System::Impl {
/// Service State
Service::Glue::ARPManager arp_manager;
+ Service::Account::ProfileManager profile_manager;
Service::Time::TimeManager time_manager;
/// Service manager
@@ -600,14 +601,6 @@ bool System::IsPaused() const {
return impl->IsPaused();
}
-void System::InvalidateCpuInstructionCaches() {
- impl->kernel.InvalidateAllInstructionCaches();
-}
-
-void System::InvalidateCpuInstructionCacheRange(u64 addr, std::size_t size) {
- impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
-}
-
void System::ShutdownMainProcess() {
impl->ShutdownMainProcess();
}
@@ -696,14 +689,6 @@ const TelemetrySession& System::TelemetrySession() const {
return *impl->telemetry_session;
}
-ARM_Interface& System::CurrentArmInterface() {
- return impl->kernel.CurrentPhysicalCore().ArmInterface();
-}
-
-const ARM_Interface& System::CurrentArmInterface() const {
- return impl->kernel.CurrentPhysicalCore().ArmInterface();
-}
-
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
return impl->kernel.CurrentPhysicalCore();
}
@@ -738,14 +723,6 @@ const Kernel::KProcess* System::ApplicationProcess() const {
return impl->kernel.ApplicationProcess();
}
-ARM_Interface& System::ArmInterface(std::size_t core_index) {
- return impl->kernel.PhysicalCore(core_index).ArmInterface();
-}
-
-const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
- return impl->kernel.PhysicalCore(core_index).ArmInterface();
-}
-
ExclusiveMonitor& System::Monitor() {
return impl->kernel.GetExclusiveMonitor();
}
@@ -946,6 +923,14 @@ const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller;
}
+Service::Account::ProfileManager& System::GetProfileManager() {
+ return impl->profile_manager;
+}
+
+const Service::Account::ProfileManager& System::GetProfileManager() const {
+ return impl->profile_manager;
+}
+
Service::Time::TimeManager& System::GetTimeManager() {
return impl->time_manager;
}
diff --git a/src/core/core.h b/src/core/core.h
index df20f26f3..473204db7 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -45,6 +45,10 @@ class Memory;
namespace Service {
+namespace Account {
+class ProfileManager;
+} // namespace Account
+
namespace AM::Applets {
struct AppletFrontendSet;
class AppletManager;
@@ -108,7 +112,6 @@ class RenderdocAPI;
namespace Core {
-class ARM_Interface;
class CpuManager;
class Debugger;
class DeviceMemory;
@@ -171,15 +174,6 @@ public:
/// Check if the core is currently paused.
[[nodiscard]] bool IsPaused() const;
- /**
- * Invalidate the CPU instruction caches
- * This function should only be used by GDB Stub to support breakpoints, memory updates and
- * step/continue commands.
- */
- void InvalidateCpuInstructionCaches();
-
- void InvalidateCpuInstructionCacheRange(u64 addr, std::size_t size);
-
/// Shutdown the main emulated process.
void ShutdownMainProcess();
@@ -244,24 +238,12 @@ public:
/// Gets and resets core performance statistics
[[nodiscard]] PerfStatsResults GetAndResetPerfStats();
- /// Gets an ARM interface to the CPU core that is currently running
- [[nodiscard]] ARM_Interface& CurrentArmInterface();
-
- /// Gets an ARM interface to the CPU core that is currently running
- [[nodiscard]] const ARM_Interface& CurrentArmInterface() const;
-
/// Gets the physical core for the CPU core that is currently running
[[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore();
/// Gets the physical core for the CPU core that is currently running
[[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const;
- /// Gets a reference to an ARM interface for the CPU core with the specified index
- [[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index);
-
- /// Gets a const reference to an ARM interface from the CPU core with the specified index
- [[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const;
-
/// Gets a reference to the underlying CPU manager.
[[nodiscard]] CpuManager& GetCpuManager();
@@ -405,6 +387,9 @@ public:
[[nodiscard]] Service::APM::Controller& GetAPMController();
[[nodiscard]] const Service::APM::Controller& GetAPMController() const;
+ [[nodiscard]] Service::Account::ProfileManager& GetProfileManager();
+ [[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const;
+
[[nodiscard]] Service::Time::TimeManager& GetTimeManager();
[[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const;
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 151eb3870..7a5c22f78 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -73,12 +73,13 @@ void CpuManager::HandleInterrupt() {
void CpuManager::MultiCoreRunGuestThread() {
// Similar to UserModeThreadStarter in HOS
auto& kernel = system.Kernel();
+ auto* thread = Kernel::GetCurrentThreadPointer(kernel);
kernel.CurrentScheduler()->OnThreadStart();
while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore();
while (!physical_core->IsInterrupted()) {
- physical_core->Run();
+ physical_core->RunThread(thread);
physical_core = &kernel.CurrentPhysicalCore();
}
@@ -110,12 +111,13 @@ void CpuManager::MultiCoreRunIdleThread() {
void CpuManager::SingleCoreRunGuestThread() {
auto& kernel = system.Kernel();
+ auto* thread = Kernel::GetCurrentThreadPointer(kernel);
kernel.CurrentScheduler()->OnThreadStart();
while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore();
if (!physical_core->IsInterrupted()) {
- physical_core->Run();
+ physical_core->RunThread(thread);
physical_core = &kernel.CurrentPhysicalCore();
}
@@ -211,8 +213,6 @@ void CpuManager::RunThread(std::stop_token token, std::size_t core) {
system.GPU().ObtainContext();
}
- system.ArmInterface(core).Initialize();
-
auto& kernel = system.Kernel();
auto& scheduler = *kernel.CurrentScheduler();
auto* thread = scheduler.GetSchedulerCurrentThread();
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 148dd3e39..66e46c4ba 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -16,6 +16,7 @@
#include "common/settings.h"
#include "common/string_util.h"
#include "core/arm/arm_interface.h"
+#include "core/arm/debug.h"
#include "core/core.h"
#include "core/debugger/gdbstub.h"
#include "core/debugger/gdbstub_arch.h"
@@ -310,7 +311,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
const auto mem{Common::HexStringToVector(mem_substr, false)};
if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) {
- system.InvalidateCpuInstructionCacheRange(addr, size);
+ Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size);
SendReply(GDB_STUB_REPLY_OK);
} else {
SendReply(GDB_STUB_REPLY_ERR);
@@ -363,7 +364,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
case BreakpointType::Software:
replaced_instructions[addr] = system.ApplicationMemory().Read32(addr);
system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction());
- system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
+ Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
success = true;
break;
case BreakpointType::WriteWatch:
@@ -411,7 +412,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
const auto orig_insn{replaced_instructions.find(addr)};
if (orig_insn != replaced_instructions.end()) {
system.ApplicationMemory().Write32(addr, orig_insn->second);
- system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
+ Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
replaced_instructions.erase(addr);
success = true;
}
@@ -442,114 +443,6 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
}
}
-// Structure offsets are from Atmosphere
-// See osdbg_thread_local_region.os.horizon.hpp and osdbg_thread_type.os.horizon.hpp
-
-static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory,
- const Kernel::KThread& thread) {
- // Read thread type from TLS
- const VAddr tls_thread_type{memory.Read32(thread.GetTlsAddress() + 0x1fc)};
- const VAddr argument_thread_type{thread.GetArgument()};
-
- if (argument_thread_type && tls_thread_type != argument_thread_type) {
- // Probably not created by nnsdk, no name available.
- return std::nullopt;
- }
-
- if (!tls_thread_type) {
- return std::nullopt;
- }
-
- const u16 version{memory.Read16(tls_thread_type + 0x26)};
- VAddr name_pointer{};
- if (version == 1) {
- name_pointer = memory.Read32(tls_thread_type + 0xe4);
- } else {
- name_pointer = memory.Read32(tls_thread_type + 0xe8);
- }
-
- if (!name_pointer) {
- // No name provided.
- return std::nullopt;
- }
-
- return memory.ReadCString(name_pointer, 256);
-}
-
-static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory,
- const Kernel::KThread& thread) {
- // Read thread type from TLS
- const VAddr tls_thread_type{memory.Read64(thread.GetTlsAddress() + 0x1f8)};
- const VAddr argument_thread_type{thread.GetArgument()};
-
- if (argument_thread_type && tls_thread_type != argument_thread_type) {
- // Probably not created by nnsdk, no name available.
- return std::nullopt;
- }
-
- if (!tls_thread_type) {
- return std::nullopt;
- }
-
- const u16 version{memory.Read16(tls_thread_type + 0x46)};
- VAddr name_pointer{};
- if (version == 1) {
- name_pointer = memory.Read64(tls_thread_type + 0x1a0);
- } else {
- name_pointer = memory.Read64(tls_thread_type + 0x1a8);
- }
-
- if (!name_pointer) {
- // No name provided.
- return std::nullopt;
- }
-
- return memory.ReadCString(name_pointer, 256);
-}
-
-static std::optional<std::string> GetThreadName(Core::System& system,
- const Kernel::KThread& thread) {
- if (system.ApplicationProcess()->Is64Bit()) {
- return GetNameFromThreadType64(system.ApplicationMemory(), thread);
- } else {
- return GetNameFromThreadType32(system.ApplicationMemory(), thread);
- }
-}
-
-static std::string_view GetThreadWaitReason(const Kernel::KThread& thread) {
- switch (thread.GetWaitReasonForDebugging()) {
- case Kernel::ThreadWaitReasonForDebugging::Sleep:
- return "Sleep";
- case Kernel::ThreadWaitReasonForDebugging::IPC:
- return "IPC";
- case Kernel::ThreadWaitReasonForDebugging::Synchronization:
- return "Synchronization";
- case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
- return "ConditionVar";
- case Kernel::ThreadWaitReasonForDebugging::Arbitration:
- return "Arbitration";
- case Kernel::ThreadWaitReasonForDebugging::Suspended:
- return "Suspended";
- default:
- return "Unknown";
- }
-}
-
-static std::string GetThreadState(const Kernel::KThread& thread) {
- switch (thread.GetState()) {
- case Kernel::ThreadState::Initialized:
- return "Initialized";
- case Kernel::ThreadState::Waiting:
- return fmt::format("Waiting ({})", GetThreadWaitReason(thread));
- case Kernel::ThreadState::Runnable:
- return "Runnable";
- case Kernel::ThreadState::Terminated:
- return "Terminated";
- default:
- return "Unknown";
- }
-}
-
static std::string PaginateBuffer(std::string_view buffer, std::string_view request) {
const auto amount{request.substr(request.find(',') + 1)};
const auto offset_val{static_cast<u64>(strtoll(request.data(), nullptr, 16))};
@@ -562,120 +455,6 @@ static std::string PaginateBuffer(std::string_view buffer, std::string_view requ
}
}
-static VAddr GetModuleEnd(Kernel::KProcessPageTable& page_table, VAddr base) {
- Kernel::KMemoryInfo mem_info;
- Kernel::Svc::MemoryInfo svc_mem_info;
- Kernel::Svc::PageInfo page_info;
- VAddr cur_addr{base};
-
- // Expect: r-x Code (.text)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
- svc_mem_info.permission != Kernel::Svc::MemoryPermission::ReadExecute) {
- return cur_addr - 1;
- }
-
- // Expect: r-- Code (.rodata)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- if (svc_mem_info.state != Kernel::Svc::MemoryState::Code ||
- svc_mem_info.permission != Kernel::Svc::MemoryPermission::Read) {
- return cur_addr - 1;
- }
-
- // Expect: rw- CodeData (.data)
- R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- svc_mem_info = mem_info.GetSvcMemoryInfo();
- cur_addr = svc_mem_info.base_address + svc_mem_info.size;
- return cur_addr - 1;
-}
-
-static Loader::AppLoader::Modules FindModules(Core::System& system) {
- Loader::AppLoader::Modules modules;
-
- auto& page_table = system.ApplicationProcess()->GetPageTable();
- auto& memory = system.ApplicationMemory();
- VAddr cur_addr = 0;
-
- // Look for executable sections in Code or AliasCode regions.
- while (true) {
- Kernel::KMemoryInfo mem_info{};
- Kernel::Svc::PageInfo page_info{};
- R_ASSERT(
- page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), cur_addr));
- auto svc_mem_info = mem_info.GetSvcMemoryInfo();
-
- if (svc_mem_info.permission == Kernel::Svc::MemoryPermission::ReadExecute &&
- (svc_mem_info.state == Kernel::Svc::MemoryState::Code ||
- svc_mem_info.state == Kernel::Svc::MemoryState::AliasCode)) {
- // Try to read the module name from its path.
- constexpr s32 PathLengthMax = 0x200;
- struct {
- u32 zero;
- s32 path_length;
- std::array<char, PathLengthMax> path;
- } module_path;
-
- if (memory.ReadBlock(svc_mem_info.base_address + svc_mem_info.size, &module_path,
- sizeof(module_path))) {
- if (module_path.zero == 0 && module_path.path_length > 0) {
- // Truncate module name.
- module_path.path[PathLengthMax - 1] = '\0';
-
- // Ignore leading directories.
- char* path_pointer = module_path.path.data();
-
- for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) &&
- module_path.path[i] != '\0';
- i++) {
- if (module_path.path[i] == '/' || module_path.path[i] == '\\') {
- path_pointer = module_path.path.data() + i + 1;
- }
- }
-
- // Insert output.
- modules.emplace(svc_mem_info.base_address, path_pointer);
- }
- }
- }
-
- // Check if we're done.
- const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
- if (next_address <= cur_addr) {
- break;
- }
-
- cur_addr = next_address;
- }
-
- return modules;
-}
-
-static VAddr FindMainModuleEntrypoint(Core::System& system) {
- Loader::AppLoader::Modules modules;
- system.GetAppLoader().ReadNSOModules(modules);
-
- // Do we have a module named main?
- const auto main = std::find_if(modules.begin(), modules.end(),
- [](const auto& key) { return key.second == "main"; });
-
- if (main != modules.end()) {
- return main->first;
- }
-
- // Do we have any loaded executable sections?
- modules = FindModules(system);
- if (!modules.empty()) {
- return modules.begin()->first;
- }
-
- // As a last resort, use the start of the code region.
- return GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart());
-}
-
void GDBStub::HandleQuery(std::string_view command) {
if (command.starts_with("TStatus")) {
// no tracepoint support
@@ -687,10 +466,10 @@ void GDBStub::HandleQuery(std::string_view command) {
const auto target_xml{arch->GetTargetXML()};
SendReply(PaginateBuffer(target_xml, command.substr(30)));
} else if (command.starts_with("Offsets")) {
- const auto main_offset = FindMainModuleEntrypoint(system);
- SendReply(fmt::format("TextSeg={:x}", main_offset));
+ const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess());
+ SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset)));
} else if (command.starts_with("Xfer:libraries:read::")) {
- auto modules = FindModules(system);
+ auto modules = Core::FindModules(system.ApplicationProcess());
std::string buffer;
buffer += R"(<?xml version="1.0"?>)";
@@ -720,14 +499,14 @@ void GDBStub::HandleQuery(std::string_view command) {
const auto& threads = system.ApplicationProcess()->GetThreadList();
for (const auto& thread : threads) {
- auto thread_name{GetThreadName(system, thread)};
+ auto thread_name{Core::GetThreadName(&thread)};
if (!thread_name) {
thread_name = fmt::format("Thread {:d}", thread.GetThreadId());
}
buffer += fmt::format(R"(<thread id="{:x}" core="{:d}" name="{}">{}</thread>)",
thread.GetThreadId(), thread.GetActiveCore(),
- EscapeXML(*thread_name), GetThreadState(thread));
+ EscapeXML(*thread_name), GetThreadState(&thread));
}
buffer += "</threads>";
@@ -856,7 +635,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
reply = "Fastmem is not enabled.\n";
}
} else if (command_str == "get info") {
- auto modules = FindModules(system);
+ auto modules = Core::FindModules(process);
reply = fmt::format("Process: {:#x} ({})\n"
"Program Id: {:#018x}\n",
@@ -880,7 +659,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
for (const auto& [vaddr, name] : modules) {
reply += fmt::format(" {:#012x} - {:#012x} {}\n", vaddr,
- GetModuleEnd(page_table, vaddr), name);
+ GetInteger(Core::GetModuleEnd(process, vaddr)), name);
}
} else if (command_str == "get mappings") {
reply = "Mappings:\n";
diff --git a/src/core/debugger/gdbstub_arch.cpp b/src/core/debugger/gdbstub_arch.cpp
index 75c94a91a..f2a407dc8 100644
--- a/src/core/debugger/gdbstub_arch.cpp
+++ b/src/core/debugger/gdbstub_arch.cpp
@@ -24,21 +24,6 @@ static std::string ValueToHex(const T value) {
return Common::HexToString(mem);
}
-template <typename T>
-static T GetSIMDRegister(const std::array<u32, 64>& simd_regs, size_t offset) {
- static_assert(std::is_trivially_copyable_v<T>);
- T value{};
- std::memcpy(&value, reinterpret_cast<const u8*>(simd_regs.data()) + sizeof(T) * offset,
- sizeof(T));
- return value;
-}
-
-template <typename T>
-static void PutSIMDRegister(std::array<u32, 64>& simd_regs, size_t offset, const T value) {
- static_assert(std::is_trivially_copyable_v<T>);
- std::memcpy(reinterpret_cast<u8*>(simd_regs.data()) + sizeof(T) * offset, &value, sizeof(T));
-}
-
// For sample XML files see the GDB source /gdb/features
// This XML defines what the registers are for this specific ARM device
std::string_view GDBStubA64::GetTargetXML() const {
@@ -184,12 +169,16 @@ std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const
return "";
}
- const auto& context{thread->GetContext64()};
- const auto& gprs{context.cpu_registers};
- const auto& fprs{context.vector_registers};
+ const auto& context{thread->GetContext()};
+ const auto& gprs{context.r};
+ const auto& fprs{context.v};
- if (id < SP_REGISTER) {
+ if (id < FP_REGISTER) {
return ValueToHex(gprs[id]);
+ } else if (id == FP_REGISTER) {
+ return ValueToHex(context.fp);
+ } else if (id == LR_REGISTER) {
+ return ValueToHex(context.lr);
} else if (id == SP_REGISTER) {
return ValueToHex(context.sp);
} else if (id == PC_REGISTER) {
@@ -212,10 +201,14 @@ void GDBStubA64::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v
return;
}
- auto& context{thread->GetContext64()};
+ auto& context{thread->GetContext()};
- if (id < SP_REGISTER) {
- context.cpu_registers[id] = HexToValue<u64>(value);
+ if (id < FP_REGISTER) {
+ context.r[id] = HexToValue<u64>(value);
+ } else if (id == FP_REGISTER) {
+ context.fp = HexToValue<u64>(value);
+ } else if (id == LR_REGISTER) {
+ context.lr = HexToValue<u64>(value);
} else if (id == SP_REGISTER) {
context.sp = HexToValue<u64>(value);
} else if (id == PC_REGISTER) {
@@ -223,7 +216,7 @@ void GDBStubA64::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v
} else if (id == PSTATE_REGISTER) {
context.pstate = HexToValue<u32>(value);
} else if (id >= Q0_REGISTER && id < FPSR_REGISTER) {
- context.vector_registers[id - Q0_REGISTER] = HexToValue<u128>(value);
+ context.v[id - Q0_REGISTER] = HexToValue<u128>(value);
} else if (id == FPSR_REGISTER) {
context.fpsr = HexToValue<u32>(value);
} else if (id == FPCR_REGISTER) {
@@ -381,22 +374,20 @@ std::string GDBStubA32::RegRead(const Kernel::KThread* thread, size_t id) const
return "";
}
- const auto& context{thread->GetContext32()};
- const auto& gprs{context.cpu_registers};
- const auto& fprs{context.extension_registers};
+ const auto& context{thread->GetContext()};
+ const auto& gprs{context.r};
+ const auto& fprs{context.v};
if (id <= PC_REGISTER) {
- return ValueToHex(gprs[id]);
+ return ValueToHex(static_cast<u32>(gprs[id]));
} else if (id == CPSR_REGISTER) {
- return ValueToHex(context.cpsr);
+ return ValueToHex(context.pstate);
} else if (id >= D0_REGISTER && id < Q0_REGISTER) {
- const u64 dN{GetSIMDRegister<u64>(fprs, id - D0_REGISTER)};
- return ValueToHex(dN);
+ return ValueToHex(fprs[id - D0_REGISTER][0]);
} else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) {
- const u128 qN{GetSIMDRegister<u128>(fprs, id - Q0_REGISTER)};
- return ValueToHex(qN);
+ return ValueToHex(fprs[id - Q0_REGISTER]);
} else if (id == FPSCR_REGISTER) {
- return ValueToHex(context.fpscr);
+ return ValueToHex(context.fpcr | context.fpsr);
} else {
return "";
}
@@ -407,19 +398,20 @@ void GDBStubA32::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v
return;
}
- auto& context{thread->GetContext32()};
- auto& fprs{context.extension_registers};
+ auto& context{thread->GetContext()};
+ auto& fprs{context.v};
if (id <= PC_REGISTER) {
- context.cpu_registers[id] = HexToValue<u32>(value);
+ context.r[id] = HexToValue<u32>(value);
} else if (id == CPSR_REGISTER) {
- context.cpsr = HexToValue<u32>(value);
+ context.pstate = HexToValue<u32>(value);
} else if (id >= D0_REGISTER && id < Q0_REGISTER) {
- PutSIMDRegister(fprs, id - D0_REGISTER, HexToValue<u64>(value));
+ fprs[id - D0_REGISTER] = {HexToValue<u64>(value), 0};
} else if (id >= Q0_REGISTER && id < FPSCR_REGISTER) {
- PutSIMDRegister(fprs, id - Q0_REGISTER, HexToValue<u128>(value));
+ fprs[id - Q0_REGISTER] = HexToValue<u128>(value);
} else if (id == FPSCR_REGISTER) {
- context.fpscr = HexToValue<u32>(value);
+ context.fpcr = HexToValue<u32>(value);
+ context.fpsr = HexToValue<u32>(value);
}
}
diff --git a/src/core/debugger/gdbstub_arch.h b/src/core/debugger/gdbstub_arch.h
index 34530c788..d53714d69 100644
--- a/src/core/debugger/gdbstub_arch.h
+++ b/src/core/debugger/gdbstub_arch.h
@@ -36,6 +36,7 @@ public:
u32 BreakpointInstruction() const override;
private:
+ static constexpr u32 FP_REGISTER = 29;
static constexpr u32 LR_REGISTER = 30;
static constexpr u32 SP_REGISTER = 31;
static constexpr u32 PC_REGISTER = 32;
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp
index f1d3e4129..dd9cca103 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.cpp
+++ b/src/core/file_sys/fsmitm_romfsbuild.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
+#include <span>
#include <string_view>
#include "common/alignment.h"
#include "common/assert.h"
@@ -134,7 +135,7 @@ void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir,
child->size = child->source->GetSize();
- AddFile(parent, child);
+ AddFile(parent, std::move(child));
}
for (auto& child_romfs_dir : romfs_dir->GetSubdirectories()) {
@@ -163,36 +164,24 @@ void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir,
bool RomFSBuildContext::AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx,
std::shared_ptr<RomFSBuildDirectoryContext> dir_ctx) {
- // Check whether it's already in the known directories.
- const auto [it, is_new] = directories.emplace(dir_ctx->path, nullptr);
- if (!is_new) {
- return false;
- }
-
// Add a new directory.
num_dirs++;
dir_table_size +=
sizeof(RomFSDirectoryEntry) + Common::AlignUp(dir_ctx->path_len - dir_ctx->cur_path_ofs, 4);
- dir_ctx->parent = parent_dir_ctx;
- it->second = dir_ctx;
+ dir_ctx->parent = std::move(parent_dir_ctx);
+ directories.emplace_back(std::move(dir_ctx));
return true;
}
bool RomFSBuildContext::AddFile(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx,
std::shared_ptr<RomFSBuildFileContext> file_ctx) {
- // Check whether it's already in the known files.
- const auto [it, is_new] = files.emplace(file_ctx->path, nullptr);
- if (!is_new) {
- return false;
- }
-
// Add a new file.
num_files++;
file_table_size +=
sizeof(RomFSFileEntry) + Common::AlignUp(file_ctx->path_len - file_ctx->cur_path_ofs, 4);
- file_ctx->parent = parent_dir_ctx;
- it->second = file_ctx;
+ file_ctx->parent = std::move(parent_dir_ctx);
+ files.emplace_back(std::move(file_ctx));
return true;
}
@@ -201,7 +190,7 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_)
: base(std::move(base_)), ext(std::move(ext_)) {
root = std::make_shared<RomFSBuildDirectoryContext>();
root->path = "\0";
- directories.emplace(root->path, root);
+ directories.emplace_back(root);
num_dirs = 1;
dir_table_size = 0x18;
@@ -210,28 +199,43 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_)
RomFSBuildContext::~RomFSBuildContext() = default;
-std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
+std::vector<std::pair<u64, VirtualFile>> RomFSBuildContext::Build() {
const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs);
const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files);
dir_hash_table_size = 4 * dir_hash_table_entry_count;
file_hash_table_size = 4 * file_hash_table_entry_count;
- // Assign metadata pointers
+ // Assign metadata pointers.
RomFSHeader header{};
- std::vector<u32> dir_hash_table(dir_hash_table_entry_count, ROMFS_ENTRY_EMPTY);
- std::vector<u32> file_hash_table(file_hash_table_entry_count, ROMFS_ENTRY_EMPTY);
-
- std::vector<u8> dir_table(dir_table_size);
- std::vector<u8> file_table(file_table_size);
-
- std::shared_ptr<RomFSBuildFileContext> cur_file;
+ std::vector<u8> metadata(file_hash_table_size + file_table_size + dir_hash_table_size +
+ dir_table_size);
+ u32* const dir_hash_table_pointer = reinterpret_cast<u32*>(metadata.data());
+ u8* const dir_table_pointer = metadata.data() + dir_hash_table_size;
+ u32* const file_hash_table_pointer =
+ reinterpret_cast<u32*>(metadata.data() + dir_hash_table_size + dir_table_size);
+ u8* const file_table_pointer =
+ metadata.data() + dir_hash_table_size + dir_table_size + file_hash_table_size;
+
+ std::span<u32> dir_hash_table(dir_hash_table_pointer, dir_hash_table_entry_count);
+ std::span<u32> file_hash_table(file_hash_table_pointer, file_hash_table_entry_count);
+ std::span<u8> dir_table(dir_table_pointer, dir_table_size);
+ std::span<u8> file_table(file_table_pointer, file_table_size);
+
+ // Initialize hash tables.
+ std::memset(dir_hash_table.data(), 0xFF, dir_hash_table.size_bytes());
+ std::memset(file_hash_table.data(), 0xFF, file_hash_table.size_bytes());
+
+ // Sort tables by name.
+ std::sort(files.begin(), files.end(),
+ [](const auto& a, const auto& b) { return a->path < b->path; });
+ std::sort(directories.begin(), directories.end(),
+ [](const auto& a, const auto& b) { return a->path < b->path; });
// Determine file offsets.
u32 entry_offset = 0;
std::shared_ptr<RomFSBuildFileContext> prev_file = nullptr;
- for (const auto& it : files) {
- cur_file = it.second;
+ for (const auto& cur_file : files) {
file_partition_size = Common::AlignUp(file_partition_size, 16);
cur_file->offset = file_partition_size;
file_partition_size += cur_file->size;
@@ -243,34 +247,48 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
}
// Assign deferred parent/sibling ownership.
for (auto it = files.rbegin(); it != files.rend(); ++it) {
- cur_file = it->second;
+ auto& cur_file = *it;
cur_file->sibling = cur_file->parent->file;
cur_file->parent->file = cur_file;
}
- std::shared_ptr<RomFSBuildDirectoryContext> cur_dir;
-
// Determine directory offsets.
entry_offset = 0;
- for (const auto& it : directories) {
- cur_dir = it.second;
+ for (const auto& cur_dir : directories) {
cur_dir->entry_offset = entry_offset;
entry_offset +=
static_cast<u32>(sizeof(RomFSDirectoryEntry) +
Common::AlignUp(cur_dir->path_len - cur_dir->cur_path_ofs, 4));
}
// Assign deferred parent/sibling ownership.
- for (auto it = directories.rbegin(); it->second != root; ++it) {
- cur_dir = it->second;
+ for (auto it = directories.rbegin(); (*it) != root; ++it) {
+ auto& cur_dir = *it;
cur_dir->sibling = cur_dir->parent->child;
cur_dir->parent->child = cur_dir;
}
- std::multimap<u64, VirtualFile> out;
+ // Create output map.
+ std::vector<std::pair<u64, VirtualFile>> out;
+ out.reserve(num_files + 2);
+
+ // Set header fields.
+ header.header_size = sizeof(RomFSHeader);
+ header.file_hash_table_size = file_hash_table_size;
+ header.file_table_size = file_table_size;
+ header.dir_hash_table_size = dir_hash_table_size;
+ header.dir_table_size = dir_table_size;
+ header.file_partition_ofs = ROMFS_FILEPARTITION_OFS;
+ header.dir_hash_table_ofs = Common::AlignUp(header.file_partition_ofs + file_partition_size, 4);
+ header.dir_table_ofs = header.dir_hash_table_ofs + header.dir_hash_table_size;
+ header.file_hash_table_ofs = header.dir_table_ofs + header.dir_table_size;
+ header.file_table_ofs = header.file_hash_table_ofs + header.file_hash_table_size;
+
+ std::vector<u8> header_data(sizeof(RomFSHeader));
+ std::memcpy(header_data.data(), &header, header_data.size());
+ out.emplace_back(0, std::make_shared<VectorVfsFile>(std::move(header_data)));
// Populate file tables.
- for (const auto& it : files) {
- cur_file = it.second;
+ for (const auto& cur_file : files) {
RomFSFileEntry cur_entry{};
cur_entry.parent = cur_file->parent->entry_offset;
@@ -287,7 +305,7 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
cur_entry.name_size = name_size;
- out.emplace(cur_file->offset + ROMFS_FILEPARTITION_OFS, std::move(cur_file->source));
+ out.emplace_back(cur_file->offset + ROMFS_FILEPARTITION_OFS, std::move(cur_file->source));
std::memcpy(file_table.data() + cur_file->entry_offset, &cur_entry, sizeof(RomFSFileEntry));
std::memset(file_table.data() + cur_file->entry_offset + sizeof(RomFSFileEntry), 0,
Common::AlignUp(cur_entry.name_size, 4));
@@ -296,8 +314,7 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
}
// Populate dir tables.
- for (const auto& it : directories) {
- cur_dir = it.second;
+ for (const auto& cur_dir : directories) {
RomFSDirectoryEntry cur_entry{};
cur_entry.parent = cur_dir == root ? 0 : cur_dir->parent->entry_offset;
@@ -323,34 +340,13 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
cur_dir->path.data() + cur_dir->cur_path_ofs, name_size);
}
- // Set header fields.
- header.header_size = sizeof(RomFSHeader);
- header.file_hash_table_size = file_hash_table_size;
- header.file_table_size = file_table_size;
- header.dir_hash_table_size = dir_hash_table_size;
- header.dir_table_size = dir_table_size;
- header.file_partition_ofs = ROMFS_FILEPARTITION_OFS;
- header.dir_hash_table_ofs = Common::AlignUp(header.file_partition_ofs + file_partition_size, 4);
- header.dir_table_ofs = header.dir_hash_table_ofs + header.dir_hash_table_size;
- header.file_hash_table_ofs = header.dir_table_ofs + header.dir_table_size;
- header.file_table_ofs = header.file_hash_table_ofs + header.file_hash_table_size;
-
- std::vector<u8> header_data(sizeof(RomFSHeader));
- std::memcpy(header_data.data(), &header, header_data.size());
- out.emplace(0, std::make_shared<VectorVfsFile>(std::move(header_data)));
+ // Write metadata.
+ out.emplace_back(header.dir_hash_table_ofs,
+ std::make_shared<VectorVfsFile>(std::move(metadata)));
- std::vector<u8> metadata(file_hash_table_size + file_table_size + dir_hash_table_size +
- dir_table_size);
- std::size_t index = 0;
- std::memcpy(metadata.data(), dir_hash_table.data(), dir_hash_table.size() * sizeof(u32));
- index += dir_hash_table.size() * sizeof(u32);
- std::memcpy(metadata.data() + index, dir_table.data(), dir_table.size());
- index += dir_table.size();
- std::memcpy(metadata.data() + index, file_hash_table.data(),
- file_hash_table.size() * sizeof(u32));
- index += file_hash_table.size() * sizeof(u32);
- std::memcpy(metadata.data() + index, file_table.data(), file_table.size());
- out.emplace(header.dir_hash_table_ofs, std::make_shared<VectorVfsFile>(std::move(metadata)));
+ // Sort the output.
+ std::sort(out.begin(), out.end(),
+ [](const auto& a, const auto& b) { return a.first < b.first; });
return out;
}
diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h
index 06e5d5a47..f387c79f1 100644
--- a/src/core/file_sys/fsmitm_romfsbuild.h
+++ b/src/core/file_sys/fsmitm_romfsbuild.h
@@ -22,14 +22,14 @@ public:
~RomFSBuildContext();
// This finalizes the context.
- std::multimap<u64, VirtualFile> Build();
+ std::vector<std::pair<u64, VirtualFile>> Build();
private:
VirtualDir base;
VirtualDir ext;
std::shared_ptr<RomFSBuildDirectoryContext> root;
- std::map<std::string, std::shared_ptr<RomFSBuildDirectoryContext>, std::less<>> directories;
- std::map<std::string, std::shared_ptr<RomFSBuildFileContext>, std::less<>> files;
+ std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> directories;
+ std::vector<std::shared_ptr<RomFSBuildFileContext>> files;
u64 num_dirs = 0;
u64 num_files = 0;
u64 dir_table_size = 0;
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp
index 6de2103a0..6182598ae 100644
--- a/src/core/file_sys/romfs.cpp
+++ b/src/core/file_sys/romfs.cpp
@@ -55,44 +55,68 @@ struct FileEntry {
};
static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
-template <typename Entry>
-std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offset) {
- Entry entry{};
- if (file->ReadObject(&entry, offset) != sizeof(Entry))
- return {};
- std::string string(entry.name_length, '\0');
- if (file->ReadArray(&string[0], string.size(), offset + sizeof(Entry)) != string.size())
+struct RomFSTraversalContext {
+ RomFSHeader header;
+ VirtualFile file;
+ std::vector<u8> directory_meta;
+ std::vector<u8> file_meta;
+};
+
+template <typename EntryType, auto Member>
+std::pair<EntryType, std::string> GetEntry(const RomFSTraversalContext& ctx, size_t offset) {
+ const size_t entry_end = offset + sizeof(EntryType);
+ const std::vector<u8>& vec = ctx.*Member;
+ const size_t size = vec.size();
+ const u8* data = vec.data();
+ EntryType entry{};
+
+ if (entry_end > size) {
return {};
- return {entry, string};
+ }
+ std::memcpy(&entry, data + offset, sizeof(EntryType));
+
+ const size_t name_length = std::min(entry_end + entry.name_length, size) - entry_end;
+ std::string name(reinterpret_cast<const char*>(data + entry_end), name_length);
+
+ return {entry, std::move(name)};
+}
+
+std::pair<DirectoryEntry, std::string> GetDirectoryEntry(const RomFSTraversalContext& ctx,
+ size_t directory_offset) {
+ return GetEntry<DirectoryEntry, &RomFSTraversalContext::directory_meta>(ctx, directory_offset);
+}
+
+std::pair<FileEntry, std::string> GetFileEntry(const RomFSTraversalContext& ctx,
+ size_t file_offset) {
+ return GetEntry<FileEntry, &RomFSTraversalContext::file_meta>(ctx, file_offset);
}
-void ProcessFile(const VirtualFile& file, std::size_t file_offset, std::size_t data_offset,
- u32 this_file_offset, std::shared_ptr<VectorVfsDirectory>& parent) {
+void ProcessFile(const RomFSTraversalContext& ctx, u32 this_file_offset,
+ std::shared_ptr<VectorVfsDirectory>& parent) {
while (this_file_offset != ROMFS_ENTRY_EMPTY) {
- auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset);
+ auto entry = GetFileEntry(ctx, this_file_offset);
- parent->AddFile(std::make_shared<OffsetVfsFile>(
- file, entry.first.size, entry.first.offset + data_offset, entry.second));
+ parent->AddFile(std::make_shared<OffsetVfsFile>(ctx.file, entry.first.size,
+ entry.first.offset + ctx.header.data_offset,
+ std::move(entry.second)));
this_file_offset = entry.first.sibling;
}
}
-void ProcessDirectory(const VirtualFile& file, std::size_t dir_offset, std::size_t file_offset,
- std::size_t data_offset, u32 this_dir_offset,
+void ProcessDirectory(const RomFSTraversalContext& ctx, u32 this_dir_offset,
std::shared_ptr<VectorVfsDirectory>& parent) {
while (this_dir_offset != ROMFS_ENTRY_EMPTY) {
- auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset);
+ auto entry = GetDirectoryEntry(ctx, this_dir_offset);
auto current = std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, entry.second);
if (entry.first.child_file != ROMFS_ENTRY_EMPTY) {
- ProcessFile(file, file_offset, data_offset, entry.first.child_file, current);
+ ProcessFile(ctx, entry.first.child_file, current);
}
if (entry.first.child_dir != ROMFS_ENTRY_EMPTY) {
- ProcessDirectory(file, dir_offset, file_offset, data_offset, entry.first.child_dir,
- current);
+ ProcessDirectory(ctx, entry.first.child_dir, current);
}
parent->AddDirectory(current);
@@ -107,22 +131,25 @@ VirtualDir ExtractRomFS(VirtualFile file) {
return root_container;
}
- RomFSHeader header{};
- if (file->ReadObject(&header) != sizeof(RomFSHeader)) {
- return root_container;
+ RomFSTraversalContext ctx{};
+
+ if (file->ReadObject(&ctx.header) != sizeof(RomFSHeader)) {
+ return nullptr;
}
- if (header.header_size != sizeof(RomFSHeader)) {
- return root_container;
+ if (ctx.header.header_size != sizeof(RomFSHeader)) {
+ return nullptr;
}
- const u64 file_offset = header.file_meta.offset;
- const u64 dir_offset = header.directory_meta.offset;
+ ctx.file = file;
+ ctx.directory_meta =
+ file->ReadBytes(ctx.header.directory_meta.size, ctx.header.directory_meta.offset);
+ ctx.file_meta = file->ReadBytes(ctx.header.file_meta.size, ctx.header.file_meta.offset);
- ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container);
+ ProcessDirectory(ctx, 0, root_container);
if (auto root = root_container->GetSubdirectory(""); root) {
- return std::make_shared<CachedVfsDirectory>(std::move(root));
+ return root;
}
ASSERT(false);
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index a4d060007..8d5d593e8 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -12,8 +12,6 @@
namespace FileSys {
-constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
-
namespace {
void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) {
@@ -197,7 +195,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
- const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME);
+ const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize)) {
return {0, 0};
}
@@ -216,7 +214,7 @@ void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 us
GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
- const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
+ const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());
if (size_file == nullptr) {
return;
}
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index 45c7c81fb..e3a0f8cef 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -83,6 +83,10 @@ struct SaveDataSize {
u64 journal;
};
+constexpr const char* GetSaveDataSizeFileName() {
+ return ".yuzu_save_size";
+}
+
/// File system interface to the SaveData archive
class SaveDataFactory {
public:
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 168b9cbec..7c7298527 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -59,8 +59,8 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::string&& name,
return VirtualFile(new ConcatenatedVfsFile(std::move(name), std::move(concatenation_map)));
}
-VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, std::string&& name,
- std::multimap<u64, VirtualFile>&& files) {
+VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(
+ u8 filler_byte, std::string&& name, std::vector<std::pair<u64, VirtualFile>>&& files) {
// Fold trivial cases.
if (files.empty()) {
return nullptr;
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h
index cbddd12bd..b5f3d72e3 100644
--- a/src/core/file_sys/vfs_concat.h
+++ b/src/core/file_sys/vfs_concat.h
@@ -37,7 +37,7 @@ public:
/// Convenience function that turns a map of offsets to files into a concatenated file, filling
/// gaps with a given filler byte.
static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::string&& name,
- std::multimap<u64, VirtualFile>&& files);
+ std::vector<std::pair<u64, VirtualFile>>&& files);
std::string GetName() const override;
std::size_t GetSize() const override;
diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp
index 08daca397..5551743fb 100644
--- a/src/core/file_sys/vfs_layered.cpp
+++ b/src/core/file_sys/vfs_layered.cpp
@@ -3,6 +3,7 @@
#include <algorithm>
#include <set>
+#include <unordered_set>
#include <utility>
#include "core/file_sys/vfs_layered.h"
@@ -59,13 +60,12 @@ std::string LayeredVfsDirectory::GetFullPath() const {
std::vector<VirtualFile> LayeredVfsDirectory::GetFiles() const {
std::vector<VirtualFile> out;
- std::set<std::string, std::less<>> out_names;
+ std::unordered_set<std::string> out_names;
for (const auto& layer : dirs) {
for (auto& file : layer->GetFiles()) {
- auto file_name = file->GetName();
- if (!out_names.contains(file_name)) {
- out_names.emplace(std::move(file_name));
+ const auto [it, is_new] = out_names.emplace(file->GetName());
+ if (is_new) {
out.emplace_back(std::move(file));
}
}
@@ -75,18 +75,19 @@ std::vector<VirtualFile> LayeredVfsDirectory::GetFiles() const {
}
std::vector<VirtualDir> LayeredVfsDirectory::GetSubdirectories() const {
- std::vector<std::string> names;
+ std::vector<VirtualDir> out;
+ std::unordered_set<std::string> out_names;
+
for (const auto& layer : dirs) {
for (const auto& sd : layer->GetSubdirectories()) {
- if (std::find(names.begin(), names.end(), sd->GetName()) == names.end())
- names.push_back(sd->GetName());
+ out_names.emplace(sd->GetName());
}
}
- std::vector<VirtualDir> out;
- out.reserve(names.size());
- for (const auto& subdir : names)
+ out.reserve(out_names.size());
+ for (const auto& subdir : out_names) {
out.emplace_back(GetSubdirectory(subdir));
+ }
return out;
}
diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp
index a6bdd28f2..072f38a68 100644
--- a/src/core/hid/input_interpreter.cpp
+++ b/src/core/hid/input_interpreter.cpp
@@ -20,6 +20,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
InputInterpreter::~InputInterpreter() = default;
void InputInterpreter::PollInput() {
+ if (npad == nullptr) {
+ return;
+ }
const auto button_state = npad->GetAndResetPressState();
previous_index = current_index;
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index 40e09e532..11b1b977e 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -3,6 +3,7 @@
#include "common/scope_exit.h"
#include "core/hle/kernel/k_client_port.h"
+#include "core/hle/kernel/k_light_session.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
@@ -63,6 +64,7 @@ Result KClientPort::CreateSession(KClientSession** out) {
R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
// Allocate a session normally.
+ // TODO: Dynamic resource limits
session = KSession::Create(m_kernel);
// Check that we successfully created a session.
@@ -119,4 +121,71 @@ Result KClientPort::CreateSession(KClientSession** out) {
R_SUCCEED();
}
+Result KClientPort::CreateLightSession(KLightClientSession** out) {
+ // Declare the session we're going to allocate.
+ KLightSession* session{};
+
+ // Reserve a new session from the resource limit.
+ KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel),
+ Svc::LimitableResource::SessionCountMax);
+ R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
+
+ // Allocate a session normally.
+ // TODO: Dynamic resource limits
+ session = KLightSession::Create(m_kernel);
+
+ // Check that we successfully created a session.
+ R_UNLESS(session != nullptr, ResultOutOfResource);
+
+ // Update the session counts.
+ {
+ ON_RESULT_FAILURE {
+ session->Close();
+ };
+
+ // Atomically increment the number of sessions.
+ s32 new_sessions;
+ {
+ const auto max = m_max_sessions;
+ auto cur_sessions = m_num_sessions.load(std::memory_order_acquire);
+ do {
+ R_UNLESS(cur_sessions < max, ResultOutOfSessions);
+ new_sessions = cur_sessions + 1;
+ } while (!m_num_sessions.compare_exchange_weak(cur_sessions, new_sessions,
+ std::memory_order_relaxed));
+ }
+
+ // Atomically update the peak session tracking.
+ {
+ auto peak = m_peak_sessions.load(std::memory_order_acquire);
+ do {
+ if (peak >= new_sessions) {
+ break;
+ }
+ } while (!m_peak_sessions.compare_exchange_weak(peak, new_sessions,
+ std::memory_order_relaxed));
+ }
+ }
+
+ // Initialize the session.
+ session->Initialize(this, m_parent->GetName());
+
+ // Commit the session reservation.
+ session_reservation.Commit();
+
+ // Register the session.
+ KLightSession::Register(m_kernel, session);
+ ON_RESULT_FAILURE {
+ session->GetClientSession().Close();
+ session->GetServerSession().Close();
+ };
+
+ // Enqueue the session with our parent.
+ R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession())));
+
+ // We succeeded, so set the output.
+ *out = std::addressof(session->GetClientSession());
+ R_SUCCEED();
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index 23db06ddf..28b332608 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -11,6 +11,7 @@
namespace Kernel {
+class KLightClientSession;
class KClientSession;
class KernelCore;
class KPort;
@@ -51,6 +52,7 @@ public:
bool IsSignaled() const override;
Result CreateSession(KClientSession** out);
+ Result CreateLightSession(KLightClientSession** out);
private:
std::atomic<s32> m_num_sessions{};
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 72b66270d..472e8571c 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -10,9 +10,7 @@
namespace Kernel {
-static constexpr u32 MessageBufferSize = 0x100;
-
-KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {}
+KClientSession::KClientSession(KernelCore& kernel) : KAutoObject{kernel} {}
KClientSession::~KClientSession() = default;
void KClientSession::Destroy() {
@@ -22,18 +20,30 @@ void KClientSession::Destroy() {
void KClientSession::OnServerClosed() {}
-Result KClientSession::SendSyncRequest() {
+Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) {
+ // Create a session request.
+ KSessionRequest* request = KSessionRequest::Create(m_kernel);
+ R_UNLESS(request != nullptr, ResultOutOfResource);
+ SCOPE_EXIT({ request->Close(); });
+
+ // Initialize the request.
+ request->Initialize(nullptr, address, size);
+
+ // Send the request.
+ R_RETURN(m_parent->OnRequest(request));
+}
+
+Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t size) {
// Create a session request.
KSessionRequest* request = KSessionRequest::Create(m_kernel);
R_UNLESS(request != nullptr, ResultOutOfResource);
SCOPE_EXIT({ request->Close(); });
// Initialize the request.
- request->Initialize(nullptr, GetInteger(GetCurrentThread(m_kernel).GetTlsAddress()),
- MessageBufferSize);
+ request->Initialize(event, address, size);
// Send the request.
- R_RETURN(m_parent->GetServerSession().OnRequest(request));
+ R_RETURN(m_parent->OnRequest(request));
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 9b62e55e4..a39213e17 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -9,24 +9,12 @@
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/result.h"
-union Result;
-
-namespace Core::Memory {
-class Memory;
-}
-
-namespace Core::Timing {
-class CoreTiming;
-}
-
namespace Kernel {
class KernelCore;
class KSession;
-class KThread;
-class KClientSession final
- : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> {
+class KClientSession final : public KAutoObject {
KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject);
public:
@@ -39,13 +27,13 @@ public:
}
void Destroy() override;
- static void PostDestroy(uintptr_t arg) {}
KSession* GetParent() const {
return m_parent;
}
- Result SendSyncRequest();
+ Result SendSyncRequest(uintptr_t address, size_t size);
+ Result SendAsyncRequest(KEvent* event, uintptr_t address, size_t size);
void OnServerClosed();
diff --git a/src/core/hle/kernel/k_light_client_session.cpp b/src/core/hle/kernel/k_light_client_session.cpp
new file mode 100644
index 000000000..8ce3e1ae4
--- /dev/null
+++ b/src/core/hle/kernel/k_light_client_session.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_light_client_session.h"
+#include "core/hle/kernel/k_light_session.h"
+#include "core/hle/kernel/k_thread.h"
+
+namespace Kernel {
+
+KLightClientSession::KLightClientSession(KernelCore& kernel) : KAutoObject(kernel) {}
+
+KLightClientSession::~KLightClientSession() = default;
+
+void KLightClientSession::Destroy() {
+ m_parent->OnClientClosed();
+}
+
+void KLightClientSession::OnServerClosed() {}
+
+Result KLightClientSession::SendSyncRequest(u32* data) {
+ // Get the request thread.
+ KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
+
+ // Set the light data.
+ cur_thread->SetLightSessionData(data);
+
+ // Send the request.
+ R_RETURN(m_parent->OnRequest(cur_thread));
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_client_session.h b/src/core/hle/kernel/k_light_client_session.h
new file mode 100644
index 000000000..881a15cbd
--- /dev/null
+++ b/src/core/hle/kernel/k_light_client_session.h
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/kernel/k_auto_object.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KLightSession;
+
+class KLightClientSession final : public KAutoObject {
+ KERNEL_AUTOOBJECT_TRAITS(KLightClientSession, KAutoObject);
+
+public:
+ explicit KLightClientSession(KernelCore& kernel);
+ ~KLightClientSession();
+
+ void Initialize(KLightSession* parent) {
+ // Set member variables.
+ m_parent = parent;
+ }
+
+ virtual void Destroy() override;
+
+ const KLightSession* GetParent() const {
+ return m_parent;
+ }
+
+ Result SendSyncRequest(u32* data);
+
+ void OnServerClosed();
+
+private:
+ KLightSession* m_parent;
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_server_session.cpp b/src/core/hle/kernel/k_light_server_session.cpp
new file mode 100644
index 000000000..e5ceb01f2
--- /dev/null
+++ b/src/core/hle/kernel/k_light_server_session.cpp
@@ -0,0 +1,247 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_light_server_session.h"
+#include "core/hle/kernel/k_light_session.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_thread_queue.h"
+#include "core/hle/kernel/svc_results.h"
+
+namespace Kernel {
+
+namespace {
+
+constexpr u64 InvalidThreadId = std::numeric_limits<u64>::max();
+
+class ThreadQueueImplForKLightServerSessionRequest final : public KThreadQueue {
+private:
+ KThread::WaiterList* m_wait_list;
+
+public:
+ ThreadQueueImplForKLightServerSessionRequest(KernelCore& kernel, KThread::WaiterList* wl)
+ : KThreadQueue(kernel), m_wait_list(wl) {}
+
+ virtual void EndWait(KThread* waiting_thread, Result wait_result) override {
+ // Remove the thread from our wait list.
+ m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
+
+ // Invoke the base end wait handler.
+ KThreadQueue::EndWait(waiting_thread, wait_result);
+ }
+
+ virtual void CancelWait(KThread* waiting_thread, Result wait_result,
+ bool cancel_timer_task) override {
+ // Remove the thread from our wait list.
+ m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
+
+ // Invoke the base cancel wait handler.
+ KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
+ }
+};
+
+class ThreadQueueImplForKLightServerSessionReceive final : public KThreadQueue {
+private:
+ KThread** m_server_thread;
+
+public:
+ ThreadQueueImplForKLightServerSessionReceive(KernelCore& kernel, KThread** st)
+ : KThreadQueue(kernel), m_server_thread(st) {}
+
+ virtual void EndWait(KThread* waiting_thread, Result wait_result) override {
+ // Clear the server thread.
+ *m_server_thread = nullptr;
+
+ // Set the waiting thread as not cancelable.
+ waiting_thread->ClearCancellable();
+
+ // Invoke the base end wait handler.
+ KThreadQueue::EndWait(waiting_thread, wait_result);
+ }
+
+ virtual void CancelWait(KThread* waiting_thread, Result wait_result,
+ bool cancel_timer_task) override {
+ // Clear the server thread.
+ *m_server_thread = nullptr;
+
+ // Set the waiting thread as not cancelable.
+ waiting_thread->ClearCancellable();
+
+ // Invoke the base cancel wait handler.
+ KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
+ }
+};
+
+} // namespace
+
+KLightServerSession::KLightServerSession(KernelCore& kernel) : KAutoObject(kernel) {}
+KLightServerSession::~KLightServerSession() = default;
+
+void KLightServerSession::Destroy() {
+ this->CleanupRequests();
+
+ m_parent->OnServerClosed();
+}
+
+void KLightServerSession::OnClientClosed() {
+ this->CleanupRequests();
+}
+
+Result KLightServerSession::OnRequest(KThread* request_thread) {
+ ThreadQueueImplForKLightServerSessionRequest wait_queue(m_kernel,
+ std::addressof(m_request_list));
+
+ // Send the request.
+ {
+ // Lock the scheduler.
+ KScopedSchedulerLock sl(m_kernel);
+
+ // Check that the server isn't closed.
+ R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed);
+
+ // Check that the request thread isn't terminating.
+ R_UNLESS(!request_thread->IsTerminationRequested(), ResultTerminationRequested);
+
+ // Add the request thread to our list.
+ m_request_list.push_back(*request_thread);
+
+ // Begin waiting on the request.
+ request_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
+ request_thread->BeginWait(std::addressof(wait_queue));
+
+ // If we have a server thread, end its wait.
+ if (m_server_thread != nullptr) {
+ m_server_thread->EndWait(ResultSuccess);
+ }
+ }
+
+ // NOTE: Nintendo returns GetCurrentThread().GetWaitResult() here.
+ // This is technically incorrect, although it doesn't cause problems in practice
+ // because this is only ever called with request_thread = GetCurrentThreadPointer().
+ R_RETURN(request_thread->GetWaitResult());
+}
+
+Result KLightServerSession::ReplyAndReceive(u32* data) {
+ // Set the server context.
+ GetCurrentThread(m_kernel).SetLightSessionData(data);
+
+ // Reply, if we need to.
+ if (data[0] & KLightSession::ReplyFlag) {
+ KScopedSchedulerLock sl(m_kernel);
+
+ // Check that we're open.
+ R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed);
+ R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed);
+
+ // Check that we have a request to reply to.
+ R_UNLESS(m_current_request != nullptr, ResultInvalidState);
+
+ // Check that the server thread id is correct.
+ R_UNLESS(m_server_thread_id == GetCurrentThread(m_kernel).GetId(), ResultInvalidState);
+
+ // If we can reply, do so.
+ if (!m_current_request->IsTerminationRequested()) {
+ std::memcpy(m_current_request->GetLightSessionData(),
+ GetCurrentThread(m_kernel).GetLightSessionData(), KLightSession::DataSize);
+ m_current_request->EndWait(ResultSuccess);
+ }
+
+ // Close our current request.
+ m_current_request->Close();
+
+ // Clear our current request.
+ m_current_request = nullptr;
+ m_server_thread_id = InvalidThreadId;
+ }
+
+ // Create the wait queue for our receive.
+ ThreadQueueImplForKLightServerSessionReceive wait_queue(m_kernel,
+ std::addressof(m_server_thread));
+
+ // Receive.
+ while (true) {
+ // Try to receive a request.
+ {
+ KScopedSchedulerLock sl(m_kernel);
+
+ // Check that we aren't already receiving.
+ R_UNLESS(m_server_thread == nullptr, ResultInvalidState);
+ R_UNLESS(m_server_thread_id == InvalidThreadId, ResultInvalidState);
+
+ // Check that we're open.
+ R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed);
+ R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed);
+
+ // Check that we're not terminating.
+ R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(),
+ ResultTerminationRequested);
+
+ // If we have a request available, use it.
+ if (auto head = m_request_list.begin(); head != m_request_list.end()) {
+ // Set our current request.
+ m_current_request = std::addressof(*head);
+ m_current_request->Open();
+
+ // Set our server thread id.
+ m_server_thread_id = GetCurrentThread(m_kernel).GetId();
+
+ // Copy the client request data.
+ std::memcpy(GetCurrentThread(m_kernel).GetLightSessionData(),
+ m_current_request->GetLightSessionData(), KLightSession::DataSize);
+
+ // We successfully received.
+ R_SUCCEED();
+ }
+
+ // We need to wait for a request to come in.
+
+ // Check if we were cancelled.
+ if (GetCurrentThread(m_kernel).IsWaitCancelled()) {
+ GetCurrentThread(m_kernel).ClearWaitCancelled();
+ R_THROW(ResultCancelled);
+ }
+
+ // Mark ourselves as cancellable.
+ GetCurrentThread(m_kernel).SetCancellable();
+
+ // Wait for a request to come in.
+ m_server_thread = GetCurrentThreadPointer(m_kernel);
+ GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
+ GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue));
+ }
+
+ // We waited to receive a request; if our wait failed, return the failing result.
+ R_TRY(GetCurrentThread(m_kernel).GetWaitResult());
+ }
+}
+
+void KLightServerSession::CleanupRequests() {
+ // Cleanup all pending requests.
+ {
+ KScopedSchedulerLock sl(m_kernel);
+
+ // Handle the current request.
+ if (m_current_request != nullptr) {
+ // Reply to the current request.
+ if (!m_current_request->IsTerminationRequested()) {
+ m_current_request->EndWait(ResultSessionClosed);
+ }
+
+ // Clear our current request.
+ m_current_request->Close();
+ m_current_request = nullptr;
+ m_server_thread_id = InvalidThreadId;
+ }
+
+ // Reply to all other requests.
+ for (auto& thread : m_request_list) {
+ thread.EndWait(ResultSessionClosed);
+ }
+
+ // Wait up our server thread, if we have one.
+ if (m_server_thread != nullptr) {
+ m_server_thread->EndWait(ResultSessionClosed);
+ }
+ }
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_server_session.h b/src/core/hle/kernel/k_light_server_session.h
new file mode 100644
index 000000000..8eca3eab6
--- /dev/null
+++ b/src/core/hle/kernel/k_light_server_session.h
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/kernel/k_auto_object.h"
+#include "core/hle/kernel/k_thread.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KLightSession;
+
+class KLightServerSession final : public KAutoObject,
+ public Common::IntrusiveListBaseNode<KLightServerSession> {
+ KERNEL_AUTOOBJECT_TRAITS(KLightServerSession, KAutoObject);
+
+private:
+ KLightSession* m_parent{};
+ KThread::WaiterList m_request_list{};
+ KThread* m_current_request{};
+ u64 m_server_thread_id{std::numeric_limits<u64>::max()};
+ KThread* m_server_thread{};
+
+public:
+ explicit KLightServerSession(KernelCore& kernel);
+ ~KLightServerSession();
+
+ void Initialize(KLightSession* parent) {
+ // Set member variables. */
+ m_parent = parent;
+ }
+
+ virtual void Destroy() override;
+
+ constexpr const KLightSession* GetParent() const {
+ return m_parent;
+ }
+
+ Result OnRequest(KThread* request_thread);
+ Result ReplyAndReceive(u32* data);
+
+ void OnClientClosed();
+
+private:
+ void CleanupRequests();
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_session.cpp b/src/core/hle/kernel/k_light_session.cpp
new file mode 100644
index 000000000..d8b1e6958
--- /dev/null
+++ b/src/core/hle/kernel/k_light_session.cpp
@@ -0,0 +1,81 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_client_port.h"
+#include "core/hle/kernel/k_light_client_session.h"
+#include "core/hle/kernel/k_light_server_session.h"
+#include "core/hle/kernel/k_light_session.h"
+#include "core/hle/kernel/k_process.h"
+
+namespace Kernel {
+
+KLightSession::KLightSession(KernelCore& kernel)
+ : KAutoObjectWithSlabHeapAndContainer(kernel), m_server(kernel), m_client(kernel) {}
+KLightSession::~KLightSession() = default;
+
+void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) {
+ // Increment reference count.
+ // Because reference count is one on creation, this will result
+ // in a reference count of two. Thus, when both server and client are closed
+ // this object will be destroyed.
+ this->Open();
+
+ // Create our sub sessions.
+ KAutoObject::Create(std::addressof(m_server));
+ KAutoObject::Create(std::addressof(m_client));
+
+ // Initialize our sub sessions.
+ m_server.Initialize(this);
+ m_client.Initialize(this);
+
+ // Set state and name.
+ m_state = State::Normal;
+ m_name = name;
+
+ // Set our owner process.
+ m_process = GetCurrentProcessPointer(m_kernel);
+ m_process->Open();
+
+ // Set our port.
+ m_port = client_port;
+ if (m_port != nullptr) {
+ m_port->Open();
+ }
+
+ // Mark initialized.
+ m_initialized = true;
+}
+
+void KLightSession::Finalize() {
+ if (m_port != nullptr) {
+ m_port->OnSessionFinalized();
+ m_port->Close();
+ }
+}
+
+void KLightSession::OnServerClosed() {
+ if (m_state == State::Normal) {
+ m_state = State::ServerClosed;
+ m_client.OnServerClosed();
+ }
+
+ this->Close();
+}
+
+void KLightSession::OnClientClosed() {
+ if (m_state == State::Normal) {
+ m_state = State::ClientClosed;
+ m_server.OnClientClosed();
+ }
+
+ this->Close();
+}
+
+void KLightSession::PostDestroy(uintptr_t arg) {
+ // Release the session count resource the owner process holds.
+ KProcess* owner = reinterpret_cast<KProcess*>(arg);
+ owner->ReleaseResource(Svc::LimitableResource::SessionCountMax, 1);
+ owner->Close();
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_light_session.h b/src/core/hle/kernel/k_light_session.h
new file mode 100644
index 000000000..f78d8e689
--- /dev/null
+++ b/src/core/hle/kernel/k_light_session.h
@@ -0,0 +1,86 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/kernel/k_light_client_session.h"
+#include "core/hle/kernel/k_light_server_session.h"
+#include "core/hle/kernel/slab_helpers.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KClientPort;
+class KProcess;
+
+// TODO: SupportDynamicExpansion for SlabHeap
+class KLightSession final
+ : public KAutoObjectWithSlabHeapAndContainer<KLightSession, KAutoObjectWithList> {
+ KERNEL_AUTOOBJECT_TRAITS(KLightSession, KAutoObject);
+
+private:
+ enum class State : u8 {
+ Invalid = 0,
+ Normal = 1,
+ ClientClosed = 2,
+ ServerClosed = 3,
+ };
+
+public:
+ static constexpr size_t DataSize = sizeof(u32) * 7;
+ static constexpr u32 ReplyFlag = (1U << 31);
+
+private:
+ KLightServerSession m_server;
+ KLightClientSession m_client;
+ State m_state{State::Invalid};
+ KClientPort* m_port{};
+ uintptr_t m_name{};
+ KProcess* m_process{};
+ bool m_initialized{};
+
+public:
+ explicit KLightSession(KernelCore& kernel);
+ ~KLightSession();
+
+ void Initialize(KClientPort* client_port, uintptr_t name);
+ void Finalize() override;
+
+ bool IsInitialized() const override {
+ return m_initialized;
+ }
+ uintptr_t GetPostDestroyArgument() const override {
+ return reinterpret_cast<uintptr_t>(m_process);
+ }
+
+ static void PostDestroy(uintptr_t arg);
+
+ void OnServerClosed();
+ void OnClientClosed();
+
+ bool IsServerClosed() const {
+ return m_state != State::Normal;
+ }
+ bool IsClientClosed() const {
+ return m_state != State::Normal;
+ }
+
+ Result OnRequest(KThread* request_thread) {
+ R_RETURN(m_server.OnRequest(request_thread));
+ }
+
+ KLightClientSession& GetClientSession() {
+ return m_client;
+ }
+ KLightServerSession& GetServerSession() {
+ return m_server;
+ }
+ const KLightClientSession& GetClientSession() const {
+ return m_client;
+ }
+ const KLightServerSession& GetServerSession() const {
+ return m_server;
+ }
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 0a973ec8c..d6bd27296 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -421,8 +421,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
} else {
// Set all the allocated memory.
for (const auto& block : *out) {
- std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern,
- block.GetSize());
+ m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) -
+ Core::DramMemoryMap::Base,
+ block.GetSize(), fill_pattern);
}
}
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 6691586ed..423289145 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -69,8 +69,21 @@ public:
};
template <typename AddressType>
-void InvalidateInstructionCache(Core::System& system, AddressType addr, u64 size) {
- system.InvalidateCpuInstructionCacheRange(GetInteger(addr), size);
+void InvalidateInstructionCache(KernelCore& kernel, AddressType addr, u64 size) {
+ // TODO: lock the process list
+ for (auto& process : kernel.GetProcessList()) {
+ for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ auto* interface = process->GetArmInterface(i);
+ if (interface) {
+ interface->InvalidateCacheRange(GetInteger(addr), size);
+ }
+ }
+ }
+}
+
+void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) {
+ system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base,
+ size, fill_value);
}
template <typename AddressType>
@@ -1261,7 +1274,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
bool reprotected_pages = false;
SCOPE_EXIT({
if (reprotected_pages && any_code_pages) {
- InvalidateInstructionCache(m_system, dst_address, size);
+ InvalidateInstructionCache(m_kernel, dst_address, size);
}
});
@@ -1355,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// Clear all the newly allocated pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()),
- static_cast<u32>(m_heap_fill_value), it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Lock the table.
@@ -1562,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
// Clear all pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()),
- static_cast<u32>(m_heap_fill_value), it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Map the pages.
@@ -1997,7 +2008,7 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s
for (const auto& block : pg) {
StoreDataCache(GetHeapVirtualPointer(m_kernel, block.GetAddress()), block.GetSize());
}
- InvalidateInstructionCache(m_system, addr, size);
+ InvalidateInstructionCache(m_kernel, addr, size);
}
R_SUCCEED();
@@ -2151,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
// Clear all the newly allocated pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value,
- it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Map the pages.
@@ -3239,7 +3249,7 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd
R_TRY(PerformCopy());
// Invalidate the instruction cache, as this svc allows modifying executable pages.
- InvalidateInstructionCache(m_system, dst_address, size);
+ InvalidateInstructionCache(m_kernel, dst_address, size);
R_SUCCEED();
}
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp
index 1621ca1d3..e5f5d8028 100644
--- a/src/core/hle/kernel/k_port.cpp
+++ b/src/core/hle/kernel/k_port.cpp
@@ -58,4 +58,13 @@ Result KPort::EnqueueSession(KServerSession* session) {
R_SUCCEED();
}
+Result KPort::EnqueueSession(KLightServerSession* session) {
+ KScopedSchedulerLock sl{m_kernel};
+
+ R_UNLESS(m_state == State::Normal, ResultPortClosed);
+
+ m_server.EnqueueSession(session);
+ R_SUCCEED();
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index 991be27ab..26f5f14ef 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -13,6 +13,7 @@
namespace Kernel {
+class KLightServerSession;
class KServerSession;
class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> {
@@ -38,6 +39,7 @@ public:
bool IsServerClosed() const;
Result EnqueueSession(KServerSession* session);
+ Result EnqueueSession(KLightServerSession* session);
KClientPort& GetClientPort() {
return m_client;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 6c29eb72c..3a2635e1f 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -13,6 +13,12 @@
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/k_worker_task_manager.h"
+#include "core/arm/dynarmic/arm_dynarmic_32.h"
+#include "core/arm/dynarmic/arm_dynarmic_64.h"
+#ifdef HAS_NCE
+#include "core/arm/nce/arm_nce.h"
+#endif
+
namespace Kernel {
namespace {
@@ -957,10 +963,8 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread));
// Set the thread arguments.
- main_thread->GetContext32().cpu_registers[0] = 0;
- main_thread->GetContext64().cpu_registers[0] = 0;
- main_thread->GetContext32().cpu_registers[1] = thread_handle;
- main_thread->GetContext64().cpu_registers[1] = thread_handle;
+ main_thread->GetContext().r[0] = 0;
+ main_thread->GetContext().r[1] = thread_handle;
// Update our state.
this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached);
@@ -1199,6 +1203,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
m_is_hbl = is_hbl;
m_ideal_core_id = metadata.GetMainThreadCore();
+ // Set up emulation context.
+ this->InitializeInterfaces();
+
// We succeeded.
R_SUCCEED();
}
@@ -1227,6 +1234,31 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
#endif
}
+void KProcess::InitializeInterfaces() {
+ this->GetMemory().SetCurrentPageTable(*this);
+
+#ifdef HAS_NCE
+ if (this->Is64Bit() && Settings::IsNceEnabled()) {
+ for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i);
+ }
+ } else
+#endif
+ if (this->Is64Bit()) {
+ for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic64>(
+ m_kernel.System(), m_kernel.IsMulticore(), this,
+ static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i);
+ }
+ } else {
+ for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic32>(
+ m_kernel.System(), m_kernel.IsMulticore(), this,
+ static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i);
+ }
+ }
+}
+
bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
return wp.type == DebugWatchpointType::None;
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index d8cd0fdde..4b114e39b 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -5,6 +5,7 @@
#include <map>
+#include "core/arm/arm_interface.h"
#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/code_set.h"
#include "core/hle/kernel/k_address_arbiter.h"
@@ -106,6 +107,8 @@ private:
bool m_is_suspended{};
bool m_is_immortal{};
bool m_is_handle_table_initialized{};
+ std::array<std::unique_ptr<Core::ArmInterface>, Core::Hardware::NUM_CPU_CORES>
+ m_arm_interfaces{};
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{};
std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_switch_counts{};
@@ -476,6 +479,10 @@ public:
}
#endif
+ Core::ArmInterface* GetArmInterface(size_t core_index) const {
+ return m_arm_interfaces[core_index].get();
+ }
+
public:
// Attempts to insert a watchpoint into a free slot. Returns false if none are available.
bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
@@ -493,6 +500,8 @@ public:
void LoadModule(CodeSet code_set, KProcessAddress base_addr);
+ void InitializeInterfaces();
+
Core::Memory::Memory& GetMemory() const;
public:
diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h
index 9e40f68bc..346d7ca08 100644
--- a/src/core/hle/kernel/k_process_page_table.h
+++ b/src/core/hle/kernel/k_process_page_table.h
@@ -7,10 +7,6 @@
#include "core/hle/kernel/k_scoped_lock.h"
#include "core/hle/kernel/svc_types.h"
-namespace Core {
-class ARM_Interface;
-}
-
namespace Kernel {
class KProcessPageTable {
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 1bce63a56..27d1c3846 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -494,12 +494,7 @@ void KScheduler::ScheduleImplFiber() {
}
void KScheduler::Unload(KThread* thread) {
- auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
- cpu_core.SaveContext(thread->GetContext32());
- cpu_core.SaveContext(thread->GetContext64());
- // Save the TPIDR_EL0 system register in case it was modified.
- thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0());
- cpu_core.ClearExclusiveState();
+ m_kernel.PhysicalCore(m_core_id).SaveContext(thread);
// Check if the thread is terminated by checking the DPC flags.
if ((thread->GetStackParameters().dpc_flags & static_cast<u32>(DpcFlag::Terminated)) == 0) {
@@ -509,14 +504,7 @@ void KScheduler::Unload(KThread* thread) {
}
void KScheduler::Reload(KThread* thread) {
- auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
- auto* process = thread->GetOwnerProcess();
- cpu_core.LoadContext(thread->GetContext32());
- cpu_core.LoadContext(thread->GetContext64());
- cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
- cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
- cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
- cpu_core.ClearExclusiveState();
+ m_kernel.PhysicalCore(m_core_id).LoadContext(thread);
}
void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) {
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp
index a29d34bc1..bb6632f58 100644
--- a/src/core/hle/kernel/k_server_port.cpp
+++ b/src/core/hle/kernel/k_server_port.cpp
@@ -27,12 +27,14 @@ bool KServerPort::IsLight() const {
void KServerPort::CleanupSessions() {
// Ensure our preconditions are met.
if (this->IsLight()) {
- UNIMPLEMENTED();
+ ASSERT(m_session_list.empty());
+ } else {
+ ASSERT(m_light_session_list.empty());
}
// Cleanup the session list.
while (true) {
- // Get the last session in the list
+ // Get the last session in the list.
KServerSession* session = nullptr;
{
KScopedSchedulerLock sl{m_kernel};
@@ -49,6 +51,26 @@ void KServerPort::CleanupSessions() {
break;
}
}
+
+ // Cleanup the light session list.
+ while (true) {
+ // Get the last session in the list.
+ KLightServerSession* session = nullptr;
+ {
+ KScopedSchedulerLock sl{m_kernel};
+ if (!m_light_session_list.empty()) {
+ session = std::addressof(m_light_session_list.front());
+ m_light_session_list.pop_front();
+ }
+ }
+
+ // Close the session.
+ if (session != nullptr) {
+ session->Close();
+ } else {
+ break;
+ }
+ }
}
void KServerPort::Destroy() {
@@ -64,8 +86,7 @@ void KServerPort::Destroy() {
bool KServerPort::IsSignaled() const {
if (this->IsLight()) {
- UNIMPLEMENTED();
- return false;
+ return !m_light_session_list.empty();
} else {
return !m_session_list.empty();
}
@@ -83,6 +104,18 @@ void KServerPort::EnqueueSession(KServerSession* session) {
}
}
+void KServerPort::EnqueueSession(KLightServerSession* session) {
+ ASSERT(this->IsLight());
+
+ KScopedSchedulerLock sl{m_kernel};
+
+ // Add the session to our queue.
+ m_light_session_list.push_back(*session);
+ if (m_light_session_list.size() == 1) {
+ this->NotifyAvailable();
+ }
+}
+
KServerSession* KServerPort::AcceptSession() {
ASSERT(!this->IsLight());
@@ -98,4 +131,19 @@ KServerSession* KServerPort::AcceptSession() {
return session;
}
+KLightServerSession* KServerPort::AcceptLightSession() {
+ ASSERT(this->IsLight());
+
+ KScopedSchedulerLock sl{m_kernel};
+
+ // Return the first session in the list.
+ if (m_light_session_list.empty()) {
+ return nullptr;
+ }
+
+ KLightServerSession* session = std::addressof(m_light_session_list.front());
+ m_light_session_list.pop_front();
+ return session;
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index 625280290..72fdb6734 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -9,6 +9,7 @@
#include "common/intrusive_list.h"
+#include "core/hle/kernel/k_light_server_session.h"
#include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/k_synchronization_object.h"
@@ -28,8 +29,10 @@ public:
void Initialize(KPort* parent);
void EnqueueSession(KServerSession* session);
+ void EnqueueSession(KLightServerSession* session);
KServerSession* AcceptSession();
+ KLightServerSession* AcceptLightSession();
const KPort* GetParent() const {
return m_parent;
@@ -43,10 +46,12 @@ public:
private:
using SessionList = Common::IntrusiveListBaseTraits<KServerSession>::ListType;
+ using LightSessionList = Common::IntrusiveListBaseTraits<KLightServerSession>::ListType;
void CleanupSessions();
SessionList m_session_list{};
+ LightSessionList m_light_session_list{};
KPort* m_parent{};
};
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 3ea653163..e33a88e24 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -453,6 +453,11 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
size_t client_buffer_size = request->GetSize();
// bool recv_list_broken = false;
+ if (!client_message) {
+ client_message = GetInteger(client_thread->GetTlsAddress());
+ client_buffer_size = MessageBufferSize;
+ }
+
// Receive the message.
Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
if (out_context != nullptr) {
@@ -462,8 +467,7 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
std::make_shared<Service::HLERequestContext>(m_kernel, memory, this, client_thread);
(*out_context)->SetSessionRequestManager(manager);
(*out_context)
- ->PopulateFromIncomingCommandBuffer(client_thread->GetOwnerProcess()->GetHandleTable(),
- cmd_buf);
+ ->PopulateFromIncomingCommandBuffer(*client_thread->GetOwnerProcess(), cmd_buf);
} else {
KThread* server_thread = GetCurrentThreadPointer(m_kernel);
KProcess& src_process = *client_thread->GetOwnerProcess();
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index f69bab088..3f4dd5989 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -46,6 +46,10 @@ public:
return this->GetState() != State::Normal;
}
+ Result OnRequest(KSessionRequest* request) {
+ R_RETURN(m_server.OnRequest(request));
+ }
+
KClientSession& GetClientSession() {
return m_client;
}
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index a6deb50ec..7d9a6e9cf 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -41,24 +41,25 @@ namespace {
constexpr inline s32 TerminatingThreadPriority = Kernel::Svc::SystemThreadPriorityHighest - 1;
-static void ResetThreadContext32(Kernel::KThread::ThreadContext32& context, u32 stack_top,
- u32 entry_point, u32 arg) {
- context = {};
- context.cpu_registers[0] = arg;
- context.cpu_registers[15] = entry_point;
- context.cpu_registers[13] = stack_top;
- context.fpscr = 0;
-}
-
-static void ResetThreadContext64(Kernel::KThread::ThreadContext64& context, u64 stack_top,
- u64 entry_point, u64 arg) {
- context = {};
- context.cpu_registers[0] = arg;
- context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
- context.pc = entry_point;
- context.sp = stack_top;
- context.fpcr = 0;
- context.fpsr = 0;
+static void ResetThreadContext32(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point,
+ u64 arg) {
+ ctx = {};
+ ctx.r[0] = arg;
+ ctx.r[15] = entry_point;
+ ctx.r[13] = stack_top;
+ ctx.fpcr = 0;
+ ctx.fpsr = 0;
+}
+
+static void ResetThreadContext64(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point,
+ u64 arg) {
+ ctx = {};
+ ctx.r[0] = arg;
+ ctx.r[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
+ ctx.pc = entry_point;
+ ctx.sp = stack_top;
+ ctx.fpcr = 0;
+ ctx.fpsr = 0;
}
} // namespace
@@ -223,9 +224,11 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
}
// Initialize thread context.
- ResetThreadContext64(m_thread_context_64, GetInteger(user_stack_top), GetInteger(func), arg);
- ResetThreadContext32(m_thread_context_32, static_cast<u32>(GetInteger(user_stack_top)),
- static_cast<u32>(GetInteger(func)), static_cast<u32>(arg));
+ if (m_parent != nullptr && !m_parent->Is64Bit()) {
+ ResetThreadContext32(m_thread_context, GetInteger(user_stack_top), GetInteger(func), arg);
+ } else {
+ ResetThreadContext64(m_thread_context, GetInteger(user_stack_top), GetInteger(func), arg);
+ }
// Setup the stack parameters.
StackParameters& sp = this->GetStackParameters();
@@ -823,20 +826,7 @@ void KThread::CloneFpuStatus() {
ASSERT(this->GetOwnerProcess() != nullptr);
ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel));
- if (this->GetOwnerProcess()->Is64Bit()) {
- // Clone FPSR and FPCR.
- ThreadContext64 cur_ctx{};
- m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
-
- this->GetContext64().fpcr = cur_ctx.fpcr;
- this->GetContext64().fpsr = cur_ctx.fpsr;
- } else {
- // Clone FPSCR.
- ThreadContext32 cur_ctx{};
- m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
-
- this->GetContext32().fpscr = cur_ctx.fpscr;
- }
+ m_kernel.CurrentPhysicalCore().CloneFpuStatus(this);
}
Result KThread::SetActivity(Svc::ThreadActivity activity) {
@@ -912,7 +902,7 @@ Result KThread::SetActivity(Svc::ThreadActivity activity) {
R_SUCCEED();
}
-Result KThread::GetThreadContext3(Common::ScratchBuffer<u8>& out) {
+Result KThread::GetThreadContext3(Svc::ThreadContext* out) {
// Lock ourselves.
KScopedLightLock lk{m_activity_pause_lock};
@@ -926,18 +916,16 @@ Result KThread::GetThreadContext3(Common::ScratchBuffer<u8>& out) {
// If we're not terminating, get the thread's user context.
if (!this->IsTerminationRequested()) {
+ *out = m_thread_context;
+
+ // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
+ constexpr u32 El0Aarch64PsrMask = 0xF0000000;
+ constexpr u32 El0Aarch32PsrMask = 0xFE0FFE20;
+
if (m_parent->Is64Bit()) {
- // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
- auto context = GetContext64();
- context.pstate &= 0xFF0FFE20;
- out.resize_destructive(sizeof(context));
- std::memcpy(out.data(), std::addressof(context), sizeof(context));
+ out->pstate &= El0Aarch64PsrMask;
} else {
- // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
- auto context = GetContext32();
- context.cpsr &= 0xFF0FFE20;
- out.resize_destructive(sizeof(context));
- std::memcpy(out.data(), std::addressof(context), sizeof(context));
+ out->pstate &= El0Aarch32PsrMask;
}
}
}
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index e9ca5dfca..e9925d231 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -38,7 +38,6 @@ namespace Core {
namespace Memory {
class Memory;
}
-class ARM_Interface;
class System;
} // namespace Core
@@ -137,8 +136,6 @@ public:
~KThread() override;
public:
- using ThreadContext32 = Core::ARM_Interface::ThreadContext32;
- using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
using WaiterList = Common::IntrusiveListBaseTraits<KThread>::ListType;
/**
@@ -246,31 +243,22 @@ public:
* @returns The value of the TPIDR_EL0 register.
*/
u64 GetTpidrEl0() const {
- return m_thread_context_64.tpidr;
+ return m_thread_context.tpidr;
}
/// Sets the value of the TPIDR_EL0 Read/Write system register for this thread.
void SetTpidrEl0(u64 value) {
- m_thread_context_64.tpidr = value;
- m_thread_context_32.tpidr = static_cast<u32>(value);
+ m_thread_context.tpidr = value;
}
void CloneFpuStatus();
- ThreadContext32& GetContext32() {
- return m_thread_context_32;
+ Svc::ThreadContext& GetContext() {
+ return m_thread_context;
}
- const ThreadContext32& GetContext32() const {
- return m_thread_context_32;
- }
-
- ThreadContext64& GetContext64() {
- return m_thread_context_64;
- }
-
- const ThreadContext64& GetContext64() const {
- return m_thread_context_64;
+ const Svc::ThreadContext& GetContext() const {
+ return m_thread_context;
}
std::shared_ptr<Common::Fiber>& GetHostContext();
@@ -397,6 +385,13 @@ public:
m_cancellable = false;
}
+ u32* GetLightSessionData() const {
+ return m_light_ipc_data;
+ }
+ void SetLightSessionData(u32* data) {
+ m_light_ipc_data = data;
+ }
+
bool IsTerminationRequested() const {
return m_termination_requested || GetRawState() == ThreadState::Terminated;
}
@@ -577,7 +572,7 @@ public:
void RemoveWaiter(KThread* thread);
- Result GetThreadContext3(Common::ScratchBuffer<u8>& out);
+ Result GetThreadContext3(Svc::ThreadContext* out);
KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) {
return this->RemoveWaiterByKey(out_has_waiters, key, false);
@@ -734,8 +729,7 @@ private:
std::function<void()>&& init_func);
// For core KThread implementation
- ThreadContext32 m_thread_context_32{};
- ThreadContext64 m_thread_context_64{};
+ Svc::ThreadContext m_thread_context{};
Common::IntrusiveListNode m_process_list_node;
Common::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node{};
s32 m_priority{};
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4a1559291..e479dacde 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -99,13 +99,6 @@ struct KernelCore::Impl {
RegisterHostThread(nullptr);
}
- void InitializeCores() {
- for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
- cores[core_id]->Initialize((*application_process).Is64Bit());
- system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id);
- }
- }
-
void TerminateApplicationProcess() {
application_process.load()->Terminate();
}
@@ -142,7 +135,6 @@ struct KernelCore::Impl {
obj = nullptr;
}
};
- CleanupObject(hid_shared_mem);
CleanupObject(font_shared_mem);
CleanupObject(irs_shared_mem);
CleanupObject(time_shared_mem);
@@ -205,7 +197,7 @@ struct KernelCore::Impl {
const s32 core{static_cast<s32>(i)};
schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel());
- cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]);
+ cores[i] = std::make_unique<Kernel::PhysicalCore>(system.Kernel(), i);
auto* main_thread{Kernel::KThread::Create(system.Kernel())};
main_thread->SetCurrentCore(core);
@@ -751,22 +743,16 @@ struct KernelCore::Impl {
void InitializeHackSharedMemory(KernelCore& kernel) {
// Setup memory regions for emulated processes
// TODO(bunnei): These should not be hardcoded regions initialized within the kernel
- constexpr std::size_t hid_size{0x40000};
constexpr std::size_t font_size{0x1100000};
constexpr std::size_t irs_size{0x8000};
constexpr std::size_t time_size{0x1000};
constexpr std::size_t hidbus_size{0x1000};
- hid_shared_mem = KSharedMemory::Create(system.Kernel());
font_shared_mem = KSharedMemory::Create(system.Kernel());
irs_shared_mem = KSharedMemory::Create(system.Kernel());
time_shared_mem = KSharedMemory::Create(system.Kernel());
hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
- hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
- Svc::MemoryPermission::Read, hid_size);
- KSharedMemory::Register(kernel, hid_shared_mem);
-
font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, font_size);
KSharedMemory::Register(kernel, font_shared_mem);
@@ -880,10 +866,6 @@ void KernelCore::Initialize() {
impl->Initialize(*this);
}
-void KernelCore::InitializeCores() {
- impl->InitializeCores();
-}
-
void KernelCore::Shutdown() {
impl->Shutdown();
}
@@ -993,21 +975,6 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
return *impl->global_object_list_container;
}
-void KernelCore::InvalidateAllInstructionCaches() {
- for (auto& physical_core : impl->cores) {
- physical_core->ArmInterface().ClearInstructionCache();
- }
-}
-
-void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) {
- for (auto& physical_core : impl->cores) {
- if (!physical_core->IsInitialized()) {
- continue;
- }
- physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size);
- }
-}
-
void KernelCore::PrepareReschedule(std::size_t id) {
// TODO: Reimplement, this
}
@@ -1216,14 +1183,6 @@ const KSystemResource& KernelCore::GetSystemSystemResource() const {
return *impl->sys_system_resource;
}
-Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
- return *impl->hid_shared_mem;
-}
-
-const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
- return *impl->hid_shared_mem;
-}
-
Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
return *impl->font_shared_mem;
}
@@ -1366,6 +1325,7 @@ struct KernelCore::SlabHeapContainer {
KSlabHeap<KProcess> process;
KSlabHeap<KResourceLimit> resource_limit;
KSlabHeap<KSession> session;
+ KSlabHeap<KLightSession> light_session;
KSlabHeap<KSharedMemory> shared_memory;
KSlabHeap<KSharedMemoryInfo> shared_memory_info;
KSlabHeap<KThread> thread;
@@ -1396,6 +1356,8 @@ KSlabHeap<T>& KernelCore::SlabHeap() {
return slab_heap_container->resource_limit;
} else if constexpr (std::is_same_v<T, KSession>) {
return slab_heap_container->session;
+ } else if constexpr (std::is_same_v<T, KLightSession>) {
+ return slab_heap_container->light_session;
} else if constexpr (std::is_same_v<T, KSharedMemory>) {
return slab_heap_container->shared_memory;
} else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) {
@@ -1433,6 +1395,7 @@ template KSlabHeap<KPort>& KernelCore::SlabHeap();
template KSlabHeap<KProcess>& KernelCore::SlabHeap();
template KSlabHeap<KResourceLimit>& KernelCore::SlabHeap();
template KSlabHeap<KSession>& KernelCore::SlabHeap();
+template KSlabHeap<KLightSession>& KernelCore::SlabHeap();
template KSlabHeap<KSharedMemory>& KernelCore::SlabHeap();
template KSlabHeap<KSharedMemoryInfo>& KernelCore::SlabHeap();
template KSlabHeap<KThread>& KernelCore::SlabHeap();
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d8086c0ea..78c88902c 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -104,9 +104,6 @@ public:
/// Resets the kernel to a clean slate for use.
void Initialize();
- /// Initializes the CPU cores.
- void InitializeCores();
-
/// Clears all resources in use by the kernel instance.
void Shutdown();
@@ -181,10 +178,6 @@ public:
const KAutoObjectWithListContainer& ObjectListContainer() const;
- void InvalidateAllInstructionCaches();
-
- void InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size);
-
/// Registers all kernel objects with the global emulation state, this is purely for tracking
/// leaks after emulation has been shutdown.
void RegisterKernelObject(KAutoObject* object);
@@ -246,12 +239,6 @@ public:
/// Gets the system resource manager.
const KSystemResource& GetSystemSystemResource() const;
- /// Gets the shared memory object for HID services.
- Kernel::KSharedMemory& GetHidSharedMem();
-
- /// Gets the shared memory object for HID services.
- const Kernel::KSharedMemory& GetHidSharedMem() const;
-
/// Gets the shared memory object for font services.
Kernel::KSharedMemory& GetFontSharedMem();
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 073039825..0f45a3249 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -1,62 +1,206 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "common/scope_exit.h"
#include "common/settings.h"
-#include "core/arm/dynarmic/arm_dynarmic_32.h"
-#include "core/arm/dynarmic/arm_dynarmic_64.h"
-#ifdef HAS_NCE
-#include "core/arm/nce/arm_nce.h"
-#endif
#include "core/core.h"
-#include "core/hle/kernel/k_scheduler.h"
+#include "core/debugger/debugger.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
+#include "core/hle/kernel/svc.h"
namespace Kernel {
-PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KScheduler& scheduler)
- : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} {
-#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
- // TODO(bunnei): Initialization relies on a core being available. We may later replace this with
- // an NCE interface or a 32-bit instance of Dynarmic. This should be abstracted out to a CPU
- // manager.
- auto& kernel = system.Kernel();
- m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
- system, kernel.IsMulticore(),
- reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
- m_core_index);
-#else
-#error Platform not supported yet.
-#endif
+PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index)
+ : m_kernel{kernel}, m_core_index{core_index} {
+ m_is_single_core = !kernel.IsMulticore();
}
-
PhysicalCore::~PhysicalCore() = default;
-void PhysicalCore::Initialize(bool is_64_bit) {
-#if defined(HAS_NCE)
- if (Settings::IsNceEnabled()) {
- m_arm_interface = std::make_unique<Core::ARM_NCE>(m_system, m_system.Kernel().IsMulticore(),
- m_core_index);
+void PhysicalCore::RunThread(Kernel::KThread* thread) {
+ auto* process = thread->GetOwnerProcess();
+ auto& system = m_kernel.System();
+ auto* interface = process->GetArmInterface(m_core_index);
+
+ interface->Initialize();
+
+ const auto EnterContext = [&]() {
+ system.EnterCPUProfile();
+
+ // Lock the core context.
+ std::scoped_lock lk{m_guard};
+
+ // Check if we are already interrupted. If we are, we can just stop immediately.
+ if (m_is_interrupted) {
+ return false;
+ }
+
+ // Mark that we are running.
+ m_arm_interface = interface;
+ m_current_thread = thread;
+
+ // Acquire the lock on the thread parameters.
+ // This allows us to force synchronization with Interrupt.
+ interface->LockThread(thread);
+
+ return true;
+ };
+
+ const auto ExitContext = [&]() {
+ // Unlock the thread.
+ interface->UnlockThread(thread);
+
+ // Lock the core context.
+ std::scoped_lock lk{m_guard};
+
+ // On exit, we no longer are running.
+ m_arm_interface = nullptr;
+ m_current_thread = nullptr;
+
+ system.ExitCPUProfile();
+ };
+
+ while (true) {
+ // If the thread is scheduled for termination, exit.
+ if (thread->HasDpc() && thread->IsTerminationRequested()) {
+ thread->Exit();
+ }
+
+ // Notify the debugger and go to sleep if a step was performed
+ // and this thread has been scheduled again.
+ if (thread->GetStepState() == StepState::StepPerformed) {
+ system.GetDebugger().NotifyThreadStopped(thread);
+ thread->RequestSuspend(SuspendType::Debug);
+ return;
+ }
+
+ // Otherwise, run the thread.
+ Core::HaltReason hr{};
+ {
+ // If we were interrupted, exit immediately.
+ if (!EnterContext()) {
+ return;
+ }
+
+ if (thread->GetStepState() == StepState::StepPending) {
+ hr = interface->StepThread(thread);
+
+ if (True(hr & Core::HaltReason::StepThread)) {
+ thread->SetStepState(StepState::StepPerformed);
+ }
+ } else {
+ hr = interface->RunThread(thread);
+ }
+
+ ExitContext();
+ }
+
+ // Determine why we stopped.
+ const bool supervisor_call = True(hr & Core::HaltReason::SupervisorCall);
+ const bool prefetch_abort = True(hr & Core::HaltReason::PrefetchAbort);
+ const bool breakpoint = True(hr & Core::HaltReason::InstructionBreakpoint);
+ const bool data_abort = True(hr & Core::HaltReason::DataAbort);
+ const bool interrupt = True(hr & Core::HaltReason::BreakLoop);
+
+ // Since scheduling may occur here, we cannot use any cached
+ // state after returning from calls we make.
+
+ // Notify the debugger and go to sleep if a breakpoint was hit,
+ // or if the thread is unable to continue for any reason.
+ if (breakpoint || prefetch_abort) {
+ if (breakpoint) {
+ interface->RewindBreakpointInstruction();
+ }
+ if (system.DebuggerEnabled()) {
+ system.GetDebugger().NotifyThreadStopped(thread);
+ } else {
+ interface->LogBacktrace(process);
+ }
+ thread->RequestSuspend(SuspendType::Debug);
+ return;
+ }
+
+ // Notify the debugger and go to sleep on data abort.
+ if (data_abort) {
+ if (system.DebuggerEnabled()) {
+ system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint());
+ }
+ thread->RequestSuspend(SuspendType::Debug);
+ return;
+ }
+
+ // Handle system calls.
+ if (supervisor_call) {
+ // Perform call.
+ Svc::Call(system, interface->GetSvcNumber());
+ return;
+ }
+
+ // Handle external interrupt sources.
+ if (interrupt || m_is_single_core) {
+ return;
+ }
+ }
+}
+
+void PhysicalCore::LoadContext(const KThread* thread) {
+ auto* const process = thread->GetOwnerProcess();
+ if (!process) {
+ // Kernel threads do not run on emulated CPU cores.
return;
}
-#endif
-#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
- auto& kernel = m_system.Kernel();
- if (!is_64_bit) {
- // We already initialized a 64-bit core, replace with a 32-bit one.
- m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
- m_system, kernel.IsMulticore(),
- reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
- m_core_index);
+
+ auto* interface = process->GetArmInterface(m_core_index);
+ if (interface) {
+ interface->SetContext(thread->GetContext());
+ interface->SetTpidrroEl0(GetInteger(thread->GetTlsAddress()));
+ interface->SetWatchpointArray(&process->GetWatchpoints());
}
-#else
-#error Platform not supported yet.
-#endif
}
-void PhysicalCore::Run() {
- m_arm_interface->Run();
- m_arm_interface->ClearExclusiveState();
+void PhysicalCore::LoadSvcArguments(const KProcess& process, std::span<const uint64_t, 8> args) {
+ process.GetArmInterface(m_core_index)->SetSvcArguments(args);
+}
+
+void PhysicalCore::SaveContext(KThread* thread) const {
+ auto* const process = thread->GetOwnerProcess();
+ if (!process) {
+ // Kernel threads do not run on emulated CPU cores.
+ return;
+ }
+
+ auto* interface = process->GetArmInterface(m_core_index);
+ if (interface) {
+ interface->GetContext(thread->GetContext());
+ }
+}
+
+void PhysicalCore::SaveSvcArguments(KProcess& process, std::span<uint64_t, 8> args) const {
+ process.GetArmInterface(m_core_index)->GetSvcArguments(args);
+}
+
+void PhysicalCore::CloneFpuStatus(KThread* dst) const {
+ auto* process = dst->GetOwnerProcess();
+
+ Svc::ThreadContext ctx{};
+ process->GetArmInterface(m_core_index)->GetContext(ctx);
+
+ dst->GetContext().fpcr = ctx.fpcr;
+ dst->GetContext().fpsr = ctx.fpsr;
+}
+
+void PhysicalCore::LogBacktrace() {
+ auto* process = GetCurrentProcessPointer(m_kernel);
+ if (!process) {
+ return;
+ }
+
+ auto* interface = process->GetArmInterface(m_core_index);
+ if (interface) {
+ interface->LogBacktrace(process);
+ }
}
void PhysicalCore::Idle() {
@@ -69,16 +213,31 @@ bool PhysicalCore::IsInterrupted() const {
}
void PhysicalCore::Interrupt() {
- std::unique_lock lk{m_guard};
+ // Lock core context.
+ std::scoped_lock lk{m_guard};
+
+ // Load members.
+ auto* arm_interface = m_arm_interface;
+ auto* thread = m_current_thread;
+
+ // Add interrupt flag.
m_is_interrupted = true;
- m_arm_interface->SignalInterrupt();
- m_on_interrupt.notify_all();
+
+ // Interrupt ourselves.
+ m_on_interrupt.notify_one();
+
+ // If there is no thread running, we are done.
+ if (arm_interface == nullptr) {
+ return;
+ }
+
+ // Interrupt the CPU.
+ arm_interface->SignalInterrupt(thread);
}
void PhysicalCore::ClearInterrupt() {
- std::unique_lock lk{m_guard};
+ std::scoped_lock lk{m_guard};
m_is_interrupted = false;
- m_arm_interface->ClearInterrupt();
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
index 5cb398fdc..bae4fe5b8 100644
--- a/src/core/hle/kernel/physical_core.h
+++ b/src/core/hle/kernel/physical_core.h
@@ -11,7 +11,7 @@
#include "core/arm/arm_interface.h"
namespace Kernel {
-class KScheduler;
+class KernelCore;
} // namespace Kernel
namespace Core {
@@ -23,62 +23,55 @@ namespace Kernel {
class PhysicalCore {
public:
- PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
+ PhysicalCore(KernelCore& kernel, std::size_t core_index);
~PhysicalCore();
YUZU_NON_COPYABLE(PhysicalCore);
YUZU_NON_MOVEABLE(PhysicalCore);
- /// Initialize the core for the specified parameters.
- void Initialize(bool is_64_bit);
+ // Execute guest code running on the given thread.
+ void RunThread(KThread* thread);
- /// Execute current jit state
- void Run();
+ // Copy context from thread to current core.
+ void LoadContext(const KThread* thread);
+ void LoadSvcArguments(const KProcess& process, std::span<const uint64_t, 8> args);
+ // Copy context from current core to thread.
+ void SaveContext(KThread* thread) const;
+ void SaveSvcArguments(KProcess& process, std::span<uint64_t, 8> args) const;
+
+ // Copy floating point status registers to the target thread.
+ void CloneFpuStatus(KThread* dst) const;
+
+ // Log backtrace of current processor state.
+ void LogBacktrace();
+
+ // Wait for an interrupt.
void Idle();
- /// Interrupt this physical core.
+ // Interrupt this core.
void Interrupt();
- /// Clear this core's interrupt
+ // Clear this core's interrupt.
void ClearInterrupt();
- /// Check if this core is interrupted
+ // Check if this core is interrupted.
bool IsInterrupted() const;
- bool IsInitialized() const {
- return m_arm_interface != nullptr;
- }
-
- Core::ARM_Interface& ArmInterface() {
- return *m_arm_interface;
- }
-
- const Core::ARM_Interface& ArmInterface() const {
- return *m_arm_interface;
- }
-
std::size_t CoreIndex() const {
return m_core_index;
}
- Kernel::KScheduler& Scheduler() {
- return m_scheduler;
- }
-
- const Kernel::KScheduler& Scheduler() const {
- return m_scheduler;
- }
-
private:
+ KernelCore& m_kernel;
const std::size_t m_core_index;
- Core::System& m_system;
- Kernel::KScheduler& m_scheduler;
std::mutex m_guard;
std::condition_variable m_on_interrupt;
- std::unique_ptr<Core::ARM_Interface> m_arm_interface;
+ Core::ArmInterface* m_arm_interface{};
+ KThread* m_current_thread{};
bool m_is_interrupted{};
+ bool m_is_single_core{};
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b76683969..c55dc0c8a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -12,20 +12,20 @@
namespace Kernel::Svc {
-static uint32_t GetReg32(Core::System& system, int n) {
- return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n));
+static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
+ return static_cast<uint32_t>(args[n]);
}
-static void SetReg32(Core::System& system, int n, uint32_t result) {
- system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
+static void SetArg32(std::span<uint64_t, 8> args, int n, uint32_t result) {
+ args[n] = result;
}
-static uint64_t GetReg64(Core::System& system, int n) {
- return system.CurrentArmInterface().GetReg(n);
+static uint64_t GetArg64(std::span<uint64_t, 8> args, int n) {
+ return args[n];
}
-static void SetReg64(Core::System& system, int n, uint64_t result) {
- system.CurrentArmInterface().SetReg(n, result);
+static void SetArg64(std::span<uint64_t, 8> args, int n, uint64_t result) {
+ args[n] = result;
}
// Like bit_cast, but handles the case when the source and dest
@@ -79,37 +79,37 @@ static_assert(sizeof(int64_t) == 8);
static_assert(sizeof(uint32_t) == 4);
static_assert(sizeof(uint64_t) == 8);
-static void SvcWrap_SetHeapSize64From32(Core::System& system) {
+static void SvcWrap_SetHeapSize64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_address{};
uint32_t size{};
- size = Convert<uint32_t>(GetReg32(system, 1));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = SetHeapSize64From32(system, std::addressof(out_address), size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_address));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_address));
}
-static void SvcWrap_SetMemoryPermission64From32(Core::System& system) {
+static void SvcWrap_SetMemoryPermission64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
MemoryPermission perm{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
- perm = Convert<MemoryPermission>(GetReg32(system, 2));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
+ perm = Convert<MemoryPermission>(GetArg32(args, 2));
ret = SetMemoryPermission64From32(system, address, size, perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SetMemoryAttribute64From32(Core::System& system) {
+static void SvcWrap_SetMemoryAttribute64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
@@ -117,69 +117,69 @@ static void SvcWrap_SetMemoryAttribute64From32(Core::System& system) {
uint32_t mask{};
uint32_t attr{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
- mask = Convert<uint32_t>(GetReg32(system, 2));
- attr = Convert<uint32_t>(GetReg32(system, 3));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
+ mask = Convert<uint32_t>(GetArg32(args, 2));
+ attr = Convert<uint32_t>(GetArg32(args, 3));
ret = SetMemoryAttribute64From32(system, address, size, mask, attr);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapMemory64From32(Core::System& system) {
+static void SvcWrap_MapMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t dst_address{};
uint32_t src_address{};
uint32_t size{};
- dst_address = Convert<uint32_t>(GetReg32(system, 0));
- src_address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ dst_address = Convert<uint32_t>(GetArg32(args, 0));
+ src_address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = MapMemory64From32(system, dst_address, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t dst_address{};
uint32_t src_address{};
uint32_t size{};
- dst_address = Convert<uint32_t>(GetReg32(system, 0));
- src_address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ dst_address = Convert<uint32_t>(GetArg32(args, 0));
+ src_address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = UnmapMemory64From32(system, dst_address, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_QueryMemory64From32(Core::System& system) {
+static void SvcWrap_QueryMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
uint32_t out_memory_info{};
uint32_t address{};
- out_memory_info = Convert<uint32_t>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 2));
+ out_memory_info = Convert<uint32_t>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 2));
ret = QueryMemory64From32(system, out_memory_info, std::addressof(out_page_info), address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_page_info));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_page_info));
}
-static void SvcWrap_ExitProcess64From32(Core::System& system) {
+static void SvcWrap_ExitProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
ExitProcess64From32(system);
}
-static void SvcWrap_CreateThread64From32(Core::System& system) {
+static void SvcWrap_CreateThread64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -189,143 +189,143 @@ static void SvcWrap_CreateThread64From32(Core::System& system) {
int32_t priority{};
int32_t core_id{};
- func = Convert<uint32_t>(GetReg32(system, 1));
- arg = Convert<uint32_t>(GetReg32(system, 2));
- stack_bottom = Convert<uint32_t>(GetReg32(system, 3));
- priority = Convert<int32_t>(GetReg32(system, 0));
- core_id = Convert<int32_t>(GetReg32(system, 4));
+ func = Convert<uint32_t>(GetArg32(args, 1));
+ arg = Convert<uint32_t>(GetArg32(args, 2));
+ stack_bottom = Convert<uint32_t>(GetArg32(args, 3));
+ priority = Convert<int32_t>(GetArg32(args, 0));
+ core_id = Convert<int32_t>(GetArg32(args, 4));
ret = CreateThread64From32(system, std::addressof(out_handle), func, arg, stack_bottom, priority, core_id);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_StartThread64From32(Core::System& system) {
+static void SvcWrap_StartThread64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg32(system, 0));
+ thread_handle = Convert<Handle>(GetArg32(args, 0));
ret = StartThread64From32(system, thread_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ExitThread64From32(Core::System& system) {
+static void SvcWrap_ExitThread64From32(Core::System& system, std::span<uint64_t, 8> args) {
ExitThread64From32(system);
}
-static void SvcWrap_SleepThread64From32(Core::System& system) {
+static void SvcWrap_SleepThread64From32(Core::System& system, std::span<uint64_t, 8> args) {
int64_t ns{};
std::array<uint32_t, 2> ns_gather{};
- ns_gather[0] = GetReg32(system, 0);
- ns_gather[1] = GetReg32(system, 1);
+ ns_gather[0] = GetArg32(args, 0);
+ ns_gather[1] = GetArg32(args, 1);
ns = Convert<int64_t>(ns_gather);
SleepThread64From32(system, ns);
}
-static void SvcWrap_GetThreadPriority64From32(Core::System& system) {
+static void SvcWrap_GetThreadPriority64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_priority{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg32(system, 1));
+ thread_handle = Convert<Handle>(GetArg32(args, 1));
ret = GetThreadPriority64From32(system, std::addressof(out_priority), thread_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_priority));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_priority));
}
-static void SvcWrap_SetThreadPriority64From32(Core::System& system) {
+static void SvcWrap_SetThreadPriority64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
int32_t priority{};
- thread_handle = Convert<Handle>(GetReg32(system, 0));
- priority = Convert<int32_t>(GetReg32(system, 1));
+ thread_handle = Convert<Handle>(GetArg32(args, 0));
+ priority = Convert<int32_t>(GetArg32(args, 1));
ret = SetThreadPriority64From32(system, thread_handle, priority);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetThreadCoreMask64From32(Core::System& system) {
+static void SvcWrap_GetThreadCoreMask64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_core_id{};
uint64_t out_affinity_mask{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg32(system, 2));
+ thread_handle = Convert<Handle>(GetArg32(args, 2));
ret = GetThreadCoreMask64From32(system, std::addressof(out_core_id), std::addressof(out_affinity_mask), thread_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_core_id));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_core_id));
auto out_affinity_mask_scatter = Convert<std::array<uint32_t, 2>>(out_affinity_mask);
- SetReg32(system, 2, out_affinity_mask_scatter[0]);
- SetReg32(system, 3, out_affinity_mask_scatter[1]);
+ SetArg32(args, 2, out_affinity_mask_scatter[0]);
+ SetArg32(args, 3, out_affinity_mask_scatter[1]);
}
-static void SvcWrap_SetThreadCoreMask64From32(Core::System& system) {
+static void SvcWrap_SetThreadCoreMask64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
int32_t core_id{};
uint64_t affinity_mask{};
- thread_handle = Convert<Handle>(GetReg32(system, 0));
- core_id = Convert<int32_t>(GetReg32(system, 1));
+ thread_handle = Convert<Handle>(GetArg32(args, 0));
+ core_id = Convert<int32_t>(GetArg32(args, 1));
std::array<uint32_t, 2> affinity_mask_gather{};
- affinity_mask_gather[0] = GetReg32(system, 2);
- affinity_mask_gather[1] = GetReg32(system, 3);
+ affinity_mask_gather[0] = GetArg32(args, 2);
+ affinity_mask_gather[1] = GetArg32(args, 3);
affinity_mask = Convert<uint64_t>(affinity_mask_gather);
ret = SetThreadCoreMask64From32(system, thread_handle, core_id, affinity_mask);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetCurrentProcessorNumber64From32(Core::System& system) {
+static void SvcWrap_GetCurrentProcessorNumber64From32(Core::System& system, std::span<uint64_t, 8> args) {
int32_t ret{};
ret = GetCurrentProcessorNumber64From32(system);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SignalEvent64From32(Core::System& system) {
+static void SvcWrap_SignalEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle event_handle{};
- event_handle = Convert<Handle>(GetReg32(system, 0));
+ event_handle = Convert<Handle>(GetArg32(args, 0));
ret = SignalEvent64From32(system, event_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ClearEvent64From32(Core::System& system) {
+static void SvcWrap_ClearEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle event_handle{};
- event_handle = Convert<Handle>(GetReg32(system, 0));
+ event_handle = Convert<Handle>(GetArg32(args, 0));
ret = ClearEvent64From32(system, event_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapSharedMemory64From32(Core::System& system) {
+static void SvcWrap_MapSharedMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle shmem_handle{};
@@ -333,33 +333,33 @@ static void SvcWrap_MapSharedMemory64From32(Core::System& system) {
uint32_t size{};
MemoryPermission map_perm{};
- shmem_handle = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
- map_perm = Convert<MemoryPermission>(GetReg32(system, 3));
+ shmem_handle = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
+ map_perm = Convert<MemoryPermission>(GetArg32(args, 3));
ret = MapSharedMemory64From32(system, shmem_handle, address, size, map_perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapSharedMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapSharedMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle shmem_handle{};
uint32_t address{};
uint32_t size{};
- shmem_handle = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ shmem_handle = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = UnmapSharedMemory64From32(system, shmem_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_CreateTransferMemory64From32(Core::System& system) {
+static void SvcWrap_CreateTransferMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -367,41 +367,41 @@ static void SvcWrap_CreateTransferMemory64From32(Core::System& system) {
uint32_t size{};
MemoryPermission map_perm{};
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
- map_perm = Convert<MemoryPermission>(GetReg32(system, 3));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
+ map_perm = Convert<MemoryPermission>(GetArg32(args, 3));
ret = CreateTransferMemory64From32(system, std::addressof(out_handle), address, size, map_perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_CloseHandle64From32(Core::System& system) {
+static void SvcWrap_CloseHandle64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg32(system, 0));
+ handle = Convert<Handle>(GetArg32(args, 0));
ret = CloseHandle64From32(system, handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ResetSignal64From32(Core::System& system) {
+static void SvcWrap_ResetSignal64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg32(system, 0));
+ handle = Convert<Handle>(GetArg32(args, 0));
ret = ResetSignal64From32(system, handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_WaitSynchronization64From32(Core::System& system) {
+static void SvcWrap_WaitSynchronization64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -409,60 +409,60 @@ static void SvcWrap_WaitSynchronization64From32(Core::System& system) {
int32_t num_handles{};
int64_t timeout_ns{};
- handles = Convert<uint32_t>(GetReg32(system, 1));
- num_handles = Convert<int32_t>(GetReg32(system, 2));
+ handles = Convert<uint32_t>(GetArg32(args, 1));
+ num_handles = Convert<int32_t>(GetArg32(args, 2));
std::array<uint32_t, 2> timeout_ns_gather{};
- timeout_ns_gather[0] = GetReg32(system, 0);
- timeout_ns_gather[1] = GetReg32(system, 3);
+ timeout_ns_gather[0] = GetArg32(args, 0);
+ timeout_ns_gather[1] = GetArg32(args, 3);
timeout_ns = Convert<int64_t>(timeout_ns_gather);
ret = WaitSynchronization64From32(system, std::addressof(out_index), handles, num_handles, timeout_ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_index));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_index));
}
-static void SvcWrap_CancelSynchronization64From32(Core::System& system) {
+static void SvcWrap_CancelSynchronization64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg32(system, 0));
+ handle = Convert<Handle>(GetArg32(args, 0));
ret = CancelSynchronization64From32(system, handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ArbitrateLock64From32(Core::System& system) {
+static void SvcWrap_ArbitrateLock64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
uint32_t address{};
uint32_t tag{};
- thread_handle = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- tag = Convert<uint32_t>(GetReg32(system, 2));
+ thread_handle = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ tag = Convert<uint32_t>(GetArg32(args, 2));
ret = ArbitrateLock64From32(system, thread_handle, address, tag);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ArbitrateUnlock64From32(Core::System& system) {
+static void SvcWrap_ArbitrateUnlock64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
- address = Convert<uint32_t>(GetReg32(system, 0));
+ address = Convert<uint32_t>(GetArg32(args, 0));
ret = ArbitrateUnlock64From32(system, address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_WaitProcessWideKeyAtomic64From32(Core::System& system) {
+static void SvcWrap_WaitProcessWideKeyAtomic64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
@@ -470,82 +470,82 @@ static void SvcWrap_WaitProcessWideKeyAtomic64From32(Core::System& system) {
uint32_t tag{};
int64_t timeout_ns{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- cv_key = Convert<uint32_t>(GetReg32(system, 1));
- tag = Convert<uint32_t>(GetReg32(system, 2));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ cv_key = Convert<uint32_t>(GetArg32(args, 1));
+ tag = Convert<uint32_t>(GetArg32(args, 2));
std::array<uint32_t, 2> timeout_ns_gather{};
- timeout_ns_gather[0] = GetReg32(system, 3);
- timeout_ns_gather[1] = GetReg32(system, 4);
+ timeout_ns_gather[0] = GetArg32(args, 3);
+ timeout_ns_gather[1] = GetArg32(args, 4);
timeout_ns = Convert<int64_t>(timeout_ns_gather);
ret = WaitProcessWideKeyAtomic64From32(system, address, cv_key, tag, timeout_ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SignalProcessWideKey64From32(Core::System& system) {
+static void SvcWrap_SignalProcessWideKey64From32(Core::System& system, std::span<uint64_t, 8> args) {
uint32_t cv_key{};
int32_t count{};
- cv_key = Convert<uint32_t>(GetReg32(system, 0));
- count = Convert<int32_t>(GetReg32(system, 1));
+ cv_key = Convert<uint32_t>(GetArg32(args, 0));
+ count = Convert<int32_t>(GetArg32(args, 1));
SignalProcessWideKey64From32(system, cv_key, count);
}
-static void SvcWrap_GetSystemTick64From32(Core::System& system) {
+static void SvcWrap_GetSystemTick64From32(Core::System& system, std::span<uint64_t, 8> args) {
int64_t ret{};
ret = GetSystemTick64From32(system);
auto ret_scatter = Convert<std::array<uint32_t, 2>>(ret);
- SetReg32(system, 0, ret_scatter[0]);
- SetReg32(system, 1, ret_scatter[1]);
+ SetArg32(args, 0, ret_scatter[0]);
+ SetArg32(args, 1, ret_scatter[1]);
}
-static void SvcWrap_ConnectToNamedPort64From32(Core::System& system) {
+static void SvcWrap_ConnectToNamedPort64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint32_t name{};
- name = Convert<uint32_t>(GetReg32(system, 1));
+ name = Convert<uint32_t>(GetArg32(args, 1));
ret = ConnectToNamedPort64From32(system, std::addressof(out_handle), name);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_SendSyncRequest64From32(Core::System& system) {
+static void SvcWrap_SendSyncRequest64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle session_handle{};
- session_handle = Convert<Handle>(GetReg32(system, 0));
+ session_handle = Convert<Handle>(GetArg32(args, 0));
ret = SendSyncRequest64From32(system, session_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SendSyncRequestWithUserBuffer64From32(Core::System& system) {
+static void SvcWrap_SendSyncRequestWithUserBuffer64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t message_buffer{};
uint32_t message_buffer_size{};
Handle session_handle{};
- message_buffer = Convert<uint32_t>(GetReg32(system, 0));
- message_buffer_size = Convert<uint32_t>(GetReg32(system, 1));
- session_handle = Convert<Handle>(GetReg32(system, 2));
+ message_buffer = Convert<uint32_t>(GetArg32(args, 0));
+ message_buffer_size = Convert<uint32_t>(GetArg32(args, 1));
+ session_handle = Convert<Handle>(GetArg32(args, 2));
ret = SendSyncRequestWithUserBuffer64From32(system, message_buffer, message_buffer_size, session_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SendAsyncRequestWithUserBuffer64From32(Core::System& system) {
+static void SvcWrap_SendAsyncRequestWithUserBuffer64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_event_handle{};
@@ -553,83 +553,83 @@ static void SvcWrap_SendAsyncRequestWithUserBuffer64From32(Core::System& system)
uint32_t message_buffer_size{};
Handle session_handle{};
- message_buffer = Convert<uint32_t>(GetReg32(system, 1));
- message_buffer_size = Convert<uint32_t>(GetReg32(system, 2));
- session_handle = Convert<Handle>(GetReg32(system, 3));
+ message_buffer = Convert<uint32_t>(GetArg32(args, 1));
+ message_buffer_size = Convert<uint32_t>(GetArg32(args, 2));
+ session_handle = Convert<Handle>(GetArg32(args, 3));
ret = SendAsyncRequestWithUserBuffer64From32(system, std::addressof(out_event_handle), message_buffer, message_buffer_size, session_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_event_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_event_handle));
}
-static void SvcWrap_GetProcessId64From32(Core::System& system) {
+static void SvcWrap_GetProcessId64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_process_id{};
Handle process_handle{};
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
ret = GetProcessId64From32(system, std::addressof(out_process_id), process_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_process_id_scatter = Convert<std::array<uint32_t, 2>>(out_process_id);
- SetReg32(system, 1, out_process_id_scatter[0]);
- SetReg32(system, 2, out_process_id_scatter[1]);
+ SetArg32(args, 1, out_process_id_scatter[0]);
+ SetArg32(args, 2, out_process_id_scatter[1]);
}
-static void SvcWrap_GetThreadId64From32(Core::System& system) {
+static void SvcWrap_GetThreadId64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_thread_id{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg32(system, 1));
+ thread_handle = Convert<Handle>(GetArg32(args, 1));
ret = GetThreadId64From32(system, std::addressof(out_thread_id), thread_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_thread_id_scatter = Convert<std::array<uint32_t, 2>>(out_thread_id);
- SetReg32(system, 1, out_thread_id_scatter[0]);
- SetReg32(system, 2, out_thread_id_scatter[1]);
+ SetArg32(args, 1, out_thread_id_scatter[0]);
+ SetArg32(args, 2, out_thread_id_scatter[1]);
}
-static void SvcWrap_Break64From32(Core::System& system) {
+static void SvcWrap_Break64From32(Core::System& system, std::span<uint64_t, 8> args) {
BreakReason break_reason{};
uint32_t arg{};
uint32_t size{};
- break_reason = Convert<BreakReason>(GetReg32(system, 0));
- arg = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ break_reason = Convert<BreakReason>(GetArg32(args, 0));
+ arg = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
Break64From32(system, break_reason, arg, size);
}
-static void SvcWrap_OutputDebugString64From32(Core::System& system) {
+static void SvcWrap_OutputDebugString64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t debug_str{};
uint32_t len{};
- debug_str = Convert<uint32_t>(GetReg32(system, 0));
- len = Convert<uint32_t>(GetReg32(system, 1));
+ debug_str = Convert<uint32_t>(GetArg32(args, 0));
+ len = Convert<uint32_t>(GetArg32(args, 1));
ret = OutputDebugString64From32(system, debug_str, len);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ReturnFromException64From32(Core::System& system) {
+static void SvcWrap_ReturnFromException64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result result{};
- result = Convert<Result>(GetReg32(system, 0));
+ result = Convert<Result>(GetArg32(args, 0));
ReturnFromException64From32(system, result);
}
-static void SvcWrap_GetInfo64From32(Core::System& system) {
+static void SvcWrap_GetInfo64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out{};
@@ -637,68 +637,68 @@ static void SvcWrap_GetInfo64From32(Core::System& system) {
Handle handle{};
uint64_t info_subtype{};
- info_type = Convert<InfoType>(GetReg32(system, 1));
- handle = Convert<Handle>(GetReg32(system, 2));
+ info_type = Convert<InfoType>(GetArg32(args, 1));
+ handle = Convert<Handle>(GetArg32(args, 2));
std::array<uint32_t, 2> info_subtype_gather{};
- info_subtype_gather[0] = GetReg32(system, 0);
- info_subtype_gather[1] = GetReg32(system, 3);
+ info_subtype_gather[0] = GetArg32(args, 0);
+ info_subtype_gather[1] = GetArg32(args, 3);
info_subtype = Convert<uint64_t>(info_subtype_gather);
ret = GetInfo64From32(system, std::addressof(out), info_type, handle, info_subtype);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_scatter = Convert<std::array<uint32_t, 2>>(out);
- SetReg32(system, 1, out_scatter[0]);
- SetReg32(system, 2, out_scatter[1]);
+ SetArg32(args, 1, out_scatter[0]);
+ SetArg32(args, 2, out_scatter[1]);
}
-static void SvcWrap_FlushEntireDataCache64From32(Core::System& system) {
+static void SvcWrap_FlushEntireDataCache64From32(Core::System& system, std::span<uint64_t, 8> args) {
FlushEntireDataCache64From32(system);
}
-static void SvcWrap_FlushDataCache64From32(Core::System& system) {
+static void SvcWrap_FlushDataCache64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = FlushDataCache64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapPhysicalMemory64From32(Core::System& system) {
+static void SvcWrap_MapPhysicalMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = MapPhysicalMemory64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapPhysicalMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapPhysicalMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = UnmapPhysicalMemory64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetDebugFutureThreadInfo64From32(Core::System& system) {
+static void SvcWrap_GetDebugFutureThreadInfo64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
ilp32::LastThreadContext out_context{};
@@ -706,26 +706,26 @@ static void SvcWrap_GetDebugFutureThreadInfo64From32(Core::System& system) {
Handle debug_handle{};
int64_t ns{};
- debug_handle = Convert<Handle>(GetReg32(system, 2));
+ debug_handle = Convert<Handle>(GetArg32(args, 2));
std::array<uint32_t, 2> ns_gather{};
- ns_gather[0] = GetReg32(system, 0);
- ns_gather[1] = GetReg32(system, 1);
+ ns_gather[0] = GetArg32(args, 0);
+ ns_gather[1] = GetArg32(args, 1);
ns = Convert<int64_t>(ns_gather);
ret = GetDebugFutureThreadInfo64From32(system, std::addressof(out_context), std::addressof(out_thread_id), debug_handle, ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_context_scatter = Convert<std::array<uint32_t, 4>>(out_context);
- SetReg32(system, 1, out_context_scatter[0]);
- SetReg32(system, 2, out_context_scatter[1]);
- SetReg32(system, 3, out_context_scatter[2]);
- SetReg32(system, 4, out_context_scatter[3]);
+ SetArg32(args, 1, out_context_scatter[0]);
+ SetArg32(args, 2, out_context_scatter[1]);
+ SetArg32(args, 3, out_context_scatter[2]);
+ SetArg32(args, 4, out_context_scatter[3]);
auto out_thread_id_scatter = Convert<std::array<uint32_t, 2>>(out_thread_id);
- SetReg32(system, 5, out_thread_id_scatter[0]);
- SetReg32(system, 6, out_thread_id_scatter[1]);
+ SetArg32(args, 5, out_thread_id_scatter[0]);
+ SetArg32(args, 6, out_thread_id_scatter[1]);
}
-static void SvcWrap_GetLastThreadInfo64From32(Core::System& system) {
+static void SvcWrap_GetLastThreadInfo64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
ilp32::LastThreadContext out_context{};
@@ -734,81 +734,81 @@ static void SvcWrap_GetLastThreadInfo64From32(Core::System& system) {
ret = GetLastThreadInfo64From32(system, std::addressof(out_context), std::addressof(out_tls_address), std::addressof(out_flags));
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_context_scatter = Convert<std::array<uint32_t, 4>>(out_context);
- SetReg32(system, 1, out_context_scatter[0]);
- SetReg32(system, 2, out_context_scatter[1]);
- SetReg32(system, 3, out_context_scatter[2]);
- SetReg32(system, 4, out_context_scatter[3]);
- SetReg32(system, 5, Convert<uint32_t>(out_tls_address));
- SetReg32(system, 6, Convert<uint32_t>(out_flags));
+ SetArg32(args, 1, out_context_scatter[0]);
+ SetArg32(args, 2, out_context_scatter[1]);
+ SetArg32(args, 3, out_context_scatter[2]);
+ SetArg32(args, 4, out_context_scatter[3]);
+ SetArg32(args, 5, Convert<uint32_t>(out_tls_address));
+ SetArg32(args, 6, Convert<uint32_t>(out_flags));
}
-static void SvcWrap_GetResourceLimitLimitValue64From32(Core::System& system) {
+static void SvcWrap_GetResourceLimitLimitValue64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_limit_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg32(system, 1));
- which = Convert<LimitableResource>(GetReg32(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg32(args, 1));
+ which = Convert<LimitableResource>(GetArg32(args, 2));
ret = GetResourceLimitLimitValue64From32(system, std::addressof(out_limit_value), resource_limit_handle, which);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_limit_value_scatter = Convert<std::array<uint32_t, 2>>(out_limit_value);
- SetReg32(system, 1, out_limit_value_scatter[0]);
- SetReg32(system, 2, out_limit_value_scatter[1]);
+ SetArg32(args, 1, out_limit_value_scatter[0]);
+ SetArg32(args, 2, out_limit_value_scatter[1]);
}
-static void SvcWrap_GetResourceLimitCurrentValue64From32(Core::System& system) {
+static void SvcWrap_GetResourceLimitCurrentValue64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_current_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg32(system, 1));
- which = Convert<LimitableResource>(GetReg32(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg32(args, 1));
+ which = Convert<LimitableResource>(GetArg32(args, 2));
ret = GetResourceLimitCurrentValue64From32(system, std::addressof(out_current_value), resource_limit_handle, which);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_current_value_scatter = Convert<std::array<uint32_t, 2>>(out_current_value);
- SetReg32(system, 1, out_current_value_scatter[0]);
- SetReg32(system, 2, out_current_value_scatter[1]);
+ SetArg32(args, 1, out_current_value_scatter[0]);
+ SetArg32(args, 2, out_current_value_scatter[1]);
}
-static void SvcWrap_SetThreadActivity64From32(Core::System& system) {
+static void SvcWrap_SetThreadActivity64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
ThreadActivity thread_activity{};
- thread_handle = Convert<Handle>(GetReg32(system, 0));
- thread_activity = Convert<ThreadActivity>(GetReg32(system, 1));
+ thread_handle = Convert<Handle>(GetArg32(args, 0));
+ thread_activity = Convert<ThreadActivity>(GetArg32(args, 1));
ret = SetThreadActivity64From32(system, thread_handle, thread_activity);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetThreadContext364From32(Core::System& system) {
+static void SvcWrap_GetThreadContext364From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t out_context{};
Handle thread_handle{};
- out_context = Convert<uint32_t>(GetReg32(system, 0));
- thread_handle = Convert<Handle>(GetReg32(system, 1));
+ out_context = Convert<uint32_t>(GetArg32(args, 0));
+ thread_handle = Convert<Handle>(GetArg32(args, 1));
ret = GetThreadContext364From32(system, out_context, thread_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_WaitForAddress64From32(Core::System& system) {
+static void SvcWrap_WaitForAddress64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
@@ -816,20 +816,20 @@ static void SvcWrap_WaitForAddress64From32(Core::System& system) {
int32_t value{};
int64_t timeout_ns{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- arb_type = Convert<ArbitrationType>(GetReg32(system, 1));
- value = Convert<int32_t>(GetReg32(system, 2));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ arb_type = Convert<ArbitrationType>(GetArg32(args, 1));
+ value = Convert<int32_t>(GetArg32(args, 2));
std::array<uint32_t, 2> timeout_ns_gather{};
- timeout_ns_gather[0] = GetReg32(system, 3);
- timeout_ns_gather[1] = GetReg32(system, 4);
+ timeout_ns_gather[0] = GetArg32(args, 3);
+ timeout_ns_gather[1] = GetArg32(args, 4);
timeout_ns = Convert<int64_t>(timeout_ns_gather);
ret = WaitForAddress64From32(system, address, arb_type, value, timeout_ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SignalToAddress64From32(Core::System& system) {
+static void SvcWrap_SignalToAddress64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
@@ -837,53 +837,53 @@ static void SvcWrap_SignalToAddress64From32(Core::System& system) {
int32_t value{};
int32_t count{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- signal_type = Convert<SignalType>(GetReg32(system, 1));
- value = Convert<int32_t>(GetReg32(system, 2));
- count = Convert<int32_t>(GetReg32(system, 3));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ signal_type = Convert<SignalType>(GetArg32(args, 1));
+ value = Convert<int32_t>(GetArg32(args, 2));
+ count = Convert<int32_t>(GetArg32(args, 3));
ret = SignalToAddress64From32(system, address, signal_type, value, count);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SynchronizePreemptionState64From32(Core::System& system) {
+static void SvcWrap_SynchronizePreemptionState64From32(Core::System& system, std::span<uint64_t, 8> args) {
SynchronizePreemptionState64From32(system);
}
-static void SvcWrap_GetResourceLimitPeakValue64From32(Core::System& system) {
+static void SvcWrap_GetResourceLimitPeakValue64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_peak_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg32(system, 1));
- which = Convert<LimitableResource>(GetReg32(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg32(args, 1));
+ which = Convert<LimitableResource>(GetArg32(args, 2));
ret = GetResourceLimitPeakValue64From32(system, std::addressof(out_peak_value), resource_limit_handle, which);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_peak_value_scatter = Convert<std::array<uint32_t, 2>>(out_peak_value);
- SetReg32(system, 1, out_peak_value_scatter[0]);
- SetReg32(system, 2, out_peak_value_scatter[1]);
+ SetArg32(args, 1, out_peak_value_scatter[0]);
+ SetArg32(args, 2, out_peak_value_scatter[1]);
}
-static void SvcWrap_CreateIoPool64From32(Core::System& system) {
+static void SvcWrap_CreateIoPool64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
IoPoolType which{};
- which = Convert<IoPoolType>(GetReg32(system, 1));
+ which = Convert<IoPoolType>(GetArg32(args, 1));
ret = CreateIoPool64From32(system, std::addressof(out_handle), which);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_CreateIoRegion64From32(Core::System& system) {
+static void SvcWrap_CreateIoRegion64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -893,53 +893,53 @@ static void SvcWrap_CreateIoRegion64From32(Core::System& system) {
MemoryMapping mapping{};
MemoryPermission perm{};
- io_pool = Convert<Handle>(GetReg32(system, 1));
+ io_pool = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> physical_address_gather{};
- physical_address_gather[0] = GetReg32(system, 2);
- physical_address_gather[1] = GetReg32(system, 3);
+ physical_address_gather[0] = GetArg32(args, 2);
+ physical_address_gather[1] = GetArg32(args, 3);
physical_address = Convert<uint64_t>(physical_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 0));
- mapping = Convert<MemoryMapping>(GetReg32(system, 4));
- perm = Convert<MemoryPermission>(GetReg32(system, 5));
+ size = Convert<uint32_t>(GetArg32(args, 0));
+ mapping = Convert<MemoryMapping>(GetArg32(args, 4));
+ perm = Convert<MemoryPermission>(GetArg32(args, 5));
ret = CreateIoRegion64From32(system, std::addressof(out_handle), io_pool, physical_address, size, mapping, perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_KernelDebug64From32(Core::System& system) {
+static void SvcWrap_KernelDebug64From32(Core::System& system, std::span<uint64_t, 8> args) {
KernelDebugType kern_debug_type{};
uint64_t arg0{};
uint64_t arg1{};
uint64_t arg2{};
- kern_debug_type = Convert<KernelDebugType>(GetReg32(system, 0));
+ kern_debug_type = Convert<KernelDebugType>(GetArg32(args, 0));
std::array<uint32_t, 2> arg0_gather{};
- arg0_gather[0] = GetReg32(system, 2);
- arg0_gather[1] = GetReg32(system, 3);
+ arg0_gather[0] = GetArg32(args, 2);
+ arg0_gather[1] = GetArg32(args, 3);
arg0 = Convert<uint64_t>(arg0_gather);
std::array<uint32_t, 2> arg1_gather{};
- arg1_gather[0] = GetReg32(system, 1);
- arg1_gather[1] = GetReg32(system, 4);
+ arg1_gather[0] = GetArg32(args, 1);
+ arg1_gather[1] = GetArg32(args, 4);
arg1 = Convert<uint64_t>(arg1_gather);
std::array<uint32_t, 2> arg2_gather{};
- arg2_gather[0] = GetReg32(system, 5);
- arg2_gather[1] = GetReg32(system, 6);
+ arg2_gather[0] = GetArg32(args, 5);
+ arg2_gather[1] = GetArg32(args, 6);
arg2 = Convert<uint64_t>(arg2_gather);
KernelDebug64From32(system, kern_debug_type, arg0, arg1, arg2);
}
-static void SvcWrap_ChangeKernelTraceState64From32(Core::System& system) {
+static void SvcWrap_ChangeKernelTraceState64From32(Core::System& system, std::span<uint64_t, 8> args) {
KernelTraceState kern_trace_state{};
- kern_trace_state = Convert<KernelTraceState>(GetReg32(system, 0));
+ kern_trace_state = Convert<KernelTraceState>(GetArg32(args, 0));
ChangeKernelTraceState64From32(system, kern_trace_state);
}
-static void SvcWrap_CreateSession64From32(Core::System& system) {
+static void SvcWrap_CreateSession64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_session_handle{};
@@ -947,31 +947,31 @@ static void SvcWrap_CreateSession64From32(Core::System& system) {
bool is_light{};
uint32_t name{};
- is_light = Convert<bool>(GetReg32(system, 2));
- name = Convert<uint32_t>(GetReg32(system, 3));
+ is_light = Convert<bool>(GetArg32(args, 2));
+ name = Convert<uint32_t>(GetArg32(args, 3));
ret = CreateSession64From32(system, std::addressof(out_server_session_handle), std::addressof(out_client_session_handle), is_light, name);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_server_session_handle));
- SetReg32(system, 2, Convert<uint32_t>(out_client_session_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_server_session_handle));
+ SetArg32(args, 2, Convert<uint32_t>(out_client_session_handle));
}
-static void SvcWrap_AcceptSession64From32(Core::System& system) {
+static void SvcWrap_AcceptSession64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
Handle port{};
- port = Convert<Handle>(GetReg32(system, 1));
+ port = Convert<Handle>(GetArg32(args, 1));
ret = AcceptSession64From32(system, std::addressof(out_handle), port);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_ReplyAndReceive64From32(Core::System& system) {
+static void SvcWrap_ReplyAndReceive64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -980,21 +980,21 @@ static void SvcWrap_ReplyAndReceive64From32(Core::System& system) {
Handle reply_target{};
int64_t timeout_ns{};
- handles = Convert<uint32_t>(GetReg32(system, 1));
- num_handles = Convert<int32_t>(GetReg32(system, 2));
- reply_target = Convert<Handle>(GetReg32(system, 3));
+ handles = Convert<uint32_t>(GetArg32(args, 1));
+ num_handles = Convert<int32_t>(GetArg32(args, 2));
+ reply_target = Convert<Handle>(GetArg32(args, 3));
std::array<uint32_t, 2> timeout_ns_gather{};
- timeout_ns_gather[0] = GetReg32(system, 0);
- timeout_ns_gather[1] = GetReg32(system, 4);
+ timeout_ns_gather[0] = GetArg32(args, 0);
+ timeout_ns_gather[1] = GetArg32(args, 4);
timeout_ns = Convert<int64_t>(timeout_ns_gather);
ret = ReplyAndReceive64From32(system, std::addressof(out_index), handles, num_handles, reply_target, timeout_ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_index));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_index));
}
-static void SvcWrap_ReplyAndReceiveWithUserBuffer64From32(Core::System& system) {
+static void SvcWrap_ReplyAndReceiveWithUserBuffer64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -1005,23 +1005,23 @@ static void SvcWrap_ReplyAndReceiveWithUserBuffer64From32(Core::System& system)
Handle reply_target{};
int64_t timeout_ns{};
- message_buffer = Convert<uint32_t>(GetReg32(system, 1));
- message_buffer_size = Convert<uint32_t>(GetReg32(system, 2));
- handles = Convert<uint32_t>(GetReg32(system, 3));
- num_handles = Convert<int32_t>(GetReg32(system, 0));
- reply_target = Convert<Handle>(GetReg32(system, 4));
+ message_buffer = Convert<uint32_t>(GetArg32(args, 1));
+ message_buffer_size = Convert<uint32_t>(GetArg32(args, 2));
+ handles = Convert<uint32_t>(GetArg32(args, 3));
+ num_handles = Convert<int32_t>(GetArg32(args, 0));
+ reply_target = Convert<Handle>(GetArg32(args, 4));
std::array<uint32_t, 2> timeout_ns_gather{};
- timeout_ns_gather[0] = GetReg32(system, 5);
- timeout_ns_gather[1] = GetReg32(system, 6);
+ timeout_ns_gather[0] = GetArg32(args, 5);
+ timeout_ns_gather[1] = GetArg32(args, 6);
timeout_ns = Convert<int64_t>(timeout_ns_gather);
ret = ReplyAndReceiveWithUserBuffer64From32(system, std::addressof(out_index), message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_index));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_index));
}
-static void SvcWrap_CreateEvent64From32(Core::System& system) {
+static void SvcWrap_CreateEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_write_handle{};
@@ -1029,12 +1029,12 @@ static void SvcWrap_CreateEvent64From32(Core::System& system) {
ret = CreateEvent64From32(system, std::addressof(out_write_handle), std::addressof(out_read_handle));
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_write_handle));
- SetReg32(system, 2, Convert<uint32_t>(out_read_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_write_handle));
+ SetArg32(args, 2, Convert<uint32_t>(out_read_handle));
}
-static void SvcWrap_MapIoRegion64From32(Core::System& system) {
+static void SvcWrap_MapIoRegion64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle io_region{};
@@ -1042,89 +1042,89 @@ static void SvcWrap_MapIoRegion64From32(Core::System& system) {
uint32_t size{};
MemoryPermission perm{};
- io_region = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
- perm = Convert<MemoryPermission>(GetReg32(system, 3));
+ io_region = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
+ perm = Convert<MemoryPermission>(GetArg32(args, 3));
ret = MapIoRegion64From32(system, io_region, address, size, perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapIoRegion64From32(Core::System& system) {
+static void SvcWrap_UnmapIoRegion64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle io_region{};
uint32_t address{};
uint32_t size{};
- io_region = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ io_region = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = UnmapIoRegion64From32(system, io_region, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapPhysicalMemoryUnsafe64From32(Core::System& system) {
+static void SvcWrap_MapPhysicalMemoryUnsafe64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = MapPhysicalMemoryUnsafe64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapPhysicalMemoryUnsafe64From32(Core::System& system) {
+static void SvcWrap_UnmapPhysicalMemoryUnsafe64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = UnmapPhysicalMemoryUnsafe64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SetUnsafeLimit64From32(Core::System& system) {
+static void SvcWrap_SetUnsafeLimit64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t limit{};
- limit = Convert<uint32_t>(GetReg32(system, 0));
+ limit = Convert<uint32_t>(GetArg32(args, 0));
ret = SetUnsafeLimit64From32(system, limit);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_CreateCodeMemory64From32(Core::System& system) {
+static void SvcWrap_CreateCodeMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = CreateCodeMemory64From32(system, std::addressof(out_handle), address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_ControlCodeMemory64From32(Core::System& system) {
+static void SvcWrap_ControlCodeMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle code_memory_handle{};
@@ -1133,28 +1133,28 @@ static void SvcWrap_ControlCodeMemory64From32(Core::System& system) {
uint64_t size{};
MemoryPermission perm{};
- code_memory_handle = Convert<Handle>(GetReg32(system, 0));
- operation = Convert<CodeMemoryOperation>(GetReg32(system, 1));
+ code_memory_handle = Convert<Handle>(GetArg32(args, 0));
+ operation = Convert<CodeMemoryOperation>(GetArg32(args, 1));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 4);
- size_gather[1] = GetReg32(system, 5);
+ size_gather[0] = GetArg32(args, 4);
+ size_gather[1] = GetArg32(args, 5);
size = Convert<uint64_t>(size_gather);
- perm = Convert<MemoryPermission>(GetReg32(system, 6));
+ perm = Convert<MemoryPermission>(GetArg32(args, 6));
ret = ControlCodeMemory64From32(system, code_memory_handle, operation, address, size, perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SleepSystem64From32(Core::System& system) {
+static void SvcWrap_SleepSystem64From32(Core::System& system, std::span<uint64_t, 8> args) {
SleepSystem64From32(system);
}
-static void SvcWrap_ReadWriteRegister64From32(Core::System& system) {
+static void SvcWrap_ReadWriteRegister64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t out_value{};
@@ -1163,33 +1163,33 @@ static void SvcWrap_ReadWriteRegister64From32(Core::System& system) {
uint32_t value{};
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
- mask = Convert<uint32_t>(GetReg32(system, 0));
- value = Convert<uint32_t>(GetReg32(system, 1));
+ mask = Convert<uint32_t>(GetArg32(args, 0));
+ value = Convert<uint32_t>(GetArg32(args, 1));
ret = ReadWriteRegister64From32(system, std::addressof(out_value), address, mask, value);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_value));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_value));
}
-static void SvcWrap_SetProcessActivity64From32(Core::System& system) {
+static void SvcWrap_SetProcessActivity64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
ProcessActivity process_activity{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
- process_activity = Convert<ProcessActivity>(GetReg32(system, 1));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
+ process_activity = Convert<ProcessActivity>(GetArg32(args, 1));
ret = SetProcessActivity64From32(system, process_handle, process_activity);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_CreateSharedMemory64From32(Core::System& system) {
+static void SvcWrap_CreateSharedMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -1197,17 +1197,17 @@ static void SvcWrap_CreateSharedMemory64From32(Core::System& system) {
MemoryPermission owner_perm{};
MemoryPermission remote_perm{};
- size = Convert<uint32_t>(GetReg32(system, 1));
- owner_perm = Convert<MemoryPermission>(GetReg32(system, 2));
- remote_perm = Convert<MemoryPermission>(GetReg32(system, 3));
+ size = Convert<uint32_t>(GetArg32(args, 1));
+ owner_perm = Convert<MemoryPermission>(GetArg32(args, 2));
+ remote_perm = Convert<MemoryPermission>(GetArg32(args, 3));
ret = CreateSharedMemory64From32(system, std::addressof(out_handle), size, owner_perm, remote_perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_MapTransferMemory64From32(Core::System& system) {
+static void SvcWrap_MapTransferMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle trmem_handle{};
@@ -1215,67 +1215,67 @@ static void SvcWrap_MapTransferMemory64From32(Core::System& system) {
uint32_t size{};
MemoryPermission owner_perm{};
- trmem_handle = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
- owner_perm = Convert<MemoryPermission>(GetReg32(system, 3));
+ trmem_handle = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
+ owner_perm = Convert<MemoryPermission>(GetArg32(args, 3));
ret = MapTransferMemory64From32(system, trmem_handle, address, size, owner_perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapTransferMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapTransferMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle trmem_handle{};
uint32_t address{};
uint32_t size{};
- trmem_handle = Convert<Handle>(GetReg32(system, 0));
- address = Convert<uint32_t>(GetReg32(system, 1));
- size = Convert<uint32_t>(GetReg32(system, 2));
+ trmem_handle = Convert<Handle>(GetArg32(args, 0));
+ address = Convert<uint32_t>(GetArg32(args, 1));
+ size = Convert<uint32_t>(GetArg32(args, 2));
ret = UnmapTransferMemory64From32(system, trmem_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_CreateInterruptEvent64From32(Core::System& system) {
+static void SvcWrap_CreateInterruptEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_read_handle{};
int32_t interrupt_id{};
InterruptType interrupt_type{};
- interrupt_id = Convert<int32_t>(GetReg32(system, 1));
- interrupt_type = Convert<InterruptType>(GetReg32(system, 2));
+ interrupt_id = Convert<int32_t>(GetArg32(args, 1));
+ interrupt_type = Convert<InterruptType>(GetArg32(args, 2));
ret = CreateInterruptEvent64From32(system, std::addressof(out_read_handle), interrupt_id, interrupt_type);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_read_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_read_handle));
}
-static void SvcWrap_QueryPhysicalAddress64From32(Core::System& system) {
+static void SvcWrap_QueryPhysicalAddress64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
ilp32::PhysicalMemoryInfo out_info{};
uint32_t address{};
- address = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 1));
ret = QueryPhysicalAddress64From32(system, std::addressof(out_info), address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_info_scatter = Convert<std::array<uint32_t, 4>>(out_info);
- SetReg32(system, 1, out_info_scatter[0]);
- SetReg32(system, 2, out_info_scatter[1]);
- SetReg32(system, 3, out_info_scatter[2]);
- SetReg32(system, 4, out_info_scatter[3]);
+ SetArg32(args, 1, out_info_scatter[0]);
+ SetArg32(args, 2, out_info_scatter[1]);
+ SetArg32(args, 3, out_info_scatter[2]);
+ SetArg32(args, 4, out_info_scatter[3]);
}
-static void SvcWrap_QueryIoMapping64From32(Core::System& system) {
+static void SvcWrap_QueryIoMapping64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_address{};
@@ -1284,19 +1284,19 @@ static void SvcWrap_QueryIoMapping64From32(Core::System& system) {
uint32_t size{};
std::array<uint32_t, 2> physical_address_gather{};
- physical_address_gather[0] = GetReg32(system, 2);
- physical_address_gather[1] = GetReg32(system, 3);
+ physical_address_gather[0] = GetArg32(args, 2);
+ physical_address_gather[1] = GetArg32(args, 3);
physical_address = Convert<uint64_t>(physical_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 0));
+ size = Convert<uint32_t>(GetArg32(args, 0));
ret = QueryIoMapping64From32(system, std::addressof(out_address), std::addressof(out_size), physical_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_address));
- SetReg32(system, 2, Convert<uint32_t>(out_size));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_address));
+ SetArg32(args, 2, Convert<uint32_t>(out_size));
}
-static void SvcWrap_CreateDeviceAddressSpace64From32(Core::System& system) {
+static void SvcWrap_CreateDeviceAddressSpace64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -1304,49 +1304,49 @@ static void SvcWrap_CreateDeviceAddressSpace64From32(Core::System& system) {
uint64_t das_size{};
std::array<uint32_t, 2> das_address_gather{};
- das_address_gather[0] = GetReg32(system, 2);
- das_address_gather[1] = GetReg32(system, 3);
+ das_address_gather[0] = GetArg32(args, 2);
+ das_address_gather[1] = GetArg32(args, 3);
das_address = Convert<uint64_t>(das_address_gather);
std::array<uint32_t, 2> das_size_gather{};
- das_size_gather[0] = GetReg32(system, 0);
- das_size_gather[1] = GetReg32(system, 1);
+ das_size_gather[0] = GetArg32(args, 0);
+ das_size_gather[1] = GetArg32(args, 1);
das_size = Convert<uint64_t>(das_size_gather);
ret = CreateDeviceAddressSpace64From32(system, std::addressof(out_handle), das_address, das_size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_AttachDeviceAddressSpace64From32(Core::System& system) {
+static void SvcWrap_AttachDeviceAddressSpace64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
DeviceName device_name{};
Handle das_handle{};
- device_name = Convert<DeviceName>(GetReg32(system, 0));
- das_handle = Convert<Handle>(GetReg32(system, 1));
+ device_name = Convert<DeviceName>(GetArg32(args, 0));
+ das_handle = Convert<Handle>(GetArg32(args, 1));
ret = AttachDeviceAddressSpace64From32(system, device_name, das_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_DetachDeviceAddressSpace64From32(Core::System& system) {
+static void SvcWrap_DetachDeviceAddressSpace64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
DeviceName device_name{};
Handle das_handle{};
- device_name = Convert<DeviceName>(GetReg32(system, 0));
- das_handle = Convert<Handle>(GetReg32(system, 1));
+ device_name = Convert<DeviceName>(GetArg32(args, 0));
+ das_handle = Convert<Handle>(GetArg32(args, 1));
ret = DetachDeviceAddressSpace64From32(system, device_name, das_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapDeviceAddressSpaceByForce64From32(Core::System& system) {
+static void SvcWrap_MapDeviceAddressSpaceByForce64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -1356,25 +1356,25 @@ static void SvcWrap_MapDeviceAddressSpaceByForce64From32(Core::System& system) {
uint64_t device_address{};
uint32_t option{};
- das_handle = Convert<Handle>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ das_handle = Convert<Handle>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> process_address_gather{};
- process_address_gather[0] = GetReg32(system, 2);
- process_address_gather[1] = GetReg32(system, 3);
+ process_address_gather[0] = GetArg32(args, 2);
+ process_address_gather[1] = GetArg32(args, 3);
process_address = Convert<uint64_t>(process_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 4));
+ size = Convert<uint32_t>(GetArg32(args, 4));
std::array<uint32_t, 2> device_address_gather{};
- device_address_gather[0] = GetReg32(system, 5);
- device_address_gather[1] = GetReg32(system, 6);
+ device_address_gather[0] = GetArg32(args, 5);
+ device_address_gather[1] = GetArg32(args, 6);
device_address = Convert<uint64_t>(device_address_gather);
- option = Convert<uint32_t>(GetReg32(system, 7));
+ option = Convert<uint32_t>(GetArg32(args, 7));
ret = MapDeviceAddressSpaceByForce64From32(system, das_handle, process_handle, process_address, size, device_address, option);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapDeviceAddressSpaceAligned64From32(Core::System& system) {
+static void SvcWrap_MapDeviceAddressSpaceAligned64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -1384,25 +1384,25 @@ static void SvcWrap_MapDeviceAddressSpaceAligned64From32(Core::System& system) {
uint64_t device_address{};
uint32_t option{};
- das_handle = Convert<Handle>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ das_handle = Convert<Handle>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> process_address_gather{};
- process_address_gather[0] = GetReg32(system, 2);
- process_address_gather[1] = GetReg32(system, 3);
+ process_address_gather[0] = GetArg32(args, 2);
+ process_address_gather[1] = GetArg32(args, 3);
process_address = Convert<uint64_t>(process_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 4));
+ size = Convert<uint32_t>(GetArg32(args, 4));
std::array<uint32_t, 2> device_address_gather{};
- device_address_gather[0] = GetReg32(system, 5);
- device_address_gather[1] = GetReg32(system, 6);
+ device_address_gather[0] = GetArg32(args, 5);
+ device_address_gather[1] = GetArg32(args, 6);
device_address = Convert<uint64_t>(device_address_gather);
- option = Convert<uint32_t>(GetReg32(system, 7));
+ option = Convert<uint32_t>(GetArg32(args, 7));
ret = MapDeviceAddressSpaceAligned64From32(system, das_handle, process_handle, process_address, size, device_address, option);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapDeviceAddressSpace64From32(Core::System& system) {
+static void SvcWrap_UnmapDeviceAddressSpace64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -1411,145 +1411,145 @@ static void SvcWrap_UnmapDeviceAddressSpace64From32(Core::System& system) {
uint32_t size{};
uint64_t device_address{};
- das_handle = Convert<Handle>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ das_handle = Convert<Handle>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> process_address_gather{};
- process_address_gather[0] = GetReg32(system, 2);
- process_address_gather[1] = GetReg32(system, 3);
+ process_address_gather[0] = GetArg32(args, 2);
+ process_address_gather[1] = GetArg32(args, 3);
process_address = Convert<uint64_t>(process_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 4));
+ size = Convert<uint32_t>(GetArg32(args, 4));
std::array<uint32_t, 2> device_address_gather{};
- device_address_gather[0] = GetReg32(system, 5);
- device_address_gather[1] = GetReg32(system, 6);
+ device_address_gather[0] = GetArg32(args, 5);
+ device_address_gather[1] = GetArg32(args, 6);
device_address = Convert<uint64_t>(device_address_gather);
ret = UnmapDeviceAddressSpace64From32(system, das_handle, process_handle, process_address, size, device_address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_InvalidateProcessDataCache64From32(Core::System& system) {
+static void SvcWrap_InvalidateProcessDataCache64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 1);
- size_gather[1] = GetReg32(system, 4);
+ size_gather[0] = GetArg32(args, 1);
+ size_gather[1] = GetArg32(args, 4);
size = Convert<uint64_t>(size_gather);
ret = InvalidateProcessDataCache64From32(system, process_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_StoreProcessDataCache64From32(Core::System& system) {
+static void SvcWrap_StoreProcessDataCache64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 1);
- size_gather[1] = GetReg32(system, 4);
+ size_gather[0] = GetArg32(args, 1);
+ size_gather[1] = GetArg32(args, 4);
size = Convert<uint64_t>(size_gather);
ret = StoreProcessDataCache64From32(system, process_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_FlushProcessDataCache64From32(Core::System& system) {
+static void SvcWrap_FlushProcessDataCache64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 1);
- size_gather[1] = GetReg32(system, 4);
+ size_gather[0] = GetArg32(args, 1);
+ size_gather[1] = GetArg32(args, 4);
size = Convert<uint64_t>(size_gather);
ret = FlushProcessDataCache64From32(system, process_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_DebugActiveProcess64From32(Core::System& system) {
+static void SvcWrap_DebugActiveProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint64_t process_id{};
std::array<uint32_t, 2> process_id_gather{};
- process_id_gather[0] = GetReg32(system, 2);
- process_id_gather[1] = GetReg32(system, 3);
+ process_id_gather[0] = GetArg32(args, 2);
+ process_id_gather[1] = GetArg32(args, 3);
process_id = Convert<uint64_t>(process_id_gather);
ret = DebugActiveProcess64From32(system, std::addressof(out_handle), process_id);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_BreakDebugProcess64From32(Core::System& system) {
+static void SvcWrap_BreakDebugProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
- debug_handle = Convert<Handle>(GetReg32(system, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 0));
ret = BreakDebugProcess64From32(system, debug_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_TerminateDebugProcess64From32(Core::System& system) {
+static void SvcWrap_TerminateDebugProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
- debug_handle = Convert<Handle>(GetReg32(system, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 0));
ret = TerminateDebugProcess64From32(system, debug_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetDebugEvent64From32(Core::System& system) {
+static void SvcWrap_GetDebugEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t out_info{};
Handle debug_handle{};
- out_info = Convert<uint32_t>(GetReg32(system, 0));
- debug_handle = Convert<Handle>(GetReg32(system, 1));
+ out_info = Convert<uint32_t>(GetArg32(args, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 1));
ret = GetDebugEvent64From32(system, out_info, debug_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_ContinueDebugEvent64From32(Core::System& system) {
+static void SvcWrap_ContinueDebugEvent64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -1557,33 +1557,33 @@ static void SvcWrap_ContinueDebugEvent64From32(Core::System& system) {
uint32_t thread_ids{};
int32_t num_thread_ids{};
- debug_handle = Convert<Handle>(GetReg32(system, 0));
- flags = Convert<uint32_t>(GetReg32(system, 1));
- thread_ids = Convert<uint32_t>(GetReg32(system, 2));
- num_thread_ids = Convert<int32_t>(GetReg32(system, 3));
+ debug_handle = Convert<Handle>(GetArg32(args, 0));
+ flags = Convert<uint32_t>(GetArg32(args, 1));
+ thread_ids = Convert<uint32_t>(GetArg32(args, 2));
+ num_thread_ids = Convert<int32_t>(GetArg32(args, 3));
ret = ContinueDebugEvent64From32(system, debug_handle, flags, thread_ids, num_thread_ids);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetProcessList64From32(Core::System& system) {
+static void SvcWrap_GetProcessList64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_num_processes{};
uint32_t out_process_ids{};
int32_t max_out_count{};
- out_process_ids = Convert<uint32_t>(GetReg32(system, 1));
- max_out_count = Convert<int32_t>(GetReg32(system, 2));
+ out_process_ids = Convert<uint32_t>(GetArg32(args, 1));
+ max_out_count = Convert<int32_t>(GetArg32(args, 2));
ret = GetProcessList64From32(system, std::addressof(out_num_processes), out_process_ids, max_out_count);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_num_processes));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_num_processes));
}
-static void SvcWrap_GetThreadList64From32(Core::System& system) {
+static void SvcWrap_GetThreadList64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_num_threads{};
@@ -1591,17 +1591,17 @@ static void SvcWrap_GetThreadList64From32(Core::System& system) {
int32_t max_out_count{};
Handle debug_handle{};
- out_thread_ids = Convert<uint32_t>(GetReg32(system, 1));
- max_out_count = Convert<int32_t>(GetReg32(system, 2));
- debug_handle = Convert<Handle>(GetReg32(system, 3));
+ out_thread_ids = Convert<uint32_t>(GetArg32(args, 1));
+ max_out_count = Convert<int32_t>(GetArg32(args, 2));
+ debug_handle = Convert<Handle>(GetArg32(args, 3));
ret = GetThreadList64From32(system, std::addressof(out_num_threads), out_thread_ids, max_out_count, debug_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_num_threads));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_num_threads));
}
-static void SvcWrap_GetDebugThreadContext64From32(Core::System& system) {
+static void SvcWrap_GetDebugThreadContext64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t out_context{};
@@ -1609,20 +1609,20 @@ static void SvcWrap_GetDebugThreadContext64From32(Core::System& system) {
uint64_t thread_id{};
uint32_t context_flags{};
- out_context = Convert<uint32_t>(GetReg32(system, 0));
- debug_handle = Convert<Handle>(GetReg32(system, 1));
+ out_context = Convert<uint32_t>(GetArg32(args, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> thread_id_gather{};
- thread_id_gather[0] = GetReg32(system, 2);
- thread_id_gather[1] = GetReg32(system, 3);
+ thread_id_gather[0] = GetArg32(args, 2);
+ thread_id_gather[1] = GetArg32(args, 3);
thread_id = Convert<uint64_t>(thread_id_gather);
- context_flags = Convert<uint32_t>(GetReg32(system, 4));
+ context_flags = Convert<uint32_t>(GetArg32(args, 4));
ret = GetDebugThreadContext64From32(system, out_context, debug_handle, thread_id, context_flags);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SetDebugThreadContext64From32(Core::System& system) {
+static void SvcWrap_SetDebugThreadContext64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -1630,20 +1630,20 @@ static void SvcWrap_SetDebugThreadContext64From32(Core::System& system) {
uint32_t context{};
uint32_t context_flags{};
- debug_handle = Convert<Handle>(GetReg32(system, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> thread_id_gather{};
- thread_id_gather[0] = GetReg32(system, 2);
- thread_id_gather[1] = GetReg32(system, 3);
+ thread_id_gather[0] = GetArg32(args, 2);
+ thread_id_gather[1] = GetArg32(args, 3);
thread_id = Convert<uint64_t>(thread_id_gather);
- context = Convert<uint32_t>(GetReg32(system, 1));
- context_flags = Convert<uint32_t>(GetReg32(system, 4));
+ context = Convert<uint32_t>(GetArg32(args, 1));
+ context_flags = Convert<uint32_t>(GetArg32(args, 4));
ret = SetDebugThreadContext64From32(system, debug_handle, thread_id, context, context_flags);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_QueryDebugProcessMemory64From32(Core::System& system) {
+static void SvcWrap_QueryDebugProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
@@ -1651,17 +1651,17 @@ static void SvcWrap_QueryDebugProcessMemory64From32(Core::System& system) {
Handle process_handle{};
uint32_t address{};
- out_memory_info = Convert<uint32_t>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 2));
- address = Convert<uint32_t>(GetReg32(system, 3));
+ out_memory_info = Convert<uint32_t>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 2));
+ address = Convert<uint32_t>(GetArg32(args, 3));
ret = QueryDebugProcessMemory64From32(system, out_memory_info, std::addressof(out_page_info), process_handle, address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_page_info));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_page_info));
}
-static void SvcWrap_ReadDebugProcessMemory64From32(Core::System& system) {
+static void SvcWrap_ReadDebugProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t buffer{};
@@ -1669,17 +1669,17 @@ static void SvcWrap_ReadDebugProcessMemory64From32(Core::System& system) {
uint32_t address{};
uint32_t size{};
- buffer = Convert<uint32_t>(GetReg32(system, 0));
- debug_handle = Convert<Handle>(GetReg32(system, 1));
- address = Convert<uint32_t>(GetReg32(system, 2));
- size = Convert<uint32_t>(GetReg32(system, 3));
+ buffer = Convert<uint32_t>(GetArg32(args, 0));
+ debug_handle = Convert<Handle>(GetArg32(args, 1));
+ address = Convert<uint32_t>(GetArg32(args, 2));
+ size = Convert<uint32_t>(GetArg32(args, 3));
ret = ReadDebugProcessMemory64From32(system, buffer, debug_handle, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_WriteDebugProcessMemory64From32(Core::System& system) {
+static void SvcWrap_WriteDebugProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -1687,39 +1687,39 @@ static void SvcWrap_WriteDebugProcessMemory64From32(Core::System& system) {
uint32_t address{};
uint32_t size{};
- debug_handle = Convert<Handle>(GetReg32(system, 0));
- buffer = Convert<uint32_t>(GetReg32(system, 1));
- address = Convert<uint32_t>(GetReg32(system, 2));
- size = Convert<uint32_t>(GetReg32(system, 3));
+ debug_handle = Convert<Handle>(GetArg32(args, 0));
+ buffer = Convert<uint32_t>(GetArg32(args, 1));
+ address = Convert<uint32_t>(GetArg32(args, 2));
+ size = Convert<uint32_t>(GetArg32(args, 3));
ret = WriteDebugProcessMemory64From32(system, debug_handle, buffer, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SetHardwareBreakPoint64From32(Core::System& system) {
+static void SvcWrap_SetHardwareBreakPoint64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
HardwareBreakPointRegisterName name{};
uint64_t flags{};
uint64_t value{};
- name = Convert<HardwareBreakPointRegisterName>(GetReg32(system, 0));
+ name = Convert<HardwareBreakPointRegisterName>(GetArg32(args, 0));
std::array<uint32_t, 2> flags_gather{};
- flags_gather[0] = GetReg32(system, 2);
- flags_gather[1] = GetReg32(system, 3);
+ flags_gather[0] = GetArg32(args, 2);
+ flags_gather[1] = GetArg32(args, 3);
flags = Convert<uint64_t>(flags_gather);
std::array<uint32_t, 2> value_gather{};
- value_gather[0] = GetReg32(system, 1);
- value_gather[1] = GetReg32(system, 4);
+ value_gather[0] = GetArg32(args, 1);
+ value_gather[1] = GetArg32(args, 4);
value = Convert<uint64_t>(value_gather);
ret = SetHardwareBreakPoint64From32(system, name, flags, value);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetDebugThreadParam64From32(Core::System& system) {
+static void SvcWrap_GetDebugThreadParam64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_64{};
@@ -1728,23 +1728,23 @@ static void SvcWrap_GetDebugThreadParam64From32(Core::System& system) {
uint64_t thread_id{};
DebugThreadParam param{};
- debug_handle = Convert<Handle>(GetReg32(system, 2));
+ debug_handle = Convert<Handle>(GetArg32(args, 2));
std::array<uint32_t, 2> thread_id_gather{};
- thread_id_gather[0] = GetReg32(system, 0);
- thread_id_gather[1] = GetReg32(system, 1);
+ thread_id_gather[0] = GetArg32(args, 0);
+ thread_id_gather[1] = GetArg32(args, 1);
thread_id = Convert<uint64_t>(thread_id_gather);
- param = Convert<DebugThreadParam>(GetReg32(system, 3));
+ param = Convert<DebugThreadParam>(GetArg32(args, 3));
ret = GetDebugThreadParam64From32(system, std::addressof(out_64), std::addressof(out_32), debug_handle, thread_id, param);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_64_scatter = Convert<std::array<uint32_t, 2>>(out_64);
- SetReg32(system, 1, out_64_scatter[0]);
- SetReg32(system, 2, out_64_scatter[1]);
- SetReg32(system, 3, Convert<uint32_t>(out_32));
+ SetArg32(args, 1, out_64_scatter[0]);
+ SetArg32(args, 2, out_64_scatter[1]);
+ SetArg32(args, 3, Convert<uint32_t>(out_32));
}
-static void SvcWrap_GetSystemInfo64From32(Core::System& system) {
+static void SvcWrap_GetSystemInfo64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out{};
@@ -1752,22 +1752,22 @@ static void SvcWrap_GetSystemInfo64From32(Core::System& system) {
Handle handle{};
uint64_t info_subtype{};
- info_type = Convert<SystemInfoType>(GetReg32(system, 1));
- handle = Convert<Handle>(GetReg32(system, 2));
+ info_type = Convert<SystemInfoType>(GetArg32(args, 1));
+ handle = Convert<Handle>(GetArg32(args, 2));
std::array<uint32_t, 2> info_subtype_gather{};
- info_subtype_gather[0] = GetReg32(system, 0);
- info_subtype_gather[1] = GetReg32(system, 3);
+ info_subtype_gather[0] = GetArg32(args, 0);
+ info_subtype_gather[1] = GetArg32(args, 3);
info_subtype = Convert<uint64_t>(info_subtype_gather);
ret = GetSystemInfo64From32(system, std::addressof(out), info_type, handle, info_subtype);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_scatter = Convert<std::array<uint32_t, 2>>(out);
- SetReg32(system, 1, out_scatter[0]);
- SetReg32(system, 2, out_scatter[1]);
+ SetArg32(args, 1, out_scatter[0]);
+ SetArg32(args, 2, out_scatter[1]);
}
-static void SvcWrap_CreatePort64From32(Core::System& system) {
+static void SvcWrap_CreatePort64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_handle{};
@@ -1776,48 +1776,48 @@ static void SvcWrap_CreatePort64From32(Core::System& system) {
bool is_light{};
uint32_t name{};
- max_sessions = Convert<int32_t>(GetReg32(system, 2));
- is_light = Convert<bool>(GetReg32(system, 3));
- name = Convert<uint32_t>(GetReg32(system, 0));
+ max_sessions = Convert<int32_t>(GetArg32(args, 2));
+ is_light = Convert<bool>(GetArg32(args, 3));
+ name = Convert<uint32_t>(GetArg32(args, 0));
ret = CreatePort64From32(system, std::addressof(out_server_handle), std::addressof(out_client_handle), max_sessions, is_light, name);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_server_handle));
- SetReg32(system, 2, Convert<uint32_t>(out_client_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_server_handle));
+ SetArg32(args, 2, Convert<uint32_t>(out_client_handle));
}
-static void SvcWrap_ManageNamedPort64From32(Core::System& system) {
+static void SvcWrap_ManageNamedPort64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_handle{};
uint32_t name{};
int32_t max_sessions{};
- name = Convert<uint32_t>(GetReg32(system, 1));
- max_sessions = Convert<int32_t>(GetReg32(system, 2));
+ name = Convert<uint32_t>(GetArg32(args, 1));
+ max_sessions = Convert<int32_t>(GetArg32(args, 2));
ret = ManageNamedPort64From32(system, std::addressof(out_server_handle), name, max_sessions);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_server_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_server_handle));
}
-static void SvcWrap_ConnectToPort64From32(Core::System& system) {
+static void SvcWrap_ConnectToPort64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
Handle port{};
- port = Convert<Handle>(GetReg32(system, 1));
+ port = Convert<Handle>(GetArg32(args, 1));
ret = ConnectToPort64From32(system, std::addressof(out_handle), port);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_SetProcessMemoryPermission64From32(Core::System& system) {
+static void SvcWrap_SetProcessMemoryPermission64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -1825,23 +1825,23 @@ static void SvcWrap_SetProcessMemoryPermission64From32(Core::System& system) {
uint64_t size{};
MemoryPermission perm{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 2);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 2);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 1);
- size_gather[1] = GetReg32(system, 4);
+ size_gather[0] = GetArg32(args, 1);
+ size_gather[1] = GetArg32(args, 4);
size = Convert<uint64_t>(size_gather);
- perm = Convert<MemoryPermission>(GetReg32(system, 5));
+ perm = Convert<MemoryPermission>(GetArg32(args, 5));
ret = SetProcessMemoryPermission64From32(system, process_handle, address, size, perm);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapProcessMemory64From32(Core::System& system) {
+static void SvcWrap_MapProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t dst_address{};
@@ -1849,20 +1849,20 @@ static void SvcWrap_MapProcessMemory64From32(Core::System& system) {
uint64_t src_address{};
uint32_t size{};
- dst_address = Convert<uint32_t>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ dst_address = Convert<uint32_t>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> src_address_gather{};
- src_address_gather[0] = GetReg32(system, 2);
- src_address_gather[1] = GetReg32(system, 3);
+ src_address_gather[0] = GetArg32(args, 2);
+ src_address_gather[1] = GetArg32(args, 3);
src_address = Convert<uint64_t>(src_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 4));
+ size = Convert<uint32_t>(GetArg32(args, 4));
ret = MapProcessMemory64From32(system, dst_address, process_handle, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapProcessMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t dst_address{};
@@ -1870,20 +1870,20 @@ static void SvcWrap_UnmapProcessMemory64From32(Core::System& system) {
uint64_t src_address{};
uint32_t size{};
- dst_address = Convert<uint32_t>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 1));
+ dst_address = Convert<uint32_t>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
std::array<uint32_t, 2> src_address_gather{};
- src_address_gather[0] = GetReg32(system, 2);
- src_address_gather[1] = GetReg32(system, 3);
+ src_address_gather[0] = GetArg32(args, 2);
+ src_address_gather[1] = GetArg32(args, 3);
src_address = Convert<uint64_t>(src_address_gather);
- size = Convert<uint32_t>(GetReg32(system, 4));
+ size = Convert<uint32_t>(GetArg32(args, 4));
ret = UnmapProcessMemory64From32(system, dst_address, process_handle, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_QueryProcessMemory64From32(Core::System& system) {
+static void SvcWrap_QueryProcessMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
@@ -1891,20 +1891,20 @@ static void SvcWrap_QueryProcessMemory64From32(Core::System& system) {
Handle process_handle{};
uint64_t address{};
- out_memory_info = Convert<uint32_t>(GetReg32(system, 0));
- process_handle = Convert<Handle>(GetReg32(system, 2));
+ out_memory_info = Convert<uint32_t>(GetArg32(args, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 2));
std::array<uint32_t, 2> address_gather{};
- address_gather[0] = GetReg32(system, 1);
- address_gather[1] = GetReg32(system, 3);
+ address_gather[0] = GetArg32(args, 1);
+ address_gather[1] = GetArg32(args, 3);
address = Convert<uint64_t>(address_gather);
ret = QueryProcessMemory64From32(system, out_memory_info, std::addressof(out_page_info), process_handle, address);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_page_info));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_page_info));
}
-static void SvcWrap_MapProcessCodeMemory64From32(Core::System& system) {
+static void SvcWrap_MapProcessCodeMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -1912,26 +1912,26 @@ static void SvcWrap_MapProcessCodeMemory64From32(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> dst_address_gather{};
- dst_address_gather[0] = GetReg32(system, 2);
- dst_address_gather[1] = GetReg32(system, 3);
+ dst_address_gather[0] = GetArg32(args, 2);
+ dst_address_gather[1] = GetArg32(args, 3);
dst_address = Convert<uint64_t>(dst_address_gather);
std::array<uint32_t, 2> src_address_gather{};
- src_address_gather[0] = GetReg32(system, 1);
- src_address_gather[1] = GetReg32(system, 4);
+ src_address_gather[0] = GetArg32(args, 1);
+ src_address_gather[1] = GetArg32(args, 4);
src_address = Convert<uint64_t>(src_address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 5);
- size_gather[1] = GetReg32(system, 6);
+ size_gather[0] = GetArg32(args, 5);
+ size_gather[1] = GetArg32(args, 6);
size = Convert<uint64_t>(size_gather);
ret = MapProcessCodeMemory64From32(system, process_handle, dst_address, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapProcessCodeMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapProcessCodeMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -1939,26 +1939,26 @@ static void SvcWrap_UnmapProcessCodeMemory64From32(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
std::array<uint32_t, 2> dst_address_gather{};
- dst_address_gather[0] = GetReg32(system, 2);
- dst_address_gather[1] = GetReg32(system, 3);
+ dst_address_gather[0] = GetArg32(args, 2);
+ dst_address_gather[1] = GetArg32(args, 3);
dst_address = Convert<uint64_t>(dst_address_gather);
std::array<uint32_t, 2> src_address_gather{};
- src_address_gather[0] = GetReg32(system, 1);
- src_address_gather[1] = GetReg32(system, 4);
+ src_address_gather[0] = GetArg32(args, 1);
+ src_address_gather[1] = GetArg32(args, 4);
src_address = Convert<uint64_t>(src_address_gather);
std::array<uint32_t, 2> size_gather{};
- size_gather[0] = GetReg32(system, 5);
- size_gather[1] = GetReg32(system, 6);
+ size_gather[0] = GetArg32(args, 5);
+ size_gather[1] = GetArg32(args, 6);
size = Convert<uint64_t>(size_gather);
ret = UnmapProcessCodeMemory64From32(system, process_handle, dst_address, src_address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_CreateProcess64From32(Core::System& system) {
+static void SvcWrap_CreateProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -1966,17 +1966,17 @@ static void SvcWrap_CreateProcess64From32(Core::System& system) {
uint32_t caps{};
int32_t num_caps{};
- parameters = Convert<uint32_t>(GetReg32(system, 1));
- caps = Convert<uint32_t>(GetReg32(system, 2));
- num_caps = Convert<int32_t>(GetReg32(system, 3));
+ parameters = Convert<uint32_t>(GetArg32(args, 1));
+ caps = Convert<uint32_t>(GetArg32(args, 2));
+ num_caps = Convert<int32_t>(GetArg32(args, 3));
ret = CreateProcess64From32(system, std::addressof(out_handle), parameters, caps, num_caps);
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_StartProcess64From32(Core::System& system) {
+static void SvcWrap_StartProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -1984,138 +1984,138 @@ static void SvcWrap_StartProcess64From32(Core::System& system) {
int32_t core_id{};
uint64_t main_thread_stack_size{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
- priority = Convert<int32_t>(GetReg32(system, 1));
- core_id = Convert<int32_t>(GetReg32(system, 2));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
+ priority = Convert<int32_t>(GetArg32(args, 1));
+ core_id = Convert<int32_t>(GetArg32(args, 2));
std::array<uint32_t, 2> main_thread_stack_size_gather{};
- main_thread_stack_size_gather[0] = GetReg32(system, 3);
- main_thread_stack_size_gather[1] = GetReg32(system, 4);
+ main_thread_stack_size_gather[0] = GetArg32(args, 3);
+ main_thread_stack_size_gather[1] = GetArg32(args, 4);
main_thread_stack_size = Convert<uint64_t>(main_thread_stack_size_gather);
ret = StartProcess64From32(system, process_handle, priority, core_id, main_thread_stack_size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_TerminateProcess64From32(Core::System& system) {
+static void SvcWrap_TerminateProcess64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
- process_handle = Convert<Handle>(GetReg32(system, 0));
+ process_handle = Convert<Handle>(GetArg32(args, 0));
ret = TerminateProcess64From32(system, process_handle);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_GetProcessInfo64From32(Core::System& system) {
+static void SvcWrap_GetProcessInfo64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_info{};
Handle process_handle{};
ProcessInfoType info_type{};
- process_handle = Convert<Handle>(GetReg32(system, 1));
- info_type = Convert<ProcessInfoType>(GetReg32(system, 2));
+ process_handle = Convert<Handle>(GetArg32(args, 1));
+ info_type = Convert<ProcessInfoType>(GetArg32(args, 2));
ret = GetProcessInfo64From32(system, std::addressof(out_info), process_handle, info_type);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
auto out_info_scatter = Convert<std::array<uint32_t, 2>>(out_info);
- SetReg32(system, 1, out_info_scatter[0]);
- SetReg32(system, 2, out_info_scatter[1]);
+ SetArg32(args, 1, out_info_scatter[0]);
+ SetArg32(args, 2, out_info_scatter[1]);
}
-static void SvcWrap_CreateResourceLimit64From32(Core::System& system) {
+static void SvcWrap_CreateResourceLimit64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
ret = CreateResourceLimit64From32(system, std::addressof(out_handle));
- SetReg32(system, 0, Convert<uint32_t>(ret));
- SetReg32(system, 1, Convert<uint32_t>(out_handle));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 1, Convert<uint32_t>(out_handle));
}
-static void SvcWrap_SetResourceLimitLimitValue64From32(Core::System& system) {
+static void SvcWrap_SetResourceLimitLimitValue64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle resource_limit_handle{};
LimitableResource which{};
int64_t limit_value{};
- resource_limit_handle = Convert<Handle>(GetReg32(system, 0));
- which = Convert<LimitableResource>(GetReg32(system, 1));
+ resource_limit_handle = Convert<Handle>(GetArg32(args, 0));
+ which = Convert<LimitableResource>(GetArg32(args, 1));
std::array<uint32_t, 2> limit_value_gather{};
- limit_value_gather[0] = GetReg32(system, 2);
- limit_value_gather[1] = GetReg32(system, 3);
+ limit_value_gather[0] = GetArg32(args, 2);
+ limit_value_gather[1] = GetArg32(args, 3);
limit_value = Convert<int64_t>(limit_value_gather);
ret = SetResourceLimitLimitValue64From32(system, resource_limit_handle, which, limit_value);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_MapInsecureMemory64From32(Core::System& system) {
+static void SvcWrap_MapInsecureMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = MapInsecureMemory64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_UnmapInsecureMemory64From32(Core::System& system) {
+static void SvcWrap_UnmapInsecureMemory64From32(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t address{};
uint32_t size{};
- address = Convert<uint32_t>(GetReg32(system, 0));
- size = Convert<uint32_t>(GetReg32(system, 1));
+ address = Convert<uint32_t>(GetArg32(args, 0));
+ size = Convert<uint32_t>(GetArg32(args, 1));
ret = UnmapInsecureMemory64From32(system, address, size);
- SetReg32(system, 0, Convert<uint32_t>(ret));
+ SetArg32(args, 0, Convert<uint32_t>(ret));
}
-static void SvcWrap_SetHeapSize64(Core::System& system) {
+static void SvcWrap_SetHeapSize64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_address{};
uint64_t size{};
- size = Convert<uint64_t>(GetReg64(system, 1));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = SetHeapSize64(system, std::addressof(out_address), size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_address));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_address));
}
-static void SvcWrap_SetMemoryPermission64(Core::System& system) {
+static void SvcWrap_SetMemoryPermission64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
MemoryPermission perm{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
- perm = Convert<MemoryPermission>(GetReg64(system, 2));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
+ perm = Convert<MemoryPermission>(GetArg64(args, 2));
ret = SetMemoryPermission64(system, address, size, perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SetMemoryAttribute64(Core::System& system) {
+static void SvcWrap_SetMemoryAttribute64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
@@ -2123,69 +2123,69 @@ static void SvcWrap_SetMemoryAttribute64(Core::System& system) {
uint32_t mask{};
uint32_t attr{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
- mask = Convert<uint32_t>(GetReg64(system, 2));
- attr = Convert<uint32_t>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
+ mask = Convert<uint32_t>(GetArg64(args, 2));
+ attr = Convert<uint32_t>(GetArg64(args, 3));
ret = SetMemoryAttribute64(system, address, size, mask, attr);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapMemory64(Core::System& system) {
+static void SvcWrap_MapMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t dst_address{};
uint64_t src_address{};
uint64_t size{};
- dst_address = Convert<uint64_t>(GetReg64(system, 0));
- src_address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ dst_address = Convert<uint64_t>(GetArg64(args, 0));
+ src_address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = MapMemory64(system, dst_address, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapMemory64(Core::System& system) {
+static void SvcWrap_UnmapMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t dst_address{};
uint64_t src_address{};
uint64_t size{};
- dst_address = Convert<uint64_t>(GetReg64(system, 0));
- src_address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ dst_address = Convert<uint64_t>(GetArg64(args, 0));
+ src_address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = UnmapMemory64(system, dst_address, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_QueryMemory64(Core::System& system) {
+static void SvcWrap_QueryMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
uint64_t out_memory_info{};
uint64_t address{};
- out_memory_info = Convert<uint64_t>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 2));
+ out_memory_info = Convert<uint64_t>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 2));
ret = QueryMemory64(system, out_memory_info, std::addressof(out_page_info), address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_page_info));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_page_info));
}
-static void SvcWrap_ExitProcess64(Core::System& system) {
+static void SvcWrap_ExitProcess64(Core::System& system, std::span<uint64_t, 8> args) {
ExitProcess64(system);
}
-static void SvcWrap_CreateThread64(Core::System& system) {
+static void SvcWrap_CreateThread64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -2195,135 +2195,135 @@ static void SvcWrap_CreateThread64(Core::System& system) {
int32_t priority{};
int32_t core_id{};
- func = Convert<uint64_t>(GetReg64(system, 1));
- arg = Convert<uint64_t>(GetReg64(system, 2));
- stack_bottom = Convert<uint64_t>(GetReg64(system, 3));
- priority = Convert<int32_t>(GetReg64(system, 4));
- core_id = Convert<int32_t>(GetReg64(system, 5));
+ func = Convert<uint64_t>(GetArg64(args, 1));
+ arg = Convert<uint64_t>(GetArg64(args, 2));
+ stack_bottom = Convert<uint64_t>(GetArg64(args, 3));
+ priority = Convert<int32_t>(GetArg64(args, 4));
+ core_id = Convert<int32_t>(GetArg64(args, 5));
ret = CreateThread64(system, std::addressof(out_handle), func, arg, stack_bottom, priority, core_id);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_StartThread64(Core::System& system) {
+static void SvcWrap_StartThread64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg64(system, 0));
+ thread_handle = Convert<Handle>(GetArg64(args, 0));
ret = StartThread64(system, thread_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ExitThread64(Core::System& system) {
+static void SvcWrap_ExitThread64(Core::System& system, std::span<uint64_t, 8> args) {
ExitThread64(system);
}
-static void SvcWrap_SleepThread64(Core::System& system) {
+static void SvcWrap_SleepThread64(Core::System& system, std::span<uint64_t, 8> args) {
int64_t ns{};
- ns = Convert<int64_t>(GetReg64(system, 0));
+ ns = Convert<int64_t>(GetArg64(args, 0));
SleepThread64(system, ns);
}
-static void SvcWrap_GetThreadPriority64(Core::System& system) {
+static void SvcWrap_GetThreadPriority64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_priority{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg64(system, 1));
+ thread_handle = Convert<Handle>(GetArg64(args, 1));
ret = GetThreadPriority64(system, std::addressof(out_priority), thread_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_priority));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_priority));
}
-static void SvcWrap_SetThreadPriority64(Core::System& system) {
+static void SvcWrap_SetThreadPriority64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
int32_t priority{};
- thread_handle = Convert<Handle>(GetReg64(system, 0));
- priority = Convert<int32_t>(GetReg64(system, 1));
+ thread_handle = Convert<Handle>(GetArg64(args, 0));
+ priority = Convert<int32_t>(GetArg64(args, 1));
ret = SetThreadPriority64(system, thread_handle, priority);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetThreadCoreMask64(Core::System& system) {
+static void SvcWrap_GetThreadCoreMask64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_core_id{};
uint64_t out_affinity_mask{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg64(system, 2));
+ thread_handle = Convert<Handle>(GetArg64(args, 2));
ret = GetThreadCoreMask64(system, std::addressof(out_core_id), std::addressof(out_affinity_mask), thread_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_core_id));
- SetReg64(system, 2, Convert<uint64_t>(out_affinity_mask));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_core_id));
+ SetArg64(args, 2, Convert<uint64_t>(out_affinity_mask));
}
-static void SvcWrap_SetThreadCoreMask64(Core::System& system) {
+static void SvcWrap_SetThreadCoreMask64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
int32_t core_id{};
uint64_t affinity_mask{};
- thread_handle = Convert<Handle>(GetReg64(system, 0));
- core_id = Convert<int32_t>(GetReg64(system, 1));
- affinity_mask = Convert<uint64_t>(GetReg64(system, 2));
+ thread_handle = Convert<Handle>(GetArg64(args, 0));
+ core_id = Convert<int32_t>(GetArg64(args, 1));
+ affinity_mask = Convert<uint64_t>(GetArg64(args, 2));
ret = SetThreadCoreMask64(system, thread_handle, core_id, affinity_mask);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetCurrentProcessorNumber64(Core::System& system) {
+static void SvcWrap_GetCurrentProcessorNumber64(Core::System& system, std::span<uint64_t, 8> args) {
int32_t ret{};
ret = GetCurrentProcessorNumber64(system);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SignalEvent64(Core::System& system) {
+static void SvcWrap_SignalEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle event_handle{};
- event_handle = Convert<Handle>(GetReg64(system, 0));
+ event_handle = Convert<Handle>(GetArg64(args, 0));
ret = SignalEvent64(system, event_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ClearEvent64(Core::System& system) {
+static void SvcWrap_ClearEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle event_handle{};
- event_handle = Convert<Handle>(GetReg64(system, 0));
+ event_handle = Convert<Handle>(GetArg64(args, 0));
ret = ClearEvent64(system, event_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapSharedMemory64(Core::System& system) {
+static void SvcWrap_MapSharedMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle shmem_handle{};
@@ -2331,33 +2331,33 @@ static void SvcWrap_MapSharedMemory64(Core::System& system) {
uint64_t size{};
MemoryPermission map_perm{};
- shmem_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
- map_perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ shmem_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
+ map_perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = MapSharedMemory64(system, shmem_handle, address, size, map_perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapSharedMemory64(Core::System& system) {
+static void SvcWrap_UnmapSharedMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle shmem_handle{};
uint64_t address{};
uint64_t size{};
- shmem_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ shmem_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = UnmapSharedMemory64(system, shmem_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_CreateTransferMemory64(Core::System& system) {
+static void SvcWrap_CreateTransferMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -2365,41 +2365,41 @@ static void SvcWrap_CreateTransferMemory64(Core::System& system) {
uint64_t size{};
MemoryPermission map_perm{};
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
- map_perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
+ map_perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = CreateTransferMemory64(system, std::addressof(out_handle), address, size, map_perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_CloseHandle64(Core::System& system) {
+static void SvcWrap_CloseHandle64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg64(system, 0));
+ handle = Convert<Handle>(GetArg64(args, 0));
ret = CloseHandle64(system, handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ResetSignal64(Core::System& system) {
+static void SvcWrap_ResetSignal64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg64(system, 0));
+ handle = Convert<Handle>(GetArg64(args, 0));
ret = ResetSignal64(system, handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_WaitSynchronization64(Core::System& system) {
+static void SvcWrap_WaitSynchronization64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -2407,57 +2407,57 @@ static void SvcWrap_WaitSynchronization64(Core::System& system) {
int32_t num_handles{};
int64_t timeout_ns{};
- handles = Convert<uint64_t>(GetReg64(system, 1));
- num_handles = Convert<int32_t>(GetReg64(system, 2));
- timeout_ns = Convert<int64_t>(GetReg64(system, 3));
+ handles = Convert<uint64_t>(GetArg64(args, 1));
+ num_handles = Convert<int32_t>(GetArg64(args, 2));
+ timeout_ns = Convert<int64_t>(GetArg64(args, 3));
ret = WaitSynchronization64(system, std::addressof(out_index), handles, num_handles, timeout_ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_index));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_index));
}
-static void SvcWrap_CancelSynchronization64(Core::System& system) {
+static void SvcWrap_CancelSynchronization64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle handle{};
- handle = Convert<Handle>(GetReg64(system, 0));
+ handle = Convert<Handle>(GetArg64(args, 0));
ret = CancelSynchronization64(system, handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ArbitrateLock64(Core::System& system) {
+static void SvcWrap_ArbitrateLock64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
uint64_t address{};
uint32_t tag{};
- thread_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- tag = Convert<uint32_t>(GetReg64(system, 2));
+ thread_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ tag = Convert<uint32_t>(GetArg64(args, 2));
ret = ArbitrateLock64(system, thread_handle, address, tag);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ArbitrateUnlock64(Core::System& system) {
+static void SvcWrap_ArbitrateUnlock64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
- address = Convert<uint64_t>(GetReg64(system, 0));
+ address = Convert<uint64_t>(GetArg64(args, 0));
ret = ArbitrateUnlock64(system, address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_WaitProcessWideKeyAtomic64(Core::System& system) {
+static void SvcWrap_WaitProcessWideKeyAtomic64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
@@ -2465,77 +2465,77 @@ static void SvcWrap_WaitProcessWideKeyAtomic64(Core::System& system) {
uint32_t tag{};
int64_t timeout_ns{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- cv_key = Convert<uint64_t>(GetReg64(system, 1));
- tag = Convert<uint32_t>(GetReg64(system, 2));
- timeout_ns = Convert<int64_t>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ cv_key = Convert<uint64_t>(GetArg64(args, 1));
+ tag = Convert<uint32_t>(GetArg64(args, 2));
+ timeout_ns = Convert<int64_t>(GetArg64(args, 3));
ret = WaitProcessWideKeyAtomic64(system, address, cv_key, tag, timeout_ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SignalProcessWideKey64(Core::System& system) {
+static void SvcWrap_SignalProcessWideKey64(Core::System& system, std::span<uint64_t, 8> args) {
uint64_t cv_key{};
int32_t count{};
- cv_key = Convert<uint64_t>(GetReg64(system, 0));
- count = Convert<int32_t>(GetReg64(system, 1));
+ cv_key = Convert<uint64_t>(GetArg64(args, 0));
+ count = Convert<int32_t>(GetArg64(args, 1));
SignalProcessWideKey64(system, cv_key, count);
}
-static void SvcWrap_GetSystemTick64(Core::System& system) {
+static void SvcWrap_GetSystemTick64(Core::System& system, std::span<uint64_t, 8> args) {
int64_t ret{};
ret = GetSystemTick64(system);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ConnectToNamedPort64(Core::System& system) {
+static void SvcWrap_ConnectToNamedPort64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint64_t name{};
- name = Convert<uint64_t>(GetReg64(system, 1));
+ name = Convert<uint64_t>(GetArg64(args, 1));
ret = ConnectToNamedPort64(system, std::addressof(out_handle), name);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_SendSyncRequest64(Core::System& system) {
+static void SvcWrap_SendSyncRequest64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle session_handle{};
- session_handle = Convert<Handle>(GetReg64(system, 0));
+ session_handle = Convert<Handle>(GetArg64(args, 0));
ret = SendSyncRequest64(system, session_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SendSyncRequestWithUserBuffer64(Core::System& system) {
+static void SvcWrap_SendSyncRequestWithUserBuffer64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t message_buffer{};
uint64_t message_buffer_size{};
Handle session_handle{};
- message_buffer = Convert<uint64_t>(GetReg64(system, 0));
- message_buffer_size = Convert<uint64_t>(GetReg64(system, 1));
- session_handle = Convert<Handle>(GetReg64(system, 2));
+ message_buffer = Convert<uint64_t>(GetArg64(args, 0));
+ message_buffer_size = Convert<uint64_t>(GetArg64(args, 1));
+ session_handle = Convert<Handle>(GetArg64(args, 2));
ret = SendSyncRequestWithUserBuffer64(system, message_buffer, message_buffer_size, session_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SendAsyncRequestWithUserBuffer64(Core::System& system) {
+static void SvcWrap_SendAsyncRequestWithUserBuffer64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_event_handle{};
@@ -2543,79 +2543,79 @@ static void SvcWrap_SendAsyncRequestWithUserBuffer64(Core::System& system) {
uint64_t message_buffer_size{};
Handle session_handle{};
- message_buffer = Convert<uint64_t>(GetReg64(system, 1));
- message_buffer_size = Convert<uint64_t>(GetReg64(system, 2));
- session_handle = Convert<Handle>(GetReg64(system, 3));
+ message_buffer = Convert<uint64_t>(GetArg64(args, 1));
+ message_buffer_size = Convert<uint64_t>(GetArg64(args, 2));
+ session_handle = Convert<Handle>(GetArg64(args, 3));
ret = SendAsyncRequestWithUserBuffer64(system, std::addressof(out_event_handle), message_buffer, message_buffer_size, session_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_event_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_event_handle));
}
-static void SvcWrap_GetProcessId64(Core::System& system) {
+static void SvcWrap_GetProcessId64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_process_id{};
Handle process_handle{};
- process_handle = Convert<Handle>(GetReg64(system, 1));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
ret = GetProcessId64(system, std::addressof(out_process_id), process_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_process_id));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_process_id));
}
-static void SvcWrap_GetThreadId64(Core::System& system) {
+static void SvcWrap_GetThreadId64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_thread_id{};
Handle thread_handle{};
- thread_handle = Convert<Handle>(GetReg64(system, 1));
+ thread_handle = Convert<Handle>(GetArg64(args, 1));
ret = GetThreadId64(system, std::addressof(out_thread_id), thread_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_thread_id));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_thread_id));
}
-static void SvcWrap_Break64(Core::System& system) {
+static void SvcWrap_Break64(Core::System& system, std::span<uint64_t, 8> args) {
BreakReason break_reason{};
uint64_t arg{};
uint64_t size{};
- break_reason = Convert<BreakReason>(GetReg64(system, 0));
- arg = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ break_reason = Convert<BreakReason>(GetArg64(args, 0));
+ arg = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
Break64(system, break_reason, arg, size);
}
-static void SvcWrap_OutputDebugString64(Core::System& system) {
+static void SvcWrap_OutputDebugString64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t debug_str{};
uint64_t len{};
- debug_str = Convert<uint64_t>(GetReg64(system, 0));
- len = Convert<uint64_t>(GetReg64(system, 1));
+ debug_str = Convert<uint64_t>(GetArg64(args, 0));
+ len = Convert<uint64_t>(GetArg64(args, 1));
ret = OutputDebugString64(system, debug_str, len);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ReturnFromException64(Core::System& system) {
+static void SvcWrap_ReturnFromException64(Core::System& system, std::span<uint64_t, 8> args) {
Result result{};
- result = Convert<Result>(GetReg64(system, 0));
+ result = Convert<Result>(GetArg64(args, 0));
ReturnFromException64(system, result);
}
-static void SvcWrap_GetInfo64(Core::System& system) {
+static void SvcWrap_GetInfo64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out{};
@@ -2623,63 +2623,63 @@ static void SvcWrap_GetInfo64(Core::System& system) {
Handle handle{};
uint64_t info_subtype{};
- info_type = Convert<InfoType>(GetReg64(system, 1));
- handle = Convert<Handle>(GetReg64(system, 2));
- info_subtype = Convert<uint64_t>(GetReg64(system, 3));
+ info_type = Convert<InfoType>(GetArg64(args, 1));
+ handle = Convert<Handle>(GetArg64(args, 2));
+ info_subtype = Convert<uint64_t>(GetArg64(args, 3));
ret = GetInfo64(system, std::addressof(out), info_type, handle, info_subtype);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out));
}
-static void SvcWrap_FlushEntireDataCache64(Core::System& system) {
+static void SvcWrap_FlushEntireDataCache64(Core::System& system, std::span<uint64_t, 8> args) {
FlushEntireDataCache64(system);
}
-static void SvcWrap_FlushDataCache64(Core::System& system) {
+static void SvcWrap_FlushDataCache64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = FlushDataCache64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapPhysicalMemory64(Core::System& system) {
+static void SvcWrap_MapPhysicalMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = MapPhysicalMemory64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapPhysicalMemory64(Core::System& system) {
+static void SvcWrap_UnmapPhysicalMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = UnmapPhysicalMemory64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetDebugFutureThreadInfo64(Core::System& system) {
+static void SvcWrap_GetDebugFutureThreadInfo64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
lp64::LastThreadContext out_context{};
@@ -2687,21 +2687,21 @@ static void SvcWrap_GetDebugFutureThreadInfo64(Core::System& system) {
Handle debug_handle{};
int64_t ns{};
- debug_handle = Convert<Handle>(GetReg64(system, 2));
- ns = Convert<int64_t>(GetReg64(system, 3));
+ debug_handle = Convert<Handle>(GetArg64(args, 2));
+ ns = Convert<int64_t>(GetArg64(args, 3));
ret = GetDebugFutureThreadInfo64(system, std::addressof(out_context), std::addressof(out_thread_id), debug_handle, ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
auto out_context_scatter = Convert<std::array<uint64_t, 4>>(out_context);
- SetReg64(system, 1, out_context_scatter[0]);
- SetReg64(system, 2, out_context_scatter[1]);
- SetReg64(system, 3, out_context_scatter[2]);
- SetReg64(system, 4, out_context_scatter[3]);
- SetReg64(system, 5, Convert<uint64_t>(out_thread_id));
+ SetArg64(args, 1, out_context_scatter[0]);
+ SetArg64(args, 2, out_context_scatter[1]);
+ SetArg64(args, 3, out_context_scatter[2]);
+ SetArg64(args, 4, out_context_scatter[3]);
+ SetArg64(args, 5, Convert<uint64_t>(out_thread_id));
}
-static void SvcWrap_GetLastThreadInfo64(Core::System& system) {
+static void SvcWrap_GetLastThreadInfo64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
lp64::LastThreadContext out_context{};
@@ -2710,77 +2710,77 @@ static void SvcWrap_GetLastThreadInfo64(Core::System& system) {
ret = GetLastThreadInfo64(system, std::addressof(out_context), std::addressof(out_tls_address), std::addressof(out_flags));
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
auto out_context_scatter = Convert<std::array<uint64_t, 4>>(out_context);
- SetReg64(system, 1, out_context_scatter[0]);
- SetReg64(system, 2, out_context_scatter[1]);
- SetReg64(system, 3, out_context_scatter[2]);
- SetReg64(system, 4, out_context_scatter[3]);
- SetReg64(system, 5, Convert<uint64_t>(out_tls_address));
- SetReg64(system, 6, Convert<uint64_t>(out_flags));
+ SetArg64(args, 1, out_context_scatter[0]);
+ SetArg64(args, 2, out_context_scatter[1]);
+ SetArg64(args, 3, out_context_scatter[2]);
+ SetArg64(args, 4, out_context_scatter[3]);
+ SetArg64(args, 5, Convert<uint64_t>(out_tls_address));
+ SetArg64(args, 6, Convert<uint64_t>(out_flags));
}
-static void SvcWrap_GetResourceLimitLimitValue64(Core::System& system) {
+static void SvcWrap_GetResourceLimitLimitValue64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_limit_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg64(system, 1));
- which = Convert<LimitableResource>(GetReg64(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg64(args, 1));
+ which = Convert<LimitableResource>(GetArg64(args, 2));
ret = GetResourceLimitLimitValue64(system, std::addressof(out_limit_value), resource_limit_handle, which);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_limit_value));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_limit_value));
}
-static void SvcWrap_GetResourceLimitCurrentValue64(Core::System& system) {
+static void SvcWrap_GetResourceLimitCurrentValue64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_current_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg64(system, 1));
- which = Convert<LimitableResource>(GetReg64(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg64(args, 1));
+ which = Convert<LimitableResource>(GetArg64(args, 2));
ret = GetResourceLimitCurrentValue64(system, std::addressof(out_current_value), resource_limit_handle, which);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_current_value));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_current_value));
}
-static void SvcWrap_SetThreadActivity64(Core::System& system) {
+static void SvcWrap_SetThreadActivity64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle thread_handle{};
ThreadActivity thread_activity{};
- thread_handle = Convert<Handle>(GetReg64(system, 0));
- thread_activity = Convert<ThreadActivity>(GetReg64(system, 1));
+ thread_handle = Convert<Handle>(GetArg64(args, 0));
+ thread_activity = Convert<ThreadActivity>(GetArg64(args, 1));
ret = SetThreadActivity64(system, thread_handle, thread_activity);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetThreadContext364(Core::System& system) {
+static void SvcWrap_GetThreadContext364(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_context{};
Handle thread_handle{};
- out_context = Convert<uint64_t>(GetReg64(system, 0));
- thread_handle = Convert<Handle>(GetReg64(system, 1));
+ out_context = Convert<uint64_t>(GetArg64(args, 0));
+ thread_handle = Convert<Handle>(GetArg64(args, 1));
ret = GetThreadContext364(system, out_context, thread_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_WaitForAddress64(Core::System& system) {
+static void SvcWrap_WaitForAddress64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
@@ -2788,17 +2788,17 @@ static void SvcWrap_WaitForAddress64(Core::System& system) {
int32_t value{};
int64_t timeout_ns{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- arb_type = Convert<ArbitrationType>(GetReg64(system, 1));
- value = Convert<int32_t>(GetReg64(system, 2));
- timeout_ns = Convert<int64_t>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ arb_type = Convert<ArbitrationType>(GetArg64(args, 1));
+ value = Convert<int32_t>(GetArg64(args, 2));
+ timeout_ns = Convert<int64_t>(GetArg64(args, 3));
ret = WaitForAddress64(system, address, arb_type, value, timeout_ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SignalToAddress64(Core::System& system) {
+static void SvcWrap_SignalToAddress64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
@@ -2806,51 +2806,51 @@ static void SvcWrap_SignalToAddress64(Core::System& system) {
int32_t value{};
int32_t count{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- signal_type = Convert<SignalType>(GetReg64(system, 1));
- value = Convert<int32_t>(GetReg64(system, 2));
- count = Convert<int32_t>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ signal_type = Convert<SignalType>(GetArg64(args, 1));
+ value = Convert<int32_t>(GetArg64(args, 2));
+ count = Convert<int32_t>(GetArg64(args, 3));
ret = SignalToAddress64(system, address, signal_type, value, count);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SynchronizePreemptionState64(Core::System& system) {
+static void SvcWrap_SynchronizePreemptionState64(Core::System& system, std::span<uint64_t, 8> args) {
SynchronizePreemptionState64(system);
}
-static void SvcWrap_GetResourceLimitPeakValue64(Core::System& system) {
+static void SvcWrap_GetResourceLimitPeakValue64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_peak_value{};
Handle resource_limit_handle{};
LimitableResource which{};
- resource_limit_handle = Convert<Handle>(GetReg64(system, 1));
- which = Convert<LimitableResource>(GetReg64(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg64(args, 1));
+ which = Convert<LimitableResource>(GetArg64(args, 2));
ret = GetResourceLimitPeakValue64(system, std::addressof(out_peak_value), resource_limit_handle, which);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_peak_value));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_peak_value));
}
-static void SvcWrap_CreateIoPool64(Core::System& system) {
+static void SvcWrap_CreateIoPool64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
IoPoolType which{};
- which = Convert<IoPoolType>(GetReg64(system, 1));
+ which = Convert<IoPoolType>(GetArg64(args, 1));
ret = CreateIoPool64(system, std::addressof(out_handle), which);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_CreateIoRegion64(Core::System& system) {
+static void SvcWrap_CreateIoRegion64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -2860,41 +2860,41 @@ static void SvcWrap_CreateIoRegion64(Core::System& system) {
MemoryMapping mapping{};
MemoryPermission perm{};
- io_pool = Convert<Handle>(GetReg64(system, 1));
- physical_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
- mapping = Convert<MemoryMapping>(GetReg64(system, 4));
- perm = Convert<MemoryPermission>(GetReg64(system, 5));
+ io_pool = Convert<Handle>(GetArg64(args, 1));
+ physical_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
+ mapping = Convert<MemoryMapping>(GetArg64(args, 4));
+ perm = Convert<MemoryPermission>(GetArg64(args, 5));
ret = CreateIoRegion64(system, std::addressof(out_handle), io_pool, physical_address, size, mapping, perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_KernelDebug64(Core::System& system) {
+static void SvcWrap_KernelDebug64(Core::System& system, std::span<uint64_t, 8> args) {
KernelDebugType kern_debug_type{};
uint64_t arg0{};
uint64_t arg1{};
uint64_t arg2{};
- kern_debug_type = Convert<KernelDebugType>(GetReg64(system, 0));
- arg0 = Convert<uint64_t>(GetReg64(system, 1));
- arg1 = Convert<uint64_t>(GetReg64(system, 2));
- arg2 = Convert<uint64_t>(GetReg64(system, 3));
+ kern_debug_type = Convert<KernelDebugType>(GetArg64(args, 0));
+ arg0 = Convert<uint64_t>(GetArg64(args, 1));
+ arg1 = Convert<uint64_t>(GetArg64(args, 2));
+ arg2 = Convert<uint64_t>(GetArg64(args, 3));
KernelDebug64(system, kern_debug_type, arg0, arg1, arg2);
}
-static void SvcWrap_ChangeKernelTraceState64(Core::System& system) {
+static void SvcWrap_ChangeKernelTraceState64(Core::System& system, std::span<uint64_t, 8> args) {
KernelTraceState kern_trace_state{};
- kern_trace_state = Convert<KernelTraceState>(GetReg64(system, 0));
+ kern_trace_state = Convert<KernelTraceState>(GetArg64(args, 0));
ChangeKernelTraceState64(system, kern_trace_state);
}
-static void SvcWrap_CreateSession64(Core::System& system) {
+static void SvcWrap_CreateSession64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_session_handle{};
@@ -2902,31 +2902,31 @@ static void SvcWrap_CreateSession64(Core::System& system) {
bool is_light{};
uint64_t name{};
- is_light = Convert<bool>(GetReg64(system, 2));
- name = Convert<uint64_t>(GetReg64(system, 3));
+ is_light = Convert<bool>(GetArg64(args, 2));
+ name = Convert<uint64_t>(GetArg64(args, 3));
ret = CreateSession64(system, std::addressof(out_server_session_handle), std::addressof(out_client_session_handle), is_light, name);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_server_session_handle));
- SetReg64(system, 2, Convert<uint64_t>(out_client_session_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_server_session_handle));
+ SetArg64(args, 2, Convert<uint64_t>(out_client_session_handle));
}
-static void SvcWrap_AcceptSession64(Core::System& system) {
+static void SvcWrap_AcceptSession64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
Handle port{};
- port = Convert<Handle>(GetReg64(system, 1));
+ port = Convert<Handle>(GetArg64(args, 1));
ret = AcceptSession64(system, std::addressof(out_handle), port);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_ReplyAndReceive64(Core::System& system) {
+static void SvcWrap_ReplyAndReceive64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -2935,18 +2935,18 @@ static void SvcWrap_ReplyAndReceive64(Core::System& system) {
Handle reply_target{};
int64_t timeout_ns{};
- handles = Convert<uint64_t>(GetReg64(system, 1));
- num_handles = Convert<int32_t>(GetReg64(system, 2));
- reply_target = Convert<Handle>(GetReg64(system, 3));
- timeout_ns = Convert<int64_t>(GetReg64(system, 4));
+ handles = Convert<uint64_t>(GetArg64(args, 1));
+ num_handles = Convert<int32_t>(GetArg64(args, 2));
+ reply_target = Convert<Handle>(GetArg64(args, 3));
+ timeout_ns = Convert<int64_t>(GetArg64(args, 4));
ret = ReplyAndReceive64(system, std::addressof(out_index), handles, num_handles, reply_target, timeout_ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_index));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_index));
}
-static void SvcWrap_ReplyAndReceiveWithUserBuffer64(Core::System& system) {
+static void SvcWrap_ReplyAndReceiveWithUserBuffer64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_index{};
@@ -2957,20 +2957,20 @@ static void SvcWrap_ReplyAndReceiveWithUserBuffer64(Core::System& system) {
Handle reply_target{};
int64_t timeout_ns{};
- message_buffer = Convert<uint64_t>(GetReg64(system, 1));
- message_buffer_size = Convert<uint64_t>(GetReg64(system, 2));
- handles = Convert<uint64_t>(GetReg64(system, 3));
- num_handles = Convert<int32_t>(GetReg64(system, 4));
- reply_target = Convert<Handle>(GetReg64(system, 5));
- timeout_ns = Convert<int64_t>(GetReg64(system, 6));
+ message_buffer = Convert<uint64_t>(GetArg64(args, 1));
+ message_buffer_size = Convert<uint64_t>(GetArg64(args, 2));
+ handles = Convert<uint64_t>(GetArg64(args, 3));
+ num_handles = Convert<int32_t>(GetArg64(args, 4));
+ reply_target = Convert<Handle>(GetArg64(args, 5));
+ timeout_ns = Convert<int64_t>(GetArg64(args, 6));
ret = ReplyAndReceiveWithUserBuffer64(system, std::addressof(out_index), message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_index));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_index));
}
-static void SvcWrap_CreateEvent64(Core::System& system) {
+static void SvcWrap_CreateEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_write_handle{};
@@ -2978,12 +2978,12 @@ static void SvcWrap_CreateEvent64(Core::System& system) {
ret = CreateEvent64(system, std::addressof(out_write_handle), std::addressof(out_read_handle));
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_write_handle));
- SetReg64(system, 2, Convert<uint64_t>(out_read_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_write_handle));
+ SetArg64(args, 2, Convert<uint64_t>(out_read_handle));
}
-static void SvcWrap_MapIoRegion64(Core::System& system) {
+static void SvcWrap_MapIoRegion64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle io_region{};
@@ -2991,89 +2991,89 @@ static void SvcWrap_MapIoRegion64(Core::System& system) {
uint64_t size{};
MemoryPermission perm{};
- io_region = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
- perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ io_region = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
+ perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = MapIoRegion64(system, io_region, address, size, perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapIoRegion64(Core::System& system) {
+static void SvcWrap_UnmapIoRegion64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle io_region{};
uint64_t address{};
uint64_t size{};
- io_region = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ io_region = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = UnmapIoRegion64(system, io_region, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapPhysicalMemoryUnsafe64(Core::System& system) {
+static void SvcWrap_MapPhysicalMemoryUnsafe64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = MapPhysicalMemoryUnsafe64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapPhysicalMemoryUnsafe64(Core::System& system) {
+static void SvcWrap_UnmapPhysicalMemoryUnsafe64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = UnmapPhysicalMemoryUnsafe64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SetUnsafeLimit64(Core::System& system) {
+static void SvcWrap_SetUnsafeLimit64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t limit{};
- limit = Convert<uint64_t>(GetReg64(system, 0));
+ limit = Convert<uint64_t>(GetArg64(args, 0));
ret = SetUnsafeLimit64(system, limit);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_CreateCodeMemory64(Core::System& system) {
+static void SvcWrap_CreateCodeMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = CreateCodeMemory64(system, std::addressof(out_handle), address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_ControlCodeMemory64(Core::System& system) {
+static void SvcWrap_ControlCodeMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle code_memory_handle{};
@@ -3082,22 +3082,22 @@ static void SvcWrap_ControlCodeMemory64(Core::System& system) {
uint64_t size{};
MemoryPermission perm{};
- code_memory_handle = Convert<Handle>(GetReg64(system, 0));
- operation = Convert<CodeMemoryOperation>(GetReg64(system, 1));
- address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
- perm = Convert<MemoryPermission>(GetReg64(system, 4));
+ code_memory_handle = Convert<Handle>(GetArg64(args, 0));
+ operation = Convert<CodeMemoryOperation>(GetArg64(args, 1));
+ address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
+ perm = Convert<MemoryPermission>(GetArg64(args, 4));
ret = ControlCodeMemory64(system, code_memory_handle, operation, address, size, perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SleepSystem64(Core::System& system) {
+static void SvcWrap_SleepSystem64(Core::System& system, std::span<uint64_t, 8> args) {
SleepSystem64(system);
}
-static void SvcWrap_ReadWriteRegister64(Core::System& system) {
+static void SvcWrap_ReadWriteRegister64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint32_t out_value{};
@@ -3105,31 +3105,31 @@ static void SvcWrap_ReadWriteRegister64(Core::System& system) {
uint32_t mask{};
uint32_t value{};
- address = Convert<uint64_t>(GetReg64(system, 1));
- mask = Convert<uint32_t>(GetReg64(system, 2));
- value = Convert<uint32_t>(GetReg64(system, 3));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ mask = Convert<uint32_t>(GetArg64(args, 2));
+ value = Convert<uint32_t>(GetArg64(args, 3));
ret = ReadWriteRegister64(system, std::addressof(out_value), address, mask, value);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_value));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_value));
}
-static void SvcWrap_SetProcessActivity64(Core::System& system) {
+static void SvcWrap_SetProcessActivity64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
ProcessActivity process_activity{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- process_activity = Convert<ProcessActivity>(GetReg64(system, 1));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ process_activity = Convert<ProcessActivity>(GetArg64(args, 1));
ret = SetProcessActivity64(system, process_handle, process_activity);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_CreateSharedMemory64(Core::System& system) {
+static void SvcWrap_CreateSharedMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -3137,17 +3137,17 @@ static void SvcWrap_CreateSharedMemory64(Core::System& system) {
MemoryPermission owner_perm{};
MemoryPermission remote_perm{};
- size = Convert<uint64_t>(GetReg64(system, 1));
- owner_perm = Convert<MemoryPermission>(GetReg64(system, 2));
- remote_perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ size = Convert<uint64_t>(GetArg64(args, 1));
+ owner_perm = Convert<MemoryPermission>(GetArg64(args, 2));
+ remote_perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = CreateSharedMemory64(system, std::addressof(out_handle), size, owner_perm, remote_perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_MapTransferMemory64(Core::System& system) {
+static void SvcWrap_MapTransferMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle trmem_handle{};
@@ -3155,66 +3155,66 @@ static void SvcWrap_MapTransferMemory64(Core::System& system) {
uint64_t size{};
MemoryPermission owner_perm{};
- trmem_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
- owner_perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ trmem_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
+ owner_perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = MapTransferMemory64(system, trmem_handle, address, size, owner_perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapTransferMemory64(Core::System& system) {
+static void SvcWrap_UnmapTransferMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle trmem_handle{};
uint64_t address{};
uint64_t size{};
- trmem_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ trmem_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = UnmapTransferMemory64(system, trmem_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_CreateInterruptEvent64(Core::System& system) {
+static void SvcWrap_CreateInterruptEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_read_handle{};
int32_t interrupt_id{};
InterruptType interrupt_type{};
- interrupt_id = Convert<int32_t>(GetReg64(system, 1));
- interrupt_type = Convert<InterruptType>(GetReg64(system, 2));
+ interrupt_id = Convert<int32_t>(GetArg64(args, 1));
+ interrupt_type = Convert<InterruptType>(GetArg64(args, 2));
ret = CreateInterruptEvent64(system, std::addressof(out_read_handle), interrupt_id, interrupt_type);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_read_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_read_handle));
}
-static void SvcWrap_QueryPhysicalAddress64(Core::System& system) {
+static void SvcWrap_QueryPhysicalAddress64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
lp64::PhysicalMemoryInfo out_info{};
uint64_t address{};
- address = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 1));
ret = QueryPhysicalAddress64(system, std::addressof(out_info), address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
auto out_info_scatter = Convert<std::array<uint64_t, 3>>(out_info);
- SetReg64(system, 1, out_info_scatter[0]);
- SetReg64(system, 2, out_info_scatter[1]);
- SetReg64(system, 3, out_info_scatter[2]);
+ SetArg64(args, 1, out_info_scatter[0]);
+ SetArg64(args, 2, out_info_scatter[1]);
+ SetArg64(args, 3, out_info_scatter[2]);
}
-static void SvcWrap_QueryIoMapping64(Core::System& system) {
+static void SvcWrap_QueryIoMapping64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_address{};
@@ -3222,61 +3222,61 @@ static void SvcWrap_QueryIoMapping64(Core::System& system) {
uint64_t physical_address{};
uint64_t size{};
- physical_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ physical_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = QueryIoMapping64(system, std::addressof(out_address), std::addressof(out_size), physical_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_address));
- SetReg64(system, 2, Convert<uint64_t>(out_size));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_address));
+ SetArg64(args, 2, Convert<uint64_t>(out_size));
}
-static void SvcWrap_CreateDeviceAddressSpace64(Core::System& system) {
+static void SvcWrap_CreateDeviceAddressSpace64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint64_t das_address{};
uint64_t das_size{};
- das_address = Convert<uint64_t>(GetReg64(system, 1));
- das_size = Convert<uint64_t>(GetReg64(system, 2));
+ das_address = Convert<uint64_t>(GetArg64(args, 1));
+ das_size = Convert<uint64_t>(GetArg64(args, 2));
ret = CreateDeviceAddressSpace64(system, std::addressof(out_handle), das_address, das_size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_AttachDeviceAddressSpace64(Core::System& system) {
+static void SvcWrap_AttachDeviceAddressSpace64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
DeviceName device_name{};
Handle das_handle{};
- device_name = Convert<DeviceName>(GetReg64(system, 0));
- das_handle = Convert<Handle>(GetReg64(system, 1));
+ device_name = Convert<DeviceName>(GetArg64(args, 0));
+ das_handle = Convert<Handle>(GetArg64(args, 1));
ret = AttachDeviceAddressSpace64(system, device_name, das_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_DetachDeviceAddressSpace64(Core::System& system) {
+static void SvcWrap_DetachDeviceAddressSpace64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
DeviceName device_name{};
Handle das_handle{};
- device_name = Convert<DeviceName>(GetReg64(system, 0));
- das_handle = Convert<Handle>(GetReg64(system, 1));
+ device_name = Convert<DeviceName>(GetArg64(args, 0));
+ das_handle = Convert<Handle>(GetArg64(args, 1));
ret = DetachDeviceAddressSpace64(system, device_name, das_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapDeviceAddressSpaceByForce64(Core::System& system) {
+static void SvcWrap_MapDeviceAddressSpaceByForce64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -3286,19 +3286,19 @@ static void SvcWrap_MapDeviceAddressSpaceByForce64(Core::System& system) {
uint64_t device_address{};
uint32_t option{};
- das_handle = Convert<Handle>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 1));
- process_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
- device_address = Convert<uint64_t>(GetReg64(system, 4));
- option = Convert<uint32_t>(GetReg64(system, 5));
+ das_handle = Convert<Handle>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ process_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
+ device_address = Convert<uint64_t>(GetArg64(args, 4));
+ option = Convert<uint32_t>(GetArg64(args, 5));
ret = MapDeviceAddressSpaceByForce64(system, das_handle, process_handle, process_address, size, device_address, option);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapDeviceAddressSpaceAligned64(Core::System& system) {
+static void SvcWrap_MapDeviceAddressSpaceAligned64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -3308,19 +3308,19 @@ static void SvcWrap_MapDeviceAddressSpaceAligned64(Core::System& system) {
uint64_t device_address{};
uint32_t option{};
- das_handle = Convert<Handle>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 1));
- process_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
- device_address = Convert<uint64_t>(GetReg64(system, 4));
- option = Convert<uint32_t>(GetReg64(system, 5));
+ das_handle = Convert<Handle>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ process_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
+ device_address = Convert<uint64_t>(GetArg64(args, 4));
+ option = Convert<uint32_t>(GetArg64(args, 5));
ret = MapDeviceAddressSpaceAligned64(system, das_handle, process_handle, process_address, size, device_address, option);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapDeviceAddressSpace64(Core::System& system) {
+static void SvcWrap_UnmapDeviceAddressSpace64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle das_handle{};
@@ -3329,118 +3329,118 @@ static void SvcWrap_UnmapDeviceAddressSpace64(Core::System& system) {
uint64_t size{};
uint64_t device_address{};
- das_handle = Convert<Handle>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 1));
- process_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
- device_address = Convert<uint64_t>(GetReg64(system, 4));
+ das_handle = Convert<Handle>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ process_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
+ device_address = Convert<uint64_t>(GetArg64(args, 4));
ret = UnmapDeviceAddressSpace64(system, das_handle, process_handle, process_address, size, device_address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_InvalidateProcessDataCache64(Core::System& system) {
+static void SvcWrap_InvalidateProcessDataCache64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = InvalidateProcessDataCache64(system, process_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_StoreProcessDataCache64(Core::System& system) {
+static void SvcWrap_StoreProcessDataCache64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = StoreProcessDataCache64(system, process_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_FlushProcessDataCache64(Core::System& system) {
+static void SvcWrap_FlushProcessDataCache64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
uint64_t address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
ret = FlushProcessDataCache64(system, process_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_DebugActiveProcess64(Core::System& system) {
+static void SvcWrap_DebugActiveProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
uint64_t process_id{};
- process_id = Convert<uint64_t>(GetReg64(system, 1));
+ process_id = Convert<uint64_t>(GetArg64(args, 1));
ret = DebugActiveProcess64(system, std::addressof(out_handle), process_id);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_BreakDebugProcess64(Core::System& system) {
+static void SvcWrap_BreakDebugProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
- debug_handle = Convert<Handle>(GetReg64(system, 0));
+ debug_handle = Convert<Handle>(GetArg64(args, 0));
ret = BreakDebugProcess64(system, debug_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_TerminateDebugProcess64(Core::System& system) {
+static void SvcWrap_TerminateDebugProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
- debug_handle = Convert<Handle>(GetReg64(system, 0));
+ debug_handle = Convert<Handle>(GetArg64(args, 0));
ret = TerminateDebugProcess64(system, debug_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetDebugEvent64(Core::System& system) {
+static void SvcWrap_GetDebugEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_info{};
Handle debug_handle{};
- out_info = Convert<uint64_t>(GetReg64(system, 0));
- debug_handle = Convert<Handle>(GetReg64(system, 1));
+ out_info = Convert<uint64_t>(GetArg64(args, 0));
+ debug_handle = Convert<Handle>(GetArg64(args, 1));
ret = GetDebugEvent64(system, out_info, debug_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_ContinueDebugEvent64(Core::System& system) {
+static void SvcWrap_ContinueDebugEvent64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -3448,33 +3448,33 @@ static void SvcWrap_ContinueDebugEvent64(Core::System& system) {
uint64_t thread_ids{};
int32_t num_thread_ids{};
- debug_handle = Convert<Handle>(GetReg64(system, 0));
- flags = Convert<uint32_t>(GetReg64(system, 1));
- thread_ids = Convert<uint64_t>(GetReg64(system, 2));
- num_thread_ids = Convert<int32_t>(GetReg64(system, 3));
+ debug_handle = Convert<Handle>(GetArg64(args, 0));
+ flags = Convert<uint32_t>(GetArg64(args, 1));
+ thread_ids = Convert<uint64_t>(GetArg64(args, 2));
+ num_thread_ids = Convert<int32_t>(GetArg64(args, 3));
ret = ContinueDebugEvent64(system, debug_handle, flags, thread_ids, num_thread_ids);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetProcessList64(Core::System& system) {
+static void SvcWrap_GetProcessList64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_num_processes{};
uint64_t out_process_ids{};
int32_t max_out_count{};
- out_process_ids = Convert<uint64_t>(GetReg64(system, 1));
- max_out_count = Convert<int32_t>(GetReg64(system, 2));
+ out_process_ids = Convert<uint64_t>(GetArg64(args, 1));
+ max_out_count = Convert<int32_t>(GetArg64(args, 2));
ret = GetProcessList64(system, std::addressof(out_num_processes), out_process_ids, max_out_count);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_num_processes));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_num_processes));
}
-static void SvcWrap_GetThreadList64(Core::System& system) {
+static void SvcWrap_GetThreadList64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int32_t out_num_threads{};
@@ -3482,17 +3482,17 @@ static void SvcWrap_GetThreadList64(Core::System& system) {
int32_t max_out_count{};
Handle debug_handle{};
- out_thread_ids = Convert<uint64_t>(GetReg64(system, 1));
- max_out_count = Convert<int32_t>(GetReg64(system, 2));
- debug_handle = Convert<Handle>(GetReg64(system, 3));
+ out_thread_ids = Convert<uint64_t>(GetArg64(args, 1));
+ max_out_count = Convert<int32_t>(GetArg64(args, 2));
+ debug_handle = Convert<Handle>(GetArg64(args, 3));
ret = GetThreadList64(system, std::addressof(out_num_threads), out_thread_ids, max_out_count, debug_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_num_threads));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_num_threads));
}
-static void SvcWrap_GetDebugThreadContext64(Core::System& system) {
+static void SvcWrap_GetDebugThreadContext64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_context{};
@@ -3500,17 +3500,17 @@ static void SvcWrap_GetDebugThreadContext64(Core::System& system) {
uint64_t thread_id{};
uint32_t context_flags{};
- out_context = Convert<uint64_t>(GetReg64(system, 0));
- debug_handle = Convert<Handle>(GetReg64(system, 1));
- thread_id = Convert<uint64_t>(GetReg64(system, 2));
- context_flags = Convert<uint32_t>(GetReg64(system, 3));
+ out_context = Convert<uint64_t>(GetArg64(args, 0));
+ debug_handle = Convert<Handle>(GetArg64(args, 1));
+ thread_id = Convert<uint64_t>(GetArg64(args, 2));
+ context_flags = Convert<uint32_t>(GetArg64(args, 3));
ret = GetDebugThreadContext64(system, out_context, debug_handle, thread_id, context_flags);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SetDebugThreadContext64(Core::System& system) {
+static void SvcWrap_SetDebugThreadContext64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -3518,17 +3518,17 @@ static void SvcWrap_SetDebugThreadContext64(Core::System& system) {
uint64_t context{};
uint32_t context_flags{};
- debug_handle = Convert<Handle>(GetReg64(system, 0));
- thread_id = Convert<uint64_t>(GetReg64(system, 1));
- context = Convert<uint64_t>(GetReg64(system, 2));
- context_flags = Convert<uint32_t>(GetReg64(system, 3));
+ debug_handle = Convert<Handle>(GetArg64(args, 0));
+ thread_id = Convert<uint64_t>(GetArg64(args, 1));
+ context = Convert<uint64_t>(GetArg64(args, 2));
+ context_flags = Convert<uint32_t>(GetArg64(args, 3));
ret = SetDebugThreadContext64(system, debug_handle, thread_id, context, context_flags);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_QueryDebugProcessMemory64(Core::System& system) {
+static void SvcWrap_QueryDebugProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
@@ -3536,17 +3536,17 @@ static void SvcWrap_QueryDebugProcessMemory64(Core::System& system) {
Handle process_handle{};
uint64_t address{};
- out_memory_info = Convert<uint64_t>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 2));
- address = Convert<uint64_t>(GetReg64(system, 3));
+ out_memory_info = Convert<uint64_t>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 2));
+ address = Convert<uint64_t>(GetArg64(args, 3));
ret = QueryDebugProcessMemory64(system, out_memory_info, std::addressof(out_page_info), process_handle, address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_page_info));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_page_info));
}
-static void SvcWrap_ReadDebugProcessMemory64(Core::System& system) {
+static void SvcWrap_ReadDebugProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t buffer{};
@@ -3554,17 +3554,17 @@ static void SvcWrap_ReadDebugProcessMemory64(Core::System& system) {
uint64_t address{};
uint64_t size{};
- buffer = Convert<uint64_t>(GetReg64(system, 0));
- debug_handle = Convert<Handle>(GetReg64(system, 1));
- address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ buffer = Convert<uint64_t>(GetArg64(args, 0));
+ debug_handle = Convert<Handle>(GetArg64(args, 1));
+ address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = ReadDebugProcessMemory64(system, buffer, debug_handle, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_WriteDebugProcessMemory64(Core::System& system) {
+static void SvcWrap_WriteDebugProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle debug_handle{};
@@ -3572,33 +3572,33 @@ static void SvcWrap_WriteDebugProcessMemory64(Core::System& system) {
uint64_t address{};
uint64_t size{};
- debug_handle = Convert<Handle>(GetReg64(system, 0));
- buffer = Convert<uint64_t>(GetReg64(system, 1));
- address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ debug_handle = Convert<Handle>(GetArg64(args, 0));
+ buffer = Convert<uint64_t>(GetArg64(args, 1));
+ address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = WriteDebugProcessMemory64(system, debug_handle, buffer, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_SetHardwareBreakPoint64(Core::System& system) {
+static void SvcWrap_SetHardwareBreakPoint64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
HardwareBreakPointRegisterName name{};
uint64_t flags{};
uint64_t value{};
- name = Convert<HardwareBreakPointRegisterName>(GetReg64(system, 0));
- flags = Convert<uint64_t>(GetReg64(system, 1));
- value = Convert<uint64_t>(GetReg64(system, 2));
+ name = Convert<HardwareBreakPointRegisterName>(GetArg64(args, 0));
+ flags = Convert<uint64_t>(GetArg64(args, 1));
+ value = Convert<uint64_t>(GetArg64(args, 2));
ret = SetHardwareBreakPoint64(system, name, flags, value);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetDebugThreadParam64(Core::System& system) {
+static void SvcWrap_GetDebugThreadParam64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out_64{};
@@ -3607,18 +3607,18 @@ static void SvcWrap_GetDebugThreadParam64(Core::System& system) {
uint64_t thread_id{};
DebugThreadParam param{};
- debug_handle = Convert<Handle>(GetReg64(system, 2));
- thread_id = Convert<uint64_t>(GetReg64(system, 3));
- param = Convert<DebugThreadParam>(GetReg64(system, 4));
+ debug_handle = Convert<Handle>(GetArg64(args, 2));
+ thread_id = Convert<uint64_t>(GetArg64(args, 3));
+ param = Convert<DebugThreadParam>(GetArg64(args, 4));
ret = GetDebugThreadParam64(system, std::addressof(out_64), std::addressof(out_32), debug_handle, thread_id, param);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_64));
- SetReg64(system, 2, Convert<uint64_t>(out_32));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_64));
+ SetArg64(args, 2, Convert<uint64_t>(out_32));
}
-static void SvcWrap_GetSystemInfo64(Core::System& system) {
+static void SvcWrap_GetSystemInfo64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t out{};
@@ -3626,17 +3626,17 @@ static void SvcWrap_GetSystemInfo64(Core::System& system) {
Handle handle{};
uint64_t info_subtype{};
- info_type = Convert<SystemInfoType>(GetReg64(system, 1));
- handle = Convert<Handle>(GetReg64(system, 2));
- info_subtype = Convert<uint64_t>(GetReg64(system, 3));
+ info_type = Convert<SystemInfoType>(GetArg64(args, 1));
+ handle = Convert<Handle>(GetArg64(args, 2));
+ info_subtype = Convert<uint64_t>(GetArg64(args, 3));
ret = GetSystemInfo64(system, std::addressof(out), info_type, handle, info_subtype);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out));
}
-static void SvcWrap_CreatePort64(Core::System& system) {
+static void SvcWrap_CreatePort64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_handle{};
@@ -3645,48 +3645,48 @@ static void SvcWrap_CreatePort64(Core::System& system) {
bool is_light{};
uint64_t name{};
- max_sessions = Convert<int32_t>(GetReg64(system, 2));
- is_light = Convert<bool>(GetReg64(system, 3));
- name = Convert<uint64_t>(GetReg64(system, 4));
+ max_sessions = Convert<int32_t>(GetArg64(args, 2));
+ is_light = Convert<bool>(GetArg64(args, 3));
+ name = Convert<uint64_t>(GetArg64(args, 4));
ret = CreatePort64(system, std::addressof(out_server_handle), std::addressof(out_client_handle), max_sessions, is_light, name);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_server_handle));
- SetReg64(system, 2, Convert<uint64_t>(out_client_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_server_handle));
+ SetArg64(args, 2, Convert<uint64_t>(out_client_handle));
}
-static void SvcWrap_ManageNamedPort64(Core::System& system) {
+static void SvcWrap_ManageNamedPort64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_server_handle{};
uint64_t name{};
int32_t max_sessions{};
- name = Convert<uint64_t>(GetReg64(system, 1));
- max_sessions = Convert<int32_t>(GetReg64(system, 2));
+ name = Convert<uint64_t>(GetArg64(args, 1));
+ max_sessions = Convert<int32_t>(GetArg64(args, 2));
ret = ManageNamedPort64(system, std::addressof(out_server_handle), name, max_sessions);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_server_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_server_handle));
}
-static void SvcWrap_ConnectToPort64(Core::System& system) {
+static void SvcWrap_ConnectToPort64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
Handle port{};
- port = Convert<Handle>(GetReg64(system, 1));
+ port = Convert<Handle>(GetArg64(args, 1));
ret = ConnectToPort64(system, std::addressof(out_handle), port);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_SetProcessMemoryPermission64(Core::System& system) {
+static void SvcWrap_SetProcessMemoryPermission64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -3694,17 +3694,17 @@ static void SvcWrap_SetProcessMemoryPermission64(Core::System& system) {
uint64_t size{};
MemoryPermission perm{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- address = Convert<uint64_t>(GetReg64(system, 1));
- size = Convert<uint64_t>(GetReg64(system, 2));
- perm = Convert<MemoryPermission>(GetReg64(system, 3));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ address = Convert<uint64_t>(GetArg64(args, 1));
+ size = Convert<uint64_t>(GetArg64(args, 2));
+ perm = Convert<MemoryPermission>(GetArg64(args, 3));
ret = SetProcessMemoryPermission64(system, process_handle, address, size, perm);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapProcessMemory64(Core::System& system) {
+static void SvcWrap_MapProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t dst_address{};
@@ -3712,17 +3712,17 @@ static void SvcWrap_MapProcessMemory64(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- dst_address = Convert<uint64_t>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 1));
- src_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ dst_address = Convert<uint64_t>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ src_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = MapProcessMemory64(system, dst_address, process_handle, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapProcessMemory64(Core::System& system) {
+static void SvcWrap_UnmapProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t dst_address{};
@@ -3730,17 +3730,17 @@ static void SvcWrap_UnmapProcessMemory64(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- dst_address = Convert<uint64_t>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 1));
- src_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ dst_address = Convert<uint64_t>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ src_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = UnmapProcessMemory64(system, dst_address, process_handle, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_QueryProcessMemory64(Core::System& system) {
+static void SvcWrap_QueryProcessMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
PageInfo out_page_info{};
@@ -3748,17 +3748,17 @@ static void SvcWrap_QueryProcessMemory64(Core::System& system) {
Handle process_handle{};
uint64_t address{};
- out_memory_info = Convert<uint64_t>(GetReg64(system, 0));
- process_handle = Convert<Handle>(GetReg64(system, 2));
- address = Convert<uint64_t>(GetReg64(system, 3));
+ out_memory_info = Convert<uint64_t>(GetArg64(args, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 2));
+ address = Convert<uint64_t>(GetArg64(args, 3));
ret = QueryProcessMemory64(system, out_memory_info, std::addressof(out_page_info), process_handle, address);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_page_info));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_page_info));
}
-static void SvcWrap_MapProcessCodeMemory64(Core::System& system) {
+static void SvcWrap_MapProcessCodeMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -3766,17 +3766,17 @@ static void SvcWrap_MapProcessCodeMemory64(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- dst_address = Convert<uint64_t>(GetReg64(system, 1));
- src_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ dst_address = Convert<uint64_t>(GetArg64(args, 1));
+ src_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = MapProcessCodeMemory64(system, process_handle, dst_address, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapProcessCodeMemory64(Core::System& system) {
+static void SvcWrap_UnmapProcessCodeMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -3784,17 +3784,17 @@ static void SvcWrap_UnmapProcessCodeMemory64(Core::System& system) {
uint64_t src_address{};
uint64_t size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- dst_address = Convert<uint64_t>(GetReg64(system, 1));
- src_address = Convert<uint64_t>(GetReg64(system, 2));
- size = Convert<uint64_t>(GetReg64(system, 3));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ dst_address = Convert<uint64_t>(GetArg64(args, 1));
+ src_address = Convert<uint64_t>(GetArg64(args, 2));
+ size = Convert<uint64_t>(GetArg64(args, 3));
ret = UnmapProcessCodeMemory64(system, process_handle, dst_address, src_address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_CreateProcess64(Core::System& system) {
+static void SvcWrap_CreateProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
@@ -3802,17 +3802,17 @@ static void SvcWrap_CreateProcess64(Core::System& system) {
uint64_t caps{};
int32_t num_caps{};
- parameters = Convert<uint64_t>(GetReg64(system, 1));
- caps = Convert<uint64_t>(GetReg64(system, 2));
- num_caps = Convert<int32_t>(GetReg64(system, 3));
+ parameters = Convert<uint64_t>(GetArg64(args, 1));
+ caps = Convert<uint64_t>(GetArg64(args, 2));
+ num_caps = Convert<int32_t>(GetArg64(args, 3));
ret = CreateProcess64(system, std::addressof(out_handle), parameters, caps, num_caps);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_StartProcess64(Core::System& system) {
+static void SvcWrap_StartProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
@@ -3820,601 +3820,601 @@ static void SvcWrap_StartProcess64(Core::System& system) {
int32_t core_id{};
uint64_t main_thread_stack_size{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
- priority = Convert<int32_t>(GetReg64(system, 1));
- core_id = Convert<int32_t>(GetReg64(system, 2));
- main_thread_stack_size = Convert<uint64_t>(GetReg64(system, 3));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
+ priority = Convert<int32_t>(GetArg64(args, 1));
+ core_id = Convert<int32_t>(GetArg64(args, 2));
+ main_thread_stack_size = Convert<uint64_t>(GetArg64(args, 3));
ret = StartProcess64(system, process_handle, priority, core_id, main_thread_stack_size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_TerminateProcess64(Core::System& system) {
+static void SvcWrap_TerminateProcess64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle process_handle{};
- process_handle = Convert<Handle>(GetReg64(system, 0));
+ process_handle = Convert<Handle>(GetArg64(args, 0));
ret = TerminateProcess64(system, process_handle);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_GetProcessInfo64(Core::System& system) {
+static void SvcWrap_GetProcessInfo64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
int64_t out_info{};
Handle process_handle{};
ProcessInfoType info_type{};
- process_handle = Convert<Handle>(GetReg64(system, 1));
- info_type = Convert<ProcessInfoType>(GetReg64(system, 2));
+ process_handle = Convert<Handle>(GetArg64(args, 1));
+ info_type = Convert<ProcessInfoType>(GetArg64(args, 2));
ret = GetProcessInfo64(system, std::addressof(out_info), process_handle, info_type);
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_info));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_info));
}
-static void SvcWrap_CreateResourceLimit64(Core::System& system) {
+static void SvcWrap_CreateResourceLimit64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle out_handle{};
ret = CreateResourceLimit64(system, std::addressof(out_handle));
- SetReg64(system, 0, Convert<uint64_t>(ret));
- SetReg64(system, 1, Convert<uint64_t>(out_handle));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 1, Convert<uint64_t>(out_handle));
}
-static void SvcWrap_SetResourceLimitLimitValue64(Core::System& system) {
+static void SvcWrap_SetResourceLimitLimitValue64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
Handle resource_limit_handle{};
LimitableResource which{};
int64_t limit_value{};
- resource_limit_handle = Convert<Handle>(GetReg64(system, 0));
- which = Convert<LimitableResource>(GetReg64(system, 1));
- limit_value = Convert<int64_t>(GetReg64(system, 2));
+ resource_limit_handle = Convert<Handle>(GetArg64(args, 0));
+ which = Convert<LimitableResource>(GetArg64(args, 1));
+ limit_value = Convert<int64_t>(GetArg64(args, 2));
ret = SetResourceLimitLimitValue64(system, resource_limit_handle, which, limit_value);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_MapInsecureMemory64(Core::System& system) {
+static void SvcWrap_MapInsecureMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = MapInsecureMemory64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void SvcWrap_UnmapInsecureMemory64(Core::System& system) {
+static void SvcWrap_UnmapInsecureMemory64(Core::System& system, std::span<uint64_t, 8> args) {
Result ret{};
uint64_t address{};
uint64_t size{};
- address = Convert<uint64_t>(GetReg64(system, 0));
- size = Convert<uint64_t>(GetReg64(system, 1));
+ address = Convert<uint64_t>(GetArg64(args, 0));
+ size = Convert<uint64_t>(GetArg64(args, 1));
ret = UnmapInsecureMemory64(system, address, size);
- SetReg64(system, 0, Convert<uint64_t>(ret));
+ SetArg64(args, 0, Convert<uint64_t>(ret));
}
-static void Call32(Core::System& system, u32 imm) {
+static void Call32(Core::System& system, u32 imm, std::span<uint64_t, 8> args) {
switch (static_cast<SvcId>(imm)) {
case SvcId::SetHeapSize:
- return SvcWrap_SetHeapSize64From32(system);
+ return SvcWrap_SetHeapSize64From32(system, args);
case SvcId::SetMemoryPermission:
- return SvcWrap_SetMemoryPermission64From32(system);
+ return SvcWrap_SetMemoryPermission64From32(system, args);
case SvcId::SetMemoryAttribute:
- return SvcWrap_SetMemoryAttribute64From32(system);
+ return SvcWrap_SetMemoryAttribute64From32(system, args);
case SvcId::MapMemory:
- return SvcWrap_MapMemory64From32(system);
+ return SvcWrap_MapMemory64From32(system, args);
case SvcId::UnmapMemory:
- return SvcWrap_UnmapMemory64From32(system);
+ return SvcWrap_UnmapMemory64From32(system, args);
case SvcId::QueryMemory:
- return SvcWrap_QueryMemory64From32(system);
+ return SvcWrap_QueryMemory64From32(system, args);
case SvcId::ExitProcess:
- return SvcWrap_ExitProcess64From32(system);
+ return SvcWrap_ExitProcess64From32(system, args);
case SvcId::CreateThread:
- return SvcWrap_CreateThread64From32(system);
+ return SvcWrap_CreateThread64From32(system, args);
case SvcId::StartThread:
- return SvcWrap_StartThread64From32(system);
+ return SvcWrap_StartThread64From32(system, args);
case SvcId::ExitThread:
- return SvcWrap_ExitThread64From32(system);
+ return SvcWrap_ExitThread64From32(system, args);
case SvcId::SleepThread:
- return SvcWrap_SleepThread64From32(system);
+ return SvcWrap_SleepThread64From32(system, args);
case SvcId::GetThreadPriority:
- return SvcWrap_GetThreadPriority64From32(system);
+ return SvcWrap_GetThreadPriority64From32(system, args);
case SvcId::SetThreadPriority:
- return SvcWrap_SetThreadPriority64From32(system);
+ return SvcWrap_SetThreadPriority64From32(system, args);
case SvcId::GetThreadCoreMask:
- return SvcWrap_GetThreadCoreMask64From32(system);
+ return SvcWrap_GetThreadCoreMask64From32(system, args);
case SvcId::SetThreadCoreMask:
- return SvcWrap_SetThreadCoreMask64From32(system);
+ return SvcWrap_SetThreadCoreMask64From32(system, args);
case SvcId::GetCurrentProcessorNumber:
- return SvcWrap_GetCurrentProcessorNumber64From32(system);
+ return SvcWrap_GetCurrentProcessorNumber64From32(system, args);
case SvcId::SignalEvent:
- return SvcWrap_SignalEvent64From32(system);
+ return SvcWrap_SignalEvent64From32(system, args);
case SvcId::ClearEvent:
- return SvcWrap_ClearEvent64From32(system);
+ return SvcWrap_ClearEvent64From32(system, args);
case SvcId::MapSharedMemory:
- return SvcWrap_MapSharedMemory64From32(system);
+ return SvcWrap_MapSharedMemory64From32(system, args);
case SvcId::UnmapSharedMemory:
- return SvcWrap_UnmapSharedMemory64From32(system);
+ return SvcWrap_UnmapSharedMemory64From32(system, args);
case SvcId::CreateTransferMemory:
- return SvcWrap_CreateTransferMemory64From32(system);
+ return SvcWrap_CreateTransferMemory64From32(system, args);
case SvcId::CloseHandle:
- return SvcWrap_CloseHandle64From32(system);
+ return SvcWrap_CloseHandle64From32(system, args);
case SvcId::ResetSignal:
- return SvcWrap_ResetSignal64From32(system);
+ return SvcWrap_ResetSignal64From32(system, args);
case SvcId::WaitSynchronization:
- return SvcWrap_WaitSynchronization64From32(system);
+ return SvcWrap_WaitSynchronization64From32(system, args);
case SvcId::CancelSynchronization:
- return SvcWrap_CancelSynchronization64From32(system);
+ return SvcWrap_CancelSynchronization64From32(system, args);
case SvcId::ArbitrateLock:
- return SvcWrap_ArbitrateLock64From32(system);
+ return SvcWrap_ArbitrateLock64From32(system, args);
case SvcId::ArbitrateUnlock:
- return SvcWrap_ArbitrateUnlock64From32(system);
+ return SvcWrap_ArbitrateUnlock64From32(system, args);
case SvcId::WaitProcessWideKeyAtomic:
- return SvcWrap_WaitProcessWideKeyAtomic64From32(system);
+ return SvcWrap_WaitProcessWideKeyAtomic64From32(system, args);
case SvcId::SignalProcessWideKey:
- return SvcWrap_SignalProcessWideKey64From32(system);
+ return SvcWrap_SignalProcessWideKey64From32(system, args);
case SvcId::GetSystemTick:
- return SvcWrap_GetSystemTick64From32(system);
+ return SvcWrap_GetSystemTick64From32(system, args);
case SvcId::ConnectToNamedPort:
- return SvcWrap_ConnectToNamedPort64From32(system);
+ return SvcWrap_ConnectToNamedPort64From32(system, args);
case SvcId::SendSyncRequestLight:
- return SvcWrap_SendSyncRequestLight64From32(system);
+ return SvcWrap_SendSyncRequestLight64From32(system, args);
case SvcId::SendSyncRequest:
- return SvcWrap_SendSyncRequest64From32(system);
+ return SvcWrap_SendSyncRequest64From32(system, args);
case SvcId::SendSyncRequestWithUserBuffer:
- return SvcWrap_SendSyncRequestWithUserBuffer64From32(system);
+ return SvcWrap_SendSyncRequestWithUserBuffer64From32(system, args);
case SvcId::SendAsyncRequestWithUserBuffer:
- return SvcWrap_SendAsyncRequestWithUserBuffer64From32(system);
+ return SvcWrap_SendAsyncRequestWithUserBuffer64From32(system, args);
case SvcId::GetProcessId:
- return SvcWrap_GetProcessId64From32(system);
+ return SvcWrap_GetProcessId64From32(system, args);
case SvcId::GetThreadId:
- return SvcWrap_GetThreadId64From32(system);
+ return SvcWrap_GetThreadId64From32(system, args);
case SvcId::Break:
- return SvcWrap_Break64From32(system);
+ return SvcWrap_Break64From32(system, args);
case SvcId::OutputDebugString:
- return SvcWrap_OutputDebugString64From32(system);
+ return SvcWrap_OutputDebugString64From32(system, args);
case SvcId::ReturnFromException:
- return SvcWrap_ReturnFromException64From32(system);
+ return SvcWrap_ReturnFromException64From32(system, args);
case SvcId::GetInfo:
- return SvcWrap_GetInfo64From32(system);
+ return SvcWrap_GetInfo64From32(system, args);
case SvcId::FlushEntireDataCache:
- return SvcWrap_FlushEntireDataCache64From32(system);
+ return SvcWrap_FlushEntireDataCache64From32(system, args);
case SvcId::FlushDataCache:
- return SvcWrap_FlushDataCache64From32(system);
+ return SvcWrap_FlushDataCache64From32(system, args);
case SvcId::MapPhysicalMemory:
- return SvcWrap_MapPhysicalMemory64From32(system);
+ return SvcWrap_MapPhysicalMemory64From32(system, args);
case SvcId::UnmapPhysicalMemory:
- return SvcWrap_UnmapPhysicalMemory64From32(system);
+ return SvcWrap_UnmapPhysicalMemory64From32(system, args);
case SvcId::GetDebugFutureThreadInfo:
- return SvcWrap_GetDebugFutureThreadInfo64From32(system);
+ return SvcWrap_GetDebugFutureThreadInfo64From32(system, args);
case SvcId::GetLastThreadInfo:
- return SvcWrap_GetLastThreadInfo64From32(system);
+ return SvcWrap_GetLastThreadInfo64From32(system, args);
case SvcId::GetResourceLimitLimitValue:
- return SvcWrap_GetResourceLimitLimitValue64From32(system);
+ return SvcWrap_GetResourceLimitLimitValue64From32(system, args);
case SvcId::GetResourceLimitCurrentValue:
- return SvcWrap_GetResourceLimitCurrentValue64From32(system);
+ return SvcWrap_GetResourceLimitCurrentValue64From32(system, args);
case SvcId::SetThreadActivity:
- return SvcWrap_SetThreadActivity64From32(system);
+ return SvcWrap_SetThreadActivity64From32(system, args);
case SvcId::GetThreadContext3:
- return SvcWrap_GetThreadContext364From32(system);
+ return SvcWrap_GetThreadContext364From32(system, args);
case SvcId::WaitForAddress:
- return SvcWrap_WaitForAddress64From32(system);
+ return SvcWrap_WaitForAddress64From32(system, args);
case SvcId::SignalToAddress:
- return SvcWrap_SignalToAddress64From32(system);
+ return SvcWrap_SignalToAddress64From32(system, args);
case SvcId::SynchronizePreemptionState:
- return SvcWrap_SynchronizePreemptionState64From32(system);
+ return SvcWrap_SynchronizePreemptionState64From32(system, args);
case SvcId::GetResourceLimitPeakValue:
- return SvcWrap_GetResourceLimitPeakValue64From32(system);
+ return SvcWrap_GetResourceLimitPeakValue64From32(system, args);
case SvcId::CreateIoPool:
- return SvcWrap_CreateIoPool64From32(system);
+ return SvcWrap_CreateIoPool64From32(system, args);
case SvcId::CreateIoRegion:
- return SvcWrap_CreateIoRegion64From32(system);
+ return SvcWrap_CreateIoRegion64From32(system, args);
case SvcId::KernelDebug:
- return SvcWrap_KernelDebug64From32(system);
+ return SvcWrap_KernelDebug64From32(system, args);
case SvcId::ChangeKernelTraceState:
- return SvcWrap_ChangeKernelTraceState64From32(system);
+ return SvcWrap_ChangeKernelTraceState64From32(system, args);
case SvcId::CreateSession:
- return SvcWrap_CreateSession64From32(system);
+ return SvcWrap_CreateSession64From32(system, args);
case SvcId::AcceptSession:
- return SvcWrap_AcceptSession64From32(system);
+ return SvcWrap_AcceptSession64From32(system, args);
case SvcId::ReplyAndReceiveLight:
- return SvcWrap_ReplyAndReceiveLight64From32(system);
+ return SvcWrap_ReplyAndReceiveLight64From32(system, args);
case SvcId::ReplyAndReceive:
- return SvcWrap_ReplyAndReceive64From32(system);
+ return SvcWrap_ReplyAndReceive64From32(system, args);
case SvcId::ReplyAndReceiveWithUserBuffer:
- return SvcWrap_ReplyAndReceiveWithUserBuffer64From32(system);
+ return SvcWrap_ReplyAndReceiveWithUserBuffer64From32(system, args);
case SvcId::CreateEvent:
- return SvcWrap_CreateEvent64From32(system);
+ return SvcWrap_CreateEvent64From32(system, args);
case SvcId::MapIoRegion:
- return SvcWrap_MapIoRegion64From32(system);
+ return SvcWrap_MapIoRegion64From32(system, args);
case SvcId::UnmapIoRegion:
- return SvcWrap_UnmapIoRegion64From32(system);
+ return SvcWrap_UnmapIoRegion64From32(system, args);
case SvcId::MapPhysicalMemoryUnsafe:
- return SvcWrap_MapPhysicalMemoryUnsafe64From32(system);
+ return SvcWrap_MapPhysicalMemoryUnsafe64From32(system, args);
case SvcId::UnmapPhysicalMemoryUnsafe:
- return SvcWrap_UnmapPhysicalMemoryUnsafe64From32(system);
+ return SvcWrap_UnmapPhysicalMemoryUnsafe64From32(system, args);
case SvcId::SetUnsafeLimit:
- return SvcWrap_SetUnsafeLimit64From32(system);
+ return SvcWrap_SetUnsafeLimit64From32(system, args);
case SvcId::CreateCodeMemory:
- return SvcWrap_CreateCodeMemory64From32(system);
+ return SvcWrap_CreateCodeMemory64From32(system, args);
case SvcId::ControlCodeMemory:
- return SvcWrap_ControlCodeMemory64From32(system);
+ return SvcWrap_ControlCodeMemory64From32(system, args);
case SvcId::SleepSystem:
- return SvcWrap_SleepSystem64From32(system);
+ return SvcWrap_SleepSystem64From32(system, args);
case SvcId::ReadWriteRegister:
- return SvcWrap_ReadWriteRegister64From32(system);
+ return SvcWrap_ReadWriteRegister64From32(system, args);
case SvcId::SetProcessActivity:
- return SvcWrap_SetProcessActivity64From32(system);
+ return SvcWrap_SetProcessActivity64From32(system, args);
case SvcId::CreateSharedMemory:
- return SvcWrap_CreateSharedMemory64From32(system);
+ return SvcWrap_CreateSharedMemory64From32(system, args);
case SvcId::MapTransferMemory:
- return SvcWrap_MapTransferMemory64From32(system);
+ return SvcWrap_MapTransferMemory64From32(system, args);
case SvcId::UnmapTransferMemory:
- return SvcWrap_UnmapTransferMemory64From32(system);
+ return SvcWrap_UnmapTransferMemory64From32(system, args);
case SvcId::CreateInterruptEvent:
- return SvcWrap_CreateInterruptEvent64From32(system);
+ return SvcWrap_CreateInterruptEvent64From32(system, args);
case SvcId::QueryPhysicalAddress:
- return SvcWrap_QueryPhysicalAddress64From32(system);
+ return SvcWrap_QueryPhysicalAddress64From32(system, args);
case SvcId::QueryIoMapping:
- return SvcWrap_QueryIoMapping64From32(system);
+ return SvcWrap_QueryIoMapping64From32(system, args);
case SvcId::CreateDeviceAddressSpace:
- return SvcWrap_CreateDeviceAddressSpace64From32(system);
+ return SvcWrap_CreateDeviceAddressSpace64From32(system, args);
case SvcId::AttachDeviceAddressSpace:
- return SvcWrap_AttachDeviceAddressSpace64From32(system);
+ return SvcWrap_AttachDeviceAddressSpace64From32(system, args);
case SvcId::DetachDeviceAddressSpace:
- return SvcWrap_DetachDeviceAddressSpace64From32(system);
+ return SvcWrap_DetachDeviceAddressSpace64From32(system, args);
case SvcId::MapDeviceAddressSpaceByForce:
- return SvcWrap_MapDeviceAddressSpaceByForce64From32(system);
+ return SvcWrap_MapDeviceAddressSpaceByForce64From32(system, args);
case SvcId::MapDeviceAddressSpaceAligned:
- return SvcWrap_MapDeviceAddressSpaceAligned64From32(system);
+ return SvcWrap_MapDeviceAddressSpaceAligned64From32(system, args);
case SvcId::UnmapDeviceAddressSpace:
- return SvcWrap_UnmapDeviceAddressSpace64From32(system);
+ return SvcWrap_UnmapDeviceAddressSpace64From32(system, args);
case SvcId::InvalidateProcessDataCache:
- return SvcWrap_InvalidateProcessDataCache64From32(system);
+ return SvcWrap_InvalidateProcessDataCache64From32(system, args);
case SvcId::StoreProcessDataCache:
- return SvcWrap_StoreProcessDataCache64From32(system);
+ return SvcWrap_StoreProcessDataCache64From32(system, args);
case SvcId::FlushProcessDataCache:
- return SvcWrap_FlushProcessDataCache64From32(system);
+ return SvcWrap_FlushProcessDataCache64From32(system, args);
case SvcId::DebugActiveProcess:
- return SvcWrap_DebugActiveProcess64From32(system);
+ return SvcWrap_DebugActiveProcess64From32(system, args);
case SvcId::BreakDebugProcess:
- return SvcWrap_BreakDebugProcess64From32(system);
+ return SvcWrap_BreakDebugProcess64From32(system, args);
case SvcId::TerminateDebugProcess:
- return SvcWrap_TerminateDebugProcess64From32(system);
+ return SvcWrap_TerminateDebugProcess64From32(system, args);
case SvcId::GetDebugEvent:
- return SvcWrap_GetDebugEvent64From32(system);
+ return SvcWrap_GetDebugEvent64From32(system, args);
case SvcId::ContinueDebugEvent:
- return SvcWrap_ContinueDebugEvent64From32(system);
+ return SvcWrap_ContinueDebugEvent64From32(system, args);
case SvcId::GetProcessList:
- return SvcWrap_GetProcessList64From32(system);
+ return SvcWrap_GetProcessList64From32(system, args);
case SvcId::GetThreadList:
- return SvcWrap_GetThreadList64From32(system);
+ return SvcWrap_GetThreadList64From32(system, args);
case SvcId::GetDebugThreadContext:
- return SvcWrap_GetDebugThreadContext64From32(system);
+ return SvcWrap_GetDebugThreadContext64From32(system, args);
case SvcId::SetDebugThreadContext:
- return SvcWrap_SetDebugThreadContext64From32(system);
+ return SvcWrap_SetDebugThreadContext64From32(system, args);
case SvcId::QueryDebugProcessMemory:
- return SvcWrap_QueryDebugProcessMemory64From32(system);
+ return SvcWrap_QueryDebugProcessMemory64From32(system, args);
case SvcId::ReadDebugProcessMemory:
- return SvcWrap_ReadDebugProcessMemory64From32(system);
+ return SvcWrap_ReadDebugProcessMemory64From32(system, args);
case SvcId::WriteDebugProcessMemory:
- return SvcWrap_WriteDebugProcessMemory64From32(system);
+ return SvcWrap_WriteDebugProcessMemory64From32(system, args);
case SvcId::SetHardwareBreakPoint:
- return SvcWrap_SetHardwareBreakPoint64From32(system);
+ return SvcWrap_SetHardwareBreakPoint64From32(system, args);
case SvcId::GetDebugThreadParam:
- return SvcWrap_GetDebugThreadParam64From32(system);
+ return SvcWrap_GetDebugThreadParam64From32(system, args);
case SvcId::GetSystemInfo:
- return SvcWrap_GetSystemInfo64From32(system);
+ return SvcWrap_GetSystemInfo64From32(system, args);
case SvcId::CreatePort:
- return SvcWrap_CreatePort64From32(system);
+ return SvcWrap_CreatePort64From32(system, args);
case SvcId::ManageNamedPort:
- return SvcWrap_ManageNamedPort64From32(system);
+ return SvcWrap_ManageNamedPort64From32(system, args);
case SvcId::ConnectToPort:
- return SvcWrap_ConnectToPort64From32(system);
+ return SvcWrap_ConnectToPort64From32(system, args);
case SvcId::SetProcessMemoryPermission:
- return SvcWrap_SetProcessMemoryPermission64From32(system);
+ return SvcWrap_SetProcessMemoryPermission64From32(system, args);
case SvcId::MapProcessMemory:
- return SvcWrap_MapProcessMemory64From32(system);
+ return SvcWrap_MapProcessMemory64From32(system, args);
case SvcId::UnmapProcessMemory:
- return SvcWrap_UnmapProcessMemory64From32(system);
+ return SvcWrap_UnmapProcessMemory64From32(system, args);
case SvcId::QueryProcessMemory:
- return SvcWrap_QueryProcessMemory64From32(system);
+ return SvcWrap_QueryProcessMemory64From32(system, args);
case SvcId::MapProcessCodeMemory:
- return SvcWrap_MapProcessCodeMemory64From32(system);
+ return SvcWrap_MapProcessCodeMemory64From32(system, args);
case SvcId::UnmapProcessCodeMemory:
- return SvcWrap_UnmapProcessCodeMemory64From32(system);
+ return SvcWrap_UnmapProcessCodeMemory64From32(system, args);
case SvcId::CreateProcess:
- return SvcWrap_CreateProcess64From32(system);
+ return SvcWrap_CreateProcess64From32(system, args);
case SvcId::StartProcess:
- return SvcWrap_StartProcess64From32(system);
+ return SvcWrap_StartProcess64From32(system, args);
case SvcId::TerminateProcess:
- return SvcWrap_TerminateProcess64From32(system);
+ return SvcWrap_TerminateProcess64From32(system, args);
case SvcId::GetProcessInfo:
- return SvcWrap_GetProcessInfo64From32(system);
+ return SvcWrap_GetProcessInfo64From32(system, args);
case SvcId::CreateResourceLimit:
- return SvcWrap_CreateResourceLimit64From32(system);
+ return SvcWrap_CreateResourceLimit64From32(system, args);
case SvcId::SetResourceLimitLimitValue:
- return SvcWrap_SetResourceLimitLimitValue64From32(system);
+ return SvcWrap_SetResourceLimitLimitValue64From32(system, args);
case SvcId::CallSecureMonitor:
- return SvcWrap_CallSecureMonitor64From32(system);
+ return SvcWrap_CallSecureMonitor64From32(system, args);
case SvcId::MapInsecureMemory:
- return SvcWrap_MapInsecureMemory64From32(system);
+ return SvcWrap_MapInsecureMemory64From32(system, args);
case SvcId::UnmapInsecureMemory:
- return SvcWrap_UnmapInsecureMemory64From32(system);
+ return SvcWrap_UnmapInsecureMemory64From32(system, args);
default:
LOG_CRITICAL(Kernel_SVC, "Unknown SVC {:x}!", imm);
break;
}
}
-static void Call64(Core::System& system, u32 imm) {
+static void Call64(Core::System& system, u32 imm, std::span<uint64_t, 8> args) {
switch (static_cast<SvcId>(imm)) {
case SvcId::SetHeapSize:
- return SvcWrap_SetHeapSize64(system);
+ return SvcWrap_SetHeapSize64(system, args);
case SvcId::SetMemoryPermission:
- return SvcWrap_SetMemoryPermission64(system);
+ return SvcWrap_SetMemoryPermission64(system, args);
case SvcId::SetMemoryAttribute:
- return SvcWrap_SetMemoryAttribute64(system);
+ return SvcWrap_SetMemoryAttribute64(system, args);
case SvcId::MapMemory:
- return SvcWrap_MapMemory64(system);
+ return SvcWrap_MapMemory64(system, args);
case SvcId::UnmapMemory:
- return SvcWrap_UnmapMemory64(system);
+ return SvcWrap_UnmapMemory64(system, args);
case SvcId::QueryMemory:
- return SvcWrap_QueryMemory64(system);
+ return SvcWrap_QueryMemory64(system, args);
case SvcId::ExitProcess:
- return SvcWrap_ExitProcess64(system);
+ return SvcWrap_ExitProcess64(system, args);
case SvcId::CreateThread:
- return SvcWrap_CreateThread64(system);
+ return SvcWrap_CreateThread64(system, args);
case SvcId::StartThread:
- return SvcWrap_StartThread64(system);
+ return SvcWrap_StartThread64(system, args);
case SvcId::ExitThread:
- return SvcWrap_ExitThread64(system);
+ return SvcWrap_ExitThread64(system, args);
case SvcId::SleepThread:
- return SvcWrap_SleepThread64(system);
+ return SvcWrap_SleepThread64(system, args);
case SvcId::GetThreadPriority:
- return SvcWrap_GetThreadPriority64(system);
+ return SvcWrap_GetThreadPriority64(system, args);
case SvcId::SetThreadPriority:
- return SvcWrap_SetThreadPriority64(system);
+ return SvcWrap_SetThreadPriority64(system, args);
case SvcId::GetThreadCoreMask:
- return SvcWrap_GetThreadCoreMask64(system);
+ return SvcWrap_GetThreadCoreMask64(system, args);
case SvcId::SetThreadCoreMask:
- return SvcWrap_SetThreadCoreMask64(system);
+ return SvcWrap_SetThreadCoreMask64(system, args);
case SvcId::GetCurrentProcessorNumber:
- return SvcWrap_GetCurrentProcessorNumber64(system);
+ return SvcWrap_GetCurrentProcessorNumber64(system, args);
case SvcId::SignalEvent:
- return SvcWrap_SignalEvent64(system);
+ return SvcWrap_SignalEvent64(system, args);
case SvcId::ClearEvent:
- return SvcWrap_ClearEvent64(system);
+ return SvcWrap_ClearEvent64(system, args);
case SvcId::MapSharedMemory:
- return SvcWrap_MapSharedMemory64(system);
+ return SvcWrap_MapSharedMemory64(system, args);
case SvcId::UnmapSharedMemory:
- return SvcWrap_UnmapSharedMemory64(system);
+ return SvcWrap_UnmapSharedMemory64(system, args);
case SvcId::CreateTransferMemory:
- return SvcWrap_CreateTransferMemory64(system);
+ return SvcWrap_CreateTransferMemory64(system, args);
case SvcId::CloseHandle:
- return SvcWrap_CloseHandle64(system);
+ return SvcWrap_CloseHandle64(system, args);
case SvcId::ResetSignal:
- return SvcWrap_ResetSignal64(system);
+ return SvcWrap_ResetSignal64(system, args);
case SvcId::WaitSynchronization:
- return SvcWrap_WaitSynchronization64(system);
+ return SvcWrap_WaitSynchronization64(system, args);
case SvcId::CancelSynchronization:
- return SvcWrap_CancelSynchronization64(system);
+ return SvcWrap_CancelSynchronization64(system, args);
case SvcId::ArbitrateLock:
- return SvcWrap_ArbitrateLock64(system);
+ return SvcWrap_ArbitrateLock64(system, args);
case SvcId::ArbitrateUnlock:
- return SvcWrap_ArbitrateUnlock64(system);
+ return SvcWrap_ArbitrateUnlock64(system, args);
case SvcId::WaitProcessWideKeyAtomic:
- return SvcWrap_WaitProcessWideKeyAtomic64(system);
+ return SvcWrap_WaitProcessWideKeyAtomic64(system, args);
case SvcId::SignalProcessWideKey:
- return SvcWrap_SignalProcessWideKey64(system);
+ return SvcWrap_SignalProcessWideKey64(system, args);
case SvcId::GetSystemTick:
- return SvcWrap_GetSystemTick64(system);
+ return SvcWrap_GetSystemTick64(system, args);
case SvcId::ConnectToNamedPort:
- return SvcWrap_ConnectToNamedPort64(system);
+ return SvcWrap_ConnectToNamedPort64(system, args);
case SvcId::SendSyncRequestLight:
- return SvcWrap_SendSyncRequestLight64(system);
+ return SvcWrap_SendSyncRequestLight64(system, args);
case SvcId::SendSyncRequest:
- return SvcWrap_SendSyncRequest64(system);
+ return SvcWrap_SendSyncRequest64(system, args);
case SvcId::SendSyncRequestWithUserBuffer:
- return SvcWrap_SendSyncRequestWithUserBuffer64(system);
+ return SvcWrap_SendSyncRequestWithUserBuffer64(system, args);
case SvcId::SendAsyncRequestWithUserBuffer:
- return SvcWrap_SendAsyncRequestWithUserBuffer64(system);
+ return SvcWrap_SendAsyncRequestWithUserBuffer64(system, args);
case SvcId::GetProcessId:
- return SvcWrap_GetProcessId64(system);
+ return SvcWrap_GetProcessId64(system, args);
case SvcId::GetThreadId:
- return SvcWrap_GetThreadId64(system);
+ return SvcWrap_GetThreadId64(system, args);
case SvcId::Break:
- return SvcWrap_Break64(system);
+ return SvcWrap_Break64(system, args);
case SvcId::OutputDebugString:
- return SvcWrap_OutputDebugString64(system);
+ return SvcWrap_OutputDebugString64(system, args);
case SvcId::ReturnFromException:
- return SvcWrap_ReturnFromException64(system);
+ return SvcWrap_ReturnFromException64(system, args);
case SvcId::GetInfo:
- return SvcWrap_GetInfo64(system);
+ return SvcWrap_GetInfo64(system, args);
case SvcId::FlushEntireDataCache:
- return SvcWrap_FlushEntireDataCache64(system);
+ return SvcWrap_FlushEntireDataCache64(system, args);
case SvcId::FlushDataCache:
- return SvcWrap_FlushDataCache64(system);
+ return SvcWrap_FlushDataCache64(system, args);
case SvcId::MapPhysicalMemory:
- return SvcWrap_MapPhysicalMemory64(system);
+ return SvcWrap_MapPhysicalMemory64(system, args);
case SvcId::UnmapPhysicalMemory:
- return SvcWrap_UnmapPhysicalMemory64(system);
+ return SvcWrap_UnmapPhysicalMemory64(system, args);
case SvcId::GetDebugFutureThreadInfo:
- return SvcWrap_GetDebugFutureThreadInfo64(system);
+ return SvcWrap_GetDebugFutureThreadInfo64(system, args);
case SvcId::GetLastThreadInfo:
- return SvcWrap_GetLastThreadInfo64(system);
+ return SvcWrap_GetLastThreadInfo64(system, args);
case SvcId::GetResourceLimitLimitValue:
- return SvcWrap_GetResourceLimitLimitValue64(system);
+ return SvcWrap_GetResourceLimitLimitValue64(system, args);
case SvcId::GetResourceLimitCurrentValue:
- return SvcWrap_GetResourceLimitCurrentValue64(system);
+ return SvcWrap_GetResourceLimitCurrentValue64(system, args);
case SvcId::SetThreadActivity:
- return SvcWrap_SetThreadActivity64(system);
+ return SvcWrap_SetThreadActivity64(system, args);
case SvcId::GetThreadContext3:
- return SvcWrap_GetThreadContext364(system);
+ return SvcWrap_GetThreadContext364(system, args);
case SvcId::WaitForAddress:
- return SvcWrap_WaitForAddress64(system);
+ return SvcWrap_WaitForAddress64(system, args);
case SvcId::SignalToAddress:
- return SvcWrap_SignalToAddress64(system);
+ return SvcWrap_SignalToAddress64(system, args);
case SvcId::SynchronizePreemptionState:
- return SvcWrap_SynchronizePreemptionState64(system);
+ return SvcWrap_SynchronizePreemptionState64(system, args);
case SvcId::GetResourceLimitPeakValue:
- return SvcWrap_GetResourceLimitPeakValue64(system);
+ return SvcWrap_GetResourceLimitPeakValue64(system, args);
case SvcId::CreateIoPool:
- return SvcWrap_CreateIoPool64(system);
+ return SvcWrap_CreateIoPool64(system, args);
case SvcId::CreateIoRegion:
- return SvcWrap_CreateIoRegion64(system);
+ return SvcWrap_CreateIoRegion64(system, args);
case SvcId::KernelDebug:
- return SvcWrap_KernelDebug64(system);
+ return SvcWrap_KernelDebug64(system, args);
case SvcId::ChangeKernelTraceState:
- return SvcWrap_ChangeKernelTraceState64(system);
+ return SvcWrap_ChangeKernelTraceState64(system, args);
case SvcId::CreateSession:
- return SvcWrap_CreateSession64(system);
+ return SvcWrap_CreateSession64(system, args);
case SvcId::AcceptSession:
- return SvcWrap_AcceptSession64(system);
+ return SvcWrap_AcceptSession64(system, args);
case SvcId::ReplyAndReceiveLight:
- return SvcWrap_ReplyAndReceiveLight64(system);
+ return SvcWrap_ReplyAndReceiveLight64(system, args);
case SvcId::ReplyAndReceive:
- return SvcWrap_ReplyAndReceive64(system);
+ return SvcWrap_ReplyAndReceive64(system, args);
case SvcId::ReplyAndReceiveWithUserBuffer:
- return SvcWrap_ReplyAndReceiveWithUserBuffer64(system);
+ return SvcWrap_ReplyAndReceiveWithUserBuffer64(system, args);
case SvcId::CreateEvent:
- return SvcWrap_CreateEvent64(system);
+ return SvcWrap_CreateEvent64(system, args);
case SvcId::MapIoRegion:
- return SvcWrap_MapIoRegion64(system);
+ return SvcWrap_MapIoRegion64(system, args);
case SvcId::UnmapIoRegion:
- return SvcWrap_UnmapIoRegion64(system);
+ return SvcWrap_UnmapIoRegion64(system, args);
case SvcId::MapPhysicalMemoryUnsafe:
- return SvcWrap_MapPhysicalMemoryUnsafe64(system);
+ return SvcWrap_MapPhysicalMemoryUnsafe64(system, args);
case SvcId::UnmapPhysicalMemoryUnsafe:
- return SvcWrap_UnmapPhysicalMemoryUnsafe64(system);
+ return SvcWrap_UnmapPhysicalMemoryUnsafe64(system, args);
case SvcId::SetUnsafeLimit:
- return SvcWrap_SetUnsafeLimit64(system);
+ return SvcWrap_SetUnsafeLimit64(system, args);
case SvcId::CreateCodeMemory:
- return SvcWrap_CreateCodeMemory64(system);
+ return SvcWrap_CreateCodeMemory64(system, args);
case SvcId::ControlCodeMemory:
- return SvcWrap_ControlCodeMemory64(system);
+ return SvcWrap_ControlCodeMemory64(system, args);
case SvcId::SleepSystem:
- return SvcWrap_SleepSystem64(system);
+ return SvcWrap_SleepSystem64(system, args);
case SvcId::ReadWriteRegister:
- return SvcWrap_ReadWriteRegister64(system);
+ return SvcWrap_ReadWriteRegister64(system, args);
case SvcId::SetProcessActivity:
- return SvcWrap_SetProcessActivity64(system);
+ return SvcWrap_SetProcessActivity64(system, args);
case SvcId::CreateSharedMemory:
- return SvcWrap_CreateSharedMemory64(system);
+ return SvcWrap_CreateSharedMemory64(system, args);
case SvcId::MapTransferMemory:
- return SvcWrap_MapTransferMemory64(system);
+ return SvcWrap_MapTransferMemory64(system, args);
case SvcId::UnmapTransferMemory:
- return SvcWrap_UnmapTransferMemory64(system);
+ return SvcWrap_UnmapTransferMemory64(system, args);
case SvcId::CreateInterruptEvent:
- return SvcWrap_CreateInterruptEvent64(system);
+ return SvcWrap_CreateInterruptEvent64(system, args);
case SvcId::QueryPhysicalAddress:
- return SvcWrap_QueryPhysicalAddress64(system);
+ return SvcWrap_QueryPhysicalAddress64(system, args);
case SvcId::QueryIoMapping:
- return SvcWrap_QueryIoMapping64(system);
+ return SvcWrap_QueryIoMapping64(system, args);
case SvcId::CreateDeviceAddressSpace:
- return SvcWrap_CreateDeviceAddressSpace64(system);
+ return SvcWrap_CreateDeviceAddressSpace64(system, args);
case SvcId::AttachDeviceAddressSpace:
- return SvcWrap_AttachDeviceAddressSpace64(system);
+ return SvcWrap_AttachDeviceAddressSpace64(system, args);
case SvcId::DetachDeviceAddressSpace:
- return SvcWrap_DetachDeviceAddressSpace64(system);
+ return SvcWrap_DetachDeviceAddressSpace64(system, args);
case SvcId::MapDeviceAddressSpaceByForce:
- return SvcWrap_MapDeviceAddressSpaceByForce64(system);
+ return SvcWrap_MapDeviceAddressSpaceByForce64(system, args);
case SvcId::MapDeviceAddressSpaceAligned:
- return SvcWrap_MapDeviceAddressSpaceAligned64(system);
+ return SvcWrap_MapDeviceAddressSpaceAligned64(system, args);
case SvcId::UnmapDeviceAddressSpace:
- return SvcWrap_UnmapDeviceAddressSpace64(system);
+ return SvcWrap_UnmapDeviceAddressSpace64(system, args);
case SvcId::InvalidateProcessDataCache:
- return SvcWrap_InvalidateProcessDataCache64(system);
+ return SvcWrap_InvalidateProcessDataCache64(system, args);
case SvcId::StoreProcessDataCache:
- return SvcWrap_StoreProcessDataCache64(system);
+ return SvcWrap_StoreProcessDataCache64(system, args);
case SvcId::FlushProcessDataCache:
- return SvcWrap_FlushProcessDataCache64(system);
+ return SvcWrap_FlushProcessDataCache64(system, args);
case SvcId::DebugActiveProcess:
- return SvcWrap_DebugActiveProcess64(system);
+ return SvcWrap_DebugActiveProcess64(system, args);
case SvcId::BreakDebugProcess:
- return SvcWrap_BreakDebugProcess64(system);
+ return SvcWrap_BreakDebugProcess64(system, args);
case SvcId::TerminateDebugProcess:
- return SvcWrap_TerminateDebugProcess64(system);
+ return SvcWrap_TerminateDebugProcess64(system, args);
case SvcId::GetDebugEvent:
- return SvcWrap_GetDebugEvent64(system);
+ return SvcWrap_GetDebugEvent64(system, args);
case SvcId::ContinueDebugEvent:
- return SvcWrap_ContinueDebugEvent64(system);
+ return SvcWrap_ContinueDebugEvent64(system, args);
case SvcId::GetProcessList:
- return SvcWrap_GetProcessList64(system);
+ return SvcWrap_GetProcessList64(system, args);
case SvcId::GetThreadList:
- return SvcWrap_GetThreadList64(system);
+ return SvcWrap_GetThreadList64(system, args);
case SvcId::GetDebugThreadContext:
- return SvcWrap_GetDebugThreadContext64(system);
+ return SvcWrap_GetDebugThreadContext64(system, args);
case SvcId::SetDebugThreadContext:
- return SvcWrap_SetDebugThreadContext64(system);
+ return SvcWrap_SetDebugThreadContext64(system, args);
case SvcId::QueryDebugProcessMemory:
- return SvcWrap_QueryDebugProcessMemory64(system);
+ return SvcWrap_QueryDebugProcessMemory64(system, args);
case SvcId::ReadDebugProcessMemory:
- return SvcWrap_ReadDebugProcessMemory64(system);
+ return SvcWrap_ReadDebugProcessMemory64(system, args);
case SvcId::WriteDebugProcessMemory:
- return SvcWrap_WriteDebugProcessMemory64(system);
+ return SvcWrap_WriteDebugProcessMemory64(system, args);
case SvcId::SetHardwareBreakPoint:
- return SvcWrap_SetHardwareBreakPoint64(system);
+ return SvcWrap_SetHardwareBreakPoint64(system, args);
case SvcId::GetDebugThreadParam:
- return SvcWrap_GetDebugThreadParam64(system);
+ return SvcWrap_GetDebugThreadParam64(system, args);
case SvcId::GetSystemInfo:
- return SvcWrap_GetSystemInfo64(system);
+ return SvcWrap_GetSystemInfo64(system, args);
case SvcId::CreatePort:
- return SvcWrap_CreatePort64(system);
+ return SvcWrap_CreatePort64(system, args);
case SvcId::ManageNamedPort:
- return SvcWrap_ManageNamedPort64(system);
+ return SvcWrap_ManageNamedPort64(system, args);
case SvcId::ConnectToPort:
- return SvcWrap_ConnectToPort64(system);
+ return SvcWrap_ConnectToPort64(system, args);
case SvcId::SetProcessMemoryPermission:
- return SvcWrap_SetProcessMemoryPermission64(system);
+ return SvcWrap_SetProcessMemoryPermission64(system, args);
case SvcId::MapProcessMemory:
- return SvcWrap_MapProcessMemory64(system);
+ return SvcWrap_MapProcessMemory64(system, args);
case SvcId::UnmapProcessMemory:
- return SvcWrap_UnmapProcessMemory64(system);
+ return SvcWrap_UnmapProcessMemory64(system, args);
case SvcId::QueryProcessMemory:
- return SvcWrap_QueryProcessMemory64(system);
+ return SvcWrap_QueryProcessMemory64(system, args);
case SvcId::MapProcessCodeMemory:
- return SvcWrap_MapProcessCodeMemory64(system);
+ return SvcWrap_MapProcessCodeMemory64(system, args);
case SvcId::UnmapProcessCodeMemory:
- return SvcWrap_UnmapProcessCodeMemory64(system);
+ return SvcWrap_UnmapProcessCodeMemory64(system, args);
case SvcId::CreateProcess:
- return SvcWrap_CreateProcess64(system);
+ return SvcWrap_CreateProcess64(system, args);
case SvcId::StartProcess:
- return SvcWrap_StartProcess64(system);
+ return SvcWrap_StartProcess64(system, args);
case SvcId::TerminateProcess:
- return SvcWrap_TerminateProcess64(system);
+ return SvcWrap_TerminateProcess64(system, args);
case SvcId::GetProcessInfo:
- return SvcWrap_GetProcessInfo64(system);
+ return SvcWrap_GetProcessInfo64(system, args);
case SvcId::CreateResourceLimit:
- return SvcWrap_CreateResourceLimit64(system);
+ return SvcWrap_CreateResourceLimit64(system, args);
case SvcId::SetResourceLimitLimitValue:
- return SvcWrap_SetResourceLimitLimitValue64(system);
+ return SvcWrap_SetResourceLimitLimitValue64(system, args);
case SvcId::CallSecureMonitor:
- return SvcWrap_CallSecureMonitor64(system);
+ return SvcWrap_CallSecureMonitor64(system, args);
case SvcId::MapInsecureMemory:
- return SvcWrap_MapInsecureMemory64(system);
+ return SvcWrap_MapInsecureMemory64(system, args);
case SvcId::UnmapInsecureMemory:
- return SvcWrap_UnmapInsecureMemory64(system);
+ return SvcWrap_UnmapInsecureMemory64(system, args);
default:
LOG_CRITICAL(Kernel_SVC, "Unknown SVC {:x}!", imm);
break;
@@ -4424,15 +4424,20 @@ static void Call64(Core::System& system, u32 imm) {
void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
+ auto& process = GetCurrentProcess(kernel);
+
+ std::array<uint64_t, 8> args;
+ kernel.CurrentPhysicalCore().SaveSvcArguments(process, args);
kernel.EnterSVCProfile();
- if (GetCurrentProcess(system.Kernel()).Is64Bit()) {
- Call64(system, imm);
+ if (process.Is64Bit()) {
+ Call64(system, imm, args);
} else {
- Call32(system, imm);
+ Call32(system, imm, args);
}
kernel.ExitSVCProfile();
+ kernel.CurrentPhysicalCore().LoadSvcArguments(process, args);
}
} // namespace Kernel::Svc
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h
index ac4696008..828f39611 100644
--- a/src/core/hle/kernel/svc.h
+++ b/src/core/hle/kernel/svc.h
@@ -9,6 +9,8 @@ namespace Core {
class System;
}
+#include <span>
+
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
@@ -520,15 +522,15 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
-void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
-void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
+void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args);
-void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
-void SvcWrap_SendSyncRequestLight64(Core::System& system);
+void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args);
// Defined in svc_secure_monitor_call.cpp.
-void SvcWrap_CallSecureMonitor64From32(Core::System& system);
-void SvcWrap_CallSecureMonitor64(Core::System& system);
+void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp
index c581c086b..47b756828 100644
--- a/src/core/hle/kernel/svc/svc_exception.cpp
+++ b/src/core/hle/kernel/svc/svc_exception.cpp
@@ -103,9 +103,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
handle_debug_buffer(info1, info2);
- auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
- const auto thread_processor_id = current_thread->GetActiveCore();
- system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
+ system.CurrentPhysicalCore().LogBacktrace();
}
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 6b5e1cb8d..47a3e7bb0 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -7,59 +7,127 @@
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {
-/// Makes a blocking IPC call to a service.
-Result SendSyncRequest(Core::System& system, Handle handle) {
- // Get the client session from its handle.
+namespace {
+
+Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size,
+ Handle session_handle) {
+ // Get the client session.
KScopedAutoObject session =
- GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle);
+ GetCurrentProcess(kernel).GetHandleTable().GetObject<KClientSession>(session_handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
- LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
+ // Get the parent, and persist a reference to it until we're done.
+ KScopedAutoObject parent = session->GetParent();
+ ASSERT(parent.IsNotNull());
- R_RETURN(session->SendSyncRequest());
+ // Send the request.
+ R_RETURN(session->SendSyncRequest(message, buffer_size));
}
-Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer,
- uint64_t message_buffer_size, Handle session_handle) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
-}
+Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message,
+ size_t buffer_size, KPhysicalAddress message_paddr,
+ KSynchronizationObject** objs, int32_t num_objects, Handle reply_target,
+ int64_t timeout_ns) {
+ // Reply to the target, if one is specified.
+ if (reply_target != InvalidHandle) {
+ KScopedAutoObject session =
+ GetCurrentProcess(kernel).GetHandleTable().GetObject<KServerSession>(reply_target);
+ R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
-Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle,
- uint64_t message_buffer, uint64_t message_buffer_size,
- Handle session_handle) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+ // If we fail to reply, we want to set the output index to -1.
+ ON_RESULT_FAILURE {
+ *out_index = -1;
+ };
+
+ // Send the reply.
+ R_TRY(session->SendReply());
+ // R_TRY(session->SendReply(message, buffer_size, message_paddr));
+ }
+
+ // Receive a message.
+ {
+ // Convert the timeout from nanoseconds to ticks.
+ // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
+ s64 timeout;
+ if (timeout_ns > 0) {
+ const s64 offset_tick(timeout_ns);
+ if (offset_tick > 0) {
+ timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
+ if (timeout <= 0) {
+ timeout = std::numeric_limits<s64>::max();
+ }
+ } else {
+ timeout = std::numeric_limits<s64>::max();
+ }
+ } else {
+ timeout = timeout_ns;
+ }
+
+ // Wait for a message.
+ while (true) {
+ // Wait for an object.
+ s32 index;
+ Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs,
+ num_objects, timeout);
+ if (ResultTimedOut == result) {
+ R_THROW(result);
+ }
+
+ // Receive the request.
+ if (R_SUCCEEDED(result)) {
+ KServerSession* session = objs[index]->DynamicCast<KServerSession*>();
+ if (session != nullptr) {
+ // result = session->ReceiveRequest(message, buffer_size, message_paddr);
+ result = session->ReceiveRequest();
+ if (ResultNotFound == result) {
+ continue;
+ }
+ }
+ }
+
+ *out_index = index;
+ R_RETURN(result);
+ }
+ }
}
-Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
- Handle reply_target, s64 timeout_ns) {
+Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message,
+ size_t buffer_size, KPhysicalAddress message_paddr,
+ KProcessAddress user_handles, int32_t num_handles, Handle reply_target,
+ int64_t timeout_ns) {
// Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
// Get the synchronization context.
- auto& kernel = system.Kernel();
- auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
- auto handles = GetCurrentThread(kernel).GetHandleBuffer();
+ auto& process = GetCurrentProcess(kernel);
+ auto& thread = GetCurrentThread(kernel);
+ auto& handle_table = process.GetHandleTable();
+ KSynchronizationObject** objs = thread.GetSynchronizationObjectBuffer().data();
+ Handle* handles = thread.GetHandleBuffer().data();
// Copy user handles.
if (num_handles > 0) {
- // Get the handles.
- R_UNLESS(GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
- sizeof(Handle) * num_handles),
+ // Ensure that we can try to get the handles.
+ R_UNLESS(process.GetPageTable().Contains(user_handles, num_handles * sizeof(Handle)),
ResultInvalidPointer);
+ // Get the handles
+ R_UNLESS(
+ GetCurrentMemory(kernel).ReadBlock(user_handles, handles, sizeof(Handle) * num_handles),
+ ResultInvalidPointer);
+
// Convert the handles to objects.
- R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
- objs.data(), handles.data(), num_handles),
- ResultInvalidHandle);
+ R_UNLESS(
+ handle_table.GetMultipleObjects<KSynchronizationObject>(objs, handles, num_handles),
+ ResultInvalidHandle);
}
// Ensure handles are closed when we're done.
@@ -69,69 +137,135 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
}
});
- // Reply to the target, if one is specified.
- if (reply_target != InvalidHandle) {
- KScopedAutoObject session = handle_table.GetObject<KServerSession>(reply_target);
- R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
+ R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs,
+ num_handles, reply_target, timeout_ns));
+}
- // If we fail to reply, we want to set the output index to -1.
+} // namespace
+
+/// Makes a blocking IPC call to a service.
+Result SendSyncRequest(Core::System& system, Handle session_handle) {
+ R_RETURN(SendSyncRequestImpl(system.Kernel(), 0, 0, session_handle));
+}
+
+Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message, uint64_t buffer_size,
+ Handle session_handle) {
+ auto& kernel = system.Kernel();
+
+ // Validate that the message buffer is page aligned and does not overflow.
+ R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress);
+ R_UNLESS(buffer_size > 0, ResultInvalidSize);
+ R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize);
+ R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory);
+
+ // Get the process page table.
+ auto& page_table = GetCurrentProcess(kernel).GetPageTable();
+
+ // Lock the message buffer.
+ R_TRY(page_table.LockForIpcUserBuffer(nullptr, message, buffer_size));
+
+ {
+ // If we fail to send the message, unlock the message buffer.
ON_RESULT_FAILURE {
- *out_index = -1;
+ page_table.UnlockForIpcUserBuffer(message, buffer_size);
};
- // Send the reply.
- R_TRY(session->SendReply());
+ // Send the request.
+ ASSERT(message != 0);
+ R_TRY(SendSyncRequestImpl(kernel, message, buffer_size, session_handle));
}
- // Convert the timeout from nanoseconds to ticks.
- // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
- s64 timeout;
- if (timeout_ns > 0) {
- const s64 offset_tick(timeout_ns);
- if (offset_tick > 0) {
- timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
- if (timeout <= 0) {
- timeout = std::numeric_limits<s64>::max();
- }
- } else {
- timeout = std::numeric_limits<s64>::max();
- }
- } else {
- timeout = timeout_ns;
- }
+ // We successfully processed, so try to unlock the message buffer.
+ R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size));
+}
- // Wait for a message.
- while (true) {
- // Wait for an object.
- s32 index;
- Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
- num_handles, timeout);
- if (result == ResultTimedOut) {
- R_RETURN(result);
- }
+Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle,
+ uint64_t message, uint64_t buffer_size,
+ Handle session_handle) {
+ // Get the process and handle table.
+ auto& process = GetCurrentProcess(system.Kernel());
+ auto& handle_table = process.GetHandleTable();
- // Receive the request.
- if (R_SUCCEEDED(result)) {
- KServerSession* session = objs[index]->DynamicCast<KServerSession*>();
- if (session != nullptr) {
- result = session->ReceiveRequest();
- if (result == ResultNotFound) {
- continue;
- }
- }
- }
+ // Reserve a new event from the process resource limit.
+ KScopedResourceReservation event_reservation(std::addressof(process),
+ Svc::LimitableResource::EventCountMax);
+ R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);
- *out_index = index;
- R_RETURN(result);
- }
+ // Get the client session.
+ KScopedAutoObject session = process.GetHandleTable().GetObject<KClientSession>(session_handle);
+ R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
+
+ // Get the parent, and persist a reference to it until we're done.
+ KScopedAutoObject parent = session->GetParent();
+ ASSERT(parent.IsNotNull());
+
+ // Create a new event.
+ KEvent* event = KEvent::Create(system.Kernel());
+ R_UNLESS(event != nullptr, ResultOutOfResource);
+
+ // Initialize the event.
+ event->Initialize(std::addressof(process));
+
+ // Commit our reservation.
+ event_reservation.Commit();
+
+ // At end of scope, kill the standing references to the sub events.
+ SCOPE_EXIT({
+ event->GetReadableEvent().Close();
+ event->Close();
+ });
+
+ // Register the event.
+ KEvent::Register(system.Kernel(), event);
+
+ // Add the readable event to the handle table.
+ R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent())));
+
+ // Ensure that if we fail to send the request, we close the readable handle.
+ ON_RESULT_FAILURE {
+ handle_table.Remove(*out_event_handle);
+ };
+
+ // Send the async request.
+ R_RETURN(session->SendAsyncRequest(event, message, buffer_size));
}
-Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index,
- uint64_t message_buffer, uint64_t message_buffer_size,
- uint64_t handles, int32_t num_handles, Handle reply_target,
- int64_t timeout_ns) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles,
+ Handle reply_target, s64 timeout_ns) {
+ R_RETURN(ReplyAndReceiveImpl(system.Kernel(), out_index, 0, 0, 0, handles, num_handles,
+ reply_target, timeout_ns));
+}
+
+Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, uint64_t message,
+ uint64_t buffer_size, uint64_t handles, int32_t num_handles,
+ Handle reply_target, int64_t timeout_ns) {
+ // Validate that the message buffer is page aligned and does not overflow.
+ R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress);
+ R_UNLESS(buffer_size > 0, ResultInvalidSize);
+ R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize);
+ R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory);
+
+ // Get the process page table.
+ auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();
+
+ // Lock the message buffer, getting its physical address.
+ KPhysicalAddress message_paddr;
+ R_TRY(page_table.LockForIpcUserBuffer(std::addressof(message_paddr), message, buffer_size));
+
+ {
+ // If we fail to send the message, unlock the message buffer.
+ ON_RESULT_FAILURE {
+ page_table.UnlockForIpcUserBuffer(message, buffer_size);
+ };
+
+ // Reply/Receive the request.
+ ASSERT(message != 0);
+ R_TRY(ReplyAndReceiveImpl(system.Kernel(), out_index, message, buffer_size, message_paddr,
+ handles, num_handles, reply_target, timeout_ns));
+ }
+
+ // We successfully processed, so try to unlock the message buffer.
+ R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size));
}
Result SendSyncRequest64(Core::System& system, Handle session_handle) {
diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp
index b76ce984c..4772cbda1 100644
--- a/src/core/hle/kernel/svc/svc_light_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp
@@ -1,21 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/arm/arm_interface.h"
#include "core/core.h"
+#include "core/hle/kernel/k_light_client_session.h"
+#include "core/hle/kernel/k_light_server_session.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {
Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+ // Get the light client session from its handle.
+ KScopedAutoObject session = GetCurrentProcess(system.Kernel())
+ .GetHandleTable()
+ .GetObject<KLightClientSession>(session_handle);
+ R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
+
+ // Send the request.
+ R_TRY(session->SendSyncRequest(args));
+
+ R_SUCCEED();
}
Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+ // Get the light server session from its handle.
+ KScopedAutoObject session = GetCurrentProcess(system.Kernel())
+ .GetHandleTable()
+ .GetObject<KLightServerSession>(session_handle);
+ R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
+
+ // Handle the request.
+ R_TRY(session->ReplyAndReceive(args));
+
+ R_SUCCEED();
}
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) {
@@ -37,37 +56,36 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle,
// Custom ABI implementation for light IPC.
template <typename F>
-static void SvcWrap_LightIpc(Core::System& system, F&& cb) {
- auto& core = system.CurrentArmInterface();
- std::array<u32, 7> arguments{};
+static void SvcWrap_LightIpc(Core::System& system, std::span<uint64_t, 8> args, F&& cb) {
+ std::array<u32, 7> ipc_args{};
- Handle session_handle = static_cast<Handle>(core.GetReg(0));
+ Handle session_handle = static_cast<Handle>(args[0]);
for (int i = 0; i < 7; i++) {
- arguments[i] = static_cast<u32>(core.GetReg(i + 1));
+ ipc_args[i] = static_cast<u32>(args[i + 1]);
}
- Result ret = cb(system, session_handle, arguments.data());
+ Result ret = cb(system, session_handle, ipc_args.data());
- core.SetReg(0, ret.raw);
+ args[0] = ret.raw;
for (int i = 0; i < 7; i++) {
- core.SetReg(i + 1, arguments[i]);
+ args[i + 1] = ipc_args[i];
}
}
-void SvcWrap_SendSyncRequestLight64(Core::System& system) {
- SvcWrap_LightIpc(system, SendSyncRequestLight64);
+void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args) {
+ SvcWrap_LightIpc(system, args, SendSyncRequestLight64);
}
-void SvcWrap_ReplyAndReceiveLight64(Core::System& system) {
- SvcWrap_LightIpc(system, ReplyAndReceiveLight64);
+void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args) {
+ SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64);
}
-void SvcWrap_SendSyncRequestLight64From32(Core::System& system) {
- SvcWrap_LightIpc(system, SendSyncRequestLight64From32);
+void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
+ SvcWrap_LightIpc(system, args, SendSyncRequestLight64From32);
}
-void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system) {
- SvcWrap_LightIpc(system, ReplyAndReceiveLight64From32);
+void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
+ SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64From32);
}
} // namespace Kernel::Svc
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index abba757c7..737749f7d 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -5,6 +5,7 @@
#include "core/core.h"
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
+#include "core/hle/kernel/k_light_client_session.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
@@ -51,13 +52,73 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) {
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
int32_t max_sessions, bool is_light, uint64_t name) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+ auto& kernel = system.Kernel();
+
+ // Ensure max sessions is valid.
+ R_UNLESS(max_sessions > 0, ResultOutOfRange);
+
+ // Get the current handle table.
+ auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
+
+ // Create a new port.
+ KPort* port = KPort::Create(kernel);
+ R_UNLESS(port != nullptr, ResultOutOfResource);
+
+ // Initialize the port.
+ port->Initialize(max_sessions, is_light, name);
+
+ // Ensure that we clean up the port (and its only references are handle table) on function end.
+ SCOPE_EXIT({
+ port->GetServerPort().Close();
+ port->GetClientPort().Close();
+ });
+
+ // Register the port.
+ KPort::Register(kernel, port);
+
+ // Add the client to the handle table.
+ R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort())));
+
+ // Ensure that we maintain a clean handle state on exit.
+ ON_RESULT_FAILURE {
+ handle_table.Remove(*out_client);
+ };
+
+ // Add the server to the handle table.
+ R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort())));
}
-Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+Result ConnectToPort(Core::System& system, Handle* out, Handle port) {
+ // Get the current handle table.
+ auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
+
+ // Get the client port.
+ KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(port);
+ R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle);
+
+ // Reserve a handle for the port.
+ // NOTE: Nintendo really does write directly to the output handle here.
+ R_TRY(handle_table.Reserve(out));
+ ON_RESULT_FAILURE {
+ handle_table.Unreserve(*out);
+ };
+
+ // Create the session.
+ KAutoObject* session;
+ if (client_port->IsLight()) {
+ R_TRY(client_port->CreateLightSession(
+ reinterpret_cast<KLightClientSession**>(std::addressof(session))));
+ } else {
+ R_TRY(client_port->CreateSession(
+ reinterpret_cast<KClientSession**>(std::addressof(session))));
+ }
+
+ // Register the session.
+ handle_table.Register(*out, session);
+ session->Close();
+
+ // We succeeded.
+ R_SUCCEED();
}
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
diff --git a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
index 62c781551..48b564ec8 100644
--- a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
+++ b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
@@ -22,31 +22,29 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
// Custom ABI for CallSecureMonitor.
-void SvcWrap_CallSecureMonitor64(Core::System& system) {
- auto& core = system.CurrentPhysicalCore().ArmInterface();
- lp64::SecureMonitorArguments args{};
+void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args) {
+ lp64::SecureMonitorArguments smc_args{};
for (int i = 0; i < 8; i++) {
- args.r[i] = core.GetReg(i);
+ smc_args.r[i] = args[i];
}
- CallSecureMonitor64(system, std::addressof(args));
+ CallSecureMonitor64(system, std::addressof(smc_args));
for (int i = 0; i < 8; i++) {
- core.SetReg(i, args.r[i]);
+ args[i] = smc_args.r[i];
}
}
-void SvcWrap_CallSecureMonitor64From32(Core::System& system) {
- auto& core = system.CurrentPhysicalCore().ArmInterface();
- ilp32::SecureMonitorArguments args{};
+void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args) {
+ ilp32::SecureMonitorArguments smc_args{};
for (int i = 0; i < 8; i++) {
- args.r[i] = static_cast<u32>(core.GetReg(i));
+ smc_args.r[i] = static_cast<u32>(args[i]);
}
- CallSecureMonitor64From32(system, std::addressof(args));
+ CallSecureMonitor64From32(system, std::addressof(smc_args));
for (int i = 0; i < 8; i++) {
- core.SetReg(i, args.r[i]);
+ args[i] = smc_args.r[i];
}
}
diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp
index 01b8a52ad..2f5905f32 100644
--- a/src/core/hle/kernel/svc/svc_session.cpp
+++ b/src/core/hle/kernel/svc/svc_session.cpp
@@ -3,8 +3,10 @@
#include "common/scope_exit.h"
#include "core/core.h"
+#include "core/hle/kernel/k_light_session.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
+#include "core/hle/kernel/k_server_port.h"
#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/svc.h"
@@ -20,7 +22,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
T* session;
// Reserve a new session from the process resource limit.
- // FIXME: LimitableResource_SessionCountMax
+ // TODO: Dynamic resource limits
KScopedResourceReservation session_reservation(std::addressof(process),
LimitableResource::SessionCountMax);
if (session_reservation.Succeeded()) {
@@ -92,16 +94,42 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
u64 name) {
if (is_light) {
- // return CreateSession<KLightSession>(system, out_server, out_client, name);
- R_THROW(ResultNotImplemented);
+ R_RETURN(CreateSession<KLightSession>(system, out_server, out_client, name));
} else {
R_RETURN(CreateSession<KSession>(system, out_server, out_client, name));
}
}
-Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) {
- UNIMPLEMENTED();
- R_THROW(ResultNotImplemented);
+Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) {
+ // Get the current handle table.
+ auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
+
+ // Get the server port.
+ KScopedAutoObject port = handle_table.GetObject<KServerPort>(port_handle);
+ R_UNLESS(port.IsNotNull(), ResultInvalidHandle);
+
+ // Reserve an entry for the new session.
+ R_TRY(handle_table.Reserve(out));
+ ON_RESULT_FAILURE {
+ handle_table.Unreserve(*out);
+ };
+
+ // Accept the session.
+ KAutoObject* session;
+ if (port->IsLight()) {
+ session = port->AcceptLightSession();
+ } else {
+ session = port->AcceptSession();
+ }
+
+ // Ensure we accepted successfully.
+ R_UNLESS(session != nullptr, ResultNotFound);
+
+ // Register the session.
+ handle_table.Register(*out, session);
+ session->Close();
+
+ R_SUCCEED();
}
Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 755fd62b5..7681afa33 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -90,8 +90,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
/// Called when a thread exits
void ExitThread(Core::System& system) {
- LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
-
auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
system.GlobalSchedulerContext().RemoveThread(current_thread);
current_thread->Exit();
@@ -147,47 +145,19 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Require the handle be to a non-current thread in the current process.
- const auto* current_process = GetCurrentProcessPointer(kernel);
- R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId);
-
- // Verify that the thread isn't terminated.
- R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested);
-
- /// Check that the thread is not the current one.
- /// NOTE: Nintendo does not check this, and thus the following loop will deadlock.
- R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId);
-
- // Try to get the thread context until the thread isn't current on any core.
- while (true) {
- KScopedSchedulerLock sl{kernel};
-
- // TODO(bunnei): Enforce that thread is suspended for debug here.
-
- // If the thread's raw state isn't runnable, check if it's current on some core.
- if (thread->GetRawState() != ThreadState::Runnable) {
- bool current = false;
- for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
- if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetSchedulerCurrentThread()) {
- current = true;
- break;
- }
- }
+ R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle);
+ R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy);
- // If the thread is current, retry until it isn't.
- if (current) {
- continue;
- }
- }
+ // Get the thread context.
+ Svc::ThreadContext context{};
+ R_TRY(thread->GetThreadContext3(std::addressof(context)));
- // Get the thread context.
- static thread_local Common::ScratchBuffer<u8> context;
- R_TRY(thread->GetThreadContext3(context));
+ // Copy the thread context to user space.
+ R_UNLESS(
+ GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)),
+ ResultInvalidPointer);
- // Copy the thread context to user space.
- GetCurrentMemory(kernel).WriteBlock(out_context, context.data(), context.size());
-
- R_SUCCEED();
- }
+ R_SUCCEED();
}
/// Gets the priority for the specified thread
diff --git a/src/core/hle/kernel/svc_generator.py b/src/core/hle/kernel/svc_generator.py
index 5531faac6..786189ab7 100644
--- a/src/core/hle/kernel/svc_generator.py
+++ b/src/core/hle/kernel/svc_generator.py
@@ -374,11 +374,11 @@ def get_registers(parse_result, bitness):
# Collects possibly multiple source registers into the named C++ value.
def emit_gather(sources, name, type_name, reg_size):
- get_fn = f"GetReg{reg_size*8}"
+ get_fn = f"GetArg{reg_size*8}"
if len(sources) == 1:
s, = sources
- line = f"{name} = Convert<{type_name}>({get_fn}(system, {s}));"
+ line = f"{name} = Convert<{type_name}>({get_fn}(args, {s}));"
return [line]
var_type = f"std::array<uint{reg_size*8}_t, {len(sources)}>"
@@ -387,7 +387,7 @@ def emit_gather(sources, name, type_name, reg_size):
]
for i in range(0, len(sources)):
lines.append(
- f"{name}_gather[{i}] = {get_fn}(system, {sources[i]});")
+ f"{name}_gather[{i}] = {get_fn}(args, {sources[i]});")
lines.append(f"{name} = Convert<{type_name}>({name}_gather);")
return lines
@@ -396,12 +396,12 @@ def emit_gather(sources, name, type_name, reg_size):
# Produces one or more statements which assign the named C++ value
# into possibly multiple registers.
def emit_scatter(destinations, name, reg_size):
- set_fn = f"SetReg{reg_size*8}"
+ set_fn = f"SetArg{reg_size*8}"
reg_type = f"uint{reg_size*8}_t"
if len(destinations) == 1:
d, = destinations
- line = f"{set_fn}(system, {d}, Convert<{reg_type}>({name}));"
+ line = f"{set_fn}(args, {d}, Convert<{reg_type}>({name}));"
return [line]
var_type = f"std::array<{reg_type}, {len(destinations)}>"
@@ -411,7 +411,7 @@ def emit_scatter(destinations, name, reg_size):
for i in range(0, len(destinations)):
lines.append(
- f"{set_fn}(system, {destinations[i]}, {name}_scatter[{i}]);")
+ f"{set_fn}(args, {destinations[i]}, {name}_scatter[{i}]);")
return lines
@@ -433,7 +433,7 @@ def emit_lines(lines, indent=' '):
def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
return_write, output_writes, input_reads = register_info
lines = [
- f"static void SvcWrap_{wrapped_fn}{suffix}(Core::System& system) {{"
+ f"static void SvcWrap_{wrapped_fn}{suffix}(Core::System& system, std::span<uint64_t, 8> args) {{"
]
# Get everything ready.
@@ -498,6 +498,8 @@ namespace Core {
class System;
}
+#include <span>
+
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
@@ -524,15 +526,15 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
-void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
-void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
+void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args);
-void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
-void SvcWrap_SendSyncRequestLight64(Core::System& system);
+void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args);
// Defined in svc_secure_monitor_call.cpp.
-void SvcWrap_CallSecureMonitor64From32(Core::System& system);
-void SvcWrap_CallSecureMonitor64(Core::System& system);
+void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args);
+void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
@@ -550,20 +552,20 @@ PROLOGUE_CPP = """
namespace Kernel::Svc {
-static uint32_t GetReg32(Core::System& system, int n) {
- return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n));
+static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
+ return static_cast<uint32_t>(args[n]);
}
-static void SetReg32(Core::System& system, int n, uint32_t result) {
- system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
+static void SetArg32(std::span<uint64_t, 8> args, int n, uint32_t result) {
+ args[n] = result;
}
-static uint64_t GetReg64(Core::System& system, int n) {
- return system.CurrentArmInterface().GetReg(n);
+static uint64_t GetArg64(std::span<uint64_t, 8> args, int n) {
+ return args[n];
}
-static void SetReg64(Core::System& system, int n, uint64_t result) {
- system.CurrentArmInterface().SetReg(n, result);
+static void SetArg64(std::span<uint64_t, 8> args, int n, uint64_t result) {
+ args[n] = result;
}
// Like bit_cast, but handles the case when the source and dest
@@ -590,15 +592,20 @@ EPILOGUE_CPP = """
void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
+ auto& process = GetCurrentProcess(kernel);
+
+ std::array<uint64_t, 8> args;
+ kernel.CurrentPhysicalCore().SaveSvcArguments(process, args);
kernel.EnterSVCProfile();
- if (GetCurrentProcess(system.Kernel()).Is64Bit()) {
- Call64(system, imm);
+ if (process.Is64Bit()) {
+ Call64(system, imm, args);
} else {
- Call32(system, imm);
+ Call32(system, imm, args);
}
kernel.ExitSVCProfile();
+ kernel.CurrentPhysicalCore().LoadSvcArguments(process, args);
}
} // namespace Kernel::Svc
@@ -609,13 +616,13 @@ def emit_call(bitness, names, suffix):
bit_size = REG_SIZES[bitness]*8
indent = " "
lines = [
- f"static void Call{bit_size}(Core::System& system, u32 imm) {{",
+ f"static void Call{bit_size}(Core::System& system, u32 imm, std::span<uint64_t, 8> args) {{",
f"{indent}switch (static_cast<SvcId>(imm)) {{"
]
for _, name in names:
lines.append(f"{indent}case SvcId::{name}:")
- lines.append(f"{indent*2}return SvcWrap_{name}{suffix}(system);")
+ lines.append(f"{indent*2}return SvcWrap_{name}{suffix}(system, args);")
lines.append(f"{indent}default:")
lines.append(
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 126cd6ffd..b1310d6e4 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -246,7 +246,13 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
entries.reserve(entries.size() + new_data.size());
for (const auto& new_entry : new_data) {
- entries.emplace_back(new_entry->GetName(), type,
+ auto name = new_entry->GetName();
+
+ if (type == FileSys::EntryType::File && name == FileSys::GetSaveDataSizeFileName()) {
+ continue;
+ }
+
+ entries.emplace_back(name, type,
type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize());
}
}
diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp
new file mode 100644
index 000000000..c8e74c764
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/applet_resource.cpp
@@ -0,0 +1,313 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/core.h"
+#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/service/hid/controllers/applet_resource.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
+#include "core/hle/service/hid/errors.h"
+
+namespace Service::HID {
+
+AppletResource::AppletResource(Core::System& system_) : system{system_} {}
+
+AppletResource::~AppletResource() = default;
+
+Result AppletResource::CreateAppletResource(u64 aruid) {
+ const u64 index = GetIndexFromAruid(aruid);
+
+ if (index >= AruidIndexMax) {
+ return ResultAruidNotRegistered;
+ }
+
+ if (data[index].flag.is_assigned) {
+ return ResultAruidAlreadyRegistered;
+ }
+
+ auto& shared_memory = shared_memory_holder[index];
+ if (!shared_memory.IsMapped()) {
+ const Result result = shared_memory.Initialize(system);
+ if (result.IsError()) {
+ return result;
+ }
+ if (shared_memory.GetAddress() == nullptr) {
+ shared_memory.Finalize();
+ return ResultSharedMemoryNotInitialized;
+ }
+ }
+
+ auto* shared_memory_format = shared_memory.GetAddress();
+ if (shared_memory_format != nullptr) {
+ shared_memory_format->Initialize();
+ }
+
+ data[index].shared_memory_format = shared_memory_format;
+ data[index].flag.is_assigned.Assign(true);
+ // TODO: InitializeSixAxisControllerConfig(false);
+ active_aruid = aruid;
+ return ResultSuccess;
+}
+
+Result AppletResource::RegisterAppletResourceUserId(u64 aruid, bool enable_input) {
+ const u64 index = GetIndexFromAruid(aruid);
+
+ if (index < AruidIndexMax) {
+ return ResultAruidAlreadyRegistered;
+ }
+
+ std::size_t data_index = AruidIndexMax;
+ for (std::size_t i = 0; i < AruidIndexMax; i++) {
+ if (!data[i].flag.is_initialized) {
+ data_index = i;
+ break;
+ }
+ }
+
+ if (data_index == AruidIndexMax) {
+ return ResultAruidNoAvailableEntries;
+ }
+
+ AruidData& aruid_data = data[data_index];
+
+ aruid_data.aruid = aruid;
+ aruid_data.flag.is_initialized.Assign(true);
+ if (enable_input) {
+ aruid_data.flag.enable_pad_input.Assign(true);
+ aruid_data.flag.enable_six_axis_sensor.Assign(true);
+ aruid_data.flag.bit_18.Assign(true);
+ aruid_data.flag.enable_touchscreen.Assign(true);
+ }
+
+ data_index = AruidIndexMax;
+ for (std::size_t i = 0; i < AruidIndexMax; i++) {
+ if (registration_list.flag[i] == RegistrationStatus::Initialized) {
+ if (registration_list.aruid[i] != aruid) {
+ continue;
+ }
+ data_index = i;
+ break;
+ }
+ if (registration_list.flag[i] == RegistrationStatus::None) {
+ data_index = i;
+ break;
+ }
+ }
+
+ if (data_index == AruidIndexMax) {
+ return ResultSuccess;
+ }
+
+ registration_list.flag[data_index] = RegistrationStatus::Initialized;
+ registration_list.aruid[data_index] = aruid;
+
+ return ResultSuccess;
+}
+
+void AppletResource::UnregisterAppletResourceUserId(u64 aruid) {
+ u64 index = GetIndexFromAruid(aruid);
+
+ if (index < AruidIndexMax) {
+ if (data[index].flag.is_assigned) {
+ data[index].shared_memory_format = nullptr;
+ data[index].flag.is_assigned.Assign(false);
+ }
+ }
+
+ index = GetIndexFromAruid(aruid);
+ if (index < AruidIndexMax) {
+ DestroySevenSixAxisTransferMemory();
+ data[index].flag.raw = 0;
+ data[index].aruid = 0;
+
+ index = GetIndexFromAruid(aruid);
+ if (index < AruidIndexMax) {
+ registration_list.flag[index] = RegistrationStatus::PendingDelete;
+ }
+ }
+}
+
+void AppletResource::FreeAppletResourceId(u64 aruid) {
+ u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ auto& aruid_data = data[index];
+ if (aruid_data.flag.is_assigned) {
+ aruid_data.shared_memory_format = nullptr;
+ aruid_data.flag.is_assigned.Assign(false);
+ }
+}
+
+u64 AppletResource::GetActiveAruid() {
+ return active_aruid;
+}
+
+Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
+ u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return ResultAruidNotRegistered;
+ }
+
+ *out_handle = shared_memory_holder[index].GetHandle();
+ return ResultSuccess;
+}
+
+Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
+ u64 aruid) {
+ u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return ResultAruidNotRegistered;
+ }
+
+ *out_shared_memory_format = data[index].shared_memory_format;
+ return ResultSuccess;
+}
+
+u64 AppletResource::GetIndexFromAruid(u64 aruid) {
+ for (std::size_t i = 0; i < AruidIndexMax; i++) {
+ if (registration_list.flag[i] == RegistrationStatus::Initialized &&
+ registration_list.aruid[i] == aruid) {
+ return i;
+ }
+ }
+ return AruidIndexMax;
+}
+
+Result AppletResource::DestroySevenSixAxisTransferMemory() {
+ // TODO
+ return ResultSuccess;
+}
+
+void AppletResource::EnableInput(u64 aruid, bool is_enabled) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.enable_pad_input.Assign(is_enabled);
+ data[index].flag.enable_touchscreen.Assign(is_enabled);
+}
+
+void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.enable_six_axis_sensor.Assign(is_enabled);
+}
+
+void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.enable_pad_input.Assign(is_enabled);
+}
+
+void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.enable_touchscreen.Assign(is_enabled);
+}
+
+void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.is_palma_connectable.Assign(is_connectable);
+}
+
+void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) {
+ const u64 index = GetIndexFromAruid(aruid);
+ if (index >= AruidIndexMax) {
+ return;
+ }
+
+ data[index].flag.enable_palma_boost_mode.Assign(is_enabled);
+}
+
+Result AppletResource::RegisterCoreAppletResource() {
+ if (ref_counter == std::numeric_limits<s32>::max() - 1) {
+ return ResultAppletResourceOverflow;
+ }
+ if (ref_counter == 0) {
+ const u64 index = GetIndexFromAruid(0);
+ if (index < AruidIndexMax) {
+ return ResultAruidAlreadyRegistered;
+ }
+
+ std::size_t data_index = AruidIndexMax;
+ for (std::size_t i = 0; i < AruidIndexMax; i++) {
+ if (!data[i].flag.is_initialized) {
+ data_index = i;
+ break;
+ }
+ }
+
+ if (data_index == AruidIndexMax) {
+ return ResultAruidNoAvailableEntries;
+ }
+
+ AruidData& aruid_data = data[data_index];
+
+ aruid_data.aruid = 0;
+ aruid_data.flag.is_initialized.Assign(true);
+ aruid_data.flag.enable_pad_input.Assign(true);
+ aruid_data.flag.enable_six_axis_sensor.Assign(true);
+ aruid_data.flag.bit_18.Assign(true);
+ aruid_data.flag.enable_touchscreen.Assign(true);
+
+ data_index = AruidIndexMax;
+ for (std::size_t i = 0; i < AruidIndexMax; i++) {
+ if (registration_list.flag[i] == RegistrationStatus::Initialized) {
+ if (registration_list.aruid[i] != 0) {
+ continue;
+ }
+ data_index = i;
+ break;
+ }
+ if (registration_list.flag[i] == RegistrationStatus::None) {
+ data_index = i;
+ break;
+ }
+ }
+
+ Result result = ResultSuccess;
+
+ if (data_index == AruidIndexMax) {
+ result = CreateAppletResource(0);
+ } else {
+ registration_list.flag[data_index] = RegistrationStatus::Initialized;
+ registration_list.aruid[data_index] = 0;
+ }
+
+ if (result.IsError()) {
+ UnregisterAppletResourceUserId(0);
+ return result;
+ }
+ }
+ ref_counter++;
+ return ResultSuccess;
+}
+
+Result AppletResource::UnregisterCoreAppletResource() {
+ if (ref_counter == 0) {
+ return ResultAppletResourceNotInitialized;
+ }
+
+ if (--ref_counter == 0) {
+ UnregisterAppletResourceUserId(0);
+ }
+
+ return ResultSuccess;
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h
new file mode 100644
index 000000000..e7991f93a
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/applet_resource.h
@@ -0,0 +1,98 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <array>
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "core/hle/result.h"
+#include "core/hle/service/hid/controllers/shared_memory_holder.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KSharedMemory;
+}
+
+namespace Service::HID {
+struct SharedMemoryFormat;
+
+class AppletResource {
+public:
+ explicit AppletResource(Core::System& system_);
+ ~AppletResource();
+
+ Result CreateAppletResource(u64 aruid);
+
+ Result RegisterAppletResourceUserId(u64 aruid, bool enable_input);
+ void UnregisterAppletResourceUserId(u64 aruid);
+
+ void FreeAppletResourceId(u64 aruid);
+
+ u64 GetActiveAruid();
+ Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
+ Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid);
+
+ u64 GetIndexFromAruid(u64 aruid);
+
+ Result DestroySevenSixAxisTransferMemory();
+
+ void EnableInput(u64 aruid, bool is_enabled);
+ void EnableSixAxisSensor(u64 aruid, bool is_enabled);
+ void EnablePadInput(u64 aruid, bool is_enabled);
+ void EnableTouchScreen(u64 aruid, bool is_enabled);
+ void SetIsPalmaConnectable(u64 aruid, bool is_connectable);
+ void EnablePalmaBoostMode(u64 aruid, bool is_enabled);
+
+ Result RegisterCoreAppletResource();
+ Result UnregisterCoreAppletResource();
+
+private:
+ static constexpr std::size_t AruidIndexMax = 0x20;
+
+ enum RegistrationStatus : u32 {
+ None,
+ Initialized,
+ PendingDelete,
+ };
+
+ struct DataStatusFlag {
+ union {
+ u32 raw{};
+
+ BitField<0, 1, u32> is_initialized;
+ BitField<1, 1, u32> is_assigned;
+ BitField<16, 1, u32> enable_pad_input;
+ BitField<17, 1, u32> enable_six_axis_sensor;
+ BitField<18, 1, u32> bit_18;
+ BitField<19, 1, u32> is_palma_connectable;
+ BitField<20, 1, u32> enable_palma_boost_mode;
+ BitField<21, 1, u32> enable_touchscreen;
+ };
+ };
+
+ struct AruidRegisterList {
+ std::array<RegistrationStatus, AruidIndexMax> flag{};
+ std::array<u64, AruidIndexMax> aruid{};
+ };
+ static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size");
+
+ struct AruidData {
+ DataStatusFlag flag{};
+ u64 aruid{};
+ SharedMemoryFormat* shared_memory_format{nullptr};
+ };
+
+ u64 active_aruid{};
+ AruidRegisterList registration_list{};
+ std::array<AruidData, AruidIndexMax> data{};
+ std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{};
+ s32 ref_counter{};
+
+ Core::System& system;
+};
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp
index b2bf1d78d..3961d2b5f 100644
--- a/src/core/hle/service/hid/controllers/console_six_axis.cpp
+++ b/src/core/hle/service/hid/controllers/console_six_axis.cpp
@@ -1,23 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/core.h"
#include "core/core_timing.h"
#include "core/hid/emulated_console.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/console_six_axis.h"
-#include "core/memory.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
-ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
+ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
+ ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory)
+ : ControllerBase{hid_core_}, shared_memory{console_shared_memory} {
console = hid_core.GetEmulatedConsole();
- static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
- "ConsoleSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
ConsoleSixAxis::~ConsoleSixAxis() = default;
@@ -33,10 +28,10 @@ void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
const auto motion_status = console->GetMotion();
- shared_memory->sampling_number++;
- shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
- shared_memory->verticalization_error = motion_status.verticalization_error;
- shared_memory->gyro_bias = motion_status.gyro_bias;
+ shared_memory.sampling_number++;
+ shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
+ shared_memory.verticalization_error = motion_status.verticalization_error;
+ shared_memory.gyro_bias = motion_status.gyro_bias;
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h
index 5b7c6a29a..3d1c9ce23 100644
--- a/src/core/hle/service/hid/controllers/console_six_axis.h
+++ b/src/core/hle/service/hid/controllers/console_six_axis.h
@@ -3,7 +3,6 @@
#pragma once
-#include "common/vector_math.h"
#include "core/hle/service/hid/controllers/controller_base.h"
namespace Core::HID {
@@ -11,9 +10,12 @@ class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
+struct ConsoleSixAxisSensorSharedMemoryFormat;
+
class ConsoleSixAxis final : public ControllerBase {
public:
- explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
+ ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory);
~ConsoleSixAxis() override;
// Called when the controller is initialized
@@ -26,18 +28,7 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
- // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
- struct ConsoleSharedMemory {
- u64 sampling_number{};
- bool is_seven_six_axis_sensor_at_rest{};
- INSERT_PADDING_BYTES(3); // padding
- f32 verticalization_error{};
- Common::Vec3f gyro_bias{};
- INSERT_PADDING_BYTES(4); // padding
- };
- static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
-
- ConsoleSharedMemory* shared_memory = nullptr;
+ ConsoleSixAxisSensorSharedMemoryFormat& shared_memory;
Core::HID::EmulatedConsole* console = nullptr;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 9a44ee41e..4326c7821 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -39,9 +39,6 @@ public:
bool IsControllerActivated() const;
- static const std::size_t hid_entry_count = 17;
- static const std::size_t shared_memory_size = 0x40000;
-
protected:
bool is_activated{false};
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 9de19ebfc..7d2370b4f 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -1,24 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cstring>
-#include "common/common_types.h"
#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
-
-DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
- "DebugPadSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+
+DebugPad::DebugPad(Core::HID::HIDCore& hid_core_,
+ DebugPadSharedMemoryFormat& debug_pad_shared_memory)
+ : ControllerBase{hid_core_}, shared_memory{debug_pad_shared_memory} {
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
}
@@ -30,12 +25,12 @@ void DebugPad::OnRelease() {}
void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
- shared_memory->debug_pad_lifo.buffer_count = 0;
- shared_memory->debug_pad_lifo.buffer_tail = 0;
+ shared_memory.debug_pad_lifo.buffer_count = 0;
+ shared_memory.debug_pad_lifo.buffer_tail = 0;
return;
}
- const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;
+ const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
if (Settings::values.debug_pad_enabled) {
@@ -49,7 +44,7 @@ void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
next_state.r_stick = stick_state.right;
}
- shared_memory->debug_pad_lifo.WriteNextEntry(next_state);
+ shared_memory.debug_pad_lifo.WriteNextEntry(next_state);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 5566dba77..8ab29eca8 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -3,21 +3,24 @@
#pragma once
-#include "common/bit_field.h"
-#include "common/common_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
+#include "core/hle/service/hid/controllers/types/debug_pad_types.h"
namespace Core::HID {
-class EmulatedController;
-struct DebugPadButton;
-struct AnalogStickState;
-} // namespace Core::HID
+class HIDCore;
+}
+
+namespace Core::Timing {
+class CoreTiming;
+}
namespace Service::HID {
+struct DebugPadSharedMemoryFormat;
+
class DebugPad final : public ControllerBase {
public:
- explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit DebugPad(Core::HID::HIDCore& hid_core_,
+ DebugPadSharedMemoryFormat& debug_pad_shared_memory);
~DebugPad() override;
// Called when the controller is initialized
@@ -30,35 +33,8 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
- // This is nn::hid::DebugPadAttribute
- struct DebugPadAttribute {
- union {
- u32 raw{};
- BitField<0, 1, u32> connected;
- };
- };
- static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
-
- // This is nn::hid::DebugPadState
- struct DebugPadState {
- s64 sampling_number{};
- DebugPadAttribute attribute{};
- Core::HID::DebugPadButton pad_state{};
- Core::HID::AnalogStickState r_stick{};
- Core::HID::AnalogStickState l_stick{};
- };
- static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
-
- struct DebugPadSharedMemory {
- // This is nn::hid::detail::DebugPadLifo
- Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
- static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
- INSERT_PADDING_WORDS(0x4E);
- };
- static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
-
DebugPadState next_state{};
- DebugPadSharedMemory* shared_memory = nullptr;
+ DebugPadSharedMemoryFormat& shared_memory;
Core::HID::EmulatedController* controller = nullptr;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 59b2ec73c..f658005f6 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -1,17 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "common/logging/log.h"
#include "common/math_util.h"
#include "common/settings.h"
-#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
+#include "core/hid/emulated_console.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/gesture.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
-
// HW is around 700, value is set to 400 to make it easier to trigger with mouse
constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
constexpr f32 angle_threshold = 0.015f; // Threshold in radians
@@ -23,19 +21,15 @@ constexpr f32 Square(s32 num) {
return static_cast<f32>(num * num);
}
-Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase(hid_core_) {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
- "GestureSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+Gesture::Gesture(Core::HID::HIDCore& hid_core_, GestureSharedMemoryFormat& gesture_shared_memory)
+ : ControllerBase(hid_core_), shared_memory{gesture_shared_memory} {
console = hid_core.GetEmulatedConsole();
}
Gesture::~Gesture() = default;
void Gesture::OnInit() {
- shared_memory->gesture_lifo.buffer_count = 0;
- shared_memory->gesture_lifo.buffer_tail = 0;
+ shared_memory.gesture_lifo.buffer_count = 0;
+ shared_memory.gesture_lifo.buffer_tail = 0;
force_update = true;
}
@@ -43,8 +37,8 @@ void Gesture::OnRelease() {}
void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
- shared_memory->gesture_lifo.buffer_count = 0;
- shared_memory->gesture_lifo.buffer_tail = 0;
+ shared_memory.gesture_lifo.buffer_count = 0;
+ shared_memory.gesture_lifo.buffer_tail = 0;
return;
}
@@ -52,7 +46,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
GestureProperties gesture = GetGestureProperties();
f32 time_difference =
- static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) /
+ static_cast<f32>(shared_memory.gesture_lifo.timestamp - last_update_timestamp) /
(1000 * 1000 * 1000);
// Only update if necessary
@@ -60,7 +54,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
return;
}
- last_update_timestamp = shared_memory->gesture_lifo.timestamp;
+ last_update_timestamp = shared_memory.gesture_lifo.timestamp;
UpdateGestureSharedMemory(gesture, time_difference);
}
@@ -103,7 +97,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
GestureType type = GestureType::Idle;
GestureAttribute attributes{};
- const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state;
+ const auto& last_entry = shared_memory.gesture_lifo.ReadCurrentEntry().state;
// Reset next state to default
next_state.sampling_number = last_entry.sampling_number + 1;
@@ -133,7 +127,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
next_state.points = gesture.points;
last_gesture = gesture;
- shared_memory->gesture_lifo.WriteNextEntry(next_state);
+ shared_memory.gesture_lifo.WriteNextEntry(next_state);
}
void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
@@ -305,11 +299,11 @@ void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_
next_state.direction = GestureDirection::Up;
}
-const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
- return shared_memory->gesture_lifo.ReadCurrentEntry().state;
+const GestureState& Gesture::GetLastGestureEntry() const {
+ return shared_memory.gesture_lifo.ReadCurrentEntry().state;
}
-Gesture::GestureProperties Gesture::GetGestureProperties() {
+GestureProperties Gesture::GetGestureProperties() {
GestureProperties gesture;
std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 4c6f8ee07..41fdfcd03 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -4,17 +4,22 @@
#pragma once
#include <array>
-#include "common/bit_field.h"
+
#include "common/common_types.h"
-#include "common/point.h"
-#include "core/hid/emulated_console.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
+#include "core/hle/service/hid/controllers/types/touch_types.h"
+
+namespace Core::HID {
+class EmulatedConsole;
+}
namespace Service::HID {
+struct GestureSharedMemoryFormat;
+
class Gesture final : public ControllerBase {
public:
- explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit Gesture(Core::HID::HIDCore& hid_core_,
+ GestureSharedMemoryFormat& gesture_shared_memory);
~Gesture() override;
// Called when the controller is initialized
@@ -27,79 +32,6 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
- static constexpr size_t MAX_FINGERS = 16;
- static constexpr size_t MAX_POINTS = 4;
-
- // This is nn::hid::GestureType
- enum class GestureType : u32 {
- Idle, // Nothing touching the screen
- Complete, // Set at the end of a touch event
- Cancel, // Set when the number of fingers change
- Touch, // A finger just touched the screen
- Press, // Set if last type is touch and the finger hasn't moved
- Tap, // Fast press then release
- Pan, // All points moving together across the screen
- Swipe, // Fast press movement and release of a single point
- Pinch, // All points moving away/closer to the midpoint
- Rotate, // All points rotating from the midpoint
- };
-
- // This is nn::hid::GestureDirection
- enum class GestureDirection : u32 {
- None,
- Left,
- Up,
- Right,
- Down,
- };
-
- // This is nn::hid::GestureAttribute
- struct GestureAttribute {
- union {
- u32 raw{};
-
- BitField<4, 1, u32> is_new_touch;
- BitField<8, 1, u32> is_double_tap;
- };
- };
- static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
-
- // This is nn::hid::GestureState
- struct GestureState {
- s64 sampling_number{};
- s64 detection_count{};
- GestureType type{GestureType::Idle};
- GestureDirection direction{GestureDirection::None};
- Common::Point<s32> pos{};
- Common::Point<s32> delta{};
- f32 vel_x{};
- f32 vel_y{};
- GestureAttribute attributes{};
- f32 scale{};
- f32 rotation_angle{};
- s32 point_count{};
- std::array<Common::Point<s32>, 4> points{};
- };
- static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
-
- struct GestureProperties {
- std::array<Common::Point<s32>, MAX_POINTS> points{};
- std::size_t active_points{};
- Common::Point<s32> mid_point{};
- s64 detection_count{};
- u64 delta_time{};
- f32 average_distance{};
- f32 angle{};
- };
-
- struct GestureSharedMemory {
- // This is nn::hid::detail::GestureLifo
- Lifo<GestureState, hid_entry_count> gesture_lifo{};
- static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
- INSERT_PADDING_WORDS(0x3E);
- };
- static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
-
// Reads input from all available input engines
void ReadTouchInput();
@@ -142,7 +74,7 @@ private:
GestureProperties GetGestureProperties();
GestureState next_state{};
- GestureSharedMemory* shared_memory = nullptr;
+ GestureSharedMemoryFormat& shared_memory;
Core::HID::EmulatedConsole* console = nullptr;
std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index ddb1b0ba4..871e5036a 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -1,23 +1,18 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cstring>
-#include "common/common_types.h"
#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/keyboard.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
-
-Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
- "KeyboardSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+
+Keyboard::Keyboard(Core::HID::HIDCore& hid_core_,
+ KeyboardSharedMemoryFormat& keyboard_shared_memory)
+ : ControllerBase{hid_core_}, shared_memory{keyboard_shared_memory} {
emulated_devices = hid_core.GetEmulatedDevices();
}
@@ -29,12 +24,12 @@ void Keyboard::OnRelease() {}
void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
- shared_memory->keyboard_lifo.buffer_count = 0;
- shared_memory->keyboard_lifo.buffer_tail = 0;
+ shared_memory.keyboard_lifo.buffer_count = 0;
+ shared_memory.keyboard_lifo.buffer_tail = 0;
return;
}
- const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;
+ const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
if (Settings::values.keyboard_enabled) {
@@ -46,7 +41,7 @@ void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
next_state.attribute.is_connected.Assign(1);
}
- shared_memory->keyboard_lifo.WriteNextEntry(next_state);
+ shared_memory.keyboard_lifo.WriteNextEntry(next_state);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 172ec1309..4d72171b9 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -3,20 +3,16 @@
#pragma once
-#include "common/common_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
-
-namespace Core::HID {
-class EmulatedDevices;
-struct KeyboardModifier;
-struct KeyboardKey;
-} // namespace Core::HID
+#include "core/hle/service/hid/controllers/types/keyboard_types.h"
namespace Service::HID {
+struct KeyboardSharedMemoryFormat;
+
class Keyboard final : public ControllerBase {
public:
- explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit Keyboard(Core::HID::HIDCore& hid_core_,
+ KeyboardSharedMemoryFormat& keyboard_shared_memory);
~Keyboard() override;
// Called when the controller is initialized
@@ -29,25 +25,8 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
- // This is nn::hid::detail::KeyboardState
- struct KeyboardState {
- s64 sampling_number{};
- Core::HID::KeyboardModifier modifier{};
- Core::HID::KeyboardAttribute attribute{};
- Core::HID::KeyboardKey key{};
- };
- static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
-
- struct KeyboardSharedMemory {
- // This is nn::hid::detail::KeyboardLifo
- Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
- static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
- INSERT_PADDING_WORDS(0xA);
- };
- static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
-
KeyboardState next_state{};
- KeyboardSharedMemory* shared_memory = nullptr;
+ KeyboardSharedMemoryFormat& shared_memory;
Core::HID::EmulatedDevices* emulated_devices = nullptr;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 6e5a04e34..de5b2c804 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -1,22 +1,17 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cstring>
-#include "common/common_types.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/mouse.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
-Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
- "MouseSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
+Mouse::Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory)
+ : ControllerBase{hid_core_}, shared_memory{mouse_shared_memory} {
emulated_devices = hid_core.GetEmulatedDevices();
}
@@ -27,14 +22,14 @@ void Mouse::OnRelease() {}
void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
- shared_memory->mouse_lifo.buffer_count = 0;
- shared_memory->mouse_lifo.buffer_tail = 0;
+ shared_memory.mouse_lifo.buffer_count = 0;
+ shared_memory.mouse_lifo.buffer_tail = 0;
return;
}
next_state = {};
- const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;
+ const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
if (Settings::values.mouse_enabled) {
@@ -53,7 +48,7 @@ void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
next_state.button = mouse_button_state;
}
- shared_memory->mouse_lifo.WriteNextEntry(next_state);
+ shared_memory.mouse_lifo.WriteNextEntry(next_state);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index a80f3823f..363f316a5 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -3,9 +3,7 @@
#pragma once
-#include "common/common_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
namespace Core::HID {
class EmulatedDevices;
@@ -14,9 +12,11 @@ struct AnalogStickState;
} // namespace Core::HID
namespace Service::HID {
+struct MouseSharedMemoryFormat;
+
class Mouse final : public ControllerBase {
public:
- explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory);
~Mouse() override;
// Called when the controller is initialized
@@ -29,17 +29,9 @@ public:
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
- struct MouseSharedMemory {
- // This is nn::hid::detail::MouseLifo
- Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
- static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
- INSERT_PADDING_WORDS(0x2C);
- };
- static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
-
Core::HID::MouseState next_state{};
Core::HID::AnalogStickState last_mouse_wheel_state{};
- MouseSharedMemory* shared_memory = nullptr;
+ MouseSharedMemoryFormat& shared_memory;
Core::HID::EmulatedDevices* emulated_devices = nullptr;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 08ee9de9c..53a737cf5 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -17,12 +17,12 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::HID {
-constexpr std::size_t NPAD_OFFSET = 0x9A00;
constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
@@ -30,14 +30,12 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
Core::HID::NpadIdType::Handheld,
};
-NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
- static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
- controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
- raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
+ controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state;
controller.device = hid_core.GetEmulatedControllerByIndex(i);
controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
Core::HID::DEFAULT_VIBRATION_VALUE;
@@ -617,7 +615,7 @@ void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
hold_type = joy_hold_type;
}
-NPad::NpadJoyHoldType NPad::GetHoldType() const {
+NpadJoyHoldType NPad::GetHoldType() const {
return hold_type;
}
@@ -630,7 +628,7 @@ void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_m
handheld_activation_mode = activation_mode;
}
-NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
+NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
return handheld_activation_mode;
}
@@ -638,7 +636,7 @@ void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
communication_mode = communication_mode_;
}
-NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
+NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
return communication_mode;
}
@@ -978,27 +976,27 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
return ResultSuccess;
}
-NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
}
-NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
}
-NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
}
-NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
}
-NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
}
-NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
+NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
}
@@ -1343,7 +1341,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
}
}
-NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
+AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
return {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 9167c93f0..4e2412356 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,12 +8,10 @@
#include <mutex>
#include <span>
-#include "common/bit_field.h"
#include "common/common_types.h"
-
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
+#include "core/hle/service/hid/controllers/types/npad_types.h"
namespace Core::HID {
class EmulatedController;
@@ -32,10 +30,13 @@ class ServiceContext;
union Result;
namespace Service::HID {
+struct NpadInternalState;
+struct NpadSixAxisSensorLifo;
+struct NpadSharedMemoryFormat;
class NPad final : public ControllerBase {
public:
- explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
+ explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
KernelHelpers::ServiceContext& service_context_);
~NPad() override;
@@ -48,89 +49,6 @@ public:
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
- // This is nn::hid::NpadJoyHoldType
- enum class NpadJoyHoldType : u64 {
- Vertical = 0,
- Horizontal = 1,
- };
-
- // This is nn::hid::NpadJoyAssignmentMode
- enum class NpadJoyAssignmentMode : u32 {
- Dual = 0,
- Single = 1,
- };
-
- // This is nn::hid::NpadJoyDeviceType
- enum class NpadJoyDeviceType : s64 {
- Left = 0,
- Right = 1,
- };
-
- // This is nn::hid::NpadHandheldActivationMode
- enum class NpadHandheldActivationMode : u64 {
- Dual = 0,
- Single = 1,
- None = 2,
- MaxActivationMode = 3,
- };
-
- // This is nn::hid::system::AppletFooterUiAttributesSet
- struct AppletFooterUiAttributes {
- INSERT_PADDING_BYTES(0x4);
- };
-
- // This is nn::hid::system::AppletFooterUiType
- enum class AppletFooterUiType : u8 {
- None = 0,
- HandheldNone = 1,
- HandheldJoyConLeftOnly = 2,
- HandheldJoyConRightOnly = 3,
- HandheldJoyConLeftJoyConRight = 4,
- JoyDual = 5,
- JoyDualLeftOnly = 6,
- JoyDualRightOnly = 7,
- JoyLeftHorizontal = 8,
- JoyLeftVertical = 9,
- JoyRightHorizontal = 10,
- JoyRightVertical = 11,
- SwitchProController = 12,
- CompatibleProController = 13,
- CompatibleJoyCon = 14,
- LarkHvc1 = 15,
- LarkHvc2 = 16,
- LarkNesLeft = 17,
- LarkNesRight = 18,
- Lucia = 19,
- Verification = 20,
- Lagon = 21,
- };
-
- using AppletFooterUiVariant = u8;
-
- // This is "nn::hid::system::AppletDetailedUiType".
- struct AppletDetailedUiType {
- AppletFooterUiVariant ui_variant;
- INSERT_PADDING_BYTES(0x2);
- AppletFooterUiType footer;
- };
- static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
- // This is nn::hid::NpadCommunicationMode
- enum class NpadCommunicationMode : u64 {
- Mode_5ms = 0,
- Mode_10ms = 1,
- Mode_15ms = 2,
- Default = 3,
- };
-
- enum class NpadRevision : u32 {
- Revision0 = 0,
- Revision1 = 1,
- Revision2 = 2,
- Revision3 = 3,
- };
-
- using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
-
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
@@ -188,12 +106,12 @@ public:
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
const Core::HID::SixAxisSensorHandle& sixaxis_handle);
- SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
- SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
- SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
- SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
- SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
- SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
+ NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
@@ -221,214 +139,6 @@ public:
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
private:
- static constexpr std::size_t NPAD_COUNT = 10;
-
- // This is nn::hid::detail::ColorAttribute
- enum class ColorAttribute : u32 {
- Ok = 0,
- ReadError = 1,
- NoController = 2,
- };
- static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
-
- // This is nn::hid::detail::NpadFullKeyColorState
- struct NpadFullKeyColorState {
- ColorAttribute attribute{ColorAttribute::NoController};
- Core::HID::NpadControllerColor fullkey{};
- };
- static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
-
- // This is nn::hid::detail::NpadJoyColorState
- struct NpadJoyColorState {
- ColorAttribute attribute{ColorAttribute::NoController};
- Core::HID::NpadControllerColor left{};
- Core::HID::NpadControllerColor right{};
- };
- static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
-
- // This is nn::hid::NpadAttribute
- struct NpadAttribute {
- union {
- u32 raw{};
- BitField<0, 1, u32> is_connected;
- BitField<1, 1, u32> is_wired;
- BitField<2, 1, u32> is_left_connected;
- BitField<3, 1, u32> is_left_wired;
- BitField<4, 1, u32> is_right_connected;
- BitField<5, 1, u32> is_right_wired;
- };
- };
- static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
-
- // This is nn::hid::NpadFullKeyState
- // This is nn::hid::NpadHandheldState
- // This is nn::hid::NpadJoyDualState
- // This is nn::hid::NpadJoyLeftState
- // This is nn::hid::NpadJoyRightState
- // This is nn::hid::NpadPalmaState
- // This is nn::hid::NpadSystemExtState
- struct NPadGenericState {
- s64_le sampling_number{};
- Core::HID::NpadButtonState npad_buttons{};
- Core::HID::AnalogStickState l_stick{};
- Core::HID::AnalogStickState r_stick{};
- NpadAttribute connection_status{};
- INSERT_PADDING_BYTES(4); // Reserved
- };
- static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
-
- // This is nn::hid::server::NpadGcTriggerState
- struct NpadGcTriggerState {
- s64 sampling_number{};
- s32 l_analog{};
- s32 r_analog{};
- };
- static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
-
- // This is nn::hid::NpadSystemProperties
- struct NPadSystemProperties {
- union {
- s64 raw{};
- BitField<0, 1, s64> is_charging_joy_dual;
- BitField<1, 1, s64> is_charging_joy_left;
- BitField<2, 1, s64> is_charging_joy_right;
- BitField<3, 1, s64> is_powered_joy_dual;
- BitField<4, 1, s64> is_powered_joy_left;
- BitField<5, 1, s64> is_powered_joy_right;
- BitField<9, 1, s64> is_system_unsupported_button;
- BitField<10, 1, s64> is_system_ext_unsupported_button;
- BitField<11, 1, s64> is_vertical;
- BitField<12, 1, s64> is_horizontal;
- BitField<13, 1, s64> use_plus;
- BitField<14, 1, s64> use_minus;
- BitField<15, 1, s64> use_directional_buttons;
- };
- };
- static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
-
- // This is nn::hid::NpadSystemButtonProperties
- struct NpadSystemButtonProperties {
- union {
- s32 raw{};
- BitField<0, 1, s32> is_home_button_protection_enabled;
- };
- };
- static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
- "NPadButtonProperties is an invalid size");
-
- // This is nn::hid::system::DeviceType
- struct DeviceType {
- union {
- u32 raw{};
- BitField<0, 1, s32> fullkey;
- BitField<1, 1, s32> debug_pad;
- BitField<2, 1, s32> handheld_left;
- BitField<3, 1, s32> handheld_right;
- BitField<4, 1, s32> joycon_left;
- BitField<5, 1, s32> joycon_right;
- BitField<6, 1, s32> palma;
- BitField<7, 1, s32> lark_hvc_left;
- BitField<8, 1, s32> lark_hvc_right;
- BitField<9, 1, s32> lark_nes_left;
- BitField<10, 1, s32> lark_nes_right;
- BitField<11, 1, s32> handheld_lark_hvc_left;
- BitField<12, 1, s32> handheld_lark_hvc_right;
- BitField<13, 1, s32> handheld_lark_nes_left;
- BitField<14, 1, s32> handheld_lark_nes_right;
- BitField<15, 1, s32> lucia;
- BitField<16, 1, s32> lagon;
- BitField<17, 1, s32> lager;
- BitField<31, 1, s32> system;
- };
- };
-
- // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
- struct NfcXcdDeviceHandleStateImpl {
- u64 handle{};
- bool is_available{};
- bool is_activated{};
- INSERT_PADDING_BYTES(0x6); // Reserved
- u64 sampling_number{};
- };
- static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
- "NfcXcdDeviceHandleStateImpl is an invalid size");
-
- // This is nn::hid::NpadLarkType
- enum class NpadLarkType : u32 {
- Invalid,
- H1,
- H2,
- NL,
- NR,
- };
-
- // This is nn::hid::NpadLuciaType
- enum class NpadLuciaType : u32 {
- Invalid,
- J,
- E,
- U,
- };
-
- // This is nn::hid::NpadLagonType
- enum class NpadLagonType : u32 {
- Invalid,
- };
-
- // This is nn::hid::NpadLagerType
- enum class NpadLagerType : u32 {
- Invalid,
- J,
- E,
- U,
- };
-
- // This is nn::hid::detail::NpadInternalState
- struct NpadInternalState {
- Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
- NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
- NpadFullKeyColorState fullkey_color{};
- NpadJoyColorState joycon_color{};
- Lifo<NPadGenericState, hid_entry_count> fullkey_lifo{};
- Lifo<NPadGenericState, hid_entry_count> handheld_lifo{};
- Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo{};
- Lifo<NPadGenericState, hid_entry_count> joy_left_lifo{};
- Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
- Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
- Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
- Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
- DeviceType device_type{};
- INSERT_PADDING_BYTES(0x4); // Reserved
- NPadSystemProperties system_properties{};
- NpadSystemButtonProperties button_properties{};
- Core::HID::NpadBatteryLevel battery_level_dual{};
- Core::HID::NpadBatteryLevel battery_level_left{};
- Core::HID::NpadBatteryLevel battery_level_right{};
- AppletFooterUiAttributes applet_footer_attributes{};
- AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
- INSERT_PADDING_BYTES(0x5B); // Reserved
- INSERT_PADDING_BYTES(0x20); // Unknown
- Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
- NpadLarkType lark_type_l_and_main{};
- NpadLarkType lark_type_r{};
- NpadLuciaType lucia_type{};
- NpadLagonType lagon_type{};
- NpadLagerType lager_type{};
- Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
- Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
- Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
- Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
- Core::HID::SixAxisSensorProperties sixaxis_left_properties;
- Core::HID::SixAxisSensorProperties sixaxis_right_properties;
- INSERT_PADDING_BYTES(0xc06); // Unknown
- };
- static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
-
struct VibrationData {
bool device_mounted{};
Core::HID::VibrationValue latest_vibration_value{};
@@ -479,7 +189,7 @@ private:
std::atomic<u64> press_state{};
- std::array<NpadControllerData, NPAD_COUNT> controller_data{};
+ std::array<NpadControllerData, NpadCount> controller_data{};
KernelHelpers::ServiceContext& service_context;
std::mutex mutex;
std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 588ff9d62..aa0454b5e 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -12,8 +12,7 @@
namespace Service::HID {
-Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_)
+Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h
index a6047f36a..73884230d 100644
--- a/src/core/hle/service/hid/controllers/palma.h
+++ b/src/core/hle/service/hid/controllers/palma.h
@@ -97,8 +97,7 @@ public:
static_assert(sizeof(PalmaConnectionHandle) == 0x8,
"PalmaConnectionHandle has incorrect size.");
- explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
- KernelHelpers::ServiceContext& service_context_);
+ explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_);
~Palma() override;
// Called when the controller is initialized
diff --git a/src/core/hle/service/hid/controllers/shared_memory_format.h b/src/core/hle/service/hid/controllers/shared_memory_format.h
new file mode 100644
index 000000000..2986c113e
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_format.h
@@ -0,0 +1,240 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/vector_math.h"
+#include "core/hid/hid_types.h"
+#include "core/hle/service/hid//controllers/types/debug_pad_types.h"
+#include "core/hle/service/hid//controllers/types/keyboard_types.h"
+#include "core/hle/service/hid//controllers/types/mouse_types.h"
+#include "core/hle/service/hid//controllers/types/npad_types.h"
+#include "core/hle/service/hid//controllers/types/touch_types.h"
+#include "core/hle/service/hid/ring_lifo.h"
+
+namespace Service::HID {
+static const std::size_t HidEntryCount = 17;
+
+struct CommonHeader {
+ s64 timestamp{};
+ s64 total_entry_count{};
+ s64 last_entry_index{};
+ s64 entry_count{};
+};
+static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
+
+// This is nn::hid::detail::DebugPadSharedMemoryFormat
+struct DebugPadSharedMemoryFormat {
+ // This is nn::hid::detail::DebugPadLifo
+ Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{};
+ static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
+ INSERT_PADDING_WORDS(0x4E);
+};
+static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400,
+ "DebugPadSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::TouchScreenSharedMemoryFormat
+struct TouchScreenSharedMemoryFormat {
+ // This is nn::hid::detail::TouchScreenLifo
+ Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{};
+ static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
+ INSERT_PADDING_WORDS(0xF2);
+};
+static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000,
+ "TouchScreenSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::MouseSharedMemoryFormat
+struct MouseSharedMemoryFormat {
+ // This is nn::hid::detail::MouseLifo
+ Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{};
+ static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
+ INSERT_PADDING_WORDS(0x2C);
+};
+static_assert(sizeof(MouseSharedMemoryFormat) == 0x400,
+ "MouseSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::KeyboardSharedMemoryFormat
+struct KeyboardSharedMemoryFormat {
+ // This is nn::hid::detail::KeyboardLifo
+ Lifo<KeyboardState, HidEntryCount> keyboard_lifo{};
+ static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
+ INSERT_PADDING_WORDS(0xA);
+};
+static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400,
+ "KeyboardSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::DigitizerSharedMemoryFormat
+struct DigitizerSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0xFE0);
+};
+static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
+ "DigitizerSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::HomeButtonSharedMemoryFormat
+struct HomeButtonSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0x1E0);
+};
+static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
+ "HomeButtonSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::SleepButtonSharedMemoryFormat
+struct SleepButtonSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0x1E0);
+};
+static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
+ "SleepButtonSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
+struct CaptureButtonSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0x1E0);
+};
+static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
+ "CaptureButtonSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::InputDetectorSharedMemoryFormat
+struct InputDetectorSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0x7E0);
+};
+static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800,
+ "InputDetectorSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::UniquePadSharedMemoryFormat
+struct UniquePadSharedMemoryFormat {
+ CommonHeader header;
+ INSERT_PADDING_BYTES(0x3FE0);
+};
+static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000,
+ "UniquePadSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::NpadSixAxisSensorLifo
+struct NpadSixAxisSensorLifo {
+ Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo;
+};
+
+// This is nn::hid::detail::NpadInternalState
+struct NpadInternalState {
+ Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
+ NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
+ NpadFullKeyColorState fullkey_color{};
+ NpadJoyColorState joycon_color{};
+ Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> handheld_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> palma_lifo{};
+ Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{};
+ NpadSixAxisSensorLifo sixaxis_fullkey_lifo{};
+ NpadSixAxisSensorLifo sixaxis_handheld_lifo{};
+ NpadSixAxisSensorLifo sixaxis_dual_left_lifo{};
+ NpadSixAxisSensorLifo sixaxis_dual_right_lifo{};
+ NpadSixAxisSensorLifo sixaxis_left_lifo{};
+ NpadSixAxisSensorLifo sixaxis_right_lifo{};
+ DeviceType device_type{};
+ INSERT_PADDING_BYTES(0x4); // Reserved
+ NPadSystemProperties system_properties{};
+ NpadSystemButtonProperties button_properties{};
+ Core::HID::NpadBatteryLevel battery_level_dual{};
+ Core::HID::NpadBatteryLevel battery_level_left{};
+ Core::HID::NpadBatteryLevel battery_level_right{};
+ AppletFooterUiAttributes applet_footer_attributes{};
+ AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
+ INSERT_PADDING_BYTES(0x5B); // Reserved
+ INSERT_PADDING_BYTES(0x20); // Unknown
+ Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{};
+ NpadLarkType lark_type_l_and_main{};
+ NpadLarkType lark_type_r{};
+ NpadLuciaType lucia_type{};
+ NpadLagerType lager_type{};
+ Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
+ Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
+ Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
+ Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
+ Core::HID::SixAxisSensorProperties sixaxis_left_properties;
+ Core::HID::SixAxisSensorProperties sixaxis_right_properties;
+};
+static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size");
+
+// This is nn::hid::detail::NpadSharedMemoryEntry
+struct NpadSharedMemoryEntry {
+ NpadInternalState internal_state;
+ INSERT_PADDING_BYTES(0xC08);
+};
+static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size");
+
+// This is nn::hid::detail::NpadSharedMemoryFormat
+struct NpadSharedMemoryFormat {
+ std::array<NpadSharedMemoryEntry, NpadCount> npad_entry;
+};
+static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000,
+ "NpadSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::GestureSharedMemoryFormat
+struct GestureSharedMemoryFormat {
+ // This is nn::hid::detail::GestureLifo
+ Lifo<GestureState, HidEntryCount> gesture_lifo{};
+ static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
+ INSERT_PADDING_WORDS(0x3E);
+};
+static_assert(sizeof(GestureSharedMemoryFormat) == 0x800,
+ "GestureSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
+struct ConsoleSixAxisSensorSharedMemoryFormat {
+ u64 sampling_number{};
+ bool is_seven_six_axis_sensor_at_rest{};
+ INSERT_PADDING_BYTES(3); // padding
+ f32 verticalization_error{};
+ Common::Vec3f gyro_bias{};
+ INSERT_PADDING_BYTES(4); // padding
+};
+static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
+ "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size");
+
+// This is nn::hid::detail::SharedMemoryFormat
+struct SharedMemoryFormat {
+ void Initialize() {}
+
+ DebugPadSharedMemoryFormat debug_pad;
+ TouchScreenSharedMemoryFormat touch_screen;
+ MouseSharedMemoryFormat mouse;
+ KeyboardSharedMemoryFormat keyboard;
+ DigitizerSharedMemoryFormat digitizer;
+ HomeButtonSharedMemoryFormat home_button;
+ SleepButtonSharedMemoryFormat sleep_button;
+ CaptureButtonSharedMemoryFormat capture_button;
+ InputDetectorSharedMemoryFormat input_detector;
+ UniquePadSharedMemoryFormat unique_pad;
+ NpadSharedMemoryFormat npad;
+ GestureSharedMemoryFormat gesture;
+ ConsoleSixAxisSensorSharedMemoryFormat console;
+ INSERT_PADDING_BYTES(0x19E0);
+ MouseSharedMemoryFormat debug_mouse;
+ INSERT_PADDING_BYTES(0x2000);
+};
+static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00,
+ "sleep_button has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000,
+ "capture_button has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200,
+ "input_detector has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset");
+static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset");
+static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size");
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp
new file mode 100644
index 000000000..51581188e
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/core.h"
+#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
+#include "core/hle/service/hid/controllers/shared_memory_holder.h"
+#include "core/hle/service/hid/errors.h"
+
+namespace Service::HID {
+SharedMemoryHolder::SharedMemoryHolder() {}
+
+SharedMemoryHolder::~SharedMemoryHolder() {
+ Finalize();
+}
+
+Result SharedMemoryHolder::Initialize(Core::System& system) {
+ shared_memory = Kernel::KSharedMemory::Create(system.Kernel());
+ const Result result = shared_memory->Initialize(
+ system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None,
+ Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat));
+ if (result.IsError()) {
+ return result;
+ }
+ Kernel::KSharedMemory::Register(system.Kernel(), shared_memory);
+
+ is_created = true;
+ is_mapped = true;
+ address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer()));
+ return ResultSuccess;
+}
+
+void SharedMemoryHolder::Finalize() {
+ if (address != nullptr) {
+ shared_memory->Close();
+ }
+ is_created = false;
+ is_mapped = false;
+ address = nullptr;
+}
+
+bool SharedMemoryHolder::IsMapped() {
+ return is_mapped;
+}
+
+SharedMemoryFormat* SharedMemoryHolder::GetAddress() {
+ return address;
+}
+
+Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() {
+ return shared_memory;
+}
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.h b/src/core/hle/service/hid/controllers/shared_memory_holder.h
new file mode 100644
index 000000000..943407c00
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/shared_memory_holder.h
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KSharedMemory;
+}
+
+namespace Service::HID {
+struct SharedMemoryFormat;
+
+// This is nn::hid::detail::SharedMemoryHolder
+class SharedMemoryHolder {
+public:
+ SharedMemoryHolder();
+ ~SharedMemoryHolder();
+
+ Result Initialize(Core::System& system);
+ void Finalize();
+
+ bool IsMapped();
+ SharedMemoryFormat* GetAddress();
+ Kernel::KSharedMemory* GetHandle();
+
+private:
+ bool is_owner{};
+ bool is_created{};
+ bool is_mapped{};
+ INSERT_PADDING_BYTES(0x5);
+ Kernel::KSharedMemory* shared_memory;
+ INSERT_PADDING_BYTES(0x38);
+ SharedMemoryFormat* address = nullptr;
+};
+// Correct size is 0x50 bytes
+static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size");
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp
index 3d24a5c04..36b72f9ea 100644
--- a/src/core/hle/service/hid/controllers/six_axis.cpp
+++ b/src/core/hle/service/hid/controllers/six_axis.cpp
@@ -6,6 +6,7 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"
@@ -132,30 +133,30 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
}
sixaxis_fullkey_state.sampling_number =
- sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_handheld_state.sampling_number =
- sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_left_state.sampling_number =
- sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_right_state.sampling_number =
- sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_left_lifo_state.sampling_number =
- sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_right_lifo_state.sampling_number =
- sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
+ sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
// This buffer only is updated on handheld on HW
- sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
+ sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
} else {
// Handheld doesn't update this buffer on HW
- sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
+ sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
}
- sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
- sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
- sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
- sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
+ sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
+ sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
+ sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
+ sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
}
}
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 9e2f3ab21..e2a5f5d79 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -1,18 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cstring>
-#include "common/common_types.h"
#include "core/core_timing.h"
-#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
#include "core/hle/service/hid/controllers/stubbed.h"
namespace Service::HID {
-Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_} {
- raw_shared_memory = raw_shared_memory_;
-}
+Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_,
+ CommonHeader& ring_lifo_header)
+ : ControllerBase{hid_core_}, header{ring_lifo_header} {}
Controller_Stubbed::~Controller_Stubbed() = default;
@@ -25,18 +22,10 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
return;
}
- CommonHeader header{};
header.timestamp = core_timing.GetGlobalTimeNs().count();
header.total_entry_count = 17;
header.entry_count = 0;
header.last_entry_index = 0;
-
- std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
-}
-
-void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
- common_offset = off;
- smart_update = true;
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 1483a968e..d2052fb17 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -3,13 +3,14 @@
#pragma once
-#include "common/common_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
namespace Service::HID {
+struct CommonHeader;
+
class Controller_Stubbed final : public ControllerBase {
public:
- explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, CommonHeader& ring_lifo_header);
~Controller_Stubbed() override;
// Called when the controller is initialized
@@ -21,19 +22,8 @@ public:
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
- void SetCommonHeaderOffset(std::size_t off);
-
private:
- struct CommonHeader {
- s64 timestamp{};
- s64 total_entry_count{};
- s64 last_entry_index{};
- s64 entry_count{};
- };
- static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
-
- u8* raw_shared_memory = nullptr;
+ CommonHeader& header;
bool smart_update{};
- std::size_t common_offset{};
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index fcd973414..469750006 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -2,26 +2,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
-#include <cstring>
#include "common/common_types.h"
#include "common/settings.h"
-#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/hid/emulated_console.h"
#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
-TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
- : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width),
+TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_,
+ TouchScreenSharedMemoryFormat& touch_shared_memory)
+ : ControllerBase{hid_core_}, shared_memory{touch_shared_memory},
+ touchscreen_width(Layout::ScreenUndocked::Width),
touchscreen_height(Layout::ScreenUndocked::Height) {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
- "TouchSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
console = hid_core.GetEmulatedConsole();
}
@@ -32,11 +28,11 @@ void TouchScreen::OnInit() {}
void TouchScreen::OnRelease() {}
void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
- shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
+ shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
if (!IsControllerActivated()) {
- shared_memory->touch_screen_lifo.buffer_count = 0;
- shared_memory->touch_screen_lifo.buffer_tail = 0;
+ shared_memory.touch_screen_lifo.buffer_count = 0;
+ shared_memory.touch_screen_lifo.buffer_tail = 0;
return;
}
@@ -86,7 +82,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count());
- const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;
+ const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
next_state.entry_count = static_cast<s32>(active_fingers_count);
@@ -118,7 +114,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
}
}
- shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
+ shared_memory.touch_screen_lifo.WriteNextEntry(next_state);
}
void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 79f026a81..5b6305bfc 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -3,20 +3,23 @@
#pragma once
-#include "common/common_funcs.h"
-#include "common/common_types.h"
+#include <array>
+
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
+#include "core/hle/service/hid/controllers/types/touch_types.h"
namespace Core::HID {
class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
+struct TouchScreenSharedMemoryFormat;
+
class TouchScreen final : public ControllerBase {
public:
- explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
+ explicit TouchScreen(Core::HID::HIDCore& hid_core_,
+ TouchScreenSharedMemoryFormat& touch_shared_memory);
~TouchScreen() override;
// Called when the controller is initialized
@@ -31,27 +34,8 @@ public:
void SetTouchscreenDimensions(u32 width, u32 height);
private:
- static constexpr std::size_t MAX_FINGERS = 16;
-
- // This is nn::hid::TouchScreenState
- struct TouchScreenState {
- s64 sampling_number{};
- s32 entry_count{};
- INSERT_PADDING_BYTES(4); // Reserved
- std::array<Core::HID::TouchState, MAX_FINGERS> states{};
- };
- static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
-
- struct TouchSharedMemory {
- // This is nn::hid::detail::TouchScreenLifo
- Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
- static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
- INSERT_PADDING_WORDS(0xF2);
- };
- static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
-
TouchScreenState next_state{};
- TouchSharedMemory* shared_memory = nullptr;
+ TouchScreenSharedMemoryFormat& shared_memory;
Core::HID::EmulatedConsole* console = nullptr;
std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
diff --git a/src/core/hle/service/hid/controllers/types/debug_pad_types.h b/src/core/hle/service/hid/controllers/types/debug_pad_types.h
new file mode 100644
index 000000000..a96171b62
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/debug_pad_types.h
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "core/hid/hid_types.h"
+
+namespace Service::HID {
+
+// This is nn::hid::DebugPadAttribute
+struct DebugPadAttribute {
+ union {
+ u32 raw{};
+ BitField<0, 1, u32> connected;
+ };
+};
+static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
+
+// This is nn::hid::DebugPadState
+struct DebugPadState {
+ s64 sampling_number{};
+ DebugPadAttribute attribute{};
+ Core::HID::DebugPadButton pad_state{};
+ Core::HID::AnalogStickState r_stick{};
+ Core::HID::AnalogStickState l_stick{};
+};
+static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/gesture_types.h b/src/core/hle/service/hid/controllers/types/gesture_types.h
new file mode 100644
index 000000000..b4f034cd3
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/gesture_types.h
@@ -0,0 +1,77 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <array>
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "common/point.h"
+
+namespace Service::HID {
+static constexpr size_t MAX_FINGERS = 16;
+static constexpr size_t MAX_POINTS = 4;
+
+// This is nn::hid::GestureType
+enum class GestureType : u32 {
+ Idle, // Nothing touching the screen
+ Complete, // Set at the end of a touch event
+ Cancel, // Set when the number of fingers change
+ Touch, // A finger just touched the screen
+ Press, // Set if last type is touch and the finger hasn't moved
+ Tap, // Fast press then release
+ Pan, // All points moving together across the screen
+ Swipe, // Fast press movement and release of a single point
+ Pinch, // All points moving away/closer to the midpoint
+ Rotate, // All points rotating from the midpoint
+};
+
+// This is nn::hid::GestureDirection
+enum class GestureDirection : u32 {
+ None,
+ Left,
+ Up,
+ Right,
+ Down,
+};
+
+// This is nn::hid::GestureAttribute
+struct GestureAttribute {
+ union {
+ u32 raw{};
+
+ BitField<4, 1, u32> is_new_touch;
+ BitField<8, 1, u32> is_double_tap;
+ };
+};
+static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
+
+// This is nn::hid::GestureState
+struct GestureState {
+ s64 sampling_number{};
+ s64 detection_count{};
+ GestureType type{GestureType::Idle};
+ GestureDirection direction{GestureDirection::None};
+ Common::Point<s32> pos{};
+ Common::Point<s32> delta{};
+ f32 vel_x{};
+ f32 vel_y{};
+ GestureAttribute attributes{};
+ f32 scale{};
+ f32 rotation_angle{};
+ s32 point_count{};
+ std::array<Common::Point<s32>, 4> points{};
+};
+static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
+
+struct GestureProperties {
+ std::array<Common::Point<s32>, MAX_POINTS> points{};
+ std::size_t active_points{};
+ Common::Point<s32> mid_point{};
+ s64 detection_count{};
+ u64 delta_time{};
+ f32 average_distance{};
+ f32 angle{};
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/keyboard_types.h b/src/core/hle/service/hid/controllers/types/keyboard_types.h
new file mode 100644
index 000000000..f44a536b9
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/keyboard_types.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/common_types.h"
+#include "core/hid/hid_types.h"
+
+namespace Service::HID {
+
+// This is nn::hid::detail::KeyboardState
+struct KeyboardState {
+ s64 sampling_number{};
+ Core::HID::KeyboardModifier modifier{};
+ Core::HID::KeyboardAttribute attribute{};
+ Core::HID::KeyboardKey key{};
+};
+static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/mouse_types.h b/src/core/hle/service/hid/controllers/types/mouse_types.h
new file mode 100644
index 000000000..8bd6e167c
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/mouse_types.h
@@ -0,0 +1,8 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Service::HID {} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h
new file mode 100644
index 000000000..a5ce2562b
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/npad_types.h
@@ -0,0 +1,254 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "core/hid/hid_types.h"
+
+namespace Service::HID {
+static constexpr std::size_t NpadCount = 10;
+
+// This is nn::hid::NpadJoyHoldType
+enum class NpadJoyHoldType : u64 {
+ Vertical = 0,
+ Horizontal = 1,
+};
+
+// This is nn::hid::NpadJoyAssignmentMode
+enum class NpadJoyAssignmentMode : u32 {
+ Dual = 0,
+ Single = 1,
+};
+
+// This is nn::hid::NpadJoyDeviceType
+enum class NpadJoyDeviceType : s64 {
+ Left = 0,
+ Right = 1,
+};
+
+// This is nn::hid::NpadHandheldActivationMode
+enum class NpadHandheldActivationMode : u64 {
+ Dual = 0,
+ Single = 1,
+ None = 2,
+ MaxActivationMode = 3,
+};
+
+// This is nn::hid::system::AppletFooterUiAttributesSet
+struct AppletFooterUiAttributes {
+ INSERT_PADDING_BYTES(0x4);
+};
+
+// This is nn::hid::system::AppletFooterUiType
+enum class AppletFooterUiType : u8 {
+ None = 0,
+ HandheldNone = 1,
+ HandheldJoyConLeftOnly = 2,
+ HandheldJoyConRightOnly = 3,
+ HandheldJoyConLeftJoyConRight = 4,
+ JoyDual = 5,
+ JoyDualLeftOnly = 6,
+ JoyDualRightOnly = 7,
+ JoyLeftHorizontal = 8,
+ JoyLeftVertical = 9,
+ JoyRightHorizontal = 10,
+ JoyRightVertical = 11,
+ SwitchProController = 12,
+ CompatibleProController = 13,
+ CompatibleJoyCon = 14,
+ LarkHvc1 = 15,
+ LarkHvc2 = 16,
+ LarkNesLeft = 17,
+ LarkNesRight = 18,
+ Lucia = 19,
+ Verification = 20,
+ Lagon = 21,
+};
+
+using AppletFooterUiVariant = u8;
+
+// This is "nn::hid::system::AppletDetailedUiType".
+struct AppletDetailedUiType {
+ AppletFooterUiVariant ui_variant;
+ INSERT_PADDING_BYTES(0x2);
+ AppletFooterUiType footer;
+};
+static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
+// This is nn::hid::NpadCommunicationMode
+enum class NpadCommunicationMode : u64 {
+ Mode_5ms = 0,
+ Mode_10ms = 1,
+ Mode_15ms = 2,
+ Default = 3,
+};
+
+enum class NpadRevision : u32 {
+ Revision0 = 0,
+ Revision1 = 1,
+ Revision2 = 2,
+ Revision3 = 3,
+};
+
+// This is nn::hid::detail::ColorAttribute
+enum class ColorAttribute : u32 {
+ Ok = 0,
+ ReadError = 1,
+ NoController = 2,
+};
+static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
+
+// This is nn::hid::detail::NpadFullKeyColorState
+struct NpadFullKeyColorState {
+ ColorAttribute attribute{ColorAttribute::NoController};
+ Core::HID::NpadControllerColor fullkey{};
+};
+static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
+
+// This is nn::hid::detail::NpadJoyColorState
+struct NpadJoyColorState {
+ ColorAttribute attribute{ColorAttribute::NoController};
+ Core::HID::NpadControllerColor left{};
+ Core::HID::NpadControllerColor right{};
+};
+static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
+
+// This is nn::hid::NpadAttribute
+struct NpadAttribute {
+ union {
+ u32 raw{};
+ BitField<0, 1, u32> is_connected;
+ BitField<1, 1, u32> is_wired;
+ BitField<2, 1, u32> is_left_connected;
+ BitField<3, 1, u32> is_left_wired;
+ BitField<4, 1, u32> is_right_connected;
+ BitField<5, 1, u32> is_right_wired;
+ };
+};
+static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
+
+// This is nn::hid::NpadFullKeyState
+// This is nn::hid::NpadHandheldState
+// This is nn::hid::NpadJoyDualState
+// This is nn::hid::NpadJoyLeftState
+// This is nn::hid::NpadJoyRightState
+// This is nn::hid::NpadPalmaState
+// This is nn::hid::NpadSystemExtState
+struct NPadGenericState {
+ s64_le sampling_number{};
+ Core::HID::NpadButtonState npad_buttons{};
+ Core::HID::AnalogStickState l_stick{};
+ Core::HID::AnalogStickState r_stick{};
+ NpadAttribute connection_status{};
+ INSERT_PADDING_BYTES(4); // Reserved
+};
+static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
+
+// This is nn::hid::server::NpadGcTriggerState
+struct NpadGcTriggerState {
+ s64 sampling_number{};
+ s32 l_analog{};
+ s32 r_analog{};
+};
+static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
+
+// This is nn::hid::NpadSystemProperties
+struct NPadSystemProperties {
+ union {
+ s64 raw{};
+ BitField<0, 1, s64> is_charging_joy_dual;
+ BitField<1, 1, s64> is_charging_joy_left;
+ BitField<2, 1, s64> is_charging_joy_right;
+ BitField<3, 1, s64> is_powered_joy_dual;
+ BitField<4, 1, s64> is_powered_joy_left;
+ BitField<5, 1, s64> is_powered_joy_right;
+ BitField<9, 1, s64> is_system_unsupported_button;
+ BitField<10, 1, s64> is_system_ext_unsupported_button;
+ BitField<11, 1, s64> is_vertical;
+ BitField<12, 1, s64> is_horizontal;
+ BitField<13, 1, s64> use_plus;
+ BitField<14, 1, s64> use_minus;
+ BitField<15, 1, s64> use_directional_buttons;
+ };
+};
+static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
+
+// This is nn::hid::NpadSystemButtonProperties
+struct NpadSystemButtonProperties {
+ union {
+ s32 raw{};
+ BitField<0, 1, s32> is_home_button_protection_enabled;
+ };
+};
+static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
+
+// This is nn::hid::system::DeviceType
+struct DeviceType {
+ union {
+ u32 raw{};
+ BitField<0, 1, s32> fullkey;
+ BitField<1, 1, s32> debug_pad;
+ BitField<2, 1, s32> handheld_left;
+ BitField<3, 1, s32> handheld_right;
+ BitField<4, 1, s32> joycon_left;
+ BitField<5, 1, s32> joycon_right;
+ BitField<6, 1, s32> palma;
+ BitField<7, 1, s32> lark_hvc_left;
+ BitField<8, 1, s32> lark_hvc_right;
+ BitField<9, 1, s32> lark_nes_left;
+ BitField<10, 1, s32> lark_nes_right;
+ BitField<11, 1, s32> handheld_lark_hvc_left;
+ BitField<12, 1, s32> handheld_lark_hvc_right;
+ BitField<13, 1, s32> handheld_lark_nes_left;
+ BitField<14, 1, s32> handheld_lark_nes_right;
+ BitField<15, 1, s32> lucia;
+ BitField<16, 1, s32> lagon;
+ BitField<17, 1, s32> lager;
+ BitField<31, 1, s32> system;
+ };
+};
+
+// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
+struct NfcXcdDeviceHandleStateImpl {
+ u64 handle{};
+ bool is_available{};
+ bool is_activated{};
+ INSERT_PADDING_BYTES(0x6); // Reserved
+ u64 sampling_number{};
+};
+static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
+ "NfcXcdDeviceHandleStateImpl is an invalid size");
+
+// This is nn::hid::NpadLarkType
+enum class NpadLarkType : u32 {
+ Invalid,
+ H1,
+ H2,
+ NL,
+ NR,
+};
+
+// This is nn::hid::NpadLuciaType
+enum class NpadLuciaType : u32 {
+ Invalid,
+ J,
+ E,
+ U,
+};
+
+// This is nn::hid::NpadLagonType
+enum class NpadLagonType : u32 {
+ Invalid,
+};
+
+// This is nn::hid::NpadLagerType
+enum class NpadLagerType : u32 {
+ Invalid,
+ J,
+ E,
+ U,
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/types/touch_types.h b/src/core/hle/service/hid/controllers/types/touch_types.h
new file mode 100644
index 000000000..efeaa796d
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/types/touch_types.h
@@ -0,0 +1,90 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <array>
+
+#include <array>
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/point.h"
+#include "core/hid/hid_types.h"
+
+namespace Service::HID {
+static constexpr std::size_t MAX_FINGERS = 16;
+static constexpr size_t MAX_POINTS = 4;
+
+// This is nn::hid::GestureType
+enum class GestureType : u32 {
+ Idle, // Nothing touching the screen
+ Complete, // Set at the end of a touch event
+ Cancel, // Set when the number of fingers change
+ Touch, // A finger just touched the screen
+ Press, // Set if last type is touch and the finger hasn't moved
+ Tap, // Fast press then release
+ Pan, // All points moving together across the screen
+ Swipe, // Fast press movement and release of a single point
+ Pinch, // All points moving away/closer to the midpoint
+ Rotate, // All points rotating from the midpoint
+};
+
+// This is nn::hid::GestureDirection
+enum class GestureDirection : u32 {
+ None,
+ Left,
+ Up,
+ Right,
+ Down,
+};
+
+// This is nn::hid::GestureAttribute
+struct GestureAttribute {
+ union {
+ u32 raw{};
+
+ BitField<4, 1, u32> is_new_touch;
+ BitField<8, 1, u32> is_double_tap;
+ };
+};
+static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
+
+// This is nn::hid::GestureState
+struct GestureState {
+ s64 sampling_number{};
+ s64 detection_count{};
+ GestureType type{GestureType::Idle};
+ GestureDirection direction{GestureDirection::None};
+ Common::Point<s32> pos{};
+ Common::Point<s32> delta{};
+ f32 vel_x{};
+ f32 vel_y{};
+ GestureAttribute attributes{};
+ f32 scale{};
+ f32 rotation_angle{};
+ s32 point_count{};
+ std::array<Common::Point<s32>, 4> points{};
+};
+static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
+
+struct GestureProperties {
+ std::array<Common::Point<s32>, MAX_POINTS> points{};
+ std::size_t active_points{};
+ Common::Point<s32> mid_point{};
+ s64 detection_count{};
+ u64 delta_time{};
+ f32 average_distance{};
+ f32 angle{};
+};
+
+// This is nn::hid::TouchScreenState
+struct TouchScreenState {
+ s64 sampling_number{};
+ s32 entry_count{};
+ INSERT_PADDING_BYTES(4); // Reserved
+ std::array<Core::HID::TouchState, MAX_FINGERS> states{};
+};
+static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
deleted file mode 100644
index 0aaed1fa7..000000000
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <cstring>
-#include "common/common_types.h"
-#include "core/core_timing.h"
-#include "core/hid/hid_core.h"
-#include "core/hle/service/hid/controllers/xpad.h"
-
-namespace Service::HID {
-constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
-
-XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
- static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
- "XpadSharedMemory is bigger than the shared memory");
- shared_memory = std::construct_at(
- reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
-}
-XPad::~XPad() = default;
-
-void XPad::OnInit() {}
-
-void XPad::OnRelease() {}
-
-void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
- if (!IsControllerActivated()) {
- shared_memory->basic_xpad_lifo.buffer_count = 0;
- shared_memory->basic_xpad_lifo.buffer_tail = 0;
- return;
- }
-
- const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;
- next_state.sampling_number = last_entry.sampling_number + 1;
- // TODO(ogniK): Update xpad states
-
- shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);
-}
-
-} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
deleted file mode 100644
index 9e63a317a..000000000
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "common/bit_field.h"
-#include "common/common_types.h"
-#include "core/hid/hid_types.h"
-#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/ring_lifo.h"
-
-namespace Service::HID {
-class XPad final : public ControllerBase {
-public:
- explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
- ~XPad() override;
-
- // Called when the controller is initialized
- void OnInit() override;
-
- // When the controller is released
- void OnRelease() override;
-
- // When the controller is requesting an update for the shared memory
- void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
-
-private:
- // This is nn::hid::BasicXpadAttributeSet
- struct BasicXpadAttributeSet {
- union {
- u32 raw{};
- BitField<0, 1, u32> is_connected;
- BitField<1, 1, u32> is_wired;
- BitField<2, 1, u32> is_left_connected;
- BitField<3, 1, u32> is_left_wired;
- BitField<4, 1, u32> is_right_connected;
- BitField<5, 1, u32> is_right_wired;
- };
- };
- static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
-
- // This is nn::hid::BasicXpadButtonSet
- struct BasicXpadButtonSet {
- union {
- u32 raw{};
- // Button states
- BitField<0, 1, u32> a;
- BitField<1, 1, u32> b;
- BitField<2, 1, u32> x;
- BitField<3, 1, u32> y;
- BitField<4, 1, u32> l_stick;
- BitField<5, 1, u32> r_stick;
- BitField<6, 1, u32> l;
- BitField<7, 1, u32> r;
- BitField<8, 1, u32> zl;
- BitField<9, 1, u32> zr;
- BitField<10, 1, u32> plus;
- BitField<11, 1, u32> minus;
-
- // D-Pad
- BitField<12, 1, u32> d_left;
- BitField<13, 1, u32> d_up;
- BitField<14, 1, u32> d_right;
- BitField<15, 1, u32> d_down;
-
- // Left JoyStick
- BitField<16, 1, u32> l_stick_left;
- BitField<17, 1, u32> l_stick_up;
- BitField<18, 1, u32> l_stick_right;
- BitField<19, 1, u32> l_stick_down;
-
- // Right JoyStick
- BitField<20, 1, u32> r_stick_left;
- BitField<21, 1, u32> r_stick_up;
- BitField<22, 1, u32> r_stick_right;
- BitField<23, 1, u32> r_stick_down;
-
- // Not always active?
- BitField<24, 1, u32> left_sl;
- BitField<25, 1, u32> left_sr;
-
- BitField<26, 1, u32> right_sl;
- BitField<27, 1, u32> right_sr;
-
- BitField<28, 1, u32> palma;
- BitField<30, 1, u32> handheld_left_b;
- };
- };
- static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
-
- // This is nn::hid::detail::BasicXpadState
- struct BasicXpadState {
- s64 sampling_number{};
- BasicXpadAttributeSet attributes{};
- BasicXpadButtonSet pad_states{};
- Core::HID::AnalogStickState l_stick{};
- Core::HID::AnalogStickState r_stick{};
- };
- static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
-
- struct XpadSharedMemory {
- // This is nn::hid::detail::BasicXpadLifo
- Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
- static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
- INSERT_PADDING_WORDS(0x4E);
- };
- static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size");
-
- BasicXpadState next_state{};
- XpadSharedMemory* shared_memory = nullptr;
-};
-} // namespace Service::HID
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h
index 9585bdaf0..6dc976fe1 100644
--- a/src/core/hle/service/hid/errors.h
+++ b/src/core/hle/service/hid/errors.h
@@ -19,6 +19,14 @@ constexpr Result NpadIsSameType{ErrorModule::HID, 602};
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
+
+constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041};
+constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042};
+constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043};
+constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044};
+constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046};
+constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047};
+
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 1b7381d8d..afbcb019f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/hid_debug_server.h"
#include "core/hle/service/hid/hid_firmware_settings.h"
@@ -20,6 +22,12 @@ void LoopProcess(Core::System& system) {
std::shared_ptr<HidFirmwareSettings> firmware_settings =
std::make_shared<HidFirmwareSettings>();
+ // TODO: Remove this hack until this service is emulated properly.
+ const auto process_list = system.Kernel().GetProcessList();
+ if (!process_list.empty()) {
+ resouce_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
+ }
+
server_manager->RegisterNamedService(
"hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings));
server_manager->RegisterNamedService(
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
index a7d1578d9..de24b0401 100644
--- a/src/core/hle/service/hid/hid_server.cpp
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -28,6 +28,7 @@
#include "core/hle/service/hid/controllers/seven_six_axis.h"
#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
+#include "core/hle/service/hid/controllers/types/npad_types.h"
namespace Service::HID {
@@ -222,11 +223,14 @@ void IHidServer::CreateAppletResource(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+ Result result = GetResourceManager()->CreateAppletResource(applet_resource_user_id);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}",
+ applet_resource_user_id, result.raw);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAppletResource>(system, resource_manager);
+ rb.Push(result);
+ rb.PushIpcInterface<IAppletResource>(system, resource_manager, applet_resource_user_id);
}
void IHidServer::ActivateDebugPad(HLERequestContext& ctx) {
@@ -1096,7 +1100,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
- NPad::NpadRevision revision;
+ NpadRevision revision;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
};
@@ -1119,7 +1123,7 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
+ const auto hold_type{rp.PopEnum<NpadJoyHoldType>()};
GetResourceManager()->GetNpad()->SetHoldType(hold_type);
@@ -1154,8 +1158,8 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
Core::HID::NpadIdType new_npad_id{};
auto controller = GetResourceManager()->GetNpad();
- controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
- NPad::NpadJoyAssignmentMode::Single);
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left,
+ NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
parameters.applet_resource_user_id);
@@ -1170,7 +1174,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
- NPad::NpadJoyDeviceType npad_joy_device_type;
+ NpadJoyDeviceType npad_joy_device_type;
};
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
@@ -1179,7 +1183,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
Core::HID::NpadIdType new_npad_id{};
auto controller = GetResourceManager()->GetNpad();
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- NPad::NpadJoyAssignmentMode::Single);
+ NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
parameters.npad_id, parameters.applet_resource_user_id,
@@ -1202,7 +1206,7 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
Core::HID::NpadIdType new_npad_id{};
auto controller = GetResourceManager()->GetNpad();
- controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
+ controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual);
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
parameters.applet_resource_user_id); // Spams a lot when controller applet is open
@@ -1254,7 +1258,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
+ const auto activation_mode{rp.PopEnum<NpadHandheldActivationMode>()};
GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
@@ -1346,7 +1350,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
Core::HID::NpadIdType npad_id;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
- NPad::NpadJoyDeviceType npad_joy_device_type;
+ NpadJoyDeviceType npad_joy_device_type;
};
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
@@ -1356,7 +1360,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
auto controller = GetResourceManager()->GetNpad();
const auto is_reassigned =
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- NPad::NpadJoyAssignmentMode::Single);
+ NpadJoyAssignmentMode::Single);
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
parameters.npad_id, parameters.applet_resource_user_id,
@@ -2312,7 +2316,7 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
+ const auto communication_mode{rp.PopEnum<NpadCommunicationMode>()};
GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp
index b56d0347a..5cc88c4a1 100644
--- a/src/core/hle/service/hid/hid_system_server.cpp
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -3,7 +3,9 @@
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/palma.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
+#include "core/hle/service/hid/controllers/types/npad_types.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_system_server.h"
#include "core/hle/service/hid/resource_manager.h"
@@ -63,13 +65,13 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{329, nullptr, "DetachAbstractedPadAll"},
{330, nullptr, "CheckAbstractedPadConnection"},
{500, nullptr, "SetAppletResourceUserId"},
- {501, nullptr, "RegisterAppletResourceUserId"},
- {502, nullptr, "UnregisterAppletResourceUserId"},
- {503, nullptr, "EnableAppletToGetInput"},
+ {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"},
+ {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"},
+ {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"},
{504, nullptr, "SetAruidValidForVibration"},
- {505, nullptr, "EnableAppletToGetSixAxisSensor"},
- {506, nullptr, "EnableAppletToGetPadInput"},
- {507, nullptr, "EnableAppletToGetTouchScreen"},
+ {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"},
+ {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"},
+ {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"},
{510, nullptr, "SetVibrationMasterVolume"},
{511, nullptr, "GetVibrationMasterVolume"},
{512, nullptr, "BeginPermitVibrationSession"},
@@ -327,7 +329,7 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
- const NPad::AppletDetailedUiType detailed_ui_type =
+ const AppletDetailedUiType detailed_ui_type =
GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
IPC::ResponseBuilder rb{ctx, 3};
@@ -420,6 +422,129 @@ void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
+void IHidSystemServer::RegisterAppletResourceUserId(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool enable_input;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, enable_input={}, applet_resource_user_id={}",
+ parameters.enable_input, parameters.applet_resource_user_id);
+
+ Result result = GetResourceManager()->RegisterAppletResourceUserId(
+ parameters.applet_resource_user_id, parameters.enable_input);
+
+ if (result.IsSuccess()) {
+ // result = GetResourceManager()->GetNpad()->RegisterAppletResourceUserId(
+ // parameters.applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::UnregisterAppletResourceUserId(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ u64 applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ GetResourceManager()->UnregisterAppletResourceUserId(applet_resource_user_id);
+ // GetResourceManager()->GetNpad()->UnregisterAppletResourceUserId(applet_resource_user_id);
+ // GetResourceManager()->GetPalma()->UnregisterAppletResourceUserId(applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
+ parameters.is_enabled, parameters.applet_resource_user_id);
+
+ GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled);
+ // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::EnableAppletToGetSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
+ parameters.is_enabled, parameters.applet_resource_user_id);
+
+ GetResourceManager()->EnableTouchScreen(parameters.applet_resource_user_id,
+ parameters.is_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::EnableAppletToGetPadInput(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
+ parameters.is_enabled, parameters.applet_resource_user_id);
+
+ GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled);
+ // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::EnableAppletToGetTouchScreen(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
+ parameters.is_enabled, parameters.applet_resource_user_id);
+
+ GetResourceManager()->EnableTouchScreen(parameters.applet_resource_user_id,
+ parameters.is_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
void IHidSystemServer::AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx) {
LOG_INFO(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h
index 822d5e5b9..1e623dfc2 100644
--- a/src/core/hle/service/hid/hid_system_server.h
+++ b/src/core/hle/service/hid/hid_system_server.h
@@ -38,6 +38,12 @@ private:
void HasLeftRightBattery(HLERequestContext& ctx);
void GetUniquePadsFromNpad(HLERequestContext& ctx);
void GetIrSensorState(HLERequestContext& ctx);
+ void RegisterAppletResourceUserId(HLERequestContext& ctx);
+ void UnregisterAppletResourceUserId(HLERequestContext& ctx);
+ void EnableAppletToGetInput(HLERequestContext& ctx);
+ void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx);
+ void EnableAppletToGetPadInput(HLERequestContext& ctx);
+ void EnableAppletToGetTouchScreen(HLERequestContext& ctx);
void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx);
void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx);
void GetRegisteredDevices(HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp
index e76d4eea9..6c6cbd802 100644
--- a/src/core/hle/service/hid/resource_manager.cpp
+++ b/src/core/hle/service/hid/resource_manager.cpp
@@ -9,6 +9,7 @@
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/hid/controllers/applet_resource.h"
#include "core/hle/service/hid/controllers/console_six_axis.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
#include "core/hle/service/hid/controllers/gesture.h"
@@ -17,10 +18,10 @@
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/palma.h"
#include "core/hle/service/hid/controllers/seven_six_axis.h"
+#include "core/hle/service/hid/controllers/shared_memory_format.h"
#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/controllers/stubbed.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
-#include "core/hle/service/hid/controllers/xpad.h"
namespace Service::HID {
@@ -33,7 +34,9 @@ constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 10
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
ResourceManager::ResourceManager(Core::System& system_)
- : system{system_}, service_context{system_, "hid"} {}
+ : system{system_}, service_context{system_, "hid"} {
+ applet_resource = std::make_shared<AppletResource>(system);
+}
ResourceManager::~ResourceManager() = default;
@@ -42,41 +45,49 @@ void ResourceManager::Initialize() {
return;
}
- u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
- debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
- mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
- debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
- keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
- unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
- npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
- gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
- touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
- xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
+ system.HIDCore().ReloadInputDevices();
+ is_initialized = true;
+}
+
+void ResourceManager::InitializeController(u64 aruid) {
+ SharedMemoryFormat* shared_memory = nullptr;
+ const auto result = applet_resource->GetSharedMemoryFormat(&shared_memory, aruid);
+ if (result.IsError()) {
+ return;
+ }
+
+ debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory->debug_pad);
+ mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory->mouse);
+ debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory->debug_mouse);
+ keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory->keyboard);
+ unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory->unique_pad.header);
+ npad = std::make_shared<NPad>(system.HIDCore(), shared_memory->npad, service_context);
+ gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory->gesture);
+ touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory->touch_screen);
- palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
+ palma = std::make_shared<Palma>(system.HIDCore(), service_context);
- home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
- sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
- capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
+ home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory->home_button.header);
+ sleep_button =
+ std::make_shared<SleepButton>(system.HIDCore(), shared_memory->sleep_button.header);
+ capture_button =
+ std::make_shared<CaptureButton>(system.HIDCore(), shared_memory->capture_button.header);
+ digitizer = std::make_shared<Digitizer>(system.HIDCore(), shared_memory->digitizer.header);
six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
- console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
+ console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory->console);
seven_six_axis = std::make_shared<SevenSixAxis>(system);
- home_button->SetCommonHeaderOffset(0x4C00);
- sleep_button->SetCommonHeaderOffset(0x4E00);
- capture_button->SetCommonHeaderOffset(0x5000);
- unique_pad->SetCommonHeaderOffset(0x5A00);
- debug_mouse->SetCommonHeaderOffset(0x3DC00);
-
// Homebrew doesn't try to activate some controllers, so we activate them by default
npad->Activate();
six_axis->Activate();
touch_screen->Activate();
+}
- system.HIDCore().ReloadInputDevices();
- is_initialized = true;
+std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
+ return applet_resource;
}
+
std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
return capture_button;
}
@@ -93,6 +104,10 @@ std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
return debug_pad;
}
+std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
+ return digitizer;
+}
+
std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
return gesture;
}
@@ -137,10 +152,86 @@ std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
return unique_pad;
}
+Result ResourceManager::CreateAppletResource(u64 aruid) {
+ if (aruid == 0) {
+ const auto result = RegisterCoreAppletResource();
+ if (result.IsError()) {
+ return result;
+ }
+ return GetNpad()->Activate();
+ }
+
+ const auto result = CreateAppletResourceImpl(aruid);
+ if (result.IsError()) {
+ return result;
+ }
+ return GetNpad()->Activate(aruid);
+}
+
+Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
+ std::scoped_lock lock{shared_mutex};
+ const auto result = applet_resource->CreateAppletResource(aruid);
+ if (result.IsSuccess()) {
+ InitializeController(aruid);
+ }
+ return result;
+}
+
+Result ResourceManager::RegisterCoreAppletResource() {
+ std::scoped_lock lock{shared_mutex};
+ return applet_resource->RegisterCoreAppletResource();
+}
+
+Result ResourceManager::UnregisterCoreAppletResource() {
+ std::scoped_lock lock{shared_mutex};
+ return applet_resource->UnregisterCoreAppletResource();
+}
+
+Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) {
+ std::scoped_lock lock{shared_mutex};
+ return applet_resource->RegisterAppletResourceUserId(aruid, bool_value);
+}
+
+void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->UnregisterAppletResourceUserId(aruid);
+}
+
+Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
+ std::scoped_lock lock{shared_mutex};
+ return applet_resource->GetSharedMemoryHandle(out_handle, aruid);
+}
+
+void ResourceManager::FreeAppletResourceId(u64 aruid) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->FreeAppletResourceId(aruid);
+}
+
+void ResourceManager::EnableInput(u64 aruid, bool is_enabled) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->EnableInput(aruid, is_enabled);
+}
+
+void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->EnableSixAxisSensor(aruid, is_enabled);
+}
+
+void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->EnablePadInput(aruid, is_enabled);
+}
+
+void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
+ std::scoped_lock lock{shared_mutex};
+ applet_resource->EnableTouchScreen(aruid, is_enabled);
+}
+
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
debug_pad->OnUpdate(core_timing);
+ digitizer->OnUpdate(core_timing);
unique_pad->OnUpdate(core_timing);
gesture->OnUpdate(core_timing);
touch_screen->OnUpdate(core_timing);
@@ -148,7 +239,6 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
home_button->OnUpdate(core_timing);
sleep_button->OnUpdate(core_timing);
capture_button->OnUpdate(core_timing);
- xpad->OnUpdate(core_timing);
}
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
@@ -171,15 +261,15 @@ void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose
console_six_axis->OnUpdate(core_timing);
}
-IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
- : ServiceFramework{system_, "IAppletResource"} {
+IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource,
+ u64 applet_resource_user_id)
+ : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id},
+ resource_manager{resource} {
static const FunctionInfo functions[] = {
{0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
};
RegisterHandlers(functions);
- resource->Initialize();
-
// Register update callbacks
npad_update_event = Core::Timing::CreateEvent(
"HID::UpdatePadCallback",
@@ -228,14 +318,18 @@ IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(default_update_event, 0);
system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
+ resource_manager->FreeAppletResourceId(aruid);
}
void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
+ Kernel::KSharedMemory* handle;
+ const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw);
IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
+ rb.Push(result);
+ rb.PushCopyObjects(handle);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h
index 2b6a9b5e6..5ad7cb564 100644
--- a/src/core/hle/service/hid/resource_manager.h
+++ b/src/core/hle/service/hid/resource_manager.h
@@ -6,11 +6,20 @@
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
+namespace Core {
+class System;
+}
+
namespace Core::Timing {
struct EventType;
}
+namespace Kernel {
+class KSharedMemory;
+}
+
namespace Service::HID {
+class AppletResource;
class Controller_Stubbed;
class ConsoleSixAxis;
class DebugPad;
@@ -22,10 +31,10 @@ class Palma;
class SevenSixAxis;
class SixAxis;
class TouchScreen;
-class XPad;
using CaptureButton = Controller_Stubbed;
-using DebugMouse = Controller_Stubbed;
+using DebugMouse = Mouse;
+using Digitizer = Controller_Stubbed;
using HomeButton = Controller_Stubbed;
using SleepButton = Controller_Stubbed;
using UniquePad = Controller_Stubbed;
@@ -37,11 +46,14 @@ public:
~ResourceManager();
void Initialize();
+ void InitializeController(u64 aruid);
+ std::shared_ptr<AppletResource> GetAppletResource() const;
std::shared_ptr<CaptureButton> GetCaptureButton() const;
std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
std::shared_ptr<DebugMouse> GetDebugMouse() const;
std::shared_ptr<DebugPad> GetDebugPad() const;
+ std::shared_ptr<Digitizer> GetDigitizer() const;
std::shared_ptr<Gesture> GetGesture() const;
std::shared_ptr<HomeButton> GetHomeButton() const;
std::shared_ptr<Keyboard> GetKeyboard() const;
@@ -54,18 +66,39 @@ public:
std::shared_ptr<TouchScreen> GetTouchScreen() const;
std::shared_ptr<UniquePad> GetUniquePad() const;
+ Result CreateAppletResource(u64 aruid);
+
+ Result RegisterCoreAppletResource();
+ Result UnregisterCoreAppletResource();
+ Result RegisterAppletResourceUserId(u64 aruid, bool bool_value);
+ void UnregisterAppletResourceUserId(u64 aruid);
+
+ Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
+ void FreeAppletResourceId(u64 aruid);
+
+ void EnableInput(u64 aruid, bool is_enabled);
+ void EnableSixAxisSensor(u64 aruid, bool is_enabled);
+ void EnablePadInput(u64 aruid, bool is_enabled);
+ void EnableTouchScreen(u64 aruid, bool is_enabled);
+
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
private:
+ Result CreateAppletResourceImpl(u64 aruid);
+
bool is_initialized{false};
+ mutable std::mutex shared_mutex;
+ std::shared_ptr<AppletResource> applet_resource = nullptr;
+
std::shared_ptr<CaptureButton> capture_button = nullptr;
std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
std::shared_ptr<DebugMouse> debug_mouse = nullptr;
std::shared_ptr<DebugPad> debug_pad = nullptr;
+ std::shared_ptr<Digitizer> digitizer = nullptr;
std::shared_ptr<Gesture> gesture = nullptr;
std::shared_ptr<HomeButton> home_button = nullptr;
std::shared_ptr<Keyboard> keyboard = nullptr;
@@ -77,7 +110,6 @@ private:
std::shared_ptr<SleepButton> sleep_button = nullptr;
std::shared_ptr<TouchScreen> touch_screen = nullptr;
std::shared_ptr<UniquePad> unique_pad = nullptr;
- std::shared_ptr<XPad> xpad = nullptr;
// TODO: Create these resources
// std::shared_ptr<AudioControl> audio_control = nullptr;
@@ -96,7 +128,8 @@ private:
class IAppletResource final : public ServiceFramework<IAppletResource> {
public:
- explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource);
+ explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource,
+ u64 applet_resource_user_id);
~IAppletResource() override;
private:
@@ -106,6 +139,9 @@ private:
std::shared_ptr<Core::Timing::EventType> default_update_event;
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
std::shared_ptr<Core::Timing::EventType> motion_update_event;
+
+ u64 aruid;
+ std::shared_ptr<ResourceManager> resource_manager;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp
index ff374ae39..38955932c 100644
--- a/src/core/hle/service/hle_ipc.cpp
+++ b/src/core/hle/service/hle_ipc.cpp
@@ -146,8 +146,10 @@ HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory::
HLERequestContext::~HLERequestContext() = default;
-void HLERequestContext::ParseCommandBuffer(const Kernel::KHandleTable& handle_table,
- u32_le* src_cmdbuf, bool incoming) {
+void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf,
+ bool incoming) {
+ client_handle_table = &process.GetHandleTable();
+
IPC::RequestParser rp(src_cmdbuf);
command_header = rp.PopRaw<IPC::CommandHeader>();
@@ -160,7 +162,8 @@ void HLERequestContext::ParseCommandBuffer(const Kernel::KHandleTable& handle_ta
if (command_header->enable_handle_descriptor) {
handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>();
if (handle_descriptor_header->send_current_pid) {
- pid = rp.Pop<u64>();
+ pid = process.GetProcessId();
+ rp.Skip(2, false);
}
if (incoming) {
// Populate the object lists with the data in the IPC request.
@@ -267,9 +270,9 @@ void HLERequestContext::ParseCommandBuffer(const Kernel::KHandleTable& handle_ta
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
}
-Result HLERequestContext::PopulateFromIncomingCommandBuffer(
- const Kernel::KHandleTable& handle_table, u32_le* src_cmdbuf) {
- ParseCommandBuffer(handle_table, src_cmdbuf, true);
+Result HLERequestContext::PopulateFromIncomingCommandBuffer(Kernel::KProcess& process,
+ u32_le* src_cmdbuf) {
+ ParseCommandBuffer(process, src_cmdbuf, true);
if (command_header->IsCloseCommand()) {
// Close does not populate the rest of the IPC header
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h
index ad5259a5c..18d464c63 100644
--- a/src/core/hle/service/hle_ipc.h
+++ b/src/core/hle/service/hle_ipc.h
@@ -38,6 +38,7 @@ namespace Kernel {
class KAutoObject;
class KernelCore;
class KHandleTable;
+class KProcess;
class KServerSession;
class KThread;
} // namespace Kernel
@@ -75,6 +76,7 @@ protected:
using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
+using SessionRequestHandlerFactory = std::function<SessionRequestHandlerPtr()>;
/**
* Manages the underlying HLE requests for a session, and whether (or not) the session should be
@@ -194,8 +196,7 @@ public:
}
/// Populates this context with data from the requesting process/thread.
- Result PopulateFromIncomingCommandBuffer(const Kernel::KHandleTable& handle_table,
- u32_le* src_cmdbuf);
+ Result PopulateFromIncomingCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf);
/// Writes data from this context back to the requesting process/thread.
Result WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread);
@@ -358,6 +359,10 @@ public:
return *thread;
}
+ Kernel::KHandleTable& GetClientHandleTable() {
+ return *client_handle_table;
+ }
+
[[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const {
return manager.lock();
}
@@ -373,12 +378,12 @@ public:
private:
friend class IPC::ResponseBuilder;
- void ParseCommandBuffer(const Kernel::KHandleTable& handle_table, u32_le* src_cmdbuf,
- bool incoming);
+ void ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf, bool incoming);
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
Kernel::KServerSession* server_session{};
- Kernel::KThread* thread;
+ Kernel::KHandleTable* client_handle_table{};
+ Kernel::KThread* thread{};
std::vector<Handle> incoming_move_handles;
std::vector<Handle> incoming_copy_handles;
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index be996870f..65851fc05 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "core/arm/debug.h"
#include "core/arm/symbols.h"
#include "core/core.h"
#include "core/hle/kernel/k_code_memory.h"
@@ -98,8 +99,9 @@ public:
if (return_value == 0) {
// The callback has written to the output executable code range,
// requiring an instruction cache invalidation
- system.InvalidateCpuInstructionCacheRange(configuration.user_rx_memory.offset,
- configuration.user_rx_memory.size);
+ Core::InvalidateInstructionCacheRange(process.GetPointerUnsafe(),
+ configuration.user_rx_memory.offset,
+ configuration.user_rx_memory.size);
// Write back to the IPC output buffer, if provided
if (ctx.CanWriteBuffer()) {
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 97b6a9385..ba58b3a09 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -1,117 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <memory>
-#include <fmt/format.h>
-#include <mbedtls/sha256.h>
-
-#include "common/alignment.h"
-#include "common/hex_util.h"
-#include "common/scope_exit.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_page_table.h"
-#include "core/hle/kernel/svc_results.h"
-#include "core/hle/kernel/svc_types.h"
-#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/ldr/ldr.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
-#include "core/loader/nro.h"
-#include "core/memory.h"
namespace Service::LDR {
-constexpr Result ERROR_INSUFFICIENT_ADDRESS_SPACE{ErrorModule::RO, 2};
-
-[[maybe_unused]] constexpr Result ERROR_INVALID_MEMORY_STATE{ErrorModule::Loader, 51};
-constexpr Result ERROR_INVALID_NRO{ErrorModule::Loader, 52};
-constexpr Result ERROR_INVALID_NRR{ErrorModule::Loader, 53};
-constexpr Result ERROR_MISSING_NRR_HASH{ErrorModule::Loader, 54};
-constexpr Result ERROR_MAXIMUM_NRO{ErrorModule::Loader, 55};
-constexpr Result ERROR_MAXIMUM_NRR{ErrorModule::Loader, 56};
-constexpr Result ERROR_ALREADY_LOADED{ErrorModule::Loader, 57};
-constexpr Result ERROR_INVALID_ALIGNMENT{ErrorModule::Loader, 81};
-constexpr Result ERROR_INVALID_SIZE{ErrorModule::Loader, 82};
-constexpr Result ERROR_INVALID_NRO_ADDRESS{ErrorModule::Loader, 84};
-[[maybe_unused]] constexpr Result ERROR_INVALID_NRR_ADDRESS{ErrorModule::Loader, 85};
-constexpr Result ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87};
-
-constexpr std::size_t MAXIMUM_LOADED_RO{0x40};
-constexpr std::size_t MAXIMUM_MAP_RETRIES{0x200};
-
-constexpr std::size_t TEXT_INDEX{0};
-constexpr std::size_t RO_INDEX{1};
-constexpr std::size_t DATA_INDEX{2};
-
-struct NRRCertification {
- u64_le application_id_mask;
- u64_le application_id_pattern;
- INSERT_PADDING_BYTES(0x10);
- std::array<u8, 0x100> public_key; // Also known as modulus
- std::array<u8, 0x100> signature;
-};
-static_assert(sizeof(NRRCertification) == 0x220, "NRRCertification has invalid size.");
-
-struct NRRHeader {
- u32_le magic;
- u32_le certification_signature_key_generation; // 9.0.0+
- INSERT_PADDING_WORDS(2);
- NRRCertification certification;
- std::array<u8, 0x100> signature;
- u64_le application_id;
- u32_le size;
- u8 nrr_kind; // 7.0.0+
- INSERT_PADDING_BYTES(3);
- u32_le hash_offset;
- u32_le hash_count;
- INSERT_PADDING_WORDS(2);
-};
-static_assert(sizeof(NRRHeader) == 0x350, "NRRHeader has invalid size.");
-
-struct SegmentHeader {
- u32_le memory_offset;
- u32_le memory_size;
-};
-static_assert(sizeof(SegmentHeader) == 0x8, "SegmentHeader has invalid size.");
-
-struct NROHeader {
- // Switchbrew calls this "Start" (0x10)
- INSERT_PADDING_WORDS(1);
- u32_le mod_offset;
- INSERT_PADDING_WORDS(2);
-
- // Switchbrew calls this "Header" (0x70)
- u32_le magic;
- u32_le version;
- u32_le nro_size;
- u32_le flags;
- // .text, .ro, .data
- std::array<SegmentHeader, 3> segment_headers;
- u32_le bss_size;
- INSERT_PADDING_WORDS(1);
- std::array<u8, 0x20> build_id;
- u32_le dso_handle_offset;
- INSERT_PADDING_WORDS(1);
- // .apiInfo, .dynstr, .dynsym
- std::array<SegmentHeader, 3> segment_headers_2;
-};
-static_assert(sizeof(NROHeader) == 0x80, "NROHeader has invalid size.");
-
-using SHA256Hash = std::array<u8, 0x20>;
-
-struct NROInfo {
- SHA256Hash hash{};
- VAddr nro_address{};
- std::size_t nro_size{};
- VAddr bss_address{};
- std::size_t bss_size{};
- std::size_t text_size{};
- std::size_t ro_size{};
- std::size_t data_size{};
- VAddr src_addr{};
-};
-static_assert(sizeof(NROInfo) == 0x60, "NROInfo has invalid size.");
-
class DebugMonitor final : public ServiceFramework<DebugMonitor> {
public:
explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} {
@@ -158,541 +53,12 @@ public:
}
};
-class RelocatableObject final : public ServiceFramework<RelocatableObject> {
-public:
- explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &RelocatableObject::LoadModule, "LoadModule"},
- {1, &RelocatableObject::UnloadModule, "UnloadModule"},
- {2, &RelocatableObject::RegisterModuleInfo, "RegisterModuleInfo"},
- {3, &RelocatableObject::UnregisterModuleInfo, "UnregisterModuleInfo"},
- {4, &RelocatableObject::Initialize, "Initialize"},
- {10, nullptr, "RegisterModuleInfo2"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void RegisterModuleInfo(HLERequestContext& ctx) {
- struct Parameters {
- u64_le process_id;
- u64_le nrr_address;
- u64_le nrr_size;
- };
-
- IPC::RequestParser rp{ctx};
- const auto [process_id, nrr_address, nrr_size] = rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_LDR,
- "called with process_id={:016X}, nrr_address={:016X}, nrr_size={:016X}",
- process_id, nrr_address, nrr_size);
-
- if (!initialized) {
- LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_NOT_INITIALIZED);
- return;
- }
-
- if (nrr.size() >= MAXIMUM_LOADED_RO) {
- LOG_ERROR(Service_LDR, "Loading new NRR would exceed the maximum number of loaded NRRs "
- "(0x40)! Failing...");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_MAXIMUM_NRR);
- return;
- }
-
- // NRR Address does not fall on 0x1000 byte boundary
- if (!Common::Is4KBAligned(nrr_address)) {
- LOG_ERROR(Service_LDR, "NRR Address has invalid alignment (actual {:016X})!",
- nrr_address);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ALIGNMENT);
- return;
- }
-
- // NRR Size is zero or causes overflow
- if (nrr_address + nrr_size <= nrr_address || nrr_size == 0 ||
- !Common::Is4KBAligned(nrr_size)) {
- LOG_ERROR(Service_LDR, "NRR Size is invalid! (nrr_address={:016X}, nrr_size={:016X})",
- nrr_address, nrr_size);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_SIZE);
- return;
- }
-
- // Read NRR data from memory
- std::vector<u8> nrr_data(nrr_size);
- system.ApplicationMemory().ReadBlock(nrr_address, nrr_data.data(), nrr_size);
- NRRHeader header;
- std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
-
- if (header.magic != Common::MakeMagic('N', 'R', 'R', '0')) {
- LOG_ERROR(Service_LDR, "NRR did not have magic 'NRR0' (actual {:08X})!", header.magic);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_NRR);
- return;
- }
-
- if (header.size != nrr_size) {
- LOG_ERROR(Service_LDR,
- "NRR header reported size did not match LoadNrr parameter size! "
- "(header_size={:016X}, loadnrr_size={:016X})",
- header.size, nrr_size);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_SIZE);
- return;
- }
-
- if (system.GetApplicationProcessProgramID() != header.application_id) {
- LOG_ERROR(Service_LDR,
- "Attempting to load NRR with title ID other than current process. (actual "
- "{:016X})!",
- header.application_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_NRR);
- return;
- }
-
- std::vector<SHA256Hash> hashes;
-
- // Copy all hashes in the NRR (specified by hash count/hash offset) into vector.
- for (std::size_t i = header.hash_offset;
- i < (header.hash_offset + (header.hash_count * sizeof(SHA256Hash))); i += 8) {
- SHA256Hash hash;
- std::memcpy(hash.data(), nrr_data.data() + i, sizeof(SHA256Hash));
- hashes.emplace_back(hash);
- }
-
- nrr.insert_or_assign(nrr_address, std::move(hashes));
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void UnregisterModuleInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto pid = rp.Pop<u64>();
- const auto nrr_address = rp.Pop<VAddr>();
-
- LOG_DEBUG(Service_LDR, "called with pid={}, nrr_address={:016X}", pid, nrr_address);
-
- nrr.erase(nrr_address);
-
- IPC::ResponseBuilder rb{ctx, 2};
-
- rb.Push(ResultSuccess);
- }
-
- bool ValidateRegionForMap(Kernel::KProcessPageTable& page_table, VAddr start,
- std::size_t size) const {
- const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize};
-
- Kernel::KMemoryInfo start_info;
- Kernel::Svc::PageInfo page_info;
- R_ASSERT(
- page_table.QueryInfo(std::addressof(start_info), std::addressof(page_info), start - 1));
-
- if (start_info.GetState() != Kernel::KMemoryState::Free) {
- return {};
- }
-
- if (start_info.GetAddress() > (start - padding_size)) {
- return {};
- }
-
- Kernel::KMemoryInfo end_info;
- R_ASSERT(page_table.QueryInfo(std::addressof(end_info), std::addressof(page_info),
- start + size));
-
- if (end_info.GetState() != Kernel::KMemoryState::Free) {
- return {};
- }
-
- return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize());
- }
-
- Result GetAvailableMapRegion(Kernel::KProcessPageTable& page_table, u64 size, VAddr& out_addr) {
- size = Common::AlignUp(size, Kernel::PageSize);
- size += page_table.GetNumGuardPages() * Kernel::PageSize * 4;
-
- const auto is_region_available = [&](VAddr addr) {
- const auto end_addr = addr + size;
- while (addr < end_addr) {
- if (system.ApplicationMemory().IsValidVirtualAddress(addr)) {
- return false;
- }
-
- if (!page_table.Contains(out_addr, size)) {
- return false;
- }
-
- if (page_table.IsInHeapRegion(out_addr, size)) {
- return false;
- }
-
- if (page_table.IsInAliasRegion(out_addr, size)) {
- return false;
- }
-
- addr += Kernel::PageSize;
- }
- return true;
- };
-
- bool succeeded = false;
- const auto map_region_end =
- GetInteger(page_table.GetAliasCodeRegionStart()) + page_table.GetAliasCodeRegionSize();
- while (current_map_addr < map_region_end) {
- if (is_region_available(current_map_addr)) {
- succeeded = true;
- break;
- }
- current_map_addr += 0x100000;
- }
-
- if (!succeeded) {
- ASSERT_MSG(false, "Out of address space!");
- return Kernel::ResultOutOfMemory;
- }
-
- out_addr = current_map_addr;
- current_map_addr += size;
-
- return ResultSuccess;
- }
-
- Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr,
- u64 size) {
- auto& page_table{process->GetPageTable()};
- VAddr addr{};
-
- for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
- R_TRY(GetAvailableMapRegion(page_table, size, addr));
-
- const Result result{page_table.MapCodeMemory(addr, base_addr, size)};
- if (result == Kernel::ResultInvalidCurrentMemory) {
- continue;
- }
-
- R_TRY(result);
-
- if (ValidateRegionForMap(page_table, addr, size)) {
- *out_map_location = addr;
- return ResultSuccess;
- }
- }
-
- return ERROR_INSUFFICIENT_ADDRESS_SPACE;
- }
-
- Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr,
- std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) {
- for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
- auto& page_table{process->GetPageTable()};
- VAddr addr{};
-
- R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size));
-
- if (bss_size) {
- auto block_guard = detail::ScopeExit([&] {
- page_table.UnmapCodeMemory(addr + nro_size, bss_addr, bss_size);
- page_table.UnmapCodeMemory(addr, nro_addr, nro_size);
- });
-
- const Result result{page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)};
-
- if (result == Kernel::ResultInvalidCurrentMemory) {
- continue;
- }
-
- if (result.IsError()) {
- return result;
- }
-
- block_guard.Cancel();
- }
-
- if (ValidateRegionForMap(page_table, addr, size)) {
- *out_map_location = addr;
- return ResultSuccess;
- }
- }
-
- return ERROR_INSUFFICIENT_ADDRESS_SPACE;
- }
-
- Result LoadNro(Kernel::KProcess* process, const NROHeader& nro_header, VAddr nro_addr,
- VAddr start) const {
- const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset};
- const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset};
- const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset};
- const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size};
- const VAddr bss_end_addr{
- Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)};
-
- const auto CopyCode = [this](VAddr src_addr, VAddr dst_addr, u64 size) {
- system.ApplicationMemory().CopyBlock(dst_addr, src_addr, size);
- };
- CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start,
- nro_header.segment_headers[TEXT_INDEX].memory_size);
- CopyCode(nro_addr + nro_header.segment_headers[RO_INDEX].memory_offset, ro_start,
- nro_header.segment_headers[RO_INDEX].memory_size);
- CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
- nro_header.segment_headers[DATA_INDEX].memory_size);
-
- R_TRY(process->GetPageTable().SetProcessMemoryPermission(
- text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
- R_TRY(process->GetPageTable().SetProcessMemoryPermission(
- ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
-
- return process->GetPageTable().SetProcessMemoryPermission(
- data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite);
- }
-
- void LoadModule(HLERequestContext& ctx) {
- struct Parameters {
- u64_le process_id;
- u64_le image_address;
- u64_le image_size;
- u64_le bss_address;
- u64_le bss_size;
- };
-
- IPC::RequestParser rp{ctx};
- const auto [process_id, nro_address, nro_size, bss_address, bss_size] =
- rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_LDR,
- "called with pid={:016X}, nro_addr={:016X}, nro_size={:016X}, bss_addr={:016X}, "
- "bss_size={:016X}",
- process_id, nro_address, nro_size, bss_address, bss_size);
-
- if (!initialized) {
- LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_NOT_INITIALIZED);
- return;
- }
-
- if (nro.size() >= MAXIMUM_LOADED_RO) {
- LOG_ERROR(Service_LDR, "Loading new NRO would exceed the maximum number of loaded NROs "
- "(0x40)! Failing...");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_MAXIMUM_NRO);
- return;
- }
-
- // NRO Address does not fall on 0x1000 byte boundary
- if (!Common::Is4KBAligned(nro_address)) {
- LOG_ERROR(Service_LDR, "NRO Address has invalid alignment (actual {:016X})!",
- nro_address);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ALIGNMENT);
- return;
- }
-
- // NRO Size or BSS Size is zero or causes overflow
- const auto nro_size_valid =
- nro_size != 0 && nro_address + nro_size > nro_address && Common::Is4KBAligned(nro_size);
- const auto bss_size_valid = nro_size + bss_size >= nro_size &&
- (bss_size == 0 || bss_address + bss_size > bss_address);
-
- if (!nro_size_valid || !bss_size_valid) {
- LOG_ERROR(Service_LDR,
- "NRO Size or BSS Size is invalid! (nro_address={:016X}, nro_size={:016X}, "
- "bss_address={:016X}, bss_size={:016X})",
- nro_address, nro_size, bss_address, bss_size);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_SIZE);
- return;
- }
-
- // Read NRO data from memory
- std::vector<u8> nro_data(nro_size);
- system.ApplicationMemory().ReadBlock(nro_address, nro_data.data(), nro_size);
-
- SHA256Hash hash{};
- mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0);
-
- // NRO Hash is already loaded
- if (std::any_of(nro.begin(), nro.end(), [&hash](const std::pair<VAddr, NROInfo>& info) {
- return info.second.hash == hash;
- })) {
- LOG_ERROR(Service_LDR, "NRO is already loaded!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_ALREADY_LOADED);
- return;
- }
-
- // NRO Hash is not in any loaded NRR
- if (!IsValidNROHash(hash)) {
- LOG_ERROR(Service_LDR,
- "NRO hash is not present in any currently loaded NRRs (hash={})!",
- Common::HexToString(hash));
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_MISSING_NRR_HASH);
- return;
- }
-
- // Load and validate the NRO header
- NROHeader header{};
- std::memcpy(&header, nro_data.data(), sizeof(NROHeader));
- if (!IsValidNRO(header, nro_size, bss_size)) {
- LOG_ERROR(Service_LDR, "NRO was invalid!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_NRO);
- return;
- }
-
- // Map memory for the NRO
- VAddr map_location{};
- const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address,
- nro_size, bss_address, bss_size, nro_size + bss_size)};
- if (map_result != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(map_result);
- }
-
- // Load the NRO into the mapped memory
- if (const auto result{
- LoadNro(system.ApplicationProcess(), header, nro_address, map_location)};
- result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- // Track the loaded NRO
- nro.insert_or_assign(map_location,
- NROInfo{hash, map_location, nro_size, bss_address, bss_size,
- header.segment_headers[TEXT_INDEX].memory_size,
- header.segment_headers[RO_INDEX].memory_size,
- header.segment_headers[DATA_INDEX].memory_size, nro_address});
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(map_location);
- }
-
- Result UnmapNro(const NROInfo& info) {
- // Each region must be unmapped separately to validate memory state
- auto& page_table{system.ApplicationProcess()->GetPageTable()};
-
- if (info.bss_size != 0) {
- R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size +
- info.data_size,
- info.bss_address, info.bss_size));
- }
-
- R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size,
- info.src_addr + info.text_size + info.ro_size,
- info.data_size));
- R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size,
- info.src_addr + info.text_size, info.ro_size));
- R_TRY(page_table.UnmapCodeMemory(info.nro_address, info.src_addr, info.text_size));
- return ResultSuccess;
- }
-
- void UnloadModule(HLERequestContext& ctx) {
- if (!initialized) {
- LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_NOT_INITIALIZED);
- return;
- }
-
- struct Parameters {
- u64_le process_id;
- u64_le nro_address;
- };
-
- IPC::RequestParser rp{ctx};
- const auto [process_id, nro_address] = rp.PopRaw<Parameters>();
- LOG_DEBUG(Service_LDR, "called with process_id={:016X}, nro_address=0x{:016X}", process_id,
- nro_address);
-
- if (!Common::Is4KBAligned(nro_address)) {
- LOG_ERROR(Service_LDR, "NRO address has invalid alignment (nro_address=0x{:016X})",
- nro_address);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_ALIGNMENT);
- return;
- }
-
- const auto iter = nro.find(nro_address);
- if (iter == nro.end()) {
- LOG_ERROR(Service_LDR,
- "The NRO attempting to be unmapped was not mapped or has an invalid address "
- "(nro_address=0x{:016X})!",
- nro_address);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERROR_INVALID_NRO_ADDRESS);
- return;
- }
-
- const auto result{UnmapNro(iter->second)};
-
- nro.erase(iter);
-
- IPC::ResponseBuilder rb{ctx, 2};
-
- rb.Push(result);
- }
-
- void Initialize(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDR, "(STUBBED) called");
-
- initialized = true;
- current_map_addr =
- GetInteger(system.ApplicationProcess()->GetPageTable().GetAliasCodeRegionStart());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
-private:
- bool initialized{};
-
- std::map<VAddr, NROInfo> nro;
- std::map<VAddr, std::vector<SHA256Hash>> nrr;
- VAddr current_map_addr{};
-
- bool IsValidNROHash(const SHA256Hash& hash) const {
- return std::any_of(nrr.begin(), nrr.end(), [&hash](const auto& p) {
- return std::find(p.second.begin(), p.second.end(), hash) != p.second.end();
- });
- }
-
- static bool IsValidNRO(const NROHeader& header, u64 nro_size, u64 bss_size) {
- return header.magic == Common::MakeMagic('N', 'R', 'O', '0') &&
- header.nro_size == nro_size && header.bss_size == bss_size &&
-
- header.segment_headers[RO_INDEX].memory_offset ==
- header.segment_headers[TEXT_INDEX].memory_offset +
- header.segment_headers[TEXT_INDEX].memory_size &&
-
- header.segment_headers[DATA_INDEX].memory_offset ==
- header.segment_headers[RO_INDEX].memory_offset +
- header.segment_headers[RO_INDEX].memory_size &&
-
- nro_size == header.segment_headers[DATA_INDEX].memory_offset +
- header.segment_headers[DATA_INDEX].memory_size &&
-
- Common::Is4KBAligned(header.segment_headers[TEXT_INDEX].memory_size) &&
- Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size) &&
- Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size);
- }
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("ldr:dmnt", std::make_shared<DebugMonitor>(system));
server_manager->RegisterNamedService("ldr:pm", std::make_shared<ProcessManager>(system));
server_manager->RegisterNamedService("ldr:shel", std::make_shared<Shell>(system));
- server_manager->RegisterNamedService("ldr:ro", std::make_shared<RelocatableObject>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index d7db24f42..75bf31e32 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -171,6 +171,7 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han
buffer->height = SharedBufferHeight;
buffer->stride = SharedBufferBlockLinearStride;
buffer->format = SharedBufferBlockLinearFormat;
+ buffer->external_format = SharedBufferBlockLinearFormat;
buffer->buffer_id = handle;
buffer->offset = slot * SharedBufferSlotSize;
ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp
new file mode 100644
index 000000000..17110d3f1
--- /dev/null
+++ b/src/core/hle/service/ro/ro.cpp
@@ -0,0 +1,709 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <mbedtls/sha256.h>
+
+#include "common/scope_exit.h"
+#include "core/hle/kernel/k_process.h"
+
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/ro/ro.h"
+#include "core/hle/service/ro/ro_nro_utils.h"
+#include "core/hle/service/ro/ro_results.h"
+#include "core/hle/service/ro/ro_types.h"
+#include "core/hle/service/server_manager.h"
+#include "core/hle/service/service.h"
+
+namespace Service::RO {
+
+namespace {
+
+// Convenience definitions.
+constexpr size_t MaxSessions = 0x3;
+constexpr size_t MaxNrrInfos = 0x40;
+constexpr size_t MaxNroInfos = 0x40;
+
+constexpr u64 InvalidProcessId = 0xffffffffffffffffULL;
+constexpr u64 InvalidContextId = 0xffffffffffffffffULL;
+
+// Types.
+using Sha256Hash = std::array<u8, 32>;
+
+struct NroInfo {
+ u64 base_address;
+ u64 nro_heap_address;
+ u64 nro_heap_size;
+ u64 bss_heap_address;
+ u64 bss_heap_size;
+ u64 code_size;
+ u64 rw_size;
+ ModuleId module_id;
+};
+
+struct NrrInfo {
+ u64 nrr_heap_address;
+ u64 nrr_heap_size;
+
+ // Verification.
+ std::vector<Sha256Hash> hashes;
+};
+
+struct ProcessContext {
+ constexpr ProcessContext() = default;
+
+ void Initialize(Kernel::KProcess* process, u64 process_id) {
+ ASSERT(!m_in_use);
+
+ m_nro_in_use = {};
+ m_nrr_in_use = {};
+ m_nro_infos = {};
+ m_nrr_infos = {};
+
+ m_process = process;
+ m_process_id = process_id;
+ m_in_use = true;
+
+ if (m_process) {
+ m_process->Open();
+ }
+ }
+
+ void Finalize() {
+ ASSERT(m_in_use);
+
+ if (m_process) {
+ m_process->Close();
+ }
+
+ m_nro_in_use = {};
+ m_nrr_in_use = {};
+ m_nro_infos = {};
+ m_nrr_infos = {};
+
+ m_process = nullptr;
+ m_process_id = InvalidProcessId;
+ m_in_use = false;
+ }
+
+ Kernel::KProcess* GetProcess() const {
+ return m_process;
+ }
+
+ u64 GetProcessId() const {
+ return m_process_id;
+ }
+
+ bool IsFree() const {
+ return !m_in_use;
+ }
+
+ u64 GetProgramId(Kernel::KProcess* other_process) const {
+ // Automatically select a handle, allowing for override.
+ if (other_process) {
+ return other_process->GetProgramId();
+ } else if (m_process) {
+ return m_process->GetProgramId();
+ } else {
+ return 0;
+ }
+ }
+
+ Result GetNrrInfoByAddress(NrrInfo** out, u64 nrr_heap_address) {
+ for (size_t i = 0; i < MaxNrrInfos; i++) {
+ if (m_nrr_in_use[i] && m_nrr_infos[i].nrr_heap_address == nrr_heap_address) {
+ if (out != nullptr) {
+ *out = std::addressof(m_nrr_infos[i]);
+ }
+ R_SUCCEED();
+ }
+ }
+ R_THROW(RO::ResultNotRegistered);
+ }
+
+ Result GetFreeNrrInfo(NrrInfo** out) {
+ for (size_t i = 0; i < MaxNrrInfos; i++) {
+ if (!m_nrr_in_use[i]) {
+ if (out != nullptr) {
+ *out = std::addressof(m_nrr_infos[i]);
+ }
+ R_SUCCEED();
+ }
+ }
+ R_THROW(RO::ResultTooManyNrr);
+ }
+
+ Result GetNroInfoByAddress(NroInfo** out, u64 nro_address) {
+ for (size_t i = 0; i < MaxNroInfos; i++) {
+ if (m_nro_in_use[i] && m_nro_infos[i].base_address == nro_address) {
+ if (out != nullptr) {
+ *out = std::addressof(m_nro_infos[i]);
+ }
+ R_SUCCEED();
+ }
+ }
+ R_THROW(RO::ResultNotLoaded);
+ }
+
+ Result GetNroInfoByModuleId(NroInfo** out, const ModuleId* module_id) {
+ for (size_t i = 0; i < MaxNroInfos; i++) {
+ if (m_nro_in_use[i] && std::memcmp(std::addressof(m_nro_infos[i].module_id), module_id,
+ sizeof(*module_id)) == 0) {
+ if (out != nullptr) {
+ *out = std::addressof(m_nro_infos[i]);
+ }
+ R_SUCCEED();
+ }
+ }
+ R_THROW(RO::ResultNotLoaded);
+ }
+
+ Result GetFreeNroInfo(NroInfo** out) {
+ for (size_t i = 0; i < MaxNroInfos; i++) {
+ if (!m_nro_in_use[i]) {
+ if (out != nullptr) {
+ *out = std::addressof(m_nro_infos[i]);
+ }
+ R_SUCCEED();
+ }
+ }
+ R_THROW(RO::ResultTooManyNro);
+ }
+
+ Result ValidateHasNroHash(u64 base_address, const NroHeader* nro_header) const {
+ // Calculate hash.
+ Sha256Hash hash;
+ {
+ const u64 size = nro_header->GetSize();
+
+ std::vector<u8> nro_data(size);
+ m_process->GetMemory().ReadBlock(base_address, nro_data.data(), size);
+
+ mbedtls_sha256_ret(nro_data.data(), size, hash.data(), 0);
+ }
+
+ for (size_t i = 0; i < MaxNrrInfos; i++) {
+ // Ensure we only check NRRs that are used.
+ if (!m_nrr_in_use[i]) {
+ continue;
+ }
+
+ // Locate the hash within the hash list.
+ const auto hash_it = std::ranges::find(m_nrr_infos[i].hashes, hash);
+ if (hash_it == m_nrr_infos[i].hashes.end()) {
+ continue;
+ }
+
+ // The hash is valid!
+ R_SUCCEED();
+ }
+
+ R_THROW(RO::ResultNotAuthorized);
+ }
+
+ Result ValidateNro(ModuleId* out_module_id, u64* out_rx_size, u64* out_ro_size,
+ u64* out_rw_size, u64 base_address, u64 expected_nro_size,
+ u64 expected_bss_size) {
+ // Ensure we have a process to work on.
+ R_UNLESS(m_process != nullptr, RO::ResultInvalidProcess);
+
+ // Read the NRO header.
+ NroHeader header{};
+ m_process->GetMemory().ReadBlock(base_address, std::addressof(header), sizeof(header));
+
+ // Validate header.
+ R_UNLESS(header.IsMagicValid(), RO::ResultInvalidNro);
+
+ // Read sizes from header.
+ const u64 nro_size = header.GetSize();
+ const u64 text_ofs = header.GetTextOffset();
+ const u64 text_size = header.GetTextSize();
+ const u64 ro_ofs = header.GetRoOffset();
+ const u64 ro_size = header.GetRoSize();
+ const u64 rw_ofs = header.GetRwOffset();
+ const u64 rw_size = header.GetRwSize();
+ const u64 bss_size = header.GetBssSize();
+
+ // Validate sizes meet expected.
+ R_UNLESS(nro_size == expected_nro_size, RO::ResultInvalidNro);
+ R_UNLESS(bss_size == expected_bss_size, RO::ResultInvalidNro);
+
+ // Validate all sizes are aligned.
+ R_UNLESS(Common::IsAligned(text_size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidNro);
+ R_UNLESS(Common::IsAligned(ro_size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidNro);
+ R_UNLESS(Common::IsAligned(rw_size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidNro);
+ R_UNLESS(Common::IsAligned(bss_size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidNro);
+
+ // Validate sections are in order.
+ R_UNLESS(text_ofs <= ro_ofs, RO::ResultInvalidNro);
+ R_UNLESS(ro_ofs <= rw_ofs, RO::ResultInvalidNro);
+
+ // Validate sections are sequential and contiguous.
+ R_UNLESS(text_ofs == 0, RO::ResultInvalidNro);
+ R_UNLESS(text_ofs + text_size == ro_ofs, RO::ResultInvalidNro);
+ R_UNLESS(ro_ofs + ro_size == rw_ofs, RO::ResultInvalidNro);
+ R_UNLESS(rw_ofs + rw_size == nro_size, RO::ResultInvalidNro);
+
+ // Verify NRO hash.
+ R_TRY(this->ValidateHasNroHash(base_address, std::addressof(header)));
+
+ // Check if NRO has already been loaded.
+ const ModuleId* module_id = header.GetModuleId();
+ R_UNLESS(R_FAILED(this->GetNroInfoByModuleId(nullptr, module_id)), RO::ResultAlreadyLoaded);
+
+ // Apply patches to NRO.
+ // LocateAndApplyIpsPatchesToModule(module_id, static_cast<u8*>(mapped_memory), nro_size);
+
+ // Copy to output.
+ *out_module_id = *module_id;
+ *out_rx_size = text_size;
+ *out_ro_size = ro_size;
+ *out_rw_size = rw_size;
+ R_SUCCEED();
+ }
+
+ void SetNrrInfoInUse(const NrrInfo* info, bool in_use) {
+ ASSERT(std::addressof(m_nrr_infos[0]) <= info &&
+ info <= std::addressof(m_nrr_infos[MaxNrrInfos - 1]));
+ const size_t index = info - std::addressof(m_nrr_infos[0]);
+ m_nrr_in_use[index] = in_use;
+ }
+
+ void SetNroInfoInUse(const NroInfo* info, bool in_use) {
+ ASSERT(std::addressof(m_nro_infos[0]) <= info &&
+ info <= std::addressof(m_nro_infos[MaxNroInfos - 1]));
+ const size_t index = info - std::addressof(m_nro_infos[0]);
+ m_nro_in_use[index] = in_use;
+ }
+
+private:
+ std::array<bool, MaxNroInfos> m_nro_in_use{};
+ std::array<bool, MaxNrrInfos> m_nrr_in_use{};
+ std::array<NroInfo, MaxNroInfos> m_nro_infos{};
+ std::array<NrrInfo, MaxNrrInfos> m_nrr_infos{};
+ Kernel::KProcess* m_process{};
+ u64 m_process_id{InvalidProcessId};
+ bool m_in_use{};
+};
+
+Result ValidateAddressAndNonZeroSize(u64 address, u64 size) {
+ R_UNLESS(Common::IsAligned(address, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidAddress);
+ R_UNLESS(size != 0, RO::ResultInvalidSize);
+ R_UNLESS(Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidSize);
+ R_UNLESS(address < address + size, RO::ResultInvalidSize);
+ R_SUCCEED();
+}
+
+Result ValidateAddressAndSize(u64 address, u64 size) {
+ R_UNLESS(Common::IsAligned(address, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidAddress);
+ R_UNLESS(Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE), RO::ResultInvalidSize);
+ R_UNLESS(size == 0 || address < address + size, RO::ResultInvalidSize);
+ R_SUCCEED();
+}
+
+class RoContext {
+public:
+ explicit RoContext() = default;
+
+ Result RegisterProcess(size_t* out_context_id, Kernel::KProcess* process, u64 process_id) {
+ // Validate process id.
+ R_UNLESS(process->GetProcessId() == process_id, RO::ResultInvalidProcess);
+
+ // Check if a process context already exists.
+ R_UNLESS(this->GetContextByProcessId(process_id) == nullptr, RO::ResultInvalidSession);
+
+ // Allocate a context to manage the process handle.
+ *out_context_id = this->AllocateContext(process, process_id);
+
+ R_SUCCEED();
+ }
+
+ Result ValidateProcess(size_t context_id, u64 process_id) {
+ const ProcessContext* ctx = this->GetContextById(context_id);
+ R_UNLESS(ctx != nullptr, RO::ResultInvalidProcess);
+ R_UNLESS(ctx->GetProcessId() == process_id, RO::ResultInvalidProcess);
+ R_SUCCEED();
+ }
+
+ void UnregisterProcess(size_t context_id) {
+ this->FreeContext(context_id);
+ }
+
+ Result RegisterModuleInfo(size_t context_id, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind,
+ bool enforce_nrr_kind) {
+ // Get context.
+ ProcessContext* context = this->GetContextById(context_id);
+ ASSERT(context != nullptr);
+
+ // Validate address/size.
+ R_TRY(ValidateAddressAndNonZeroSize(nrr_address, nrr_size));
+
+ // Check we have space for a new NRR.
+ NrrInfo* nrr_info = nullptr;
+ R_TRY(context->GetFreeNrrInfo(std::addressof(nrr_info)));
+
+ // Ensure we have a valid process to read from.
+ Kernel::KProcess* process = context->GetProcess();
+ R_UNLESS(process != nullptr, RO::ResultInvalidProcess);
+
+ // Read NRR.
+ NrrHeader header{};
+ process->GetMemory().ReadBlock(nrr_address, std::addressof(header), sizeof(header));
+
+ // Set NRR info.
+ context->SetNrrInfoInUse(nrr_info, true);
+ nrr_info->nrr_heap_address = nrr_address;
+ nrr_info->nrr_heap_size = nrr_size;
+
+ // Read NRR hash list.
+ nrr_info->hashes.resize(header.GetNumHashes());
+ process->GetMemory().ReadBlock(nrr_address + header.GetHashesOffset(),
+ nrr_info->hashes.data(),
+ sizeof(Sha256Hash) * header.GetNumHashes());
+
+ R_SUCCEED();
+ }
+
+ Result UnregisterModuleInfo(size_t context_id, u64 nrr_address) {
+ // Get context.
+ ProcessContext* context = this->GetContextById(context_id);
+ ASSERT(context != nullptr);
+
+ // Validate address.
+ R_UNLESS(Common::IsAligned(nrr_address, Core::Memory::YUZU_PAGESIZE),
+ RO::ResultInvalidAddress);
+
+ // Check the NRR is loaded.
+ NrrInfo* nrr_info = nullptr;
+ R_TRY(context->GetNrrInfoByAddress(std::addressof(nrr_info), nrr_address));
+
+ // Nintendo does this unconditionally, whether or not the actual unmap succeeds.
+ context->SetNrrInfoInUse(nrr_info, false);
+ *nrr_info = {};
+
+ R_SUCCEED();
+ }
+
+ Result MapManualLoadModuleMemory(u64* out_address, size_t context_id, u64 nro_address,
+ u64 nro_size, u64 bss_address, u64 bss_size) {
+ // Get context.
+ ProcessContext* context = this->GetContextById(context_id);
+ ASSERT(context != nullptr);
+
+ // Validate address/size.
+ R_TRY(ValidateAddressAndNonZeroSize(nro_address, nro_size));
+ R_TRY(ValidateAddressAndSize(bss_address, bss_size));
+
+ const u64 total_size = nro_size + bss_size;
+ R_UNLESS(total_size >= nro_size, RO::ResultInvalidSize);
+ R_UNLESS(total_size >= bss_size, RO::ResultInvalidSize);
+
+ // Check we have space for a new NRO.
+ NroInfo* nro_info = nullptr;
+ R_TRY(context->GetFreeNroInfo(std::addressof(nro_info)));
+ nro_info->nro_heap_address = nro_address;
+ nro_info->nro_heap_size = nro_size;
+ nro_info->bss_heap_address = bss_address;
+ nro_info->bss_heap_size = bss_size;
+
+ // Map the NRO.
+ R_TRY(MapNro(std::addressof(nro_info->base_address), context->GetProcess(), nro_address,
+ nro_size, bss_address, bss_size, generate_random));
+ ON_RESULT_FAILURE {
+ UnmapNro(context->GetProcess(), nro_info->base_address, nro_address, nro_size,
+ bss_address, bss_size);
+ };
+
+ // Validate the NRO (parsing region extents).
+ u64 rx_size = 0, ro_size = 0, rw_size = 0;
+ R_TRY(context->ValidateNro(std::addressof(nro_info->module_id), std::addressof(rx_size),
+ std::addressof(ro_size), std::addressof(rw_size),
+ nro_info->base_address, nro_size, bss_size));
+
+ // Set NRO perms.
+ R_TRY(SetNroPerms(context->GetProcess(), nro_info->base_address, rx_size, ro_size,
+ rw_size + bss_size));
+
+ context->SetNroInfoInUse(nro_info, true);
+ nro_info->code_size = rx_size + ro_size;
+ nro_info->rw_size = rw_size;
+ *out_address = nro_info->base_address;
+ R_SUCCEED();
+ }
+
+ Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address) {
+ // Get context.
+ ProcessContext* context = this->GetContextById(context_id);
+ ASSERT(context != nullptr);
+
+ // Validate address.
+ R_UNLESS(Common::IsAligned(nro_address, Core::Memory::YUZU_PAGESIZE),
+ RO::ResultInvalidAddress);
+
+ // Check the NRO is loaded.
+ NroInfo* nro_info = nullptr;
+ R_TRY(context->GetNroInfoByAddress(std::addressof(nro_info), nro_address));
+
+ // Unmap.
+ const NroInfo nro_backup = *nro_info;
+ {
+ // Nintendo does this unconditionally, whether or not the actual unmap succeeds.
+ context->SetNroInfoInUse(nro_info, false);
+ std::memset(nro_info, 0, sizeof(*nro_info));
+ }
+ R_RETURN(UnmapNro(context->GetProcess(), nro_backup.base_address,
+ nro_backup.nro_heap_address, nro_backup.code_size + nro_backup.rw_size,
+ nro_backup.bss_heap_address, nro_backup.bss_heap_size));
+ }
+
+private:
+ std::array<ProcessContext, MaxSessions> process_contexts;
+ std::mt19937_64 generate_random;
+
+ // Context Helpers.
+ ProcessContext* GetContextById(size_t context_id) {
+ if (context_id == InvalidContextId) {
+ return nullptr;
+ }
+
+ ASSERT(context_id < process_contexts.size());
+ return std::addressof(process_contexts[context_id]);
+ }
+
+ ProcessContext* GetContextByProcessId(u64 process_id) {
+ for (size_t i = 0; i < MaxSessions; i++) {
+ if (process_contexts[i].GetProcessId() == process_id) {
+ return std::addressof(process_contexts[i]);
+ }
+ }
+ return nullptr;
+ }
+
+ size_t AllocateContext(Kernel::KProcess* process, u64 process_id) {
+ // Find a free process context.
+ for (size_t i = 0; i < MaxSessions; i++) {
+ ProcessContext* context = std::addressof(process_contexts[i]);
+
+ if (context->IsFree()) {
+ context->Initialize(process, process_id);
+ return i;
+ }
+ }
+
+ // Failure to find a free context is actually an abort condition.
+ UNREACHABLE();
+ }
+
+ void FreeContext(size_t context_id) {
+ if (ProcessContext* context = GetContextById(context_id); context != nullptr) {
+ context->Finalize();
+ }
+ }
+};
+
+class RoInterface {
+public:
+ explicit RoInterface(std::shared_ptr<RoContext> ro, NrrKind nrr_kind)
+ : m_ro(ro), m_context_id(InvalidContextId), m_nrr_kind(nrr_kind) {}
+ ~RoInterface() {
+ m_ro->UnregisterProcess(m_context_id);
+ }
+
+ Result MapManualLoadModuleMemory(u64* out_load_address, u64 client_pid, u64 nro_address,
+ u64 nro_size, u64 bss_address, u64 bss_size) {
+ R_TRY(m_ro->ValidateProcess(m_context_id, client_pid));
+ R_RETURN(m_ro->MapManualLoadModuleMemory(out_load_address, m_context_id, nro_address,
+ nro_size, bss_address, bss_size));
+ }
+
+ Result UnmapManualLoadModuleMemory(u64 client_pid, u64 nro_address) {
+ R_TRY(m_ro->ValidateProcess(m_context_id, client_pid));
+ R_RETURN(m_ro->UnmapManualLoadModuleMemory(m_context_id, nro_address));
+ }
+
+ Result RegisterModuleInfo(u64 client_pid, u64 nrr_address, u64 nrr_size) {
+ R_TRY(m_ro->ValidateProcess(m_context_id, client_pid));
+ R_RETURN(
+ m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, NrrKind::User, true));
+ }
+
+ Result UnregisterModuleInfo(u64 client_pid, u64 nrr_address) {
+ R_TRY(m_ro->ValidateProcess(m_context_id, client_pid));
+ R_RETURN(m_ro->UnregisterModuleInfo(m_context_id, nrr_address));
+ }
+
+ Result RegisterProcessHandle(u64 client_pid, Kernel::KProcess* process) {
+ // Register the process.
+ R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process, client_pid));
+ }
+
+ Result RegisterProcessModuleInfo(u64 client_pid, u64 nrr_address, u64 nrr_size,
+ Kernel::KProcess* process) {
+ // Validate the process.
+ R_TRY(m_ro->ValidateProcess(m_context_id, client_pid));
+
+ // Register the module.
+ R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind,
+ m_nrr_kind == NrrKind::JitPlugin));
+ }
+
+private:
+ std::shared_ptr<RoContext> m_ro{};
+ size_t m_context_id{};
+ NrrKind m_nrr_kind{};
+};
+
+class IRoInterface : public ServiceFramework<IRoInterface> {
+public:
+ explicit IRoInterface(Core::System& system_, const char* name_, std::shared_ptr<RoContext> ro,
+ NrrKind nrr_kind)
+ : ServiceFramework{system_, name_}, interface {
+ ro, nrr_kind
+ } {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IRoInterface::MapManualLoadModuleMemory, "MapManualLoadModuleMemory"},
+ {1, &IRoInterface::UnmapManualLoadModuleMemory, "UnmapManualLoadModuleMemory"},
+ {2, &IRoInterface::RegisterModuleInfo, "RegisterModuleInfo"},
+ {3, &IRoInterface::UnregisterModuleInfo, "UnregisterModuleInfo"},
+ {4, &IRoInterface::RegisterProcessHandle, "RegisterProcessHandle"},
+ {10, &IRoInterface::RegisterProcessModuleInfo, "RegisterProcessModuleInfo"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void MapManualLoadModuleMemory(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ struct InputParameters {
+ u64 client_pid;
+ u64 nro_address;
+ u64 nro_size;
+ u64 bss_address;
+ u64 bss_size;
+ };
+
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<InputParameters>();
+
+ u64 load_address = 0;
+ auto result = interface.MapManualLoadModuleMemory(&load_address, ctx.GetPID(),
+ params.nro_address, params.nro_size,
+ params.bss_address, params.bss_size);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.Push(load_address);
+ }
+
+ void UnmapManualLoadModuleMemory(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ struct InputParameters {
+ u64 client_pid;
+ u64 nro_address;
+ };
+
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<InputParameters>();
+ auto result = interface.UnmapManualLoadModuleMemory(ctx.GetPID(), params.nro_address);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ void RegisterModuleInfo(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ struct InputParameters {
+ u64 client_pid;
+ u64 nrr_address;
+ u64 nrr_size;
+ };
+
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<InputParameters>();
+ auto result =
+ interface.RegisterModuleInfo(ctx.GetPID(), params.nrr_address, params.nrr_size);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ void UnregisterModuleInfo(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ struct InputParameters {
+ u64 client_pid;
+ u64 nrr_address;
+ };
+
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<InputParameters>();
+ auto result = interface.UnregisterModuleInfo(ctx.GetPID(), params.nrr_address);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ void RegisterProcessHandle(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0));
+ auto client_pid = ctx.GetPID();
+ auto result = interface.RegisterProcessHandle(client_pid,
+ process_h->DynamicCast<Kernel::KProcess*>());
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ void RegisterProcessModuleInfo(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_LDR, "(called)");
+
+ struct InputParameters {
+ u64 client_pid;
+ u64 nrr_address;
+ u64 nrr_size;
+ };
+
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<InputParameters>();
+ auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0));
+
+ auto client_pid = ctx.GetPID();
+ auto result =
+ interface.RegisterProcessModuleInfo(client_pid, params.nrr_address, params.nrr_size,
+ process_h->DynamicCast<Kernel::KProcess*>());
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ RoInterface interface;
+};
+
+} // namespace
+
+void LoopProcess(Core::System& system) {
+ auto server_manager = std::make_unique<ServerManager>(system);
+
+ auto ro = std::make_shared<RoContext>();
+
+ const auto RoInterfaceFactoryForUser = [&, ro] {
+ return std::make_shared<IRoInterface>(system, "ldr:ro", ro, NrrKind::User);
+ };
+
+ const auto RoInterfaceFactoryForJitPlugin = [&, ro] {
+ return std::make_shared<IRoInterface>(system, "ro:1", ro, NrrKind::JitPlugin);
+ };
+
+ server_manager->RegisterNamedService("ldr:ro", std::move(RoInterfaceFactoryForUser));
+ server_manager->RegisterNamedService("ro:1", std::move(RoInterfaceFactoryForJitPlugin));
+
+ ServerManager::RunServer(std::move(server_manager));
+}
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/ro/ro.h b/src/core/hle/service/ro/ro.h
new file mode 100644
index 000000000..74dc08536
--- /dev/null
+++ b/src/core/hle/service/ro/ro.h
@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+namespace Core {
+class System;
+}
+
+namespace Service::RO {
+
+void LoopProcess(Core::System& system);
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/ro/ro_nro_utils.cpp b/src/core/hle/service/ro/ro_nro_utils.cpp
new file mode 100644
index 000000000..268c7f93e
--- /dev/null
+++ b/src/core/hle/service/ro/ro_nro_utils.cpp
@@ -0,0 +1,185 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/service/ro/ro_nro_utils.h"
+#include "core/hle/service/ro/ro_results.h"
+
+namespace Service::RO {
+
+namespace {
+
+struct ProcessMemoryRegion {
+ u64 address;
+ u64 size;
+};
+
+size_t GetTotalProcessMemoryRegionSize(const ProcessMemoryRegion* regions, size_t num_regions) {
+ size_t total = 0;
+
+ for (size_t i = 0; i < num_regions; ++i) {
+ total += regions[i].size;
+ }
+
+ return total;
+}
+
+size_t SetupNroProcessMemoryRegions(ProcessMemoryRegion* regions, u64 nro_heap_address,
+ u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size) {
+ // Reset region count.
+ size_t num_regions = 0;
+
+ // We always want a region for the nro.
+ regions[num_regions++] = {nro_heap_address, nro_heap_size};
+
+ // If we have bss, create a region for bss.
+ if (bss_heap_size > 0) {
+ regions[num_regions++] = {bss_heap_address, bss_heap_size};
+ }
+
+ return num_regions;
+}
+
+Result SetProcessMemoryPermission(Kernel::KProcess* process, u64 address, u64 size,
+ Kernel::Svc::MemoryPermission permission) {
+ auto& page_table = process->GetPageTable();
+
+ // Set permission.
+ R_RETURN(page_table.SetProcessMemoryPermission(address, size, permission));
+}
+
+Result UnmapProcessCodeMemory(Kernel::KProcess* process, u64 process_code_address,
+ const ProcessMemoryRegion* regions, size_t num_regions) {
+ // Get the total process memory region size.
+ const size_t total_size = GetTotalProcessMemoryRegionSize(regions, num_regions);
+
+ auto& page_table = process->GetPageTable();
+
+ // Unmap each region in order.
+ size_t cur_offset = total_size;
+ for (size_t i = 0; i < num_regions; ++i) {
+ // We want to unmap in reverse order.
+ const auto& cur_region = regions[num_regions - 1 - i];
+
+ // Subtract to update the current offset.
+ cur_offset -= cur_region.size;
+
+ // Unmap.
+ R_TRY(page_table.UnmapCodeMemory(process_code_address + cur_offset, cur_region.address,
+ cur_region.size));
+ }
+
+ R_SUCCEED();
+}
+
+Result EnsureGuardPages(Kernel::KProcessPageTable& page_table, u64 map_address, u64 map_size) {
+ Kernel::KMemoryInfo memory_info;
+ Kernel::Svc::PageInfo page_info;
+
+ // Ensure page before mapping is unmapped.
+ R_TRY(page_table.QueryInfo(std::addressof(memory_info), std::addressof(page_info),
+ map_address - 1));
+ R_UNLESS(memory_info.GetSvcState() == Kernel::Svc::MemoryState::Free,
+ Kernel::ResultInvalidState);
+
+ // Ensure page after mapping is unmapped.
+ R_TRY(page_table.QueryInfo(std::addressof(memory_info), std::addressof(page_info),
+ map_address + map_size));
+ R_UNLESS(memory_info.GetSvcState() == Kernel::Svc::MemoryState::Free,
+ Kernel::ResultInvalidState);
+
+ // Successfully verified guard pages.
+ R_SUCCEED();
+}
+
+Result MapProcessCodeMemory(u64* out, Kernel::KProcess* process, const ProcessMemoryRegion* regions,
+ size_t num_regions, std::mt19937_64& generate_random) {
+ auto& page_table = process->GetPageTable();
+ const u64 alias_code_start =
+ GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize;
+ const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize;
+
+ for (size_t trial = 0; trial < 64; trial++) {
+ // Generate a new trial address.
+ const u64 mapped_address =
+ (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize;
+
+ const auto MapRegions = [&] {
+ // Map the regions in order.
+ u64 mapped_size = 0;
+ for (size_t i = 0; i < num_regions; ++i) {
+ // If we fail, unmap up to where we've mapped.
+ ON_RESULT_FAILURE {
+ R_ASSERT(UnmapProcessCodeMemory(process, mapped_address, regions, i));
+ };
+
+ // Map the current region.
+ R_TRY(page_table.MapCodeMemory(mapped_address + mapped_size, regions[i].address,
+ regions[i].size));
+
+ mapped_size += regions[i].size;
+ }
+
+ // If we fail, unmap all mapped regions.
+ ON_RESULT_FAILURE {
+ R_ASSERT(UnmapProcessCodeMemory(process, mapped_address, regions, num_regions));
+ };
+
+ // Ensure guard pages.
+ R_RETURN(EnsureGuardPages(page_table, mapped_address, mapped_size));
+ };
+
+ if (R_SUCCEEDED(MapRegions())) {
+ // Set the output address.
+ *out = mapped_address;
+ R_SUCCEED();
+ }
+ }
+
+ // We failed to map anything.
+ R_THROW(RO::ResultOutOfAddressSpace);
+}
+
+} // namespace
+
+Result MapNro(u64* out_base_address, Kernel::KProcess* process, u64 nro_heap_address,
+ u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size,
+ std::mt19937_64& generate_random) {
+ // Set up the process memory regions.
+ std::array<ProcessMemoryRegion, 2> regions{};
+ const size_t num_regions = SetupNroProcessMemoryRegions(
+ regions.data(), nro_heap_address, nro_heap_size, bss_heap_address, bss_heap_size);
+
+ // Re-map the nro/bss as code memory in the destination process.
+ R_RETURN(MapProcessCodeMemory(out_base_address, process, regions.data(), num_regions,
+ generate_random));
+}
+
+Result SetNroPerms(Kernel::KProcess* process, u64 base_address, u64 rx_size, u64 ro_size,
+ u64 rw_size) {
+ const u64 rx_offset = 0;
+ const u64 ro_offset = rx_offset + rx_size;
+ const u64 rw_offset = ro_offset + ro_size;
+
+ R_TRY(SetProcessMemoryPermission(process, base_address + rx_offset, rx_size,
+ Kernel::Svc::MemoryPermission::ReadExecute));
+ R_TRY(SetProcessMemoryPermission(process, base_address + ro_offset, ro_size,
+ Kernel::Svc::MemoryPermission::Read));
+ R_TRY(SetProcessMemoryPermission(process, base_address + rw_offset, rw_size,
+ Kernel::Svc::MemoryPermission::ReadWrite));
+
+ R_SUCCEED();
+}
+
+Result UnmapNro(Kernel::KProcess* process, u64 base_address, u64 nro_heap_address,
+ u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size) {
+ // Set up the process memory regions.
+ std::array<ProcessMemoryRegion, 2> regions{};
+ const size_t num_regions = SetupNroProcessMemoryRegions(
+ regions.data(), nro_heap_address, nro_heap_size, bss_heap_address, bss_heap_size);
+
+ // Unmap the nro/bss.
+ R_RETURN(UnmapProcessCodeMemory(process, base_address, regions.data(), num_regions));
+}
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/ro/ro_nro_utils.h b/src/core/hle/service/ro/ro_nro_utils.h
new file mode 100644
index 000000000..f7083a1ba
--- /dev/null
+++ b/src/core/hle/service/ro/ro_nro_utils.h
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <random>
+
+#include "common/common_types.h"
+
+namespace Kernel {
+class KProcess;
+}
+
+union Result;
+
+namespace Service::RO {
+
+Result MapNro(u64* out_base_address, Kernel::KProcess* process, u64 nro_heap_address,
+ u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size,
+ std::mt19937_64& generate_random);
+Result SetNroPerms(Kernel::KProcess* process, u64 base_address, u64 rx_size, u64 ro_size,
+ u64 rw_size);
+Result UnmapNro(Kernel::KProcess* process, u64 base_address, u64 nro_heap_address,
+ u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size);
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/ro/ro_results.h b/src/core/hle/service/ro/ro_results.h
new file mode 100644
index 000000000..00f05c5a5
--- /dev/null
+++ b/src/core/hle/service/ro/ro_results.h
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/result.h"
+
+namespace Service::RO {
+
+constexpr Result ResultOutOfAddressSpace{ErrorModule::RO, 2};
+constexpr Result ResultAlreadyLoaded{ErrorModule::RO, 3};
+constexpr Result ResultInvalidNro{ErrorModule::RO, 4};
+constexpr Result ResultInvalidNrr{ErrorModule::RO, 6};
+constexpr Result ResultTooManyNro{ErrorModule::RO, 7};
+constexpr Result ResultTooManyNrr{ErrorModule::RO, 8};
+constexpr Result ResultNotAuthorized{ErrorModule::RO, 9};
+constexpr Result ResultInvalidNrrKind{ErrorModule::RO, 10};
+constexpr Result ResultInternalError{ErrorModule::RO, 1023};
+constexpr Result ResultInvalidAddress{ErrorModule::RO, 1025};
+constexpr Result ResultInvalidSize{ErrorModule::RO, 1026};
+constexpr Result ResultNotLoaded{ErrorModule::RO, 1028};
+constexpr Result ResultNotRegistered{ErrorModule::RO, 1029};
+constexpr Result ResultInvalidSession{ErrorModule::RO, 1030};
+constexpr Result ResultInvalidProcess{ErrorModule::RO, 1031};
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/ro/ro_types.h b/src/core/hle/service/ro/ro_types.h
new file mode 100644
index 000000000..624d52ee5
--- /dev/null
+++ b/src/core/hle/service/ro/ro_types.h
@@ -0,0 +1,181 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/assert.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+
+namespace Service::RO {
+
+enum class NrrKind : u8 {
+ User = 0,
+ JitPlugin = 1,
+ Count,
+};
+
+static constexpr size_t ModuleIdSize = 0x20;
+struct ModuleId {
+ std::array<u8, ModuleIdSize> data;
+};
+static_assert(sizeof(ModuleId) == ModuleIdSize);
+
+struct NrrCertification {
+ static constexpr size_t RsaKeySize = 0x100;
+ static constexpr size_t SignedSize = 0x120;
+
+ u64 program_id_mask;
+ u64 program_id_pattern;
+ std::array<u8, 0x10> reserved_10;
+ std::array<u8, RsaKeySize> modulus;
+ std::array<u8, RsaKeySize> signature;
+};
+static_assert(sizeof(NrrCertification) ==
+ NrrCertification::RsaKeySize + NrrCertification::SignedSize);
+
+class NrrHeader {
+public:
+ static constexpr u32 Magic = Common::MakeMagic('N', 'R', 'R', '0');
+
+public:
+ bool IsMagicValid() const {
+ return m_magic == Magic;
+ }
+
+ bool IsProgramIdValid() const {
+ return (m_program_id & m_certification.program_id_mask) ==
+ m_certification.program_id_pattern;
+ }
+
+ NrrKind GetNrrKind() const {
+ const NrrKind kind = static_cast<NrrKind>(m_nrr_kind);
+ ASSERT(kind < NrrKind::Count);
+ return kind;
+ }
+
+ u64 GetProgramId() const {
+ return m_program_id;
+ }
+
+ u32 GetSize() const {
+ return m_size;
+ }
+
+ u32 GetNumHashes() const {
+ return m_num_hashes;
+ }
+
+ size_t GetHashesOffset() const {
+ return m_hashes_offset;
+ }
+
+ u32 GetKeyGeneration() const {
+ return m_key_generation;
+ }
+
+ const u8* GetCertificationSignature() const {
+ return m_certification.signature.data();
+ }
+
+ const u8* GetCertificationSignedArea() const {
+ return reinterpret_cast<const u8*>(std::addressof(m_certification));
+ }
+
+ const u8* GetCertificationModulus() const {
+ return m_certification.modulus.data();
+ }
+
+ const u8* GetSignature() const {
+ return m_signature.data();
+ }
+
+ size_t GetSignedAreaSize() const {
+ return m_size - GetSignedAreaOffset();
+ }
+
+ static constexpr size_t GetSignedAreaOffset() {
+ return offsetof(NrrHeader, m_program_id);
+ }
+
+private:
+ u32 m_magic;
+ u32 m_key_generation;
+ INSERT_PADDING_BYTES_NOINIT(8);
+ NrrCertification m_certification;
+ std::array<u8, 0x100> m_signature;
+ u64 m_program_id;
+ u32 m_size;
+ u8 m_nrr_kind; // 7.0.0+
+ INSERT_PADDING_BYTES_NOINIT(3);
+ u32 m_hashes_offset;
+ u32 m_num_hashes;
+ INSERT_PADDING_BYTES_NOINIT(8);
+};
+static_assert(sizeof(NrrHeader) == 0x350, "NrrHeader has wrong size");
+
+class NroHeader {
+public:
+ static constexpr u32 Magic = Common::MakeMagic('N', 'R', 'O', '0');
+
+public:
+ bool IsMagicValid() const {
+ return m_magic == Magic;
+ }
+
+ u32 GetSize() const {
+ return m_size;
+ }
+
+ u32 GetTextOffset() const {
+ return m_text_offset;
+ }
+
+ u32 GetTextSize() const {
+ return m_text_size;
+ }
+
+ u32 GetRoOffset() const {
+ return m_ro_offset;
+ }
+
+ u32 GetRoSize() const {
+ return m_ro_size;
+ }
+
+ u32 GetRwOffset() const {
+ return m_rw_offset;
+ }
+
+ u32 GetRwSize() const {
+ return m_rw_size;
+ }
+
+ u32 GetBssSize() const {
+ return m_bss_size;
+ }
+
+ const ModuleId* GetModuleId() const {
+ return std::addressof(m_module_id);
+ }
+
+private:
+ u32 m_entrypoint_insn;
+ u32 m_mod_offset;
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ u32 m_magic;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 m_size;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 m_text_offset;
+ u32 m_text_size;
+ u32 m_ro_offset;
+ u32 m_ro_size;
+ u32 m_rw_offset;
+ u32 m_rw_size;
+ u32 m_bss_size;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ ModuleId m_module_id;
+ INSERT_PADDING_BYTES_NOINIT(0x20);
+};
+static_assert(sizeof(NroHeader) == 0x80, "NroHeader has wrong size");
+
+} // namespace Service::RO
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp
index e2e399534..6808247a9 100644
--- a/src/core/hle/service/server_manager.cpp
+++ b/src/core/hle/service/server_manager.cpp
@@ -93,13 +93,13 @@ Result ServerManager::RegisterSession(Kernel::KServerSession* session,
}
Result ServerManager::RegisterNamedService(const std::string& service_name,
- std::shared_ptr<SessionRequestHandler>&& handler,
+ SessionRequestHandlerFactory&& handler_factory,
u32 max_sessions) {
ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
// Add the new server to sm:.
ASSERT(R_SUCCEEDED(
- m_system.ServiceManager().RegisterService(service_name, max_sessions, handler)));
+ m_system.ServiceManager().RegisterService(service_name, max_sessions, handler_factory)));
// Get the registered port.
Kernel::KPort* port{};
@@ -112,7 +112,7 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
// Begin tracking the server port.
{
std::scoped_lock ll{m_list_mutex};
- m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler));
+ m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory));
}
// Signal the wakeup event.
@@ -121,8 +121,18 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
R_SUCCEED();
}
+Result ServerManager::RegisterNamedService(const std::string& service_name,
+ std::shared_ptr<SessionRequestHandler>&& handler,
+ u32 max_sessions) {
+ // Make the factory.
+ const auto HandlerFactory = [handler]() { return handler; };
+
+ // Register the service with the new factory.
+ R_RETURN(this->RegisterNamedService(service_name, std::move(HandlerFactory), max_sessions));
+}
+
Result ServerManager::ManageNamedPort(const std::string& service_name,
- std::shared_ptr<SessionRequestHandler>&& handler,
+ SessionRequestHandlerFactory&& handler_factory,
u32 max_sessions) {
ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
@@ -149,7 +159,7 @@ Result ServerManager::ManageNamedPort(const std::string& service_name,
// Begin tracking the server port.
{
std::scoped_lock ll{m_list_mutex};
- m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler));
+ m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory));
}
// We succeeded.
@@ -269,13 +279,13 @@ Result ServerManager::WaitAndProcessImpl() {
case HandleType::Port: {
// Port signaled.
auto* port = wait_obj->DynamicCast<Kernel::KServerPort*>();
- std::shared_ptr<SessionRequestHandler> handler;
+ SessionRequestHandlerFactory handler_factory;
// Remove from tracking.
{
std::scoped_lock ll{m_list_mutex};
ASSERT(m_ports.contains(port));
- m_ports.at(port).swap(handler);
+ m_ports.at(port).swap(handler_factory);
m_ports.erase(port);
}
@@ -283,7 +293,7 @@ Result ServerManager::WaitAndProcessImpl() {
sl.unlock();
// Finish.
- R_RETURN(this->OnPortEvent(port, std::move(handler)));
+ R_RETURN(this->OnPortEvent(port, std::move(handler_factory)));
}
case HandleType::Session: {
// Session signaled.
@@ -333,19 +343,19 @@ Result ServerManager::WaitAndProcessImpl() {
}
Result ServerManager::OnPortEvent(Kernel::KServerPort* port,
- std::shared_ptr<SessionRequestHandler>&& handler) {
+ SessionRequestHandlerFactory&& handler_factory) {
// Accept a new server session.
Kernel::KServerSession* session = port->AcceptSession();
ASSERT(session != nullptr);
// Create the session manager and install the handler.
auto manager = std::make_shared<SessionRequestManager>(m_system.Kernel(), *this);
- manager->SetSessionHandler(std::shared_ptr(handler));
+ manager->SetSessionHandler(handler_factory());
// Track the server session.
{
std::scoped_lock ll{m_list_mutex};
- m_ports.emplace(port, std::move(handler));
+ m_ports.emplace(port, std::move(handler_factory));
m_sessions.emplace(session, std::move(manager));
}
diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h
index 58b0a0832..c4bc07262 100644
--- a/src/core/hle/service/server_manager.h
+++ b/src/core/hle/service/server_manager.h
@@ -13,6 +13,7 @@
#include "common/polyfill_thread.h"
#include "common/thread.h"
#include "core/hle/result.h"
+#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/mutex.h"
namespace Core {
@@ -28,10 +29,6 @@ class KSynchronizationObject;
namespace Service {
-class HLERequestContext;
-class SessionRequestHandler;
-class SessionRequestManager;
-
class ServerManager {
public:
explicit ServerManager(Core::System& system);
@@ -40,10 +37,13 @@ public:
Result RegisterSession(Kernel::KServerSession* session,
std::shared_ptr<SessionRequestManager> manager);
Result RegisterNamedService(const std::string& service_name,
+ SessionRequestHandlerFactory&& handler_factory,
+ u32 max_sessions = 64);
+ Result RegisterNamedService(const std::string& service_name,
std::shared_ptr<SessionRequestHandler>&& handler,
u32 max_sessions = 64);
Result ManageNamedPort(const std::string& service_name,
- std::shared_ptr<SessionRequestHandler>&& handler, u32 max_sessions = 64);
+ SessionRequestHandlerFactory&& handler_factory, u32 max_sessions = 64);
Result ManageDeferral(Kernel::KEvent** out_event);
Result LoopProcess();
@@ -56,7 +56,7 @@ private:
Result LoopProcessImpl();
Result WaitAndProcessImpl();
- Result OnPortEvent(Kernel::KServerPort* port, std::shared_ptr<SessionRequestHandler>&& handler);
+ Result OnPortEvent(Kernel::KServerPort* port, SessionRequestHandlerFactory&& handler_factory);
Result OnSessionEvent(Kernel::KServerSession* session,
std::shared_ptr<SessionRequestManager>&& manager);
Result OnDeferralEvent(std::list<RequestState>&& deferrals);
@@ -68,7 +68,7 @@ private:
std::mutex m_list_mutex;
// Guest state tracking
- std::map<Kernel::KServerPort*, std::shared_ptr<SessionRequestHandler>> m_ports{};
+ std::map<Kernel::KServerPort*, SessionRequestHandlerFactory> m_ports{};
std::map<Kernel::KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions{};
Kernel::KEvent* m_event{};
Kernel::KEvent* m_deferral_event{};
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 0ad607391..00531b021 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -59,6 +59,7 @@
#include "core/hle/service/prepo/prepo.h"
#include "core/hle/service/psc/psc.h"
#include "core/hle/service/ptm/ptm.h"
+#include "core/hle/service/ro/ro.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings.h"
#include "core/hle/service/sm/sm.h"
@@ -270,6 +271,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); });
kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); });
kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); });
kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); });
kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); });
kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); });
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 9ab718e0a..296ee6e89 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -51,7 +51,7 @@ static Result ValidateServiceName(const std::string& name) {
}
Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
- SessionRequestHandlerPtr handler) {
+ SessionRequestHandlerFactory handler) {
R_TRY(ValidateServiceName(name));
std::scoped_lock lk{lock};
@@ -121,7 +121,7 @@ void SM::Initialize(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
-void SM::GetService(HLERequestContext& ctx) {
+void SM::GetServiceCmif(HLERequestContext& ctx) {
Kernel::KClientSession* client_session{};
auto result = GetServiceImpl(&client_session, ctx);
if (ctx.GetIsDeferred()) {
@@ -192,19 +192,32 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
return result;
}
- LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
-
*out_client_session = session;
return ResultSuccess;
}
-void SM::RegisterService(HLERequestContext& ctx) {
+void SM::RegisterServiceCmif(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
std::string name(PopServiceName(rp));
const auto is_light = static_cast<bool>(rp.PopRaw<u32>());
const auto max_session_count = rp.PopRaw<u32>();
+ this->RegisterServiceImpl(ctx, name, max_session_count, is_light);
+}
+
+void SM::RegisterServiceTipc(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ std::string name(PopServiceName(rp));
+
+ const auto max_session_count = rp.PopRaw<u32>();
+ const auto is_light = static_cast<bool>(rp.PopRaw<u32>());
+
+ this->RegisterServiceImpl(ctx, name, max_session_count, is_light);
+}
+
+void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_session_count,
+ bool is_light) {
LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name,
max_session_count, is_light);
@@ -240,15 +253,15 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_)
service_manager{service_manager_}, kernel{system_.Kernel()} {
RegisterHandlers({
{0, &SM::Initialize, "Initialize"},
- {1, &SM::GetService, "GetService"},
- {2, &SM::RegisterService, "RegisterService"},
+ {1, &SM::GetServiceCmif, "GetService"},
+ {2, &SM::RegisterServiceCmif, "RegisterService"},
{3, &SM::UnregisterService, "UnregisterService"},
{4, nullptr, "DetachClient"},
});
RegisterHandlersTipc({
{0, &SM::Initialize, "Initialize"},
{1, &SM::GetServiceTipc, "GetService"},
- {2, &SM::RegisterService, "RegisterService"},
+ {2, &SM::RegisterServiceTipc, "RegisterService"},
{3, &SM::UnregisterService, "UnregisterService"},
{4, nullptr, "DetachClient"},
});
@@ -264,7 +277,9 @@ void LoopProcess(Core::System& system) {
server_manager->ManageDeferral(&deferral_event);
service_manager.SetDeferralEvent(deferral_event);
- server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system));
+ auto sm_service = std::make_shared<SM>(system.ServiceManager(), system);
+ server_manager->ManageNamedPort("sm:", [sm_service] { return sm_service; });
+
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 14bfaf8c2..ff74f588a 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -37,12 +37,15 @@ public:
private:
void Initialize(HLERequestContext& ctx);
- void GetService(HLERequestContext& ctx);
+ void GetServiceCmif(HLERequestContext& ctx);
void GetServiceTipc(HLERequestContext& ctx);
- void RegisterService(HLERequestContext& ctx);
+ void RegisterServiceCmif(HLERequestContext& ctx);
+ void RegisterServiceTipc(HLERequestContext& ctx);
void UnregisterService(HLERequestContext& ctx);
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx);
+ void RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_session_count,
+ bool is_light);
ServiceManager& service_manager;
Kernel::KernelCore& kernel;
@@ -53,7 +56,8 @@ public:
explicit ServiceManager(Kernel::KernelCore& kernel_);
~ServiceManager();
- Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler);
+ Result RegisterService(std::string name, u32 max_sessions,
+ SessionRequestHandlerFactory handler_factory);
Result UnregisterService(const std::string& name);
Result GetServicePort(Kernel::KPort** out_port, const std::string& name);
@@ -64,7 +68,7 @@ public:
LOG_DEBUG(Service, "Can't find service: {}", service_name);
return nullptr;
}
- return std::static_pointer_cast<T>(service->second);
+ return std::static_pointer_cast<T>(service->second());
}
void InvokeControlRequest(HLERequestContext& context);
@@ -79,7 +83,7 @@ private:
/// Map of registered services, retrieved using GetServicePort.
std::mutex lock;
- std::unordered_map<std::string, SessionRequestHandlerPtr> registered_services;
+ std::unordered_map<std::string, SessionRequestHandlerFactory> registered_services;
std::unordered_map<std::string, Kernel::KPort*> service_ports;
/// Kernel context
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 6c8427b0d..0fbb43057 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -240,7 +240,7 @@ private:
return ret;
}
- Result ReadImpl(std::vector<u8>* out_data, size_t size) {
+ Result ReadImpl(std::vector<u8>* out_data) {
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
size_t actual_size{};
Result res = backend->Read(&actual_size, *out_data);
@@ -326,8 +326,8 @@ private:
}
void Read(HLERequestContext& ctx) {
- std::vector<u8> output_bytes;
- const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize());
+ std::vector<u8> output_bytes(ctx.GetWriteBufferSize());
+ const Result res = ReadImpl(&output_bytes);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
if (res == ResultSuccess) {
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 5b376b202..169bf4c8c 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -43,13 +43,9 @@ bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessA
struct Memory::Impl {
explicit Impl(Core::System& system_) : system{system_} {}
- void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
+ void SetCurrentPageTable(Kernel::KProcess& process) {
current_page_table = &process.GetPageTable().GetImpl();
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
-
- const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
-
- system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
}
void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
@@ -871,8 +867,8 @@ void Memory::Reset() {
impl = std::make_unique<Impl>(system);
}
-void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
- impl->SetCurrentPageTable(process, core_id);
+void Memory::SetCurrentPageTable(Kernel::KProcess& process) {
+ impl->SetCurrentPageTable(process);
}
void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
diff --git a/src/core/memory.h b/src/core/memory.h
index ed8ebb5eb..c1879e78f 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -73,7 +73,7 @@ public:
*
* @param process The process to use the page table of.
*/
- void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id);
+ void SetCurrentPageTable(Kernel::KProcess& process);
/**
* Maps an allocated buffer onto a region of the emulated process address space.
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index db30ba598..3fc4024dc 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -62,7 +62,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
}
const auto applet_resource = hid->GetResourceManager();
- if (applet_resource == nullptr) {
+ if (applet_resource == nullptr || applet_resource->GetNpad() == nullptr) {
LOG_WARNING(CheatEngine,
"Attempted to read input state, but applet resource is not initialized!");
return 0;
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 5d168cbc1..dc3883528 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -109,41 +109,11 @@ json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64
return out;
}
-json GetProcessorStateDataAuto(Core::System& system) {
- const auto* process{system.ApplicationProcess()};
- auto& arm{system.CurrentArmInterface()};
-
- Core::ARM_Interface::ThreadContext64 context{};
- arm.SaveContext(context);
-
- return GetProcessorStateData(process->Is64Bit() ? "AArch64" : "AArch32",
- GetInteger(process->GetEntryPoint()), context.sp, context.pc,
- context.pstate, context.cpu_registers);
-}
-
-json GetBacktraceData(Core::System& system) {
- auto out = json::array();
- const auto& backtrace{system.CurrentArmInterface().GetBacktrace()};
- for (const auto& entry : backtrace) {
- out.push_back({
- {"module", entry.module},
- {"address", fmt::format("{:016X}", entry.address)},
- {"original_address", fmt::format("{:016X}", entry.original_address)},
- {"offset", fmt::format("{:016X}", entry.offset)},
- {"symbol_name", entry.name},
- });
- }
-
- return out;
-}
-
json GetFullDataAuto(const std::string& timestamp, u64 title_id, Core::System& system) {
json out;
out["yuzu_version"] = GetYuzuVersionData();
out["report_common"] = GetReportCommonData(title_id, ResultSuccess, timestamp);
- out["processor_state"] = GetProcessorStateDataAuto(system);
- out["backtrace"] = GetBacktraceData(system);
return out;
}
@@ -351,8 +321,6 @@ void Reporter::SaveErrorReport(u64 title_id, Result result,
out["yuzu_version"] = GetYuzuVersionData();
out["report_common"] = GetReportCommonData(title_id, result, timestamp);
- out["processor_state"] = GetProcessorStateDataAuto(system);
- out["backtrace"] = GetBacktraceData(system);
out["error_custom_text"] = {
{"main", custom_text_main.value_or("")},
diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp
index 618793668..2dbff21af 100644
--- a/src/tests/video_core/memory_tracker.cpp
+++ b/src/tests/video_core/memory_tracker.cpp
@@ -23,13 +23,13 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE;
class RasterizerInterface {
public:
- void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
+ void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS};
const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >>
Core::Memory::YUZU_PAGEBITS};
for (u64 page = page_start; page < page_end; ++page) {
int& value = page_table[page];
- value += delta;
+ value += (cache ? 1 : -1);
if (value < 0) {
throw std::logic_error{"negative page"};
}
@@ -546,4 +546,4 @@ TEST_CASE("MemoryTracker: Cached write downloads") {
REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE));
memory_track->MarkRegionAsCpuModified(c, WORD);
REQUIRE(rasterizer.Count() == 0);
-} \ No newline at end of file
+}
diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h
index a336bde41..95b752055 100644
--- a/src/video_core/buffer_cache/word_manager.h
+++ b/src/video_core/buffer_cache/word_manager.h
@@ -473,7 +473,7 @@ private:
VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
IteratePages(changed_bits, [&](size_t offset, size_t size) {
rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE,
- size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1);
+ size * BYTES_PER_PAGE, add_to_rasterizer);
});
}
diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp
index dcd07e6d2..96686da59 100644
--- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp
+++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp
@@ -233,7 +233,12 @@ std::unique_ptr<Frame> DecoderContext::ReceiveFrame(bool* out_is_interlaced) {
return false;
}
- *out_is_interlaced = frame->interlaced_frame != 0;
+ *out_is_interlaced =
+#if defined(FF_API_INTERLACED_FRAME) || LIBAVUTIL_VERSION_MAJOR >= 59
+ (frame->flags & AV_FRAME_FLAG_INTERLACED) != 0;
+#else
+ frame->interlaced_frame != 0;
+#endif
return true;
};
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index f200a650f..3c9477f6e 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -3,6 +3,7 @@
#include <atomic>
+#include "common/alignment.h"
#include "common/assert.h"
#include "common/common_types.h"
#include "common/div_ceil.h"
@@ -11,61 +12,65 @@
namespace VideoCore {
+static constexpr u16 IdentityValue = 1;
+
using namespace Core::Memory;
-RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
- : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
+RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : map{}, cpu_memory{cpu_memory_} {
+ // We are tracking CPU memory, which cannot map more than 39 bits.
+ const VAddr start_address = 0;
+ const VAddr end_address = (1ULL << 39);
+ const IntervalType address_space_interval(start_address, end_address);
+ const auto value = std::make_pair(address_space_interval, IdentityValue);
+
+ map.add(value);
+}
RasterizerAccelerated::~RasterizerAccelerated() = default;
-void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
- u64 uncache_begin = 0;
- u64 cache_begin = 0;
- u64 uncache_bytes = 0;
- u64 cache_bytes = 0;
-
- std::atomic_thread_fence(std::memory_order_acquire);
- const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
- for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
- std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
-
- if (delta > 0) {
- ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
- } else if (delta < 0) {
- ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
- } else {
- ASSERT_MSG(false, "Delta must be non-zero!");
- }
+void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
+ std::scoped_lock lk{map_lock};
- // Adds or subtracts 1, as count is a unsigned 8-bit value
- count.fetch_add(static_cast<u16>(delta), std::memory_order_release);
-
- // Assume delta is either -1 or 1
- if (count.load(std::memory_order::relaxed) == 0) {
- if (uncache_bytes == 0) {
- uncache_begin = page;
- }
- uncache_bytes += YUZU_PAGESIZE;
- } else if (uncache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes,
- false);
- uncache_bytes = 0;
- }
- if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
- if (cache_bytes == 0) {
- cache_begin = page;
- }
- cache_bytes += YUZU_PAGESIZE;
- } else if (cache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
- cache_bytes = 0;
+ // Align sizes.
+ addr = Common::AlignDown(addr, YUZU_PAGESIZE);
+ size = Common::AlignUp(size, YUZU_PAGESIZE);
+
+ // Declare the overall interval we are going to operate on.
+ const VAddr start_address = addr;
+ const VAddr end_address = addr + size;
+ const IntervalType modification_range(start_address, end_address);
+
+ // Find the boundaries of where to iterate.
+ const auto lower = map.lower_bound(modification_range);
+ const auto upper = map.upper_bound(modification_range);
+
+ // Iterate over the contained intervals.
+ for (auto it = lower; it != upper; it++) {
+ // Intersect interval range with modification range.
+ const auto current_range = modification_range & it->first;
+
+ // Calculate the address and size to operate over.
+ const auto current_addr = current_range.lower();
+ const auto current_size = current_range.upper() - current_addr;
+
+ // Get the current value of the range.
+ const auto value = it->second;
+
+ if (cache && value == IdentityValue) {
+ // If we are going to cache, and the value is not yet referenced, then cache this range.
+ cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, true);
+ } else if (!cache && value == IdentityValue + 1) {
+ // If we are going to uncache, and this is the last reference, then uncache this range.
+ cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, false);
}
}
- if (uncache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false);
- }
- if (cache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
+
+ // Update the set.
+ const auto value = std::make_pair(modification_range, IdentityValue);
+ if (cache) {
+ map.add(value);
+ } else {
+ map.subtract(value);
}
}
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index e6c0ea87a..f1968f186 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -3,8 +3,8 @@
#pragma once
-#include <array>
-#include <atomic>
+#include <mutex>
+#include <boost/icl/interval_map.hpp>
#include "common/common_types.h"
#include "video_core/rasterizer_interface.h"
@@ -21,28 +21,17 @@ public:
explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
~RasterizerAccelerated() override;
- void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
+ void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) override;
private:
- class CacheEntry final {
- public:
- CacheEntry() = default;
+ using PageIndex = VAddr;
+ using PageReferenceCount = u16;
- std::atomic_uint16_t& Count(std::size_t page) {
- return values[page & 3];
- }
+ using IntervalMap = boost::icl::interval_map<PageIndex, PageReferenceCount>;
+ using IntervalType = IntervalMap::interval_type;
- const std::atomic_uint16_t& Count(std::size_t page) const {
- return values[page & 3];
- }
-
- private:
- std::array<std::atomic_uint16_t, 4> values{};
- };
- static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
-
- using CachedPages = std::array<CacheEntry, 0x2000000>;
- std::unique_ptr<CachedPages> cached_pages;
+ IntervalMap map;
+ std::mutex map_lock;
Core::Memory::Memory& cpu_memory;
};
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index af1469147..fd42d26b5 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -162,7 +162,7 @@ public:
}
/// Increase/decrease the number of object in pages touching the specified region
- virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {}
+ virtual void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {}
/// Initialize disk cached resources for the game being emulated
virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 9995b6dd4..279e5a4e0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -714,7 +714,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
std::scoped_lock lock{texture_cache.mutex};
- ImageView* const image_view{texture_cache.TryFindFramebufferImageView(framebuffer_addr)};
+ ImageView* const image_view{
+ texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
if (!image_view) {
return false;
}
@@ -725,7 +726,6 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
screen_info.texture.width = image_view->size.width;
screen_info.texture.height = image_view->size.height;
screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
- screen_info.display_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format);
return true;
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 6bfed08a1..7a4f0c5c1 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -653,11 +653,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
};
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
- if (screen_info.display_srgb) {
- glEnable(GL_FRAMEBUFFER_SRGB);
- } else {
- glDisable(GL_FRAMEBUFFER_SRGB);
- }
+ glDisable(GL_FRAMEBUFFER_SRGB);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
static_cast<GLfloat>(layout.height));
@@ -710,8 +706,7 @@ void RendererOpenGL::RenderScreenshot() {
GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
- glRenderbufferStorage(GL_RENDERBUFFER, screen_info.display_srgb ? GL_SRGB8 : GL_RGB8,
- layout.width, layout.height);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
DrawScreen(layout);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index f1d5fd954..b70607635 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -53,7 +53,6 @@ struct TextureInfo {
struct ScreenInfo {
GLuint display_texture{};
bool was_accelerated = false;
- bool display_srgb{};
const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
TextureInfo texture;
};
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index c4c30d807..100b70918 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -94,7 +94,7 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(),
scheduler(device, state_tracker),
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
- render_window.GetFramebufferLayout().height, false),
+ render_window.GetFramebufferLayout().height),
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
surface),
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
@@ -131,11 +131,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
const bool use_accelerated =
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
- const bool is_srgb = use_accelerated && screen_info.is_srgb;
RenderScreenshot(*framebuffer, use_accelerated);
Frame* frame = present_manager.GetRenderFrame();
- blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb);
+ blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated);
scheduler.Flush(*frame->render_ready);
present_manager.Present(frame);
@@ -205,7 +204,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
.flags = 0,
.image = *staging_image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = screen_info.is_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM,
+ .format = VK_FORMAT_B8G8R8A8_UNORM,
.components{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 5e461fbd0..60432f5ad 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -127,9 +127,9 @@ BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWin
Scheduler& scheduler_, const ScreenInfo& screen_info_)
: cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
- scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_},
- current_srgb{swapchain.IsSrgb()}, image_view_format{swapchain.GetImageViewFormat()} {
+ scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
resource_ticks.resize(image_count);
+ swapchain_view_format = swapchain.GetImageViewFormat();
CreateStaticResources();
CreateDynamicResources();
@@ -480,28 +480,22 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
}
void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
- bool use_accelerated, bool is_srgb) {
- // Recreate dynamic resources if the the image count or colorspace changed
+ bool use_accelerated) {
+ // Recreate dynamic resources if the the image count or input format changed
+ const VkFormat current_framebuffer_format =
+ std::exchange(framebuffer_view_format, GetFormat(framebuffer));
if (const std::size_t swapchain_images = swapchain.GetImageCount();
- swapchain_images != image_count || current_srgb != is_srgb) {
- current_srgb = is_srgb;
-#ifdef ANDROID
- // Android is already ordered the same as Switch.
- image_view_format = current_srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
-#else
- image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
-#endif
+ swapchain_images != image_count || current_framebuffer_format != framebuffer_view_format) {
image_count = swapchain_images;
Recreate();
}
// Recreate the presentation frame if the dimensions of the window changed
const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
- if (layout.width != frame->width || layout.height != frame->height ||
- is_srgb != frame->is_srgb) {
+ if (layout.width != frame->width || layout.height != frame->height) {
Recreate();
- present_manager.RecreateFrame(frame, layout.width, layout.height, is_srgb,
- image_view_format, *renderpass);
+ present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
+ *renderpass);
}
const VkExtent2D render_area{frame->width, frame->height};
@@ -629,7 +623,7 @@ void BlitScreen::CreateDescriptorPool() {
}
void BlitScreen::CreateRenderPass() {
- renderpass = CreateRenderPassImpl(image_view_format);
+ renderpass = CreateRenderPassImpl(swapchain_view_format);
}
vk::RenderPass BlitScreen::CreateRenderPassImpl(VkFormat format) {
@@ -1149,7 +1143,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
.pNext = nullptr,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
- .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer),
+ .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format,
.extent =
{
.width = (up_scale * framebuffer.width) >> down_shift,
@@ -1174,7 +1168,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
.flags = 0,
.image = *image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer),
+ .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format,
.components =
{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 8365b5668..16b882b6d 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -52,7 +52,6 @@ struct ScreenInfo {
VkImageView image_view{};
u32 width{};
u32 height{};
- bool is_srgb{};
};
class BlitScreen {
@@ -69,7 +68,7 @@ public:
const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated);
void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
- bool use_accelerated, bool is_srgb);
+ bool use_accelerated);
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
VkExtent2D extent);
@@ -161,8 +160,8 @@ private:
u32 raw_width = 0;
u32 raw_height = 0;
Service::android::PixelFormat pixel_format{};
- bool current_srgb;
- VkFormat image_view_format;
+ VkFormat framebuffer_view_format;
+ VkFormat swapchain_view_format;
std::unique_ptr<FSR> fsr;
std::unique_ptr<SMAA> smaa;
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 2ef36583b..8e4c74b5c 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -172,13 +172,12 @@ void PresentManager::Present(Frame* frame) {
});
}
-void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb,
- VkFormat image_view_format, VkRenderPass rd) {
+void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
+ VkRenderPass rd) {
auto& dld = device.GetLogical();
frame->width = width;
frame->height = height;
- frame->is_srgb = is_srgb;
frame->image = memory_allocator.CreateImage({
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -289,7 +288,7 @@ void PresentManager::PresentThread(std::stop_token token) {
}
void PresentManager::RecreateSwapchain(Frame* frame) {
- swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb);
+ swapchain.Create(*surface, frame->width, frame->height);
image_count = swapchain.GetImageCount();
}
@@ -319,12 +318,12 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
void PresentManager::CopyToSwapchainImpl(Frame* frame) {
MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
- // If the size or colorspace of the incoming frames has changed, recreate the swapchain
+ // If the size of the incoming frames has changed, recreate the swapchain
// to account for that.
- const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb);
+ const bool is_suboptimal = swapchain.NeedsRecreation();
const bool size_changed =
swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
- if (srgb_changed || size_changed) {
+ if (is_suboptimal || size_changed) {
RecreateSwapchain(frame);
}
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index a3d825fe6..337171a09 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -25,7 +25,6 @@ class Swapchain;
struct Frame {
u32 width;
u32 height;
- bool is_srgb;
vk::Image image;
vk::ImageView image_view;
vk::Framebuffer framebuffer;
@@ -48,8 +47,8 @@ public:
void Present(Frame* frame);
/// Recreates the present frame to match the provided parameters
- void RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb,
- VkFormat image_view_format, VkRenderPass rd);
+ void RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
+ VkRenderPass rd);
/// Waits for the present thread to finish presenting all queued frames.
void WaitPresent();
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index b6f52e017..59829c88b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -783,7 +783,8 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
return false;
}
std::scoped_lock lock{texture_cache.mutex};
- ImageView* const image_view = texture_cache.TryFindFramebufferImageView(framebuffer_addr);
+ ImageView* const image_view =
+ texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
if (!image_view) {
return false;
}
@@ -792,7 +793,6 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D);
screen_info.width = image_view->size.width;
screen_info.height = image_view->size.height;
- screen_info.is_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format);
return true;
}
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 821f44f1a..86a30dcd1 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -105,14 +105,14 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
} // Anonymous namespace
Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
- u32 width_, u32 height_, bool srgb)
+ u32 width_, u32 height_)
: surface{surface_}, device{device_}, scheduler{scheduler_} {
- Create(surface_, width_, height_, srgb);
+ Create(surface_, width_, height_);
}
Swapchain::~Swapchain() = default;
-void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) {
+void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_) {
is_outdated = false;
is_suboptimal = false;
width = width_;
@@ -127,7 +127,7 @@ void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb
Destroy();
- CreateSwapchain(capabilities, srgb);
+ CreateSwapchain(capabilities);
CreateSemaphores();
resource_ticks.clear();
@@ -196,7 +196,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
}
}
-void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) {
+void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
const auto physical_device{device.GetPhysical()};
const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface);
@@ -274,15 +274,14 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci);
extent = swapchain_ci.imageExtent;
- current_srgb = srgb;
images = swapchain.GetImages();
image_count = static_cast<u32>(images.size());
#ifdef ANDROID
// Android is already ordered the same as Switch.
- image_view_format = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+ image_view_format = VK_FORMAT_R8G8B8A8_UNORM;
#else
- image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
+ image_view_format = VK_FORMAT_B8G8R8A8_UNORM;
#endif
}
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index b8a1465a6..d264f06e4 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -20,11 +20,11 @@ class Scheduler;
class Swapchain {
public:
explicit Swapchain(VkSurfaceKHR surface, const Device& device, Scheduler& scheduler, u32 width,
- u32 height, bool srgb);
+ u32 height);
~Swapchain();
/// Creates (or recreates) the swapchain with a given size.
- void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb);
+ void Create(VkSurfaceKHR surface, u32 width, u32 height);
/// Acquires the next image in the swapchain, waits as needed.
bool AcquireNextImage();
@@ -33,13 +33,8 @@ public:
void Present(VkSemaphore render_semaphore);
/// Returns true when the swapchain needs to be recreated.
- bool NeedsRecreation(bool is_srgb) const {
- return HasColorSpaceChanged(is_srgb) || IsSubOptimal() || NeedsPresentModeUpdate();
- }
-
- /// Returns true when the color space has changed.
- bool HasColorSpaceChanged(bool is_srgb) const {
- return current_srgb != is_srgb;
+ bool NeedsRecreation() const {
+ return IsSubOptimal() || NeedsPresentModeUpdate();
}
/// Returns true when the swapchain is outdated.
@@ -52,11 +47,6 @@ public:
return is_suboptimal;
}
- /// Returns true when the swapchain format is in the srgb color space
- bool IsSrgb() const {
- return current_srgb;
- }
-
VkExtent2D GetSize() const {
return extent;
}
@@ -110,7 +100,7 @@ public:
}
private:
- void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb);
+ void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities);
void CreateSemaphores();
void CreateImageViews();
@@ -144,7 +134,6 @@ private:
bool has_mailbox{false};
bool has_fifo_relaxed{false};
- bool current_srgb{};
bool is_outdated{};
bool is_suboptimal{};
};
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp
index e81cd031b..a109f9cbe 100644
--- a/src/video_core/shader_cache.cpp
+++ b/src/video_core/shader_cache.cpp
@@ -132,7 +132,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
storage.push_back(std::move(data));
- rasterizer.UpdatePagesCachedCount(addr, size, 1);
+ rasterizer.UpdatePagesCachedCount(addr, size, true);
}
void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
@@ -209,7 +209,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) {
const VAddr addr = entry->addr_start;
const size_t size = entry->addr_end - addr;
- rasterizer.UpdatePagesCachedCount(addr, size, -1);
+ rasterizer.UpdatePagesCachedCount(addr, size, false);
}
void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index dade38b18..d7941f6a4 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -712,14 +712,15 @@ bool TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
}
template <class P>
-typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_addr) {
+typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
+ const Tegra::FramebufferConfig& config, VAddr cpu_addr) {
// TODO: Properly implement this
const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
if (it == page_table.end()) {
return nullptr;
}
const auto& image_map_ids = it->second;
- boost::container::small_vector<const ImageBase*, 4> valid_images;
+ boost::container::small_vector<ImageId, 4> valid_image_ids;
for (const ImageMapId map_id : image_map_ids) {
const ImageMapView& map = slot_map_views[map_id];
const ImageBase& image = slot_images[map.image_id];
@@ -729,18 +730,34 @@ typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_ad
if (image.image_view_ids.empty()) {
continue;
}
- valid_images.push_back(&image);
+ valid_image_ids.push_back(map.image_id);
}
- if (valid_images.size() == 1) [[likely]] {
- return &slot_image_views[valid_images[0]->image_view_ids.at(0)];
+ const auto view_format = [&]() {
+ switch (config.pixel_format) {
+ case Service::android::PixelFormat::Rgb565:
+ return PixelFormat::R5G6B5_UNORM;
+ case Service::android::PixelFormat::Bgra8888:
+ return PixelFormat::B8G8R8A8_UNORM;
+ default:
+ return PixelFormat::A8B8G8R8_UNORM;
+ }
+ }();
+
+ const auto GetImageViewForFramebuffer = [&](ImageId image_id) {
+ const ImageViewInfo info{ImageViewType::e2D, view_format};
+ return &slot_image_views[FindOrEmplaceImageView(image_id, info)];
+ };
+
+ if (valid_image_ids.size() == 1) [[likely]] {
+ return GetImageViewForFramebuffer(valid_image_ids.front());
}
- if (valid_images.size() > 0) [[unlikely]] {
- std::ranges::sort(valid_images, [](const auto* a, const auto* b) {
- return a->modification_tick > b->modification_tick;
+ if (valid_image_ids.size() > 0) [[unlikely]] {
+ auto most_recent = std::ranges::max_element(valid_image_ids, [&](auto a, auto b) {
+ return slot_images[a].modification_tick < slot_images[b].modification_tick;
});
- return &slot_image_views[valid_images[0]->image_view_ids.at(0)];
+ return GetImageViewForFramebuffer(*most_recent);
}
return nullptr;
@@ -2063,7 +2080,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
ASSERT(False(image.flags & ImageFlagBits::Tracked));
image.flags |= ImageFlagBits::Tracked;
if (False(image.flags & ImageFlagBits::Sparse)) {
- rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1);
+ rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, true);
return;
}
if (True(image.flags & ImageFlagBits::Registered)) {
@@ -2074,13 +2091,13 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
const auto& map = slot_map_views[map_view_id];
const VAddr cpu_addr = map.cpu_addr;
const std::size_t size = map.size;
- rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
+ rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
}
return;
}
ForEachSparseSegment(image,
[this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) {
- rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
+ rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
});
}
@@ -2089,7 +2106,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
ASSERT(True(image.flags & ImageFlagBits::Tracked));
image.flags &= ~ImageFlagBits::Tracked;
if (False(image.flags & ImageFlagBits::Sparse)) {
- rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1);
+ rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, false);
return;
}
ASSERT(True(image.flags & ImageFlagBits::Registered));
@@ -2100,7 +2117,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
const auto& map = slot_map_views[map_view_id];
const VAddr cpu_addr = map.cpu_addr;
const std::size_t size = map.size;
- rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1);
+ rasterizer.UpdatePagesCachedCount(cpu_addr, size, false);
}
}
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index a40825c9f..cbe56e166 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -209,7 +209,8 @@ public:
const Tegra::Engines::Fermi2D::Config& copy);
/// Try to find a cached image view in the given CPU address
- [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr);
+ [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config,
+ VAddr cpu_addr);
/// Return true when there are uncommitted images to be downloaded
[[nodiscard]] bool HasUncommittedFlushes() const noexcept;
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 1f3f23038..79162a491 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -14,6 +14,8 @@
#include "common/fs/path_util.h"
#include "common/string_util.h"
#include "core/constants.h"
+#include "core/core.h"
+#include "core/hle/service/acc/profile_manager.h"
#include "yuzu/applets/qt_profile_select.h"
#include "yuzu/main.h"
#include "yuzu/util/controller_navigation.h"
@@ -47,9 +49,9 @@ QPixmap GetIcon(Common::UUID uuid) {
} // Anonymous namespace
QtProfileSelectionDialog::QtProfileSelectionDialog(
- Core::HID::HIDCore& hid_core, QWidget* parent,
+ Core::System& system, QWidget* parent,
const Core::Frontend::ProfileSelectParameters& parameters)
- : QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
+ : QDialog(parent), profile_manager{system.GetProfileManager()} {
outer_layout = new QVBoxLayout;
instruction_label = new QLabel();
@@ -68,7 +70,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(
tree_view = new QTreeView;
item_model = new QStandardItemModel(tree_view);
tree_view->setModel(item_model);
- controller_navigation = new ControllerNavigation(hid_core, this);
+ controller_navigation = new ControllerNavigation(system.HIDCore(), this);
tree_view->setAlternatingRowColors(true);
tree_view->setSelectionMode(QHeaderView::SingleSelection);
@@ -106,10 +108,10 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(
SelectUser(tree_view->currentIndex());
});
- const auto& profiles = profile_manager->GetAllUsers();
+ const auto& profiles = profile_manager.GetAllUsers();
for (const auto& user : profiles) {
Service::Account::ProfileBase profile{};
- if (!profile_manager->GetProfileBase(user, profile))
+ if (!profile_manager.GetProfileBase(user, profile))
continue;
const auto username = Common::StringFromFixedZeroTerminatedBuffer(
@@ -134,7 +136,7 @@ QtProfileSelectionDialog::~QtProfileSelectionDialog() {
int QtProfileSelectionDialog::exec() {
// Skip profile selection when there's only one.
- if (profile_manager->GetUserCount() == 1) {
+ if (profile_manager.GetUserCount() == 1) {
user_index = 0;
return QDialog::Accepted;
}
diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h
index 99056e274..607f1777c 100644
--- a/src/yuzu/applets/qt_profile_select.h
+++ b/src/yuzu/applets/qt_profile_select.h
@@ -7,7 +7,6 @@
#include <QDialog>
#include <QList>
#include "core/frontend/applets/profile_select.h"
-#include "core/hle/service/acc/profile_manager.h"
class ControllerNavigation;
class GMainWindow;
@@ -20,15 +19,19 @@ class QStandardItemModel;
class QTreeView;
class QVBoxLayout;
-namespace Core::HID {
-class HIDCore;
-} // namespace Core::HID
+namespace Core {
+class System;
+}
+
+namespace Service::Account {
+class ProfileManager;
+}
class QtProfileSelectionDialog final : public QDialog {
Q_OBJECT
public:
- explicit QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent,
+ explicit QtProfileSelectionDialog(Core::System& system, QWidget* parent,
const Core::Frontend::ProfileSelectParameters& parameters);
~QtProfileSelectionDialog() override;
@@ -58,7 +61,7 @@ private:
QScrollArea* scroll_area;
QDialogButtonBox* buttons;
- std::unique_ptr<Service::Account::ProfileManager> profile_manager;
+ Service::Account::ProfileManager& profile_manager;
ControllerNavigation* controller_navigation = nullptr;
};
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 22b51f39c..d842b0135 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -381,7 +381,7 @@
<item row="5" column="0">
<widget class="QCheckBox" name="disable_buffer_reorder">
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, disables reording of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When checked, disables reordering of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Disable Buffer Reorder</string>
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 6d2219bf5..fa5f383d6 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -76,9 +76,9 @@ QString GetProfileUsernameFromUser(QWidget* parent, const QString& description_t
}
} // Anonymous namespace
-ConfigureProfileManager::ConfigureProfileManager(const Core::System& system_, QWidget* parent)
+ConfigureProfileManager::ConfigureProfileManager(Core::System& system_, QWidget* parent)
: QWidget(parent), ui{std::make_unique<Ui::ConfigureProfileManager>()},
- profile_manager(std::make_unique<Service::Account::ProfileManager>()), system{system_} {
+ profile_manager{system_.GetProfileManager()}, system{system_} {
ui->setupUi(this);
tree_view = new QTreeView;
@@ -149,10 +149,10 @@ void ConfigureProfileManager::SetConfiguration() {
}
void ConfigureProfileManager::PopulateUserList() {
- const auto& profiles = profile_manager->GetAllUsers();
+ const auto& profiles = profile_manager.GetAllUsers();
for (const auto& user : profiles) {
Service::Account::ProfileBase profile{};
- if (!profile_manager->GetProfileBase(user, profile))
+ if (!profile_manager.GetProfileBase(user, profile))
continue;
const auto username = Common::StringFromFixedZeroTerminatedBuffer(
@@ -167,11 +167,11 @@ void ConfigureProfileManager::PopulateUserList() {
}
void ConfigureProfileManager::UpdateCurrentUser() {
- ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS);
+ ui->pm_add->setEnabled(profile_manager.GetUserCount() < Service::Account::MAX_USERS);
- const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue());
+ const auto& current_user = profile_manager.GetUser(Settings::values.current_user.GetValue());
ASSERT(current_user);
- const auto username = GetAccountUsername(*profile_manager, *current_user);
+ const auto username = GetAccountUsername(profile_manager, *current_user);
scene->clear();
scene->addPixmap(
@@ -187,11 +187,11 @@ void ConfigureProfileManager::ApplyConfiguration() {
void ConfigureProfileManager::SelectUser(const QModelIndex& index) {
Settings::values.current_user =
- std::clamp<s32>(index.row(), 0, static_cast<s32>(profile_manager->GetUserCount() - 1));
+ std::clamp<s32>(index.row(), 0, static_cast<s32>(profile_manager.GetUserCount() - 1));
UpdateCurrentUser();
- ui->pm_remove->setEnabled(profile_manager->GetUserCount() >= 2);
+ ui->pm_remove->setEnabled(profile_manager.GetUserCount() >= 2);
ui->pm_rename->setEnabled(true);
ui->pm_set_image->setEnabled(true);
}
@@ -204,18 +204,18 @@ void ConfigureProfileManager::AddUser() {
}
const auto uuid = Common::UUID::MakeRandom();
- profile_manager->CreateNewUser(uuid, username.toStdString());
+ profile_manager.CreateNewUser(uuid, username.toStdString());
item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)});
}
void ConfigureProfileManager::RenameUser() {
const auto user = tree_view->currentIndex().row();
- const auto uuid = profile_manager->GetUser(user);
+ const auto uuid = profile_manager.GetUser(user);
ASSERT(uuid);
Service::Account::ProfileBase profile{};
- if (!profile_manager->GetProfileBase(*uuid, profile))
+ if (!profile_manager.GetProfileBase(*uuid, profile))
return;
const auto new_username = GetProfileUsernameFromUser(this, tr("Enter a new username:"));
@@ -227,7 +227,7 @@ void ConfigureProfileManager::RenameUser() {
std::fill(profile.username.begin(), profile.username.end(), '\0');
std::copy(username_std.begin(), username_std.end(), profile.username.begin());
- profile_manager->SetProfileBase(*uuid, profile);
+ profile_manager.SetProfileBase(*uuid, profile);
item_model->setItem(
user, 0,
@@ -238,9 +238,9 @@ void ConfigureProfileManager::RenameUser() {
void ConfigureProfileManager::ConfirmDeleteUser() {
const auto index = tree_view->currentIndex().row();
- const auto uuid = profile_manager->GetUser(index);
+ const auto uuid = profile_manager.GetUser(index);
ASSERT(uuid);
- const auto username = GetAccountUsername(*profile_manager, *uuid);
+ const auto username = GetAccountUsername(profile_manager, *uuid);
confirm_dialog->SetInfo(username, *uuid, [this, uuid]() { DeleteUser(*uuid); });
confirm_dialog->show();
@@ -252,7 +252,7 @@ void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) {
}
UpdateCurrentUser();
- if (!profile_manager->RemoveUser(uuid)) {
+ if (!profile_manager.RemoveUser(uuid)) {
return;
}
@@ -265,7 +265,7 @@ void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) {
void ConfigureProfileManager::SetUserImage() {
const auto index = tree_view->currentIndex().row();
- const auto uuid = profile_manager->GetUser(index);
+ const auto uuid = profile_manager.GetUser(index);
ASSERT(uuid);
const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(),
@@ -317,7 +317,7 @@ void ConfigureProfileManager::SetUserImage() {
}
}
- const auto username = GetAccountUsername(*profile_manager, *uuid);
+ const auto username = GetAccountUsername(profile_manager, *uuid);
item_model->setItem(index, 0,
new QStandardItem{GetIcon(*uuid), FormatUserEntryText(username, *uuid)});
UpdateCurrentUser();
diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h
index c4b1a334e..39560fdd9 100644
--- a/src/yuzu/configuration/configure_profile_manager.h
+++ b/src/yuzu/configuration/configure_profile_manager.h
@@ -52,7 +52,7 @@ class ConfigureProfileManager : public QWidget {
Q_OBJECT
public:
- explicit ConfigureProfileManager(const Core::System& system_, QWidget* parent = nullptr);
+ explicit ConfigureProfileManager(Core::System& system_, QWidget* parent = nullptr);
~ConfigureProfileManager() override;
void ApplyConfiguration();
@@ -85,7 +85,6 @@ private:
std::unique_ptr<Ui::ConfigureProfileManager> ui;
bool enabled = false;
- std::unique_ptr<Service::Account::ProfileManager> profile_manager;
-
+ Service::Account::ProfileManager& profile_manager;
const Core::System& system;
};
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 6d227ef8d..c05a05057 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -7,7 +7,7 @@
#include "yuzu/debugger/wait_tree.h"
#include "yuzu/uisettings.h"
-#include "core/arm/arm_interface.h"
+#include "core/arm/debug.h"
#include "core/core.h"
#include "core/hle/kernel/k_class_token.h"
#include "core/hle/kernel/k_handle_table.h"
@@ -129,7 +129,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
return list;
}
- auto backtrace = Core::ARM_Interface::GetBacktraceFromContext(system, thread.GetContext64());
+ auto backtrace = Core::GetBacktraceFromContext(thread.GetOwnerProcess(), thread.GetContext());
for (auto& entry : backtrace) {
std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
@@ -238,10 +238,10 @@ QString WaitTreeThread::GetText() const {
break;
}
- const auto& context = thread.GetContext64();
+ const auto& context = thread.GetContext();
const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
.arg(context.pc, 8, 16, QLatin1Char{'0'})
- .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'});
+ .arg(context.lr, 8, 16, QLatin1Char{'0'});
return QStringLiteral("%1%2 (%3) ")
.arg(WaitTreeSynchronizationObject::GetText(), pc_info, status);
}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b056c3717..f31ed7ebb 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -346,7 +346,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
discord_rpc->Update();
- play_time_manager = std::make_unique<PlayTime::PlayTimeManager>();
+ play_time_manager = std::make_unique<PlayTime::PlayTimeManager>(system->GetProfileManager());
system->GetRoomNetwork().Init();
@@ -526,8 +526,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
continue;
}
- const Service::Account::ProfileManager manager;
- if (!manager.UserExistsIndex(selected_user)) {
+ if (!system->GetProfileManager().UserExistsIndex(selected_user)) {
LOG_ERROR(Frontend, "Selected user doesn't exist");
continue;
}
@@ -691,7 +690,7 @@ void GMainWindow::ControllerSelectorRequestExit() {
void GMainWindow::ProfileSelectorSelectProfile(
const Core::Frontend::ProfileSelectParameters& parameters) {
- profile_select_applet = new QtProfileSelectionDialog(system->HIDCore(), this, parameters);
+ profile_select_applet = new QtProfileSelectionDialog(*system, this, parameters);
SCOPE_EXIT({
profile_select_applet->deleteLater();
profile_select_applet = nullptr;
@@ -706,8 +705,8 @@ void GMainWindow::ProfileSelectorSelectProfile(
return;
}
- const Service::Account::ProfileManager manager;
- const auto uuid = manager.GetUser(static_cast<std::size_t>(profile_select_applet->GetIndex()));
+ const auto uuid = system->GetProfileManager().GetUser(
+ static_cast<std::size_t>(profile_select_applet->GetIndex()));
if (!uuid.has_value()) {
emit ProfileSelectorFinishedSelection(std::nullopt);
return;
@@ -1856,7 +1855,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
bool GMainWindow::SelectAndSetCurrentUser(
const Core::Frontend::ProfileSelectParameters& parameters) {
- QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters);
+ QtProfileSelectionDialog dialog(*system, this, parameters);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
@@ -2271,7 +2270,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
.display_options = {},
.purpose = Service::AM::Applets::UserSelectionPurpose::General,
};
- QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters);
+ QtProfileSelectionDialog dialog(*system, this, parameters);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
@@ -2288,8 +2287,8 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
return;
}
- Service::Account::ProfileManager manager;
- const auto user_id = manager.GetUser(static_cast<std::size_t>(index));
+ const auto user_id =
+ system->GetProfileManager().GetUser(static_cast<std::size_t>(index));
ASSERT(user_id);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp
index 603e9ae3d..41692c05b 100644
--- a/src/yuzu/multiplayer/lobby.cpp
+++ b/src/yuzu/multiplayer/lobby.cpp
@@ -27,9 +27,9 @@
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
- ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session),
- profile_manager(std::make_unique<Service::Account::ProfileManager>()), system{system_},
- room_network{system.GetRoomNetwork()} {
+ ui(std::make_unique<Ui::Lobby>()),
+ announce_multiplayer_session(session), system{system_}, room_network{
+ system.GetRoomNetwork()} {
ui->setupUi(this);
// setup the watcher for background connections
@@ -299,14 +299,15 @@ void Lobby::OnRefreshLobby() {
}
std::string Lobby::GetProfileUsername() {
- const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue());
+ const auto& current_user =
+ system.GetProfileManager().GetUser(Settings::values.current_user.GetValue());
Service::Account::ProfileBase profile{};
if (!current_user.has_value()) {
return "";
}
- if (!profile_manager->GetProfileBase(*current_user, profile)) {
+ if (!system.GetProfileManager().GetProfileBase(*current_user, profile)) {
return "";
}
diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h
index 2674ae7c3..e78c9cae3 100644
--- a/src/yuzu/multiplayer/lobby.h
+++ b/src/yuzu/multiplayer/lobby.h
@@ -24,10 +24,6 @@ namespace Core {
class System;
}
-namespace Service::Account {
-class ProfileManager;
-}
-
/**
* Listing of all public games pulled from services. The lobby should be simple enough for users to
* find the game they want to play, and join it.
@@ -103,7 +99,6 @@ private:
QFutureWatcher<AnnounceMultiplayerRoom::RoomList> room_list_watcher;
std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
- std::unique_ptr<Service::Account::ProfileManager> profile_manager;
QFutureWatcher<void>* watcher;
Validation validation;
Core::System& system;
diff --git a/src/yuzu/play_time_manager.cpp b/src/yuzu/play_time_manager.cpp
index 155c36b7d..94c99274d 100644
--- a/src/yuzu/play_time_manager.cpp
+++ b/src/yuzu/play_time_manager.cpp
@@ -20,8 +20,8 @@ struct PlayTimeElement {
PlayTime play_time;
};
-std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() {
- const Service::Account::ProfileManager manager;
+std::optional<std::filesystem::path> GetCurrentUserPlayTimePath(
+ const Service::Account::ProfileManager& manager) {
const auto uuid = manager.GetUser(static_cast<s32>(Settings::values.current_user));
if (!uuid.has_value()) {
return std::nullopt;
@@ -30,8 +30,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() {
uuid->RawString().append(".bin");
}
-[[nodiscard]] bool ReadPlayTimeFile(PlayTimeDatabase& out_play_time_db) {
- const auto filename = GetCurrentUserPlayTimePath();
+[[nodiscard]] bool ReadPlayTimeFile(PlayTimeDatabase& out_play_time_db,
+ const Service::Account::ProfileManager& manager) {
+ const auto filename = GetCurrentUserPlayTimePath(manager);
if (!filename.has_value()) {
LOG_ERROR(Frontend, "Failed to get current user path");
@@ -66,8 +67,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() {
return true;
}
-[[nodiscard]] bool WritePlayTimeFile(const PlayTimeDatabase& play_time_db) {
- const auto filename = GetCurrentUserPlayTimePath();
+[[nodiscard]] bool WritePlayTimeFile(const PlayTimeDatabase& play_time_db,
+ const Service::Account::ProfileManager& manager) {
+ const auto filename = GetCurrentUserPlayTimePath(manager);
if (!filename.has_value()) {
LOG_ERROR(Frontend, "Failed to get current user path");
@@ -96,8 +98,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() {
} // namespace
-PlayTimeManager::PlayTimeManager() {
- if (!ReadPlayTimeFile(database)) {
+PlayTimeManager::PlayTimeManager(Service::Account::ProfileManager& profile_manager)
+ : manager{profile_manager} {
+ if (!ReadPlayTimeFile(database, manager)) {
LOG_ERROR(Frontend, "Failed to read play time database! Resetting to default.");
}
}
@@ -142,7 +145,7 @@ void PlayTimeManager::AutoTimestamp(std::stop_token stop_token) {
}
void PlayTimeManager::Save() {
- if (!WritePlayTimeFile(database)) {
+ if (!WritePlayTimeFile(database, manager)) {
LOG_ERROR(Frontend, "Failed to update play time database!");
}
}
diff --git a/src/yuzu/play_time_manager.h b/src/yuzu/play_time_manager.h
index 5f96f3447..1714b9131 100644
--- a/src/yuzu/play_time_manager.h
+++ b/src/yuzu/play_time_manager.h
@@ -11,6 +11,10 @@
#include "common/common_types.h"
#include "common/polyfill_thread.h"
+namespace Service::Account {
+class ProfileManager;
+}
+
namespace PlayTime {
using ProgramId = u64;
@@ -19,7 +23,7 @@ using PlayTimeDatabase = std::map<ProgramId, PlayTime>;
class PlayTimeManager {
public:
- explicit PlayTimeManager();
+ explicit PlayTimeManager(Service::Account::ProfileManager& profile_manager);
~PlayTimeManager();
YUZU_NON_COPYABLE(PlayTimeManager);
@@ -32,11 +36,13 @@ public:
void Stop();
private:
+ void AutoTimestamp(std::stop_token stop_token);
+ void Save();
+
PlayTimeDatabase database;
u64 running_program_id;
std::jthread play_time_thread;
- void AutoTimestamp(std::stop_token stop_token);
- void Save();
+ Service::Account::ProfileManager& manager;
};
QString ReadablePlayTime(qulonglong time_seconds);
diff --git a/vcpkg.json b/vcpkg.json
index da4e9edb9..01a4657d4 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "yuzu",
- "builtin-baseline": "cbf56573a987527b39272e88cbdd11389b78c6e4",
+ "builtin-baseline": "a42af01b72c28a8e1d7b48107b33e4f286a55ef6",
"version": "1.0",
"dependencies": [
"boost-algorithm",
@@ -50,7 +50,7 @@
},
{
"name": "fmt",
- "version": "10.0.0"
+ "version": "10.1.1"
}
]
}