diff options
216 files changed, 8888 insertions, 7134 deletions
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 62eb69aeb..2814d3cdb 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml | |||
| @@ -73,7 +73,7 @@ jobs: | |||
| 73 | build-mac: | 73 | build-mac: |
| 74 | name: 'test build (macos)' | 74 | name: 'test build (macos)' |
| 75 | needs: format | 75 | needs: format |
| 76 | runs-on: macos-13 | 76 | runs-on: macos-14 |
| 77 | steps: | 77 | steps: |
| 78 | - uses: actions/checkout@v3 | 78 | - uses: actions/checkout@v3 |
| 79 | with: | 79 | with: |
| @@ -87,7 +87,7 @@ jobs: | |||
| 87 | run: | | 87 | run: | |
| 88 | mkdir build | 88 | mkdir build |
| 89 | cd build | 89 | cd build |
| 90 | export Qt5_DIR="/usr/local/opt/qt@5/lib/cmake" | 90 | export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake" |
| 91 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF | 91 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF |
| 92 | ninja | 92 | ninja |
| 93 | build-msvc: | 93 | build-msvc: |
diff --git a/.gitmodules b/.gitmodules index e65997afc..52256d86f 100644 --- a/.gitmodules +++ b/.gitmodules | |||
| @@ -64,3 +64,6 @@ | |||
| 64 | [submodule "oaknut"] | 64 | [submodule "oaknut"] |
| 65 | path = externals/oaknut | 65 | path = externals/oaknut |
| 66 | url = https://github.com/merryhime/oaknut | 66 | url = https://github.com/merryhime/oaknut |
| 67 | [submodule "Vulkan-Utility-Libraries"] | ||
| 68 | path = externals/Vulkan-Utility-Libraries | ||
| 69 | url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cd6b2108..f4b64544f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}") | |||
| 36 | 36 | ||
| 37 | option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) | 37 | option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) |
| 38 | 38 | ||
| 39 | option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON) | ||
| 40 | |||
| 39 | option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) | 41 | option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) |
| 40 | 42 | ||
| 41 | option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) | 43 | option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) |
| @@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS) | |||
| 308 | find_package(Vulkan 1.3.274 REQUIRED) | 310 | find_package(Vulkan 1.3.274 REQUIRED) |
| 309 | endif() | 311 | endif() |
| 310 | 312 | ||
| 313 | if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES) | ||
| 314 | find_package(VulkanUtilityLibraries REQUIRED) | ||
| 315 | endif() | ||
| 316 | |||
| 311 | if (ENABLE_LIBUSB) | 317 | if (ENABLE_LIBUSB) |
| 312 | find_package(libusb 1.0.24 MODULE) | 318 | find_package(libusb 1.0.24 MODULE) |
| 313 | endif() | 319 | endif() |
| @@ -316,6 +322,10 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) | |||
| 316 | find_package(xbyak 6 CONFIG) | 322 | find_package(xbyak 6 CONFIG) |
| 317 | endif() | 323 | endif() |
| 318 | 324 | ||
| 325 | if (ARCHITECTURE_arm64) | ||
| 326 | find_package(oaknut 2.0.1 CONFIG) | ||
| 327 | endif() | ||
| 328 | |||
| 319 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | 329 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) |
| 320 | find_package(dynarmic 6.4.0 CONFIG) | 330 | find_package(dynarmic 6.4.0 CONFIG) |
| 321 | endif() | 331 | endif() |
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 15b444338..d49a2e43e 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt | |||
| @@ -14,16 +14,17 @@ set(BUILD_SHARED_LIBS OFF) | |||
| 14 | # Skip install rules for all externals | 14 | # Skip install rules for all externals |
| 15 | set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) | 15 | set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) |
| 16 | 16 | ||
| 17 | # xbyak | 17 | # Xbyak (also used by Dynarmic, so needs to be added first) |
| 18 | if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak) | 18 | if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak) |
| 19 | add_subdirectory(xbyak) | 19 | add_subdirectory(xbyak) |
| 20 | endif() | 20 | endif() |
| 21 | 21 | ||
| 22 | # Dynarmic | 22 | # Oaknut (also used by Dynarmic, so needs to be added first) |
| 23 | if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut) | 23 | if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut) |
| 24 | add_subdirectory(oaknut) | 24 | add_subdirectory(oaknut) |
| 25 | endif() | 25 | endif() |
| 26 | 26 | ||
| 27 | # Dynarmic | ||
| 27 | if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic) | 28 | if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic) |
| 28 | set(DYNARMIC_IGNORE_ASSERTS ON) | 29 | set(DYNARMIC_IGNORE_ASSERTS ON) |
| 29 | add_subdirectory(dynarmic) | 30 | add_subdirectory(dynarmic) |
| @@ -154,6 +155,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS) | |||
| 154 | add_subdirectory(Vulkan-Headers) | 155 | add_subdirectory(Vulkan-Headers) |
| 155 | endif() | 156 | endif() |
| 156 | 157 | ||
| 158 | # Vulkan-Utility-Libraries | ||
| 159 | if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES) | ||
| 160 | add_subdirectory(Vulkan-Utility-Libraries) | ||
| 161 | endif() | ||
| 162 | |||
| 157 | # TZDB (Time Zone Database) | 163 | # TZDB (Time Zone Database) |
| 158 | add_subdirectory(nx_tzdb) | 164 | add_subdirectory(nx_tzdb) |
| 159 | 165 | ||
diff --git a/externals/Vulkan-Utility-Libraries b/externals/Vulkan-Utility-Libraries new file mode 160000 | |||
| Subproject 524f8910d0e4a5f2ec5961996b23e5b74b95cb1 | |||
diff --git a/externals/dynarmic b/externals/dynarmic | |||
| Subproject 0df09e2f6b61c2d7ad2f2053d4f020a5c33e037 | Subproject ca0e264f4f962e29baa23a3282ce484625866b9 | ||
diff --git a/externals/oaknut b/externals/oaknut | |||
| Subproject 918bd94f025d6a2de13978468351598997ae390 | Subproject 9d091109deb445bc6e9289c6195a282b7c993d4 | ||
diff --git a/externals/tz/tz/tz.cpp b/externals/tz/tz/tz.cpp index 0c8b68217..04fa6cc8a 100644 --- a/externals/tz/tz/tz.cpp +++ b/externals/tz/tz/tz.cpp | |||
| @@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) { | |||
| 1625 | return 0; | 1625 | return 0; |
| 1626 | } | 1626 | } |
| 1627 | 1627 | ||
| 1628 | bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) { | 1628 | bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) { |
| 1629 | return localsub(sp, timep, 0, tmp) == nullptr; | 1629 | return localsub(sp, timep, 0, tmp) == nullptr; |
| 1630 | } | 1630 | } |
| 1631 | 1631 | ||
| 1632 | u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) { | 1632 | u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) { |
| 1633 | return time1(out_time, tmp, localsub, sp, 0); | 1633 | return time1(out_time, tmp, localsub, sp, 0); |
| 1634 | } | 1634 | } |
| 1635 | 1635 | ||
diff --git a/externals/tz/tz/tz.h b/externals/tz/tz/tz.h index 38605cfb1..dae4459bc 100644 --- a/externals/tz/tz/tz.h +++ b/externals/tz/tz/tz.h | |||
| @@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th | |||
| 75 | 75 | ||
| 76 | s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary); | 76 | s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary); |
| 77 | 77 | ||
| 78 | bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep); | 78 | bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep); |
| 79 | u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp); | 79 | u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp); |
| 80 | 80 | ||
| 81 | } // namespace Tz | 81 | } // namespace Tz |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 53137b2e2..6ebb46af7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | |||
| @@ -261,7 +261,7 @@ object NativeLibrary { | |||
| 261 | /** | 261 | /** |
| 262 | * Begins emulation. | 262 | * Begins emulation. |
| 263 | */ | 263 | */ |
| 264 | external fun run(path: String?, programIndex: Int = 0) | 264 | external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean) |
| 265 | 265 | ||
| 266 | // Surface Handling | 266 | // Surface Handling |
| 267 | external fun surfaceChanged(surf: Surface?) | 267 | external fun surfaceChanged(surf: Surface?) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt index d6f17cf29..f218c76ef 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt | |||
| @@ -7,6 +7,7 @@ import android.text.TextUtils | |||
| 7 | import android.view.LayoutInflater | 7 | import android.view.LayoutInflater |
| 8 | import android.view.View | 8 | import android.view.View |
| 9 | import android.view.ViewGroup | 9 | import android.view.ViewGroup |
| 10 | import org.yuzu.yuzu_emu.R | ||
| 10 | import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding | 11 | import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding |
| 11 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | 12 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting |
| 12 | import org.yuzu.yuzu_emu.model.Driver | 13 | import org.yuzu.yuzu_emu.model.Driver |
| @@ -57,13 +58,9 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) : | |||
| 57 | title.text = model.title | 58 | title.text = model.title |
| 58 | version.text = model.version | 59 | version.text = model.version |
| 59 | description.text = model.description | 60 | description.text = model.description |
| 60 | if (model.description.isNotEmpty()) { | 61 | if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) { |
| 61 | version.visibility = View.VISIBLE | ||
| 62 | description.visibility = View.VISIBLE | ||
| 63 | buttonDelete.visibility = View.VISIBLE | 62 | buttonDelete.visibility = View.VISIBLE |
| 64 | } else { | 63 | } else { |
| 65 | version.visibility = View.GONE | ||
| 66 | description.visibility = View.GONE | ||
| 67 | buttonDelete.visibility = View.GONE | 64 | buttonDelete.visibility = View.GONE |
| 68 | } | 65 | } |
| 69 | } | 66 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 1f591ced1..937b8faf1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt | |||
| @@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 927 | emulationThread.join() | 927 | emulationThread.join() |
| 928 | emulationThread = Thread({ | 928 | emulationThread = Thread({ |
| 929 | Log.debug("[EmulationFragment] Starting emulation thread.") | 929 | Log.debug("[EmulationFragment] Starting emulation thread.") |
| 930 | NativeLibrary.run(gamePath, programIndex) | 930 | NativeLibrary.run(gamePath, programIndex, false) |
| 931 | }, "NativeEmulation") | 931 | }, "NativeEmulation") |
| 932 | emulationThread.start() | 932 | emulationThread.start() |
| 933 | } | 933 | } |
| @@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 981 | State.STOPPED -> { | 981 | State.STOPPED -> { |
| 982 | emulationThread = Thread({ | 982 | emulationThread = Thread({ |
| 983 | Log.debug("[EmulationFragment] Starting emulation thread.") | 983 | Log.debug("[EmulationFragment] Starting emulation thread.") |
| 984 | NativeLibrary.run(gamePath, programIndex) | 984 | NativeLibrary.run(gamePath, programIndex, true) |
| 985 | }, "NativeEmulation") | 985 | }, "NativeEmulation") |
| 986 | emulationThread.start() | 986 | emulationThread.start() |
| 987 | } | 987 | } |
diff --git a/src/android/app/src/main/jni/applets/software_keyboard.cpp b/src/android/app/src/main/jni/applets/software_keyboard.cpp index 74e040478..9943483e8 100644 --- a/src/android/app/src/main/jni/applets/software_keyboard.cpp +++ b/src/android/app/src/main/jni/applets/software_keyboard.cpp | |||
| @@ -82,7 +82,7 @@ AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobj | |||
| 82 | const jstring string = reinterpret_cast<jstring>(env->GetObjectField( | 82 | const jstring string = reinterpret_cast<jstring>(env->GetObjectField( |
| 83 | object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;"))); | 83 | object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;"))); |
| 84 | return ResultData{GetJString(env, string), | 84 | return ResultData{GetJString(env, string), |
| 85 | static_cast<Service::AM::Applets::SwkbdResult>(env->GetIntField( | 85 | static_cast<Service::AM::Frontend::SwkbdResult>(env->GetIntField( |
| 86 | object, env->GetFieldID(s_keyboard_data_class, "result", "I")))}; | 86 | object, env->GetFieldID(s_keyboard_data_class, "result", "I")))}; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| @@ -149,7 +149,7 @@ void AndroidKeyboard::ShowNormalKeyboard() const { | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | void AndroidKeyboard::ShowTextCheckDialog( | 151 | void AndroidKeyboard::ShowTextCheckDialog( |
| 152 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 152 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 153 | std::u16string text_check_message) const { | 153 | std::u16string text_check_message) const { |
| 154 | LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog."); | 154 | LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog."); |
| 155 | } | 155 | } |
| @@ -204,7 +204,7 @@ void AndroidKeyboard::InlineTextChanged( | |||
| 204 | "\ncursor_position={}", | 204 | "\ncursor_position={}", |
| 205 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); | 205 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); |
| 206 | 206 | ||
| 207 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, | 207 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, |
| 208 | text_parameters.input_text, text_parameters.cursor_position); | 208 | text_parameters.input_text, text_parameters.cursor_position); |
| 209 | } | 209 | } |
| 210 | 210 | ||
| @@ -219,7 +219,7 @@ void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) { | |||
| 219 | 219 | ||
| 220 | m_current_text += submitted_text; | 220 | m_current_text += submitted_text; |
| 221 | 221 | ||
| 222 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text, | 222 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, |
| 223 | m_current_text.size()); | 223 | m_current_text.size()); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| @@ -236,12 +236,12 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) { | |||
| 236 | case KEYCODE_BACK: | 236 | case KEYCODE_BACK: |
| 237 | case KEYCODE_ENTER: | 237 | case KEYCODE_ENTER: |
| 238 | m_is_inline_active = false; | 238 | m_is_inline_active = false; |
| 239 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, m_current_text, | 239 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, m_current_text, |
| 240 | static_cast<s32>(m_current_text.size())); | 240 | static_cast<s32>(m_current_text.size())); |
| 241 | break; | 241 | break; |
| 242 | case KEYCODE_DEL: | 242 | case KEYCODE_DEL: |
| 243 | m_current_text.pop_back(); | 243 | m_current_text.pop_back(); |
| 244 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text, | 244 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, |
| 245 | m_current_text.size()); | 245 | m_current_text.size()); |
| 246 | break; | 246 | break; |
| 247 | } | 247 | } |
diff --git a/src/android/app/src/main/jni/applets/software_keyboard.h b/src/android/app/src/main/jni/applets/software_keyboard.h index b2fb59b68..2affc01f6 100644 --- a/src/android/app/src/main/jni/applets/software_keyboard.h +++ b/src/android/app/src/main/jni/applets/software_keyboard.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 24 | 24 | ||
| 25 | void ShowNormalKeyboard() const override; | 25 | void ShowNormalKeyboard() const override; |
| 26 | 26 | ||
| 27 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 27 | void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 28 | std::u16string text_check_message) const override; | 28 | std::u16string text_check_message) const override; |
| 29 | 29 | ||
| 30 | void ShowInlineKeyboard( | 30 | void ShowInlineKeyboard( |
| @@ -45,7 +45,7 @@ private: | |||
| 45 | static ResultData CreateFromFrontend(jobject object); | 45 | static ResultData CreateFromFrontend(jobject object); |
| 46 | 46 | ||
| 47 | std::string text; | 47 | std::string text; |
| 48 | Service::AM::Applets::SwkbdResult result{}; | 48 | Service::AM::Frontend::SwkbdResult result{}; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | void SubmitNormalText(const ResultData& result) const; | 51 | void SubmitNormalText(const ResultData& result) const; |
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 64627db88..654510129 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -42,14 +42,15 @@ | |||
| 42 | #include "core/frontend/applets/cabinet.h" | 42 | #include "core/frontend/applets/cabinet.h" |
| 43 | #include "core/frontend/applets/controller.h" | 43 | #include "core/frontend/applets/controller.h" |
| 44 | #include "core/frontend/applets/error.h" | 44 | #include "core/frontend/applets/error.h" |
| 45 | #include "core/frontend/applets/general_frontend.h" | 45 | #include "core/frontend/applets/general.h" |
| 46 | #include "core/frontend/applets/mii_edit.h" | 46 | #include "core/frontend/applets/mii_edit.h" |
| 47 | #include "core/frontend/applets/profile_select.h" | 47 | #include "core/frontend/applets/profile_select.h" |
| 48 | #include "core/frontend/applets/software_keyboard.h" | 48 | #include "core/frontend/applets/software_keyboard.h" |
| 49 | #include "core/frontend/applets/web_browser.h" | 49 | #include "core/frontend/applets/web_browser.h" |
| 50 | #include "core/hle/service/am/applet_ae.h" | 50 | #include "core/hle/service/am/applet_ae.h" |
| 51 | #include "core/hle/service/am/applet_manager.h" | ||
| 51 | #include "core/hle/service/am/applet_oe.h" | 52 | #include "core/hle/service/am/applet_oe.h" |
| 52 | #include "core/hle/service/am/applets/applets.h" | 53 | #include "core/hle/service/am/frontend/applets.h" |
| 53 | #include "core/hle/service/filesystem/filesystem.h" | 54 | #include "core/hle/service/filesystem/filesystem.h" |
| 54 | #include "core/loader/loader.h" | 55 | #include "core/loader/loader.h" |
| 55 | #include "frontend_common/config.h" | 56 | #include "frontend_common/config.h" |
| @@ -211,8 +212,15 @@ void EmulationSession::InitializeSystem(bool reload) { | |||
| 211 | m_system.GetFileSystemController().CreateFactories(*m_vfs); | 212 | m_system.GetFileSystemController().CreateFactories(*m_vfs); |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 215 | void EmulationSession::SetAppletId(int applet_id) { | ||
| 216 | m_applet_id = applet_id; | ||
| 217 | m_system.GetFrontendAppletHolder().SetCurrentAppletId( | ||
| 218 | static_cast<Service::AM::AppletId>(m_applet_id)); | ||
| 219 | } | ||
| 220 | |||
| 214 | Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, | 221 | Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, |
| 215 | const std::size_t program_index) { | 222 | const std::size_t program_index, |
| 223 | const bool frontend_initiated) { | ||
| 216 | std::scoped_lock lock(m_mutex); | 224 | std::scoped_lock lock(m_mutex); |
| 217 | 225 | ||
| 218 | // Create the render window. | 226 | // Create the render window. |
| @@ -226,7 +234,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string | |||
| 226 | m_system.ApplySettings(); | 234 | m_system.ApplySettings(); |
| 227 | Settings::LogSettings(); | 235 | Settings::LogSettings(); |
| 228 | m_system.HIDCore().ReloadInputDevices(); | 236 | m_system.HIDCore().ReloadInputDevices(); |
| 229 | m_system.SetAppletFrontendSet({ | 237 | m_system.SetFrontendAppletSet({ |
| 230 | nullptr, // Amiibo Settings | 238 | nullptr, // Amiibo Settings |
| 231 | nullptr, // Controller Selector | 239 | nullptr, // Controller Selector |
| 232 | nullptr, // Error Display | 240 | nullptr, // Error Display |
| @@ -242,8 +250,13 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string | |||
| 242 | ConfigureFilesystemProvider(filepath); | 250 | ConfigureFilesystemProvider(filepath); |
| 243 | 251 | ||
| 244 | // Load the ROM. | 252 | // Load the ROM. |
| 245 | m_load_result = | 253 | Service::AM::FrontendAppletParameters params{ |
| 246 | m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index); | 254 | .applet_id = static_cast<Service::AM::AppletId>(m_applet_id), |
| 255 | .launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated | ||
| 256 | : Service::AM::LaunchType::ApplicationInitiated, | ||
| 257 | .program_index = static_cast<s32>(program_index), | ||
| 258 | }; | ||
| 259 | m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params); | ||
| 247 | if (m_load_result != Core::SystemResultStatus::Success) { | 260 | if (m_load_result != Core::SystemResultStatus::Success) { |
| 248 | return m_load_result; | 261 | return m_load_result; |
| 249 | } | 262 | } |
| @@ -339,6 +352,9 @@ void EmulationSession::RunEmulation() { | |||
| 339 | } | 352 | } |
| 340 | } | 353 | } |
| 341 | } | 354 | } |
| 355 | |||
| 356 | // Reset current applet ID. | ||
| 357 | m_applet_id = static_cast<int>(Service::AM::AppletId::Application); | ||
| 342 | } | 358 | } |
| 343 | 359 | ||
| 344 | bool EmulationSession::IsHandheldOnly() { | 360 | bool EmulationSession::IsHandheldOnly() { |
| @@ -434,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { | |||
| 434 | } | 450 | } |
| 435 | 451 | ||
| 436 | static Core::SystemResultStatus RunEmulation(const std::string& filepath, | 452 | static Core::SystemResultStatus RunEmulation(const std::string& filepath, |
| 437 | const size_t program_index = 0) { | 453 | const size_t program_index, |
| 454 | const bool frontend_initiated) { | ||
| 438 | MicroProfileOnThreadCreate("EmuThread"); | 455 | MicroProfileOnThreadCreate("EmuThread"); |
| 439 | SCOPE_EXIT({ MicroProfileShutdown(); }); | 456 | SCOPE_EXIT({ MicroProfileShutdown(); }); |
| 440 | 457 | ||
| @@ -447,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath, | |||
| 447 | 464 | ||
| 448 | SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); | 465 | SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); |
| 449 | 466 | ||
| 450 | jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index); | 467 | jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index, |
| 468 | frontend_initiated); | ||
| 451 | if (result != Core::SystemResultStatus::Success) { | 469 | if (result != Core::SystemResultStatus::Success) { |
| 452 | return result; | 470 | return result; |
| 453 | } | 471 | } |
| @@ -744,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj | |||
| 744 | } | 762 | } |
| 745 | 763 | ||
| 746 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, | 764 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, |
| 747 | jint j_program_index) { | 765 | jint j_program_index, |
| 766 | jboolean j_frontend_initiated) { | ||
| 748 | const std::string path = GetJString(env, j_path); | 767 | const std::string path = GetJString(env, j_path); |
| 749 | 768 | ||
| 750 | const Core::SystemResultStatus result{RunEmulation(path, j_program_index)}; | 769 | const Core::SystemResultStatus result{ |
| 770 | RunEmulation(path, j_program_index, j_frontend_initiated)}; | ||
| 751 | if (result != Core::SystemResultStatus::Success) { | 771 | if (result != Core::SystemResultStatus::Success) { |
| 752 | env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), | 772 | env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), |
| 753 | IDCache::GetExitEmulationActivity(), static_cast<int>(result)); | 773 | IDCache::GetExitEmulationActivity(), static_cast<int>(result)); |
| @@ -809,13 +829,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j | |||
| 809 | 829 | ||
| 810 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, | 830 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, |
| 811 | jint jappletId) { | 831 | jint jappletId) { |
| 812 | EmulationSession::GetInstance().System().GetAppletManager().SetCurrentAppletId( | 832 | EmulationSession::GetInstance().SetAppletId(jappletId); |
| 813 | static_cast<Service::AM::Applets::AppletId>(jappletId)); | ||
| 814 | } | 833 | } |
| 815 | 834 | ||
| 816 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, | 835 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, |
| 817 | jint jcabinetMode) { | 836 | jint jcabinetMode) { |
| 818 | EmulationSession::GetInstance().System().GetAppletManager().SetCabinetMode( | 837 | EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode( |
| 819 | static_cast<Service::NFP::CabinetMode>(jcabinetMode)); | 838 | static_cast<Service::NFP::CabinetMode>(jcabinetMode)); |
| 820 | } | 839 | } |
| 821 | 840 | ||
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index bfe3fccca..e49d4e015 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h | |||
| @@ -45,8 +45,10 @@ public: | |||
| 45 | const Core::PerfStatsResults& PerfStats(); | 45 | const Core::PerfStatsResults& PerfStats(); |
| 46 | void ConfigureFilesystemProvider(const std::string& filepath); | 46 | void ConfigureFilesystemProvider(const std::string& filepath); |
| 47 | void InitializeSystem(bool reload); | 47 | void InitializeSystem(bool reload); |
| 48 | void SetAppletId(int applet_id); | ||
| 48 | Core::SystemResultStatus InitializeEmulation(const std::string& filepath, | 49 | Core::SystemResultStatus InitializeEmulation(const std::string& filepath, |
| 49 | const std::size_t program_index = 0); | 50 | const std::size_t program_index, |
| 51 | const bool frontend_initiated); | ||
| 50 | 52 | ||
| 51 | bool IsHandheldOnly(); | 53 | bool IsHandheldOnly(); |
| 52 | void SetDeviceType([[maybe_unused]] int index, int type); | 54 | void SetDeviceType([[maybe_unused]] int index, int type); |
| @@ -79,6 +81,7 @@ private: | |||
| 79 | std::atomic<bool> m_is_paused = false; | 81 | std::atomic<bool> m_is_paused = false; |
| 80 | SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; | 82 | SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; |
| 81 | std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; | 83 | std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; |
| 84 | int m_applet_id{1}; | ||
| 82 | 85 | ||
| 83 | // GPU driver parameters | 86 | // GPU driver parameters |
| 84 | std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; | 87 | std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; |
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index e982d03be..4e4ed1789 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt | |||
| @@ -210,8 +210,6 @@ add_library(audio_core STATIC | |||
| 210 | sink/sink_stream.h | 210 | sink/sink_stream.h |
| 211 | ) | 211 | ) |
| 212 | 212 | ||
| 213 | create_target_directory_groups(audio_core) | ||
| 214 | |||
| 215 | if (MSVC) | 213 | if (MSVC) |
| 216 | target_compile_options(audio_core PRIVATE | 214 | target_compile_options(audio_core PRIVATE |
| 217 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data | 215 | /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data |
| @@ -267,3 +265,5 @@ endif() | |||
| 267 | if (YUZU_USE_PRECOMPILED_HEADERS) | 265 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 268 | target_precompile_headers(audio_core PRIVATE precompiled_headers.h) | 266 | target_precompile_headers(audio_core PRIVATE precompiled_headers.h) |
| 269 | endif() | 267 | endif() |
| 268 | |||
| 269 | create_target_directory_groups(audio_core) | ||
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8c57d47c6..85926fc8f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -106,6 +106,7 @@ add_library(common STATIC | |||
| 106 | precompiled_headers.h | 106 | precompiled_headers.h |
| 107 | quaternion.h | 107 | quaternion.h |
| 108 | range_map.h | 108 | range_map.h |
| 109 | range_mutex.h | ||
| 109 | reader_writer_queue.h | 110 | reader_writer_queue.h |
| 110 | ring_buffer.h | 111 | ring_buffer.h |
| 111 | ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp | 112 | ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp |
| @@ -244,8 +245,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | |||
| 244 | ) | 245 | ) |
| 245 | endif() | 246 | endif() |
| 246 | 247 | ||
| 247 | create_target_directory_groups(common) | ||
| 248 | |||
| 249 | target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads) | 248 | target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads) |
| 250 | target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) | 249 | target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) |
| 251 | 250 | ||
| @@ -257,3 +256,5 @@ endif() | |||
| 257 | if (YUZU_USE_PRECOMPILED_HEADERS) | 256 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 258 | target_precompile_headers(common PRIVATE precompiled_headers.h) | 257 | target_precompile_headers(common PRIVATE precompiled_headers.h) |
| 259 | endif() | 258 | endif() |
| 259 | |||
| 260 | create_target_directory_groups(common) | ||
diff --git a/src/common/range_mutex.h b/src/common/range_mutex.h new file mode 100644 index 000000000..d6c949811 --- /dev/null +++ b/src/common/range_mutex.h | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <condition_variable> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/intrusive_list.h" | ||
| 10 | |||
| 11 | namespace Common { | ||
| 12 | |||
| 13 | class ScopedRangeLock; | ||
| 14 | |||
| 15 | class RangeMutex { | ||
| 16 | public: | ||
| 17 | explicit RangeMutex() = default; | ||
| 18 | ~RangeMutex() = default; | ||
| 19 | |||
| 20 | private: | ||
| 21 | friend class ScopedRangeLock; | ||
| 22 | |||
| 23 | void Lock(ScopedRangeLock& l); | ||
| 24 | void Unlock(ScopedRangeLock& l); | ||
| 25 | bool HasIntersectionLocked(ScopedRangeLock& l); | ||
| 26 | |||
| 27 | private: | ||
| 28 | std::mutex m_mutex; | ||
| 29 | std::condition_variable m_cv; | ||
| 30 | |||
| 31 | using LockList = Common::IntrusiveListBaseTraits<ScopedRangeLock>::ListType; | ||
| 32 | LockList m_list; | ||
| 33 | }; | ||
| 34 | |||
| 35 | class ScopedRangeLock : public Common::IntrusiveListBaseNode<ScopedRangeLock> { | ||
| 36 | public: | ||
| 37 | explicit ScopedRangeLock(RangeMutex& mutex, u64 address, u64 size) | ||
| 38 | : m_mutex(mutex), m_address(address), m_size(size) { | ||
| 39 | if (m_size > 0) { | ||
| 40 | m_mutex.Lock(*this); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | ~ScopedRangeLock() { | ||
| 44 | if (m_size > 0) { | ||
| 45 | m_mutex.Unlock(*this); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | u64 GetAddress() const { | ||
| 50 | return m_address; | ||
| 51 | } | ||
| 52 | |||
| 53 | u64 GetSize() const { | ||
| 54 | return m_size; | ||
| 55 | } | ||
| 56 | |||
| 57 | private: | ||
| 58 | RangeMutex& m_mutex; | ||
| 59 | const u64 m_address{}; | ||
| 60 | const u64 m_size{}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | inline void RangeMutex::Lock(ScopedRangeLock& l) { | ||
| 64 | std::unique_lock lk{m_mutex}; | ||
| 65 | m_cv.wait(lk, [&] { return !HasIntersectionLocked(l); }); | ||
| 66 | m_list.push_back(l); | ||
| 67 | } | ||
| 68 | |||
| 69 | inline void RangeMutex::Unlock(ScopedRangeLock& l) { | ||
| 70 | { | ||
| 71 | std::scoped_lock lk{m_mutex}; | ||
| 72 | m_list.erase(m_list.iterator_to(l)); | ||
| 73 | } | ||
| 74 | m_cv.notify_all(); | ||
| 75 | } | ||
| 76 | |||
| 77 | inline bool RangeMutex::HasIntersectionLocked(ScopedRangeLock& l) { | ||
| 78 | const auto cur_begin = l.GetAddress(); | ||
| 79 | const auto cur_last = l.GetAddress() + l.GetSize() - 1; | ||
| 80 | |||
| 81 | for (const auto& other : m_list) { | ||
| 82 | const auto other_begin = other.GetAddress(); | ||
| 83 | const auto other_last = other.GetAddress() + other.GetSize() - 1; | ||
| 84 | |||
| 85 | if (cur_begin <= other_last && other_begin <= cur_last) { | ||
| 86 | return true; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | return false; | ||
| 91 | } | ||
| 92 | |||
| 93 | } // namespace Common | ||
diff --git a/src/common/settings.h b/src/common/settings.h index 16749ab68..f1b1add56 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -134,12 +134,12 @@ struct Values { | |||
| 134 | Linkage linkage{}; | 134 | Linkage linkage{}; |
| 135 | 135 | ||
| 136 | // Audio | 136 | // Audio |
| 137 | Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio, | 137 | SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", |
| 138 | Specialization::RuntimeList}; | 138 | Category::Audio, Specialization::RuntimeList}; |
| 139 | Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio, | 139 | SwitchableSetting<std::string> audio_output_device_id{ |
| 140 | Specialization::RuntimeList}; | 140 | linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList}; |
| 141 | Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio, | 141 | SwitchableSetting<std::string> audio_input_device_id{ |
| 142 | Specialization::RuntimeList}; | 142 | linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; |
| 143 | SwitchableSetting<AudioMode, true> sound_index{ | 143 | SwitchableSetting<AudioMode, true> sound_index{ |
| 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, | 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, |
| 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, | 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 347bbf2d0..570acb193 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -176,8 +176,8 @@ add_library(core STATIC | |||
| 176 | frontend/applets/controller.h | 176 | frontend/applets/controller.h |
| 177 | frontend/applets/error.cpp | 177 | frontend/applets/error.cpp |
| 178 | frontend/applets/error.h | 178 | frontend/applets/error.h |
| 179 | frontend/applets/general_frontend.cpp | 179 | frontend/applets/general.cpp |
| 180 | frontend/applets/general_frontend.h | 180 | frontend/applets/general.h |
| 181 | frontend/applets/mii_edit.cpp | 181 | frontend/applets/mii_edit.cpp |
| 182 | frontend/applets/mii_edit.h | 182 | frontend/applets/mii_edit.h |
| 183 | frontend/applets/profile_select.cpp | 183 | frontend/applets/profile_select.cpp |
| @@ -390,39 +390,101 @@ add_library(core STATIC | |||
| 390 | hle/service/acc/errors.h | 390 | hle/service/acc/errors.h |
| 391 | hle/service/acc/profile_manager.cpp | 391 | hle/service/acc/profile_manager.cpp |
| 392 | hle/service/acc/profile_manager.h | 392 | hle/service/acc/profile_manager.h |
| 393 | hle/service/am/frontend/applet_cabinet.cpp | ||
| 394 | hle/service/am/frontend/applet_cabinet.h | ||
| 395 | hle/service/am/frontend/applet_controller.cpp | ||
| 396 | hle/service/am/frontend/applet_controller.h | ||
| 397 | hle/service/am/frontend/applet_error.cpp | ||
| 398 | hle/service/am/frontend/applet_error.h | ||
| 399 | hle/service/am/frontend/applet_general.cpp | ||
| 400 | hle/service/am/frontend/applet_general.h | ||
| 401 | hle/service/am/frontend/applet_mii_edit.cpp | ||
| 402 | hle/service/am/frontend/applet_mii_edit.h | ||
| 403 | hle/service/am/frontend/applet_mii_edit_types.h | ||
| 404 | hle/service/am/frontend/applet_profile_select.cpp | ||
| 405 | hle/service/am/frontend/applet_profile_select.h | ||
| 406 | hle/service/am/frontend/applet_software_keyboard.cpp | ||
| 407 | hle/service/am/frontend/applet_software_keyboard.h | ||
| 408 | hle/service/am/frontend/applet_software_keyboard_types.h | ||
| 409 | hle/service/am/frontend/applet_web_browser.cpp | ||
| 410 | hle/service/am/frontend/applet_web_browser.h | ||
| 411 | hle/service/am/frontend/applet_web_browser_types.h | ||
| 412 | hle/service/am/frontend/applets.cpp | ||
| 413 | hle/service/am/frontend/applets.h | ||
| 393 | hle/service/am/am.cpp | 414 | hle/service/am/am.cpp |
| 394 | hle/service/am/am.h | 415 | hle/service/am/am.h |
| 416 | hle/service/am/am_results.h | ||
| 417 | hle/service/am/am_types.h | ||
| 418 | hle/service/am/applet.cpp | ||
| 419 | hle/service/am/applet.h | ||
| 395 | hle/service/am/applet_ae.cpp | 420 | hle/service/am/applet_ae.cpp |
| 396 | hle/service/am/applet_ae.h | 421 | hle/service/am/applet_ae.h |
| 422 | hle/service/am/applet_manager.cpp | ||
| 423 | hle/service/am/applet_data_broker.cpp | ||
| 424 | hle/service/am/applet_data_broker.h | ||
| 425 | hle/service/am/applet_manager.h | ||
| 397 | hle/service/am/applet_oe.cpp | 426 | hle/service/am/applet_oe.cpp |
| 398 | hle/service/am/applet_oe.h | 427 | hle/service/am/applet_oe.h |
| 399 | hle/service/am/applets/applet_cabinet.cpp | 428 | hle/service/am/applet_common_functions.cpp |
| 400 | hle/service/am/applets/applet_cabinet.h | 429 | hle/service/am/applet_common_functions.h |
| 401 | hle/service/am/applets/applet_controller.cpp | 430 | hle/service/am/applet_message_queue.cpp |
| 402 | hle/service/am/applets/applet_controller.h | 431 | hle/service/am/applet_message_queue.h |
| 403 | hle/service/am/applets/applet_error.cpp | 432 | hle/service/am/application_creator.cpp |
| 404 | hle/service/am/applets/applet_error.h | 433 | hle/service/am/application_creator.h |
| 405 | hle/service/am/applets/applet_general_backend.cpp | 434 | hle/service/am/application_functions.cpp |
| 406 | hle/service/am/applets/applet_general_backend.h | 435 | hle/service/am/application_functions.h |
| 407 | hle/service/am/applets/applet_mii_edit.cpp | 436 | hle/service/am/application_proxy.cpp |
| 408 | hle/service/am/applets/applet_mii_edit.h | 437 | hle/service/am/application_proxy.h |
| 409 | hle/service/am/applets/applet_mii_edit_types.h | 438 | hle/service/am/audio_controller.cpp |
| 410 | hle/service/am/applets/applet_profile_select.cpp | 439 | hle/service/am/audio_controller.h |
| 411 | hle/service/am/applets/applet_profile_select.h | 440 | hle/service/am/common_state_getter.cpp |
| 412 | hle/service/am/applets/applet_software_keyboard.cpp | 441 | hle/service/am/common_state_getter.h |
| 413 | hle/service/am/applets/applet_software_keyboard.h | 442 | hle/service/am/debug_functions.cpp |
| 414 | hle/service/am/applets/applet_software_keyboard_types.h | 443 | hle/service/am/debug_functions.h |
| 415 | hle/service/am/applets/applet_web_browser.cpp | 444 | hle/service/am/display_controller.cpp |
| 416 | hle/service/am/applets/applet_web_browser.h | 445 | hle/service/am/display_controller.h |
| 417 | hle/service/am/applets/applet_web_browser_types.h | 446 | hle/service/am/global_state_controller.cpp |
| 418 | hle/service/am/applets/applets.cpp | 447 | hle/service/am/global_state_controller.h |
| 419 | hle/service/am/applets/applets.h | 448 | hle/service/am/hid_registration.cpp |
| 449 | hle/service/am/hid_registration.h | ||
| 450 | hle/service/am/home_menu_functions.cpp | ||
| 451 | hle/service/am/home_menu_functions.h | ||
| 420 | hle/service/am/idle.cpp | 452 | hle/service/am/idle.cpp |
| 421 | hle/service/am/idle.h | 453 | hle/service/am/idle.h |
| 454 | hle/service/am/library_applet_accessor.cpp | ||
| 455 | hle/service/am/library_applet_accessor.h | ||
| 456 | hle/service/am/library_applet_creator.cpp | ||
| 457 | hle/service/am/library_applet_creator.h | ||
| 458 | hle/service/am/library_applet_proxy.cpp | ||
| 459 | hle/service/am/library_applet_proxy.h | ||
| 460 | hle/service/am/library_applet_self_accessor.cpp | ||
| 461 | hle/service/am/library_applet_self_accessor.h | ||
| 462 | hle/service/am/library_applet_storage.cpp | ||
| 463 | hle/service/am/library_applet_storage.h | ||
| 464 | hle/service/am/lock_accessor.cpp | ||
| 465 | hle/service/am/lock_accessor.h | ||
| 466 | hle/service/am/managed_layer_holder.cpp | ||
| 467 | hle/service/am/managed_layer_holder.h | ||
| 422 | hle/service/am/omm.cpp | 468 | hle/service/am/omm.cpp |
| 423 | hle/service/am/omm.h | 469 | hle/service/am/omm.h |
| 470 | hle/service/am/process_winding_controller.cpp | ||
| 471 | hle/service/am/process_winding_controller.h | ||
| 472 | hle/service/am/process.cpp | ||
| 473 | hle/service/am/process.h | ||
| 474 | hle/service/am/self_controller.cpp | ||
| 475 | hle/service/am/self_controller.h | ||
| 476 | hle/service/am/system_applet_proxy.cpp | ||
| 477 | hle/service/am/system_applet_proxy.h | ||
| 478 | hle/service/am/system_buffer_manager.cpp | ||
| 479 | hle/service/am/system_buffer_manager.h | ||
| 424 | hle/service/am/spsm.cpp | 480 | hle/service/am/spsm.cpp |
| 425 | hle/service/am/spsm.h | 481 | hle/service/am/spsm.h |
| 482 | hle/service/am/storage_accessor.cpp | ||
| 483 | hle/service/am/storage_accessor.h | ||
| 484 | hle/service/am/storage.cpp | ||
| 485 | hle/service/am/storage.h | ||
| 486 | hle/service/am/window_controller.cpp | ||
| 487 | hle/service/am/window_controller.h | ||
| 426 | hle/service/aoc/aoc_u.cpp | 488 | hle/service/aoc/aoc_u.cpp |
| 427 | hle/service/aoc/aoc_u.h | 489 | hle/service/aoc/aoc_u.h |
| 428 | hle/service/apm/apm.cpp | 490 | hle/service/apm/apm.cpp |
| @@ -486,6 +548,8 @@ add_library(core STATIC | |||
| 486 | hle/service/es/es.h | 548 | hle/service/es/es.h |
| 487 | hle/service/eupld/eupld.cpp | 549 | hle/service/eupld/eupld.cpp |
| 488 | hle/service/eupld/eupld.h | 550 | hle/service/eupld/eupld.h |
| 551 | hle/service/event.cpp | ||
| 552 | hle/service/event.h | ||
| 489 | hle/service/fatal/fatal.cpp | 553 | hle/service/fatal/fatal.cpp |
| 490 | hle/service/fatal/fatal.h | 554 | hle/service/fatal/fatal.h |
| 491 | hle/service/fatal/fatal_p.cpp | 555 | hle/service/fatal/fatal_p.cpp |
| @@ -915,8 +979,6 @@ else() | |||
| 915 | ) | 979 | ) |
| 916 | endif() | 980 | endif() |
| 917 | 981 | ||
| 918 | create_target_directory_groups(core) | ||
| 919 | |||
| 920 | target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz) | 982 | target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz) |
| 921 | target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) | 983 | target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) |
| 922 | if (MINGW) | 984 | if (MINGW) |
| @@ -994,3 +1056,5 @@ endif() | |||
| 994 | if (YUZU_ENABLE_LTO) | 1056 | if (YUZU_ENABLE_LTO) |
| 995 | set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) | 1057 | set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) |
| 996 | endif() | 1058 | endif() |
| 1059 | |||
| 1060 | create_target_directory_groups(core) | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 1b412ac98..435ef6793 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -36,7 +36,8 @@ | |||
| 36 | #include "core/hle/kernel/kernel.h" | 36 | #include "core/hle/kernel/kernel.h" |
| 37 | #include "core/hle/kernel/physical_core.h" | 37 | #include "core/hle/kernel/physical_core.h" |
| 38 | #include "core/hle/service/acc/profile_manager.h" | 38 | #include "core/hle/service/acc/profile_manager.h" |
| 39 | #include "core/hle/service/am/applets/applets.h" | 39 | #include "core/hle/service/am/applet_manager.h" |
| 40 | #include "core/hle/service/am/frontend/applets.h" | ||
| 40 | #include "core/hle/service/apm/apm_controller.h" | 41 | #include "core/hle/service/apm/apm_controller.h" |
| 41 | #include "core/hle/service/filesystem/filesystem.h" | 42 | #include "core/hle/service/filesystem/filesystem.h" |
| 42 | #include "core/hle/service/glue/glue_manager.h" | 43 | #include "core/hle/service/glue/glue_manager.h" |
| @@ -135,8 +136,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 135 | 136 | ||
| 136 | struct System::Impl { | 137 | struct System::Impl { |
| 137 | explicit Impl(System& system) | 138 | explicit Impl(System& system) |
| 138 | : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, | 139 | : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system}, |
| 139 | cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{} {} | 140 | reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} |
| 140 | 141 | ||
| 141 | void Initialize(System& system) { | 142 | void Initialize(System& system) { |
| 142 | device_memory = std::make_unique<Core::DeviceMemory>(); | 143 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| @@ -157,7 +158,7 @@ struct System::Impl { | |||
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | // Create default implementations of applets if one is not provided. | 160 | // Create default implementations of applets if one is not provided. |
| 160 | applet_manager.SetDefaultAppletsIfMissing(); | 161 | frontend_applets.SetDefaultAppletsIfMissing(); |
| 161 | 162 | ||
| 162 | is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 163 | is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 163 | 164 | ||
| @@ -200,22 +201,22 @@ struct System::Impl { | |||
| 200 | system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true); | 201 | system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true); |
| 201 | 202 | ||
| 202 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock; | 203 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock; |
| 203 | static_service_a->GetStandardUserSystemClock(user_clock); | 204 | static_service_a->GetStandardUserSystemClock(&user_clock); |
| 204 | 205 | ||
| 205 | std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; | 206 | std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; |
| 206 | static_service_a->GetStandardLocalSystemClock(local_clock); | 207 | static_service_a->GetStandardLocalSystemClock(&local_clock); |
| 207 | 208 | ||
| 208 | std::shared_ptr<Service::PSC::Time::SystemClock> network_clock; | 209 | std::shared_ptr<Service::PSC::Time::SystemClock> network_clock; |
| 209 | static_service_s->GetStandardNetworkSystemClock(network_clock); | 210 | static_service_s->GetStandardNetworkSystemClock(&network_clock); |
| 210 | 211 | ||
| 211 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service; | 212 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service; |
| 212 | static_service_a->GetTimeZoneService(timezone_service); | 213 | static_service_a->GetTimeZoneService(&timezone_service); |
| 213 | 214 | ||
| 214 | Service::PSC::Time::LocationName name{}; | 215 | Service::PSC::Time::LocationName name{}; |
| 215 | auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); | 216 | auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); |
| 216 | std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size())); | 217 | std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size())); |
| 217 | 218 | ||
| 218 | timezone_service->SetDeviceLocation(name); | 219 | timezone_service->SetDeviceLocationName(name); |
| 219 | 220 | ||
| 220 | u64 time_offset = 0; | 221 | u64 time_offset = 0; |
| 221 | if (Settings::values.custom_rtc_enabled) { | 222 | if (Settings::values.custom_rtc_enabled) { |
| @@ -233,7 +234,7 @@ struct System::Impl { | |||
| 233 | 234 | ||
| 234 | local_clock->SetCurrentTime(new_time); | 235 | local_clock->SetCurrentTime(new_time); |
| 235 | 236 | ||
| 236 | network_clock->GetSystemClockContext(context); | 237 | network_clock->GetSystemClockContext(&context); |
| 237 | settings_service->SetNetworkSystemClockContext(context); | 238 | settings_service->SetNetworkSystemClockContext(context); |
| 238 | network_clock->SetCurrentTime(new_time); | 239 | network_clock->SetCurrentTime(new_time); |
| 239 | } | 240 | } |
| @@ -330,16 +331,27 @@ struct System::Impl { | |||
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, | 333 | SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, |
| 333 | const std::string& filepath, u64 program_id, | 334 | const std::string& filepath, |
| 334 | std::size_t program_index) { | 335 | Service::AM::FrontendAppletParameters& params) { |
| 335 | app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), | 336 | app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), |
| 336 | program_id, program_index); | 337 | params.program_id, params.program_index); |
| 337 | 338 | ||
| 338 | if (!app_loader) { | 339 | if (!app_loader) { |
| 339 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | 340 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); |
| 340 | return SystemResultStatus::ErrorGetLoader; | 341 | return SystemResultStatus::ErrorGetLoader; |
| 341 | } | 342 | } |
| 342 | 343 | ||
| 344 | if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) { | ||
| 345 | LOG_ERROR(Core, "Failed to find title id for ROM!"); | ||
| 346 | } | ||
| 347 | |||
| 348 | std::string name = "Unknown program"; | ||
| 349 | if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { | ||
| 350 | LOG_ERROR(Core, "Failed to read title for ROM!"); | ||
| 351 | } | ||
| 352 | |||
| 353 | LOG_INFO(Core, "Loading {} ({})", name, params.program_id); | ||
| 354 | |||
| 343 | InitializeKernel(system); | 355 | InitializeKernel(system); |
| 344 | 356 | ||
| 345 | // Create the application process. | 357 | // Create the application process. |
| @@ -373,9 +385,14 @@ struct System::Impl { | |||
| 373 | cheat_engine->Initialize(); | 385 | cheat_engine->Initialize(); |
| 374 | } | 386 | } |
| 375 | 387 | ||
| 388 | // Register with applet manager. | ||
| 389 | applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(), | ||
| 390 | params); | ||
| 391 | |||
| 376 | // All threads are started, begin main process execution, now that we're in the clear. | 392 | // All threads are started, begin main process execution, now that we're in the clear. |
| 377 | main_process->Run(load_parameters->main_thread_priority, | 393 | main_process->Run(load_parameters->main_thread_priority, |
| 378 | load_parameters->main_thread_stack_size); | 394 | load_parameters->main_thread_stack_size); |
| 395 | main_process->Close(); | ||
| 379 | 396 | ||
| 380 | if (Settings::values.gamecard_inserted) { | 397 | if (Settings::values.gamecard_inserted) { |
| 381 | if (Settings::values.gamecard_current_game) { | 398 | if (Settings::values.gamecard_current_game) { |
| @@ -386,21 +403,13 @@ struct System::Impl { | |||
| 386 | } | 403 | } |
| 387 | } | 404 | } |
| 388 | 405 | ||
| 389 | if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) { | 406 | perf_stats = std::make_unique<PerfStats>(params.program_id); |
| 390 | LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result); | ||
| 391 | } | ||
| 392 | perf_stats = std::make_unique<PerfStats>(program_id); | ||
| 393 | // Reset counters and set time origin to current frame | 407 | // Reset counters and set time origin to current frame |
| 394 | GetAndResetPerfStats(); | 408 | GetAndResetPerfStats(); |
| 395 | perf_stats->BeginSystemFrame(); | 409 | perf_stats->BeginSystemFrame(); |
| 396 | 410 | ||
| 397 | std::string name = "Unknown Game"; | ||
| 398 | if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { | ||
| 399 | LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); | ||
| 400 | } | ||
| 401 | |||
| 402 | std::string title_version; | 411 | std::string title_version; |
| 403 | const FileSys::PatchManager pm(program_id, system.GetFileSystemController(), | 412 | const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(), |
| 404 | system.GetContentProvider()); | 413 | system.GetContentProvider()); |
| 405 | const auto metadata = pm.GetControlMetadata(); | 414 | const auto metadata = pm.GetControlMetadata(); |
| 406 | if (metadata.first != nullptr) { | 415 | if (metadata.first != nullptr) { |
| @@ -409,14 +418,15 @@ struct System::Impl { | |||
| 409 | if (auto room_member = room_network.GetRoomMember().lock()) { | 418 | if (auto room_member = room_network.GetRoomMember().lock()) { |
| 410 | Network::GameInfo game_info; | 419 | Network::GameInfo game_info; |
| 411 | game_info.name = name; | 420 | game_info.name = name; |
| 412 | game_info.id = program_id; | 421 | game_info.id = params.program_id; |
| 413 | game_info.version = title_version; | 422 | game_info.version = title_version; |
| 414 | room_member->SendGameInfo(game_info); | 423 | room_member->SendGameInfo(game_info); |
| 415 | } | 424 | } |
| 416 | 425 | ||
| 417 | // Workarounds: | 426 | // Workarounds: |
| 418 | // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK | 427 | // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK |
| 419 | Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL; | 428 | Settings::values.renderer_amdvlk_depth_bias_workaround = |
| 429 | params.program_id == 0x1006A800016E000ULL; | ||
| 420 | 430 | ||
| 421 | status = SystemResultStatus::Success; | 431 | status = SystemResultStatus::Success; |
| 422 | return status; | 432 | return status; |
| @@ -455,6 +465,7 @@ struct System::Impl { | |||
| 455 | } | 465 | } |
| 456 | kernel.CloseServices(); | 466 | kernel.CloseServices(); |
| 457 | kernel.ShutdownCores(); | 467 | kernel.ShutdownCores(); |
| 468 | applet_manager.Reset(); | ||
| 458 | services.reset(); | 469 | services.reset(); |
| 459 | service_manager.reset(); | 470 | service_manager.reset(); |
| 460 | fs_controller.Reset(); | 471 | fs_controller.Reset(); |
| @@ -566,8 +577,9 @@ struct System::Impl { | |||
| 566 | 577 | ||
| 567 | std::unique_ptr<Tools::RenderdocAPI> renderdoc_api; | 578 | std::unique_ptr<Tools::RenderdocAPI> renderdoc_api; |
| 568 | 579 | ||
| 569 | /// Frontend applets | 580 | /// Applets |
| 570 | Service::AM::Applets::AppletManager applet_manager; | 581 | Service::AM::AppletManager applet_manager; |
| 582 | Service::AM::Frontend::FrontendAppletHolder frontend_applets; | ||
| 571 | 583 | ||
| 572 | /// APM (Performance) services | 584 | /// APM (Performance) services |
| 573 | Service::APM::Controller apm_controller{core_timing}; | 585 | Service::APM::Controller apm_controller{core_timing}; |
| @@ -680,8 +692,8 @@ void System::InitializeDebugger() { | |||
| 680 | } | 692 | } |
| 681 | 693 | ||
| 682 | SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, | 694 | SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, |
| 683 | u64 program_id, std::size_t program_index) { | 695 | Service::AM::FrontendAppletParameters& params) { |
| 684 | return impl->Load(*this, emu_window, filepath, program_id, program_index); | 696 | return impl->Load(*this, emu_window, filepath, params); |
| 685 | } | 697 | } |
| 686 | 698 | ||
| 687 | bool System::IsPoweredOn() const { | 699 | bool System::IsPoweredOn() const { |
| @@ -871,19 +883,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list, | |||
| 871 | impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size); | 883 | impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size); |
| 872 | } | 884 | } |
| 873 | 885 | ||
| 874 | void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) { | 886 | void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) { |
| 875 | impl->applet_manager.SetAppletFrontendSet(std::move(set)); | 887 | impl->frontend_applets.SetFrontendAppletSet(std::move(set)); |
| 876 | } | 888 | } |
| 877 | 889 | ||
| 878 | void System::SetDefaultAppletFrontendSet() { | 890 | Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() { |
| 879 | impl->applet_manager.SetDefaultAppletFrontendSet(); | 891 | return impl->frontend_applets; |
| 880 | } | 892 | } |
| 881 | 893 | ||
| 882 | Service::AM::Applets::AppletManager& System::GetAppletManager() { | 894 | const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const { |
| 883 | return impl->applet_manager; | 895 | return impl->frontend_applets; |
| 884 | } | 896 | } |
| 885 | 897 | ||
| 886 | const Service::AM::Applets::AppletManager& System::GetAppletManager() const { | 898 | Service::AM::AppletManager& System::GetAppletManager() { |
| 887 | return impl->applet_manager; | 899 | return impl->applet_manager; |
| 888 | } | 900 | } |
| 889 | 901 | ||
diff --git a/src/core/core.h b/src/core/core.h index d8862e9ce..90826bd3a 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -50,10 +50,15 @@ namespace Account { | |||
| 50 | class ProfileManager; | 50 | class ProfileManager; |
| 51 | } // namespace Account | 51 | } // namespace Account |
| 52 | 52 | ||
| 53 | namespace AM::Applets { | 53 | namespace AM { |
| 54 | struct AppletFrontendSet; | 54 | struct FrontendAppletParameters; |
| 55 | class AppletManager; | 55 | class AppletManager; |
| 56 | } // namespace AM::Applets | 56 | } // namespace AM |
| 57 | |||
| 58 | namespace AM::Frontend { | ||
| 59 | struct FrontendAppletSet; | ||
| 60 | class FrontendAppletHolder; | ||
| 61 | } // namespace AM::Frontend | ||
| 57 | 62 | ||
| 58 | namespace APM { | 63 | namespace APM { |
| 59 | class Controller; | 64 | class Controller; |
| @@ -203,8 +208,8 @@ public: | |||
| 203 | * @returns SystemResultStatus code, indicating if the operation succeeded. | 208 | * @returns SystemResultStatus code, indicating if the operation succeeded. |
| 204 | */ | 209 | */ |
| 205 | [[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window, | 210 | [[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window, |
| 206 | const std::string& filepath, u64 program_id = 0, | 211 | const std::string& filepath, |
| 207 | std::size_t program_index = 0); | 212 | Service::AM::FrontendAppletParameters& params); |
| 208 | 213 | ||
| 209 | /** | 214 | /** |
| 210 | * Indicates if the emulated system is powered on (all subsystems initialized and able to run an | 215 | * Indicates if the emulated system is powered on (all subsystems initialized and able to run an |
| @@ -344,11 +349,13 @@ public: | |||
| 344 | const std::array<u8, 0x20>& build_id, u64 main_region_begin, | 349 | const std::array<u8, 0x20>& build_id, u64 main_region_begin, |
| 345 | u64 main_region_size); | 350 | u64 main_region_size); |
| 346 | 351 | ||
| 347 | void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); | 352 | void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set); |
| 348 | void SetDefaultAppletFrontendSet(); | 353 | |
| 354 | [[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder(); | ||
| 355 | [[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder() | ||
| 356 | const; | ||
| 349 | 357 | ||
| 350 | [[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager(); | 358 | [[nodiscard]] Service::AM::AppletManager& GetAppletManager(); |
| 351 | [[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const; | ||
| 352 | 359 | ||
| 353 | void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); | 360 | void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); |
| 354 | 361 | ||
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index ffeed46cc..0568a821b 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h | |||
| @@ -5,11 +5,13 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <bit> | ||
| 8 | #include <deque> | 9 | #include <deque> |
| 9 | #include <memory> | 10 | #include <memory> |
| 10 | #include <mutex> | 11 | #include <mutex> |
| 11 | 12 | ||
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/range_mutex.h" | ||
| 13 | #include "common/scratch_buffer.h" | 15 | #include "common/scratch_buffer.h" |
| 14 | #include "common/virtual_buffer.h" | 16 | #include "common/virtual_buffer.h" |
| 15 | 17 | ||
| @@ -180,31 +182,35 @@ private: | |||
| 180 | } | 182 | } |
| 181 | 183 | ||
| 182 | Common::VirtualBuffer<VAddr> cpu_backing_address; | 184 | Common::VirtualBuffer<VAddr> cpu_backing_address; |
| 183 | static constexpr size_t subentries = 8 / sizeof(u8); | 185 | using CounterType = u8; |
| 186 | using CounterAtomicType = std::atomic_uint8_t; | ||
| 187 | static constexpr size_t subentries = 8 / sizeof(CounterType); | ||
| 184 | static constexpr size_t subentries_mask = subentries - 1; | 188 | static constexpr size_t subentries_mask = subentries - 1; |
| 189 | static constexpr size_t subentries_shift = | ||
| 190 | std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType)); | ||
| 185 | class CounterEntry final { | 191 | class CounterEntry final { |
| 186 | public: | 192 | public: |
| 187 | CounterEntry() = default; | 193 | CounterEntry() = default; |
| 188 | 194 | ||
| 189 | std::atomic_uint8_t& Count(std::size_t page) { | 195 | CounterAtomicType& Count(std::size_t page) { |
| 190 | return values[page & subentries_mask]; | 196 | return values[page & subentries_mask]; |
| 191 | } | 197 | } |
| 192 | 198 | ||
| 193 | const std::atomic_uint8_t& Count(std::size_t page) const { | 199 | const CounterAtomicType& Count(std::size_t page) const { |
| 194 | return values[page & subentries_mask]; | 200 | return values[page & subentries_mask]; |
| 195 | } | 201 | } |
| 196 | 202 | ||
| 197 | private: | 203 | private: |
| 198 | std::array<std::atomic_uint8_t, subentries> values{}; | 204 | std::array<CounterAtomicType, subentries> values{}; |
| 199 | }; | 205 | }; |
| 200 | static_assert(sizeof(CounterEntry) == subentries * sizeof(u8), | 206 | static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType), |
| 201 | "CounterEntry should be 8 bytes!"); | 207 | "CounterEntry should be 8 bytes!"); |
| 202 | 208 | ||
| 203 | static constexpr size_t num_counter_entries = | 209 | static constexpr size_t num_counter_entries = |
| 204 | (1ULL << (device_virtual_bits - page_bits)) / subentries; | 210 | (1ULL << (device_virtual_bits - page_bits)) / subentries; |
| 205 | using CachedPages = std::array<CounterEntry, num_counter_entries>; | 211 | using CachedPages = std::array<CounterEntry, num_counter_entries>; |
| 206 | std::unique_ptr<CachedPages> cached_pages; | 212 | std::unique_ptr<CachedPages> cached_pages; |
| 207 | std::mutex counter_guard; | 213 | Common::RangeMutex counter_guard; |
| 208 | std::mutex mapping_guard; | 214 | std::mutex mapping_guard; |
| 209 | }; | 215 | }; |
| 210 | 216 | ||
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index eab8a2731..b026f4220 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc | |||
| @@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) { | |||
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | template <typename Traits> | 215 | template <typename Traits> |
| 216 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, | 216 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, |
| 217 | Asid asid, bool track) { | 217 | bool track) { |
| 218 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; | 218 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; |
| 219 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | 219 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; |
| 220 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | 220 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; |
| @@ -508,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) { | |||
| 508 | 508 | ||
| 509 | template <typename Traits> | 509 | template <typename Traits> |
| 510 | void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { | 510 | void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { |
| 511 | std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); | 511 | Common::ScopedRangeLock lk(counter_guard, addr, size); |
| 512 | const auto Lock = [&] { | ||
| 513 | if (!lk) { | ||
| 514 | lk.lock(); | ||
| 515 | } | ||
| 516 | }; | ||
| 517 | u64 uncache_begin = 0; | 512 | u64 uncache_begin = 0; |
| 518 | u64 cache_begin = 0; | 513 | u64 cache_begin = 0; |
| 519 | u64 uncache_bytes = 0; | 514 | u64 uncache_bytes = 0; |
| @@ -524,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 524 | const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); | 519 | const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); |
| 525 | size_t page = addr >> Memory::YUZU_PAGEBITS; | 520 | size_t page = addr >> Memory::YUZU_PAGEBITS; |
| 526 | auto [asid, base_vaddress] = ExtractCPUBacking(page); | 521 | auto [asid, base_vaddress] = ExtractCPUBacking(page); |
| 527 | size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS; | ||
| 528 | auto* memory_device_inter = registered_processes[asid.id]; | 522 | auto* memory_device_inter = registered_processes[asid.id]; |
| 523 | const auto release_pending = [&] { | ||
| 524 | if (uncache_bytes > 0) { | ||
| 525 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, | ||
| 526 | uncache_bytes, false); | ||
| 527 | uncache_bytes = 0; | ||
| 528 | } | ||
| 529 | if (cache_bytes > 0) { | ||
| 530 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, | ||
| 531 | cache_bytes, true); | ||
| 532 | cache_bytes = 0; | ||
| 533 | } | ||
| 534 | }; | ||
| 529 | for (; page != page_end; ++page) { | 535 | for (; page != page_end; ++page) { |
| 530 | std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page); | 536 | CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page); |
| 537 | auto [asid_2, vpage] = ExtractCPUBacking(page); | ||
| 538 | vpage >>= Memory::YUZU_PAGEBITS; | ||
| 531 | 539 | ||
| 532 | if (delta > 0) { | 540 | if (vpage == 0) [[unlikely]] { |
| 533 | ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(), | 541 | release_pending(); |
| 534 | "Count may overflow!"); | 542 | continue; |
| 535 | } else if (delta < 0) { | 543 | } |
| 536 | ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); | 544 | |
| 537 | } else { | 545 | if (asid.id != asid_2.id) [[unlikely]] { |
| 538 | ASSERT_MSG(false, "Delta must be non-zero!"); | 546 | release_pending(); |
| 547 | memory_device_inter = registered_processes[asid_2.id]; | ||
| 539 | } | 548 | } |
| 540 | 549 | ||
| 541 | // Adds or subtracts 1, as count is a unsigned 8-bit value | 550 | // Adds or subtracts 1, as count is a unsigned 8-bit value |
| 542 | count.fetch_add(static_cast<u8>(delta), std::memory_order_release); | 551 | count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release); |
| 543 | 552 | ||
| 544 | // Assume delta is either -1 or 1 | 553 | // Assume delta is either -1 or 1 |
| 545 | if (count.load(std::memory_order::relaxed) == 0) { | 554 | if (count.load(std::memory_order::relaxed) == 0) { |
| @@ -548,7 +557,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 548 | } | 557 | } |
| 549 | uncache_bytes += Memory::YUZU_PAGESIZE; | 558 | uncache_bytes += Memory::YUZU_PAGESIZE; |
| 550 | } else if (uncache_bytes > 0) { | 559 | } else if (uncache_bytes > 0) { |
| 551 | Lock(); | ||
| 552 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, | 560 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, |
| 553 | uncache_bytes, false); | 561 | uncache_bytes, false); |
| 554 | uncache_bytes = 0; | 562 | uncache_bytes = 0; |
| @@ -559,23 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size | |||
| 559 | } | 567 | } |
| 560 | cache_bytes += Memory::YUZU_PAGESIZE; | 568 | cache_bytes += Memory::YUZU_PAGESIZE; |
| 561 | } else if (cache_bytes > 0) { | 569 | } else if (cache_bytes > 0) { |
| 562 | Lock(); | 570 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, |
| 563 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | 571 | cache_bytes, true); |
| 564 | true); | ||
| 565 | cache_bytes = 0; | 572 | cache_bytes = 0; |
| 566 | } | 573 | } |
| 567 | vpage++; | ||
| 568 | } | ||
| 569 | if (uncache_bytes > 0) { | ||
| 570 | Lock(); | ||
| 571 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, | ||
| 572 | false); | ||
| 573 | } | ||
| 574 | if (cache_bytes > 0) { | ||
| 575 | Lock(); | ||
| 576 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | ||
| 577 | true); | ||
| 578 | } | 574 | } |
| 575 | release_pending(); | ||
| 579 | } | 576 | } |
| 580 | 577 | ||
| 581 | } // namespace Core | 578 | } // namespace Core |
diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general.cpp index b4b213a31..4c299ee9c 100644 --- a/src/core/frontend/applets/general_frontend.cpp +++ b/src/core/frontend/applets/general.cpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "core/frontend/applets/general_frontend.h" | 5 | #include "core/frontend/applets/general.h" |
| 6 | 6 | ||
| 7 | namespace Core::Frontend { | 7 | namespace Core::Frontend { |
| 8 | 8 | ||
diff --git a/src/core/frontend/applets/general_frontend.h b/src/core/frontend/applets/general.h index 319838ac7..319838ac7 100644 --- a/src/core/frontend/applets/general_frontend.h +++ b/src/core/frontend/applets/general.h | |||
diff --git a/src/core/frontend/applets/profile_select.h b/src/core/frontend/applets/profile_select.h index 92e2737ea..880b69ad6 100644 --- a/src/core/frontend/applets/profile_select.h +++ b/src/core/frontend/applets/profile_select.h | |||
| @@ -8,15 +8,15 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/uuid.h" | 9 | #include "common/uuid.h" |
| 10 | #include "core/frontend/applets/applet.h" | 10 | #include "core/frontend/applets/applet.h" |
| 11 | #include "core/hle/service/am/applets/applet_profile_select.h" | 11 | #include "core/hle/service/am/frontend/applet_profile_select.h" |
| 12 | 12 | ||
| 13 | namespace Core::Frontend { | 13 | namespace Core::Frontend { |
| 14 | 14 | ||
| 15 | struct ProfileSelectParameters { | 15 | struct ProfileSelectParameters { |
| 16 | Service::AM::Applets::UiMode mode; | 16 | Service::AM::Frontend::UiMode mode; |
| 17 | std::array<Common::UUID, 8> invalid_uid_list; | 17 | std::array<Common::UUID, 8> invalid_uid_list; |
| 18 | Service::AM::Applets::UiSettingsDisplayOptions display_options; | 18 | Service::AM::Frontend::UiSettingsDisplayOptions display_options; |
| 19 | Service::AM::Applets::UserSelectionPurpose purpose; | 19 | Service::AM::Frontend::UserSelectionPurpose purpose; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | class ProfileSelectApplet : public Applet { | 22 | class ProfileSelectApplet : public Applet { |
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 7655d215b..d00da8ac9 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp | |||
| @@ -69,7 +69,7 @@ void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog( | 71 | void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog( |
| 72 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 72 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 73 | std::u16string text_check_message) const { | 73 | std::u16string text_check_message) const { |
| 74 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog."); | 74 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog."); |
| 75 | } | 75 | } |
| @@ -118,7 +118,7 @@ void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_ | |||
| 118 | "\ncursor_position={}", | 118 | "\ncursor_position={}", |
| 119 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); | 119 | Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); |
| 120 | 120 | ||
| 121 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, | 121 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, |
| 122 | text_parameters.input_text, text_parameters.cursor_position); | 122 | text_parameters.input_text, text_parameters.cursor_position); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| @@ -127,22 +127,22 @@ void DefaultSoftwareKeyboardApplet::ExitKeyboard() const { | |||
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const { | 129 | void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const { |
| 130 | submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text, true); | 130 | submit_normal_callback(Service::AM::Frontend::SwkbdResult::Ok, text, true); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const { | 133 | void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const { |
| 134 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); | 134 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
| 135 | 135 | ||
| 136 | for (std::size_t index = 0; index < text.size(); ++index) { | 136 | for (std::size_t index = 0; index < text.size(); ++index) { |
| 137 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, | 137 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, |
| 138 | std::u16string(text.data(), text.data() + index + 1), | 138 | std::u16string(text.data(), text.data() + index + 1), |
| 139 | static_cast<s32>(index) + 1); | 139 | static_cast<s32>(index) + 1); |
| 140 | 140 | ||
| 141 | std::this_thread::sleep_for(std::chrono::milliseconds(250)); | 141 | std::this_thread::sleep_for(std::chrono::milliseconds(250)); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text), | 144 | submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, |
| 145 | static_cast<s32>(text.size())); | 145 | std::u16string(text), static_cast<s32>(text.size())); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | } // namespace Core::Frontend | 148 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 8ed96da24..a32a98e4c 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | #include "core/frontend/applets/applet.h" | 10 | #include "core/frontend/applets/applet.h" |
| 11 | #include "core/hle/service/am/applets/applet_software_keyboard_types.h" | 11 | #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" |
| 12 | 12 | ||
| 13 | namespace Core::Frontend { | 13 | namespace Core::Frontend { |
| 14 | 14 | ||
| @@ -23,10 +23,10 @@ struct KeyboardInitializeParameters { | |||
| 23 | u32 max_text_length; | 23 | u32 max_text_length; |
| 24 | u32 min_text_length; | 24 | u32 min_text_length; |
| 25 | s32 initial_cursor_position; | 25 | s32 initial_cursor_position; |
| 26 | Service::AM::Applets::SwkbdType type; | 26 | Service::AM::Frontend::SwkbdType type; |
| 27 | Service::AM::Applets::SwkbdPasswordMode password_mode; | 27 | Service::AM::Frontend::SwkbdPasswordMode password_mode; |
| 28 | Service::AM::Applets::SwkbdTextDrawType text_draw_type; | 28 | Service::AM::Frontend::SwkbdTextDrawType text_draw_type; |
| 29 | Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; | 29 | Service::AM::Frontend::SwkbdKeyDisableFlags key_disable_flags; |
| 30 | bool use_blur_background; | 30 | bool use_blur_background; |
| 31 | bool enable_backspace_button; | 31 | bool enable_backspace_button; |
| 32 | bool enable_return_button; | 32 | bool enable_return_button; |
| @@ -40,8 +40,8 @@ struct InlineAppearParameters { | |||
| 40 | f32 key_top_scale_y; | 40 | f32 key_top_scale_y; |
| 41 | f32 key_top_translate_x; | 41 | f32 key_top_translate_x; |
| 42 | f32 key_top_translate_y; | 42 | f32 key_top_translate_y; |
| 43 | Service::AM::Applets::SwkbdType type; | 43 | Service::AM::Frontend::SwkbdType type; |
| 44 | Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; | 44 | Service::AM::Frontend::SwkbdKeyDisableFlags key_disable_flags; |
| 45 | bool key_top_as_floating; | 45 | bool key_top_as_floating; |
| 46 | bool enable_backspace_button; | 46 | bool enable_backspace_button; |
| 47 | bool enable_return_button; | 47 | bool enable_return_button; |
| @@ -56,9 +56,9 @@ struct InlineTextParameters { | |||
| 56 | class SoftwareKeyboardApplet : public Applet { | 56 | class SoftwareKeyboardApplet : public Applet { |
| 57 | public: | 57 | public: |
| 58 | using SubmitInlineCallback = | 58 | using SubmitInlineCallback = |
| 59 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>; | 59 | std::function<void(Service::AM::Frontend::SwkbdReplyType, std::u16string, s32)>; |
| 60 | using SubmitNormalCallback = | 60 | using SubmitNormalCallback = |
| 61 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>; | 61 | std::function<void(Service::AM::Frontend::SwkbdResult, std::u16string, bool)>; |
| 62 | 62 | ||
| 63 | virtual ~SoftwareKeyboardApplet(); | 63 | virtual ~SoftwareKeyboardApplet(); |
| 64 | 64 | ||
| @@ -69,7 +69,7 @@ public: | |||
| 69 | 69 | ||
| 70 | virtual void ShowNormalKeyboard() const = 0; | 70 | virtual void ShowNormalKeyboard() const = 0; |
| 71 | 71 | ||
| 72 | virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 72 | virtual void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 73 | std::u16string text_check_message) const = 0; | 73 | std::u16string text_check_message) const = 0; |
| 74 | 74 | ||
| 75 | virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0; | 75 | virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0; |
| @@ -93,7 +93,7 @@ public: | |||
| 93 | 93 | ||
| 94 | void ShowNormalKeyboard() const override; | 94 | void ShowNormalKeyboard() const override; |
| 95 | 95 | ||
| 96 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 96 | void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 97 | std::u16string text_check_message) const override; | 97 | std::u16string text_check_message) const override; |
| 98 | 98 | ||
| 99 | void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override; | 99 | void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override; |
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 6e703ef06..eca8d6d98 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp | |||
| @@ -18,7 +18,7 @@ void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url, | |||
| 18 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", | 18 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", |
| 19 | local_url); | 19 | local_url); |
| 20 | 20 | ||
| 21 | callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); | 21 | callback(Service::AM::Frontend::WebExitReason::WindowClosed, "http://localhost/"); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url, | 24 | void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url, |
| @@ -26,7 +26,7 @@ void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_ur | |||
| 26 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}", | 26 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}", |
| 27 | external_url); | 27 | external_url); |
| 28 | 28 | ||
| 29 | callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); | 29 | callback(Service::AM::Frontend::WebExitReason::WindowClosed, "http://localhost/"); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | } // namespace Core::Frontend | 32 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index 178bbdd3f..b70856a22 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | 7 | ||
| 8 | #include "core/frontend/applets/applet.h" | 8 | #include "core/frontend/applets/applet.h" |
| 9 | #include "core/hle/service/am/applets/applet_web_browser_types.h" | 9 | #include "core/hle/service/am/frontend/applet_web_browser_types.h" |
| 10 | 10 | ||
| 11 | namespace Core::Frontend { | 11 | namespace Core::Frontend { |
| 12 | 12 | ||
| @@ -14,7 +14,7 @@ class WebBrowserApplet : public Applet { | |||
| 14 | public: | 14 | public: |
| 15 | using ExtractROMFSCallback = std::function<void()>; | 15 | using ExtractROMFSCallback = std::function<void()>; |
| 16 | using OpenWebPageCallback = | 16 | using OpenWebPageCallback = |
| 17 | std::function<void(Service::AM::Applets::WebExitReason, std::string)>; | 17 | std::function<void(Service::AM::Frontend::WebExitReason, std::string)>; |
| 18 | 18 | ||
| 19 | virtual ~WebBrowserApplet(); | 19 | virtual ~WebBrowserApplet(); |
| 20 | 20 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f3683cdcc..34b25be66 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -97,8 +97,14 @@ struct KernelCore::Impl { | |||
| 97 | RegisterHostThread(nullptr); | 97 | RegisterHostThread(nullptr); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | void TerminateApplicationProcess() { | 100 | void TerminateAllProcesses() { |
| 101 | application_process.load()->Terminate(); | 101 | std::scoped_lock lk{process_list_lock}; |
| 102 | for (auto& process : process_list) { | ||
| 103 | process->Terminate(); | ||
| 104 | process->Close(); | ||
| 105 | process = nullptr; | ||
| 106 | } | ||
| 107 | process_list.clear(); | ||
| 102 | } | 108 | } |
| 103 | 109 | ||
| 104 | void Shutdown() { | 110 | void Shutdown() { |
| @@ -107,18 +113,9 @@ struct KernelCore::Impl { | |||
| 107 | 113 | ||
| 108 | CloseServices(); | 114 | CloseServices(); |
| 109 | 115 | ||
| 110 | auto* old_process = application_process.exchange(nullptr); | 116 | if (application_process) { |
| 111 | if (old_process) { | 117 | application_process->Close(); |
| 112 | old_process->Close(); | 118 | application_process = nullptr; |
| 113 | } | ||
| 114 | |||
| 115 | { | ||
| 116 | std::scoped_lock lk{process_list_lock}; | ||
| 117 | for (auto* const process : process_list) { | ||
| 118 | process->Terminate(); | ||
| 119 | process->Close(); | ||
| 120 | } | ||
| 121 | process_list.clear(); | ||
| 122 | } | 119 | } |
| 123 | 120 | ||
| 124 | next_object_id = 0; | 121 | next_object_id = 0; |
| @@ -354,6 +351,7 @@ struct KernelCore::Impl { | |||
| 354 | 351 | ||
| 355 | void MakeApplicationProcess(KProcess* process) { | 352 | void MakeApplicationProcess(KProcess* process) { |
| 356 | application_process = process; | 353 | application_process = process; |
| 354 | application_process->Open(); | ||
| 357 | } | 355 | } |
| 358 | 356 | ||
| 359 | static inline thread_local u8 host_thread_id = UINT8_MAX; | 357 | static inline thread_local u8 host_thread_id = UINT8_MAX; |
| @@ -779,7 +777,7 @@ struct KernelCore::Impl { | |||
| 779 | // Lists all processes that exist in the current session. | 777 | // Lists all processes that exist in the current session. |
| 780 | std::mutex process_list_lock; | 778 | std::mutex process_list_lock; |
| 781 | std::vector<KProcess*> process_list; | 779 | std::vector<KProcess*> process_list; |
| 782 | std::atomic<KProcess*> application_process{}; | 780 | KProcess* application_process{}; |
| 783 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; | 781 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; |
| 784 | std::unique_ptr<Kernel::KHardwareTimer> hardware_timer; | 782 | std::unique_ptr<Kernel::KHardwareTimer> hardware_timer; |
| 785 | 783 | ||
| @@ -1243,7 +1241,7 @@ void KernelCore::SuspendApplication(bool suspended) { | |||
| 1243 | } | 1241 | } |
| 1244 | 1242 | ||
| 1245 | void KernelCore::ShutdownCores() { | 1243 | void KernelCore::ShutdownCores() { |
| 1246 | impl->TerminateApplicationProcess(); | 1244 | impl->TerminateAllProcesses(); |
| 1247 | 1245 | ||
| 1248 | KScopedSchedulerLock lk{*this}; | 1246 | KScopedSchedulerLock lk{*this}; |
| 1249 | 1247 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a768bdc54..8f90eba34 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1,2704 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include <cinttypes> | ||
| 7 | #include <cstring> | ||
| 8 | #include "common/settings.h" | ||
| 9 | #include "common/settings_enums.h" | ||
| 10 | #include "core/core.h" | ||
| 11 | #include "core/core_timing.h" | ||
| 12 | #include "core/file_sys/control_metadata.h" | ||
| 13 | #include "core/file_sys/patch_manager.h" | ||
| 14 | #include "core/file_sys/registered_cache.h" | ||
| 15 | #include "core/file_sys/savedata_factory.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | ||
| 17 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 18 | #include "core/hle/result.h" | ||
| 19 | #include "core/hle/service/acc/profile_manager.h" | ||
| 20 | #include "core/hle/service/am/am.h" | 4 | #include "core/hle/service/am/am.h" |
| 21 | #include "core/hle/service/am/applet_ae.h" | 5 | #include "core/hle/service/am/applet_ae.h" |
| 22 | #include "core/hle/service/am/applet_oe.h" | 6 | #include "core/hle/service/am/applet_oe.h" |
| 23 | #include "core/hle/service/am/applets/applet_cabinet.h" | ||
| 24 | #include "core/hle/service/am/applets/applet_controller.h" | ||
| 25 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" | ||
| 26 | #include "core/hle/service/am/applets/applet_profile_select.h" | ||
| 27 | #include "core/hle/service/am/applets/applet_software_keyboard_types.h" | ||
| 28 | #include "core/hle/service/am/applets/applet_web_browser.h" | ||
| 29 | #include "core/hle/service/am/applets/applets.h" | ||
| 30 | #include "core/hle/service/am/idle.h" | 7 | #include "core/hle/service/am/idle.h" |
| 31 | #include "core/hle/service/am/omm.h" | 8 | #include "core/hle/service/am/omm.h" |
| 32 | #include "core/hle/service/am/spsm.h" | 9 | #include "core/hle/service/am/spsm.h" |
| 33 | #include "core/hle/service/apm/apm_controller.h" | ||
| 34 | #include "core/hle/service/apm/apm_interface.h" | ||
| 35 | #include "core/hle/service/bcat/backend/backend.h" | ||
| 36 | #include "core/hle/service/caps/caps_su.h" | ||
| 37 | #include "core/hle/service/caps/caps_types.h" | ||
| 38 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 39 | #include "core/hle/service/filesystem/save_data_controller.h" | ||
| 40 | #include "core/hle/service/ipc_helpers.h" | ||
| 41 | #include "core/hle/service/ns/ns.h" | ||
| 42 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 43 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 44 | #include "core/hle/service/pm/pm.h" | ||
| 45 | #include "core/hle/service/server_manager.h" | 10 | #include "core/hle/service/server_manager.h" |
| 46 | #include "core/hle/service/sm/sm.h" | ||
| 47 | #include "core/hle/service/vi/vi.h" | ||
| 48 | #include "core/hle/service/vi/vi_results.h" | ||
| 49 | #include "core/memory.h" | ||
| 50 | #include "hid_core/hid_types.h" | ||
| 51 | #include "hid_core/resources/npad/npad.h" | ||
| 52 | 11 | ||
| 53 | namespace Service::AM { | 12 | namespace Service::AM { |
| 54 | 13 | ||
| 55 | constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | ||
| 56 | constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | ||
| 57 | constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | ||
| 58 | |||
| 59 | enum class LaunchParameterKind : u32 { | ||
| 60 | UserChannel = 1, | ||
| 61 | AccountPreselectedUser = 2, | ||
| 62 | }; | ||
| 63 | |||
| 64 | constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; | ||
| 65 | |||
| 66 | struct LaunchParameterAccountPreselectedUser { | ||
| 67 | u32_le magic; | ||
| 68 | u32_le is_account_selected; | ||
| 69 | Common::UUID current_user; | ||
| 70 | INSERT_PADDING_BYTES(0x70); | ||
| 71 | }; | ||
| 72 | static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); | ||
| 73 | |||
| 74 | IWindowController::IWindowController(Core::System& system_) | ||
| 75 | : ServiceFramework{system_, "IWindowController"} { | ||
| 76 | // clang-format off | ||
| 77 | static const FunctionInfo functions[] = { | ||
| 78 | {0, nullptr, "CreateWindow"}, | ||
| 79 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | ||
| 80 | {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 81 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | ||
| 82 | {11, nullptr, "ReleaseForegroundRights"}, | ||
| 83 | {12, nullptr, "RejectToChangeIntoBackground"}, | ||
| 84 | {20, nullptr, "SetAppletWindowVisibility"}, | ||
| 85 | {21, nullptr, "SetAppletGpuTimeSlice"}, | ||
| 86 | }; | ||
| 87 | // clang-format on | ||
| 88 | |||
| 89 | RegisterHandlers(functions); | ||
| 90 | } | ||
| 91 | |||
| 92 | IWindowController::~IWindowController() = default; | ||
| 93 | |||
| 94 | void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { | ||
| 95 | const u64 process_id = system.ApplicationProcess()->GetProcessId(); | ||
| 96 | |||
| 97 | LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id); | ||
| 98 | |||
| 99 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 100 | rb.Push(ResultSuccess); | ||
| 101 | rb.Push<u64>(process_id); | ||
| 102 | } | ||
| 103 | |||
| 104 | void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { | ||
| 105 | const u64 process_id = 0; | ||
| 106 | |||
| 107 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 108 | |||
| 109 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 110 | rb.Push(ResultSuccess); | ||
| 111 | rb.Push<u64>(process_id); | ||
| 112 | } | ||
| 113 | |||
| 114 | void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { | ||
| 115 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 116 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 117 | rb.Push(ResultSuccess); | ||
| 118 | } | ||
| 119 | |||
| 120 | IAudioController::IAudioController(Core::System& system_) | ||
| 121 | : ServiceFramework{system_, "IAudioController"} { | ||
| 122 | // clang-format off | ||
| 123 | static const FunctionInfo functions[] = { | ||
| 124 | {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, | ||
| 125 | {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"}, | ||
| 126 | {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"}, | ||
| 127 | {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"}, | ||
| 128 | {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"}, | ||
| 129 | }; | ||
| 130 | // clang-format on | ||
| 131 | |||
| 132 | RegisterHandlers(functions); | ||
| 133 | } | ||
| 134 | |||
| 135 | IAudioController::~IAudioController() = default; | ||
| 136 | |||
| 137 | void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 138 | IPC::RequestParser rp{ctx}; | ||
| 139 | const float main_applet_volume_tmp = rp.Pop<float>(); | ||
| 140 | const float library_applet_volume_tmp = rp.Pop<float>(); | ||
| 141 | |||
| 142 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", | ||
| 143 | main_applet_volume_tmp, library_applet_volume_tmp); | ||
| 144 | |||
| 145 | // Ensure the volume values remain within the 0-100% range | ||
| 146 | main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 147 | library_applet_volume = | ||
| 148 | std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 149 | |||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(ResultSuccess); | ||
| 152 | } | ||
| 153 | |||
| 154 | void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 155 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); | ||
| 156 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 157 | rb.Push(ResultSuccess); | ||
| 158 | rb.Push(main_applet_volume); | ||
| 159 | } | ||
| 160 | |||
| 161 | void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 162 | LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); | ||
| 163 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 164 | rb.Push(ResultSuccess); | ||
| 165 | rb.Push(library_applet_volume); | ||
| 166 | } | ||
| 167 | |||
| 168 | void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { | ||
| 169 | struct Parameters { | ||
| 170 | float volume; | ||
| 171 | s64 fade_time_ns; | ||
| 172 | }; | ||
| 173 | static_assert(sizeof(Parameters) == 16); | ||
| 174 | |||
| 175 | IPC::RequestParser rp{ctx}; | ||
| 176 | const auto parameters = rp.PopRaw<Parameters>(); | ||
| 177 | |||
| 178 | LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume, | ||
| 179 | parameters.fade_time_ns); | ||
| 180 | |||
| 181 | main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume); | ||
| 182 | fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns}; | ||
| 183 | |||
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | rb.Push(ResultSuccess); | ||
| 186 | } | ||
| 187 | |||
| 188 | void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { | ||
| 189 | IPC::RequestParser rp{ctx}; | ||
| 190 | const float transparent_volume_rate_tmp = rp.Pop<float>(); | ||
| 191 | |||
| 192 | LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp); | ||
| 193 | |||
| 194 | // Clamp volume range to 0-100%. | ||
| 195 | transparent_volume_rate = | ||
| 196 | std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume); | ||
| 197 | |||
| 198 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 199 | rb.Push(ResultSuccess); | ||
| 200 | } | ||
| 201 | |||
| 202 | IDisplayController::IDisplayController(Core::System& system_) | ||
| 203 | : ServiceFramework{system_, "IDisplayController"} { | ||
| 204 | // clang-format off | ||
| 205 | static const FunctionInfo functions[] = { | ||
| 206 | {0, nullptr, "GetLastForegroundCaptureImage"}, | ||
| 207 | {1, nullptr, "UpdateLastForegroundCaptureImage"}, | ||
| 208 | {2, nullptr, "GetLastApplicationCaptureImage"}, | ||
| 209 | {3, nullptr, "GetCallerAppletCaptureImage"}, | ||
| 210 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, | ||
| 211 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | ||
| 212 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | ||
| 213 | {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, | ||
| 214 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, | ||
| 215 | {9, nullptr, "CopyBetweenCaptureBuffers"}, | ||
| 216 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | ||
| 217 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | ||
| 218 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | ||
| 219 | {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, | ||
| 220 | {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, | ||
| 221 | {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, | ||
| 222 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | ||
| 223 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | ||
| 224 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | ||
| 225 | {20, nullptr, "ClearCaptureBuffer"}, | ||
| 226 | {21, nullptr, "ClearAppletTransitionBuffer"}, | ||
| 227 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, | ||
| 228 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | ||
| 229 | {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, | ||
| 230 | {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, | ||
| 231 | {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, | ||
| 232 | {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, | ||
| 233 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | ||
| 234 | }; | ||
| 235 | // clang-format on | ||
| 236 | |||
| 237 | RegisterHandlers(functions); | ||
| 238 | } | ||
| 239 | |||
| 240 | IDisplayController::~IDisplayController() = default; | ||
| 241 | |||
| 242 | void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { | ||
| 243 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 244 | |||
| 245 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 246 | rb.Push(ResultSuccess); | ||
| 247 | rb.Push(1u); | ||
| 248 | rb.Push(0); | ||
| 249 | } | ||
| 250 | |||
| 251 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | ||
| 252 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 253 | |||
| 254 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 255 | rb.Push(ResultSuccess); | ||
| 256 | } | ||
| 257 | |||
| 258 | void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 259 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 260 | |||
| 261 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 262 | rb.Push(ResultSuccess); | ||
| 263 | rb.Push(1U); | ||
| 264 | rb.Push(0); | ||
| 265 | } | ||
| 266 | |||
| 267 | void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 268 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 269 | |||
| 270 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 271 | rb.Push(ResultSuccess); | ||
| 272 | } | ||
| 273 | |||
| 274 | void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 275 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 276 | |||
| 277 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 278 | rb.Push(ResultSuccess); | ||
| 279 | rb.Push(1U); | ||
| 280 | rb.Push(0); | ||
| 281 | } | ||
| 282 | |||
| 283 | void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 284 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 285 | |||
| 286 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 287 | rb.Push(ResultSuccess); | ||
| 288 | } | ||
| 289 | |||
| 290 | IDebugFunctions::IDebugFunctions(Core::System& system_) | ||
| 291 | : ServiceFramework{system_, "IDebugFunctions"} { | ||
| 292 | // clang-format off | ||
| 293 | static const FunctionInfo functions[] = { | ||
| 294 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | ||
| 295 | {1, nullptr, "OpenMainApplication"}, | ||
| 296 | {10, nullptr, "PerformSystemButtonPressing"}, | ||
| 297 | {20, nullptr, "InvalidateTransitionLayer"}, | ||
| 298 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | ||
| 299 | {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, | ||
| 300 | {40, nullptr, "GetAppletResourceUsageInfo"}, | ||
| 301 | {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, | ||
| 302 | {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, | ||
| 303 | {100, nullptr, "SetCpuBoostModeForApplet"}, | ||
| 304 | {101, nullptr, "CancelCpuBoostModeForApplet"}, | ||
| 305 | {110, nullptr, "PushToAppletBoundChannelForDebug"}, | ||
| 306 | {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, | ||
| 307 | {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, | ||
| 308 | {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, | ||
| 309 | {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, | ||
| 310 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, | ||
| 311 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, | ||
| 312 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, | ||
| 313 | {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, | ||
| 314 | {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, | ||
| 315 | {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, | ||
| 316 | {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, | ||
| 317 | }; | ||
| 318 | // clang-format on | ||
| 319 | |||
| 320 | RegisterHandlers(functions); | ||
| 321 | } | ||
| 322 | |||
| 323 | IDebugFunctions::~IDebugFunctions() = default; | ||
| 324 | |||
| 325 | ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||
| 326 | : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, | ||
| 327 | service_context{system, "ISelfController"} { | ||
| 328 | // clang-format off | ||
| 329 | static const FunctionInfo functions[] = { | ||
| 330 | {0, &ISelfController::Exit, "Exit"}, | ||
| 331 | {1, &ISelfController::LockExit, "LockExit"}, | ||
| 332 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||
| 333 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||
| 334 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, | ||
| 335 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | ||
| 336 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | ||
| 337 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | ||
| 338 | {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, | ||
| 339 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | ||
| 340 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 341 | {15, nullptr, "SetScreenShotAppletIdentityInfo"}, | ||
| 342 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | ||
| 343 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | ||
| 344 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | ||
| 345 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, | ||
| 346 | {20, nullptr, "SetDesirableKeyboardLayout"}, | ||
| 347 | {21, nullptr, "GetScreenShotProgramId"}, | ||
| 348 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | ||
| 349 | {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, | ||
| 350 | {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, | ||
| 351 | {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, | ||
| 352 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, | ||
| 353 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, | ||
| 354 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, | ||
| 355 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, | ||
| 356 | {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, | ||
| 357 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, | ||
| 358 | {61, nullptr, "SetMediaPlaybackState"}, | ||
| 359 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, | ||
| 360 | {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, | ||
| 361 | {64, nullptr, "SetInputDetectionSourceSet"}, | ||
| 362 | {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, | ||
| 363 | {66, nullptr, "GetCurrentIlluminance"}, | ||
| 364 | {67, nullptr, "IsIlluminanceAvailable"}, | ||
| 365 | {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, | ||
| 366 | {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, | ||
| 367 | {70, nullptr, "ReportMultimediaError"}, | ||
| 368 | {71, nullptr, "GetCurrentIlluminanceEx"}, | ||
| 369 | {72, nullptr, "SetInputDetectionPolicy"}, | ||
| 370 | {80, nullptr, "SetWirelessPriorityMode"}, | ||
| 371 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, | ||
| 372 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, | ||
| 373 | {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, | ||
| 374 | {110, nullptr, "SetApplicationAlbumUserData"}, | ||
| 375 | {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, | ||
| 376 | {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, | ||
| 377 | {1000, nullptr, "GetDebugStorageChannel"}, | ||
| 378 | }; | ||
| 379 | // clang-format on | ||
| 380 | |||
| 381 | RegisterHandlers(functions); | ||
| 382 | |||
| 383 | launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); | ||
| 384 | |||
| 385 | // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is | ||
| 386 | // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple | ||
| 387 | // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not | ||
| 388 | // suspended if the event has previously been created by a call to | ||
| 389 | // GetAccumulatedSuspendedTickChangedEvent. | ||
| 390 | |||
| 391 | accumulated_suspended_tick_changed_event = | ||
| 392 | service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); | ||
| 393 | accumulated_suspended_tick_changed_event->Signal(); | ||
| 394 | } | ||
| 395 | |||
| 396 | ISelfController::~ISelfController() { | ||
| 397 | service_context.CloseEvent(launchable_event); | ||
| 398 | service_context.CloseEvent(accumulated_suspended_tick_changed_event); | ||
| 399 | } | ||
| 400 | |||
| 401 | void ISelfController::Exit(HLERequestContext& ctx) { | ||
| 402 | LOG_DEBUG(Service_AM, "called"); | ||
| 403 | |||
| 404 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 405 | rb.Push(ResultSuccess); | ||
| 406 | |||
| 407 | system.Exit(); | ||
| 408 | } | ||
| 409 | |||
| 410 | void ISelfController::LockExit(HLERequestContext& ctx) { | ||
| 411 | LOG_DEBUG(Service_AM, "called"); | ||
| 412 | |||
| 413 | system.SetExitLocked(true); | ||
| 414 | |||
| 415 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 416 | rb.Push(ResultSuccess); | ||
| 417 | } | ||
| 418 | |||
| 419 | void ISelfController::UnlockExit(HLERequestContext& ctx) { | ||
| 420 | LOG_DEBUG(Service_AM, "called"); | ||
| 421 | |||
| 422 | system.SetExitLocked(false); | ||
| 423 | |||
| 424 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 425 | rb.Push(ResultSuccess); | ||
| 426 | |||
| 427 | if (system.GetExitRequested()) { | ||
| 428 | system.Exit(); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | void ISelfController::EnterFatalSection(HLERequestContext& ctx) { | ||
| 433 | ++num_fatal_sections_entered; | ||
| 434 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); | ||
| 435 | |||
| 436 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 437 | rb.Push(ResultSuccess); | ||
| 438 | } | ||
| 439 | |||
| 440 | void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { | ||
| 441 | LOG_DEBUG(Service_AM, "called."); | ||
| 442 | |||
| 443 | // Entry and exit of fatal sections must be balanced. | ||
| 444 | if (num_fatal_sections_entered == 0) { | ||
| 445 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 446 | rb.Push(Result{ErrorModule::AM, 512}); | ||
| 447 | return; | ||
| 448 | } | ||
| 449 | |||
| 450 | --num_fatal_sections_entered; | ||
| 451 | |||
| 452 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 453 | rb.Push(ResultSuccess); | ||
| 454 | } | ||
| 455 | |||
| 456 | void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { | ||
| 457 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 458 | |||
| 459 | launchable_event->Signal(); | ||
| 460 | |||
| 461 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 462 | rb.Push(ResultSuccess); | ||
| 463 | rb.PushCopyObjects(launchable_event->GetReadableEvent()); | ||
| 464 | } | ||
| 465 | |||
| 466 | void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { | ||
| 467 | IPC::RequestParser rp{ctx}; | ||
| 468 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 469 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 470 | |||
| 471 | screenshot_permission = permission; | ||
| 472 | |||
| 473 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 474 | rb.Push(ResultSuccess); | ||
| 475 | } | ||
| 476 | |||
| 477 | void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { | ||
| 478 | IPC::RequestParser rp{ctx}; | ||
| 479 | |||
| 480 | bool flag = rp.Pop<bool>(); | ||
| 481 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 482 | |||
| 483 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 484 | rb.Push(ResultSuccess); | ||
| 485 | } | ||
| 486 | |||
| 487 | void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { | ||
| 488 | IPC::RequestParser rp{ctx}; | ||
| 489 | |||
| 490 | bool flag = rp.Pop<bool>(); | ||
| 491 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | ||
| 492 | |||
| 493 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 494 | rb.Push(ResultSuccess); | ||
| 495 | } | ||
| 496 | |||
| 497 | void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { | ||
| 498 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 499 | // u8, these are bool flags. No output. | ||
| 500 | IPC::RequestParser rp{ctx}; | ||
| 501 | |||
| 502 | struct FocusHandlingModeParams { | ||
| 503 | u8 unknown0; | ||
| 504 | u8 unknown1; | ||
| 505 | u8 unknown2; | ||
| 506 | }; | ||
| 507 | const auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 508 | |||
| 509 | LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", | ||
| 510 | flags.unknown0, flags.unknown1, flags.unknown2); | ||
| 511 | |||
| 512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 513 | rb.Push(ResultSuccess); | ||
| 514 | } | ||
| 515 | |||
| 516 | void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { | ||
| 517 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 518 | |||
| 519 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 520 | rb.Push(ResultSuccess); | ||
| 521 | } | ||
| 522 | |||
| 523 | void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { | ||
| 524 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 525 | // u8, these are bool flags. No output. | ||
| 526 | IPC::RequestParser rp{ctx}; | ||
| 527 | |||
| 528 | bool enabled = rp.Pop<bool>(); | ||
| 529 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 530 | |||
| 531 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 532 | rb.Push(ResultSuccess); | ||
| 533 | } | ||
| 534 | |||
| 535 | void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { | ||
| 536 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 537 | |||
| 538 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 539 | rb.Push(ResultSuccess); | ||
| 540 | } | ||
| 541 | |||
| 542 | void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { | ||
| 543 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 544 | |||
| 545 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 546 | // create the layer in the Default display. | ||
| 547 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 548 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 549 | |||
| 550 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 551 | rb.Push(ResultSuccess); | ||
| 552 | rb.Push(*layer_id); | ||
| 553 | } | ||
| 554 | |||
| 555 | void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { | ||
| 556 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 557 | |||
| 558 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 559 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 560 | } | ||
| 561 | |||
| 562 | void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { | ||
| 563 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 564 | |||
| 565 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 566 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 567 | rb.Push<s64>(system_shared_buffer_id); | ||
| 568 | rb.Push<s64>(system_shared_layer_id); | ||
| 569 | } | ||
| 570 | |||
| 571 | void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { | ||
| 572 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 573 | |||
| 574 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 575 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 576 | rb.Push<s64>(system_shared_buffer_id); | ||
| 577 | } | ||
| 578 | |||
| 579 | Result ISelfController::EnsureBufferSharingEnabled() { | ||
| 580 | if (buffer_sharing_enabled) { | ||
| 581 | return ResultSuccess; | ||
| 582 | } | ||
| 583 | |||
| 584 | if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { | ||
| 585 | return VI::ResultOperationFailed; | ||
| 586 | } | ||
| 587 | |||
| 588 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 589 | const auto result = nvnflinger.GetSystemBufferManager().Initialize( | ||
| 590 | &system_shared_buffer_id, &system_shared_layer_id, *display_id); | ||
| 591 | |||
| 592 | if (result.IsSuccess()) { | ||
| 593 | buffer_sharing_enabled = true; | ||
| 594 | } | ||
| 595 | |||
| 596 | return result; | ||
| 597 | } | ||
| 598 | |||
| 599 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { | ||
| 600 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 601 | |||
| 602 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 603 | // create the layer in the Default display. | ||
| 604 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 605 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 606 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 607 | // side effects. | ||
| 608 | // TODO: Support multiple layers | ||
| 609 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 610 | const auto layer_id = nvnflinger.CreateLayer(*display_id); | ||
| 611 | |||
| 612 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 613 | rb.Push(ResultSuccess); | ||
| 614 | rb.Push(*layer_id); | ||
| 615 | } | ||
| 616 | |||
| 617 | void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { | ||
| 618 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 619 | |||
| 620 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 621 | rb.Push(ResultSuccess); | ||
| 622 | } | ||
| 623 | |||
| 624 | void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { | ||
| 625 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 626 | |||
| 627 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 628 | rb.Push(ResultSuccess); | ||
| 629 | } | ||
| 630 | |||
| 631 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 632 | IPC::RequestParser rp{ctx}; | ||
| 633 | idle_time_detection_extension = rp.Pop<u32>(); | ||
| 634 | LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", | ||
| 635 | idle_time_detection_extension); | ||
| 636 | |||
| 637 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 638 | rb.Push(ResultSuccess); | ||
| 639 | } | ||
| 640 | |||
| 641 | void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 642 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 643 | |||
| 644 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 645 | rb.Push(ResultSuccess); | ||
| 646 | rb.Push<u32>(idle_time_detection_extension); | ||
| 647 | } | ||
| 648 | |||
| 649 | void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { | ||
| 650 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 651 | |||
| 652 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 653 | rb.Push(ResultSuccess); | ||
| 654 | } | ||
| 655 | |||
| 656 | void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 657 | IPC::RequestParser rp{ctx}; | ||
| 658 | is_auto_sleep_disabled = rp.Pop<bool>(); | ||
| 659 | |||
| 660 | // On the system itself, if the previous state of is_auto_sleep_disabled | ||
| 661 | // differed from the current value passed in, it'd signify the internal | ||
| 662 | // window manager to update (and also increment some statistics like update counts) | ||
| 663 | // | ||
| 664 | // It'd also indicate this change to an idle handling context. | ||
| 665 | // | ||
| 666 | // However, given we're emulating this behavior, most of this can be ignored | ||
| 667 | // and it's sufficient to simply set the member variable for querying via | ||
| 668 | // IsAutoSleepDisabled(). | ||
| 669 | |||
| 670 | LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); | ||
| 671 | |||
| 672 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 673 | rb.Push(ResultSuccess); | ||
| 674 | } | ||
| 675 | |||
| 676 | void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 677 | LOG_DEBUG(Service_AM, "called."); | ||
| 678 | |||
| 679 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 680 | rb.Push(ResultSuccess); | ||
| 681 | rb.Push(is_auto_sleep_disabled); | ||
| 682 | } | ||
| 683 | |||
| 684 | void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { | ||
| 685 | LOG_DEBUG(Service_AM, "called."); | ||
| 686 | |||
| 687 | // This command returns the total number of system ticks since ISelfController creation | ||
| 688 | // where the game was suspended. Since Yuzu doesn't implement game suspension, this command | ||
| 689 | // can just always return 0 ticks. | ||
| 690 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 691 | rb.Push(ResultSuccess); | ||
| 692 | rb.Push<u64>(0); | ||
| 693 | } | ||
| 694 | |||
| 695 | void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { | ||
| 696 | LOG_DEBUG(Service_AM, "called."); | ||
| 697 | |||
| 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 699 | rb.Push(ResultSuccess); | ||
| 700 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); | ||
| 701 | } | ||
| 702 | |||
| 703 | void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { | ||
| 704 | IPC::RequestParser rp{ctx}; | ||
| 705 | |||
| 706 | // This service call sets an internal flag whether a notification is shown when an image is | ||
| 707 | // captured. Currently we do not support capturing images via the capture button, so this can be | ||
| 708 | // stubbed for now. | ||
| 709 | const bool album_image_taken_notification_enabled = rp.Pop<bool>(); | ||
| 710 | |||
| 711 | LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", | ||
| 712 | album_image_taken_notification_enabled); | ||
| 713 | |||
| 714 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 715 | rb.Push(ResultSuccess); | ||
| 716 | } | ||
| 717 | |||
| 718 | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | ||
| 719 | IPC::RequestParser rp{ctx}; | ||
| 720 | |||
| 721 | const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); | ||
| 722 | |||
| 723 | LOG_INFO(Service_AM, "called, report_option={}", report_option); | ||
| 724 | |||
| 725 | const auto screenshot_service = | ||
| 726 | system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( | ||
| 727 | "caps:su"); | ||
| 728 | |||
| 729 | if (screenshot_service) { | ||
| 730 | screenshot_service->CaptureAndSaveScreenshot(report_option); | ||
| 731 | } | ||
| 732 | |||
| 733 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 734 | rb.Push(ResultSuccess); | ||
| 735 | } | ||
| 736 | |||
| 737 | void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { | ||
| 738 | IPC::RequestParser rp{ctx}; | ||
| 739 | |||
| 740 | const auto is_record_volume_muted = rp.Pop<bool>(); | ||
| 741 | |||
| 742 | LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); | ||
| 743 | |||
| 744 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 745 | rb.Push(ResultSuccess); | ||
| 746 | } | ||
| 747 | |||
| 748 | AppletMessageQueue::AppletMessageQueue(Core::System& system) | ||
| 749 | : service_context{system, "AppletMessageQueue"} { | ||
| 750 | on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); | ||
| 751 | on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged"); | ||
| 752 | } | ||
| 753 | |||
| 754 | AppletMessageQueue::~AppletMessageQueue() { | ||
| 755 | service_context.CloseEvent(on_new_message); | ||
| 756 | service_context.CloseEvent(on_operation_mode_changed); | ||
| 757 | } | ||
| 758 | |||
| 759 | Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() { | ||
| 760 | return on_new_message->GetReadableEvent(); | ||
| 761 | } | ||
| 762 | |||
| 763 | Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { | ||
| 764 | return on_operation_mode_changed->GetReadableEvent(); | ||
| 765 | } | ||
| 766 | |||
| 767 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | ||
| 768 | messages.push(msg); | ||
| 769 | on_new_message->Signal(); | ||
| 770 | } | ||
| 771 | |||
| 772 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | ||
| 773 | if (messages.empty()) { | ||
| 774 | on_new_message->Clear(); | ||
| 775 | return AppletMessage::None; | ||
| 776 | } | ||
| 777 | auto msg = messages.front(); | ||
| 778 | messages.pop(); | ||
| 779 | if (messages.empty()) { | ||
| 780 | on_new_message->Clear(); | ||
| 781 | } | ||
| 782 | return msg; | ||
| 783 | } | ||
| 784 | |||
| 785 | std::size_t AppletMessageQueue::GetMessageCount() const { | ||
| 786 | return messages.size(); | ||
| 787 | } | ||
| 788 | |||
| 789 | void AppletMessageQueue::RequestExit() { | ||
| 790 | PushMessage(AppletMessage::Exit); | ||
| 791 | } | ||
| 792 | |||
| 793 | void AppletMessageQueue::RequestResume() { | ||
| 794 | PushMessage(AppletMessage::Resume); | ||
| 795 | } | ||
| 796 | |||
| 797 | void AppletMessageQueue::FocusStateChanged() { | ||
| 798 | PushMessage(AppletMessage::FocusStateChanged); | ||
| 799 | } | ||
| 800 | |||
| 801 | void AppletMessageQueue::OperationModeChanged() { | ||
| 802 | PushMessage(AppletMessage::OperationModeChanged); | ||
| 803 | PushMessage(AppletMessage::PerformanceModeChanged); | ||
| 804 | on_operation_mode_changed->Signal(); | ||
| 805 | } | ||
| 806 | |||
| 807 | ILockAccessor::ILockAccessor(Core::System& system_) | ||
| 808 | : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} { | ||
| 809 | // clang-format off | ||
| 810 | static const FunctionInfo functions[] = { | ||
| 811 | {1, &ILockAccessor::TryLock, "TryLock"}, | ||
| 812 | {2, &ILockAccessor::Unlock, "Unlock"}, | ||
| 813 | {3, &ILockAccessor::GetEvent, "GetEvent"}, | ||
| 814 | {4,&ILockAccessor::IsLocked, "IsLocked"}, | ||
| 815 | }; | ||
| 816 | // clang-format on | ||
| 817 | |||
| 818 | RegisterHandlers(functions); | ||
| 819 | |||
| 820 | lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); | ||
| 821 | } | ||
| 822 | |||
| 823 | ILockAccessor::~ILockAccessor() { | ||
| 824 | service_context.CloseEvent(lock_event); | ||
| 825 | }; | ||
| 826 | |||
| 827 | void ILockAccessor::TryLock(HLERequestContext& ctx) { | ||
| 828 | IPC::RequestParser rp{ctx}; | ||
| 829 | const auto return_handle = rp.Pop<bool>(); | ||
| 830 | |||
| 831 | LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle); | ||
| 832 | |||
| 833 | // TODO: When return_handle is true this function should return the lock handle | ||
| 834 | |||
| 835 | is_locked = true; | ||
| 836 | |||
| 837 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 838 | rb.Push(ResultSuccess); | ||
| 839 | rb.Push<u8>(is_locked); | ||
| 840 | } | ||
| 841 | |||
| 842 | void ILockAccessor::Unlock(HLERequestContext& ctx) { | ||
| 843 | LOG_INFO(Service_AM, "called"); | ||
| 844 | |||
| 845 | is_locked = false; | ||
| 846 | |||
| 847 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 848 | rb.Push(ResultSuccess); | ||
| 849 | } | ||
| 850 | |||
| 851 | void ILockAccessor::GetEvent(HLERequestContext& ctx) { | ||
| 852 | LOG_INFO(Service_AM, "called"); | ||
| 853 | |||
| 854 | lock_event->Signal(); | ||
| 855 | |||
| 856 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 857 | rb.Push(ResultSuccess); | ||
| 858 | rb.PushCopyObjects(lock_event->GetReadableEvent()); | ||
| 859 | } | ||
| 860 | |||
| 861 | void ILockAccessor::IsLocked(HLERequestContext& ctx) { | ||
| 862 | LOG_INFO(Service_AM, "called"); | ||
| 863 | |||
| 864 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 865 | rb.Push(ResultSuccess); | ||
| 866 | rb.Push<u8>(is_locked); | ||
| 867 | } | ||
| 868 | |||
| 869 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, | ||
| 870 | std::shared_ptr<AppletMessageQueue> msg_queue_) | ||
| 871 | : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)}, | ||
| 872 | service_context{system_, "ICommonStateGetter"} { | ||
| 873 | // clang-format off | ||
| 874 | static const FunctionInfo functions[] = { | ||
| 875 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | ||
| 876 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | ||
| 877 | {2, nullptr, "GetThisAppletKind"}, | ||
| 878 | {3, nullptr, "AllowToEnterSleep"}, | ||
| 879 | {4, nullptr, "DisallowToEnterSleep"}, | ||
| 880 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 881 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 882 | {7, nullptr, "GetCradleStatus"}, | ||
| 883 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, | ||
| 884 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | ||
| 885 | {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, | ||
| 886 | {11, nullptr, "ReleaseSleepLock"}, | ||
| 887 | {12, nullptr, "ReleaseSleepLockTransiently"}, | ||
| 888 | {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, | ||
| 889 | {14, nullptr, "GetWakeupCount"}, | ||
| 890 | {20, nullptr, "PushToGeneralChannel"}, | ||
| 891 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | ||
| 892 | {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"}, | ||
| 893 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 894 | {40, nullptr, "GetCradleFwVersion"}, | ||
| 895 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | ||
| 896 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | ||
| 897 | {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, | ||
| 898 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, | ||
| 899 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, | ||
| 900 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, | ||
| 901 | {59, nullptr, "SetVrPositionForDebug"}, | ||
| 902 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, | ||
| 903 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, | ||
| 904 | {62, nullptr, "GetHdcpAuthenticationState"}, | ||
| 905 | {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, | ||
| 906 | {64, nullptr, "SetTvPowerStateMatchingMode"}, | ||
| 907 | {65, nullptr, "GetApplicationIdByContentActionName"}, | ||
| 908 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, | ||
| 909 | {67, nullptr, "CancelCpuBoostMode"}, | ||
| 910 | {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"}, | ||
| 911 | {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"}, | ||
| 912 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, | ||
| 913 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, | ||
| 914 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, | ||
| 915 | {110, nullptr, "OpenMyGpuErrorHandler"}, | ||
| 916 | {120, nullptr, "GetAppletLaunchedHistory"}, | ||
| 917 | {200, nullptr, "GetOperationModeSystemInfo"}, | ||
| 918 | {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"}, | ||
| 919 | {400, nullptr, "ActivateMigrationService"}, | ||
| 920 | {401, nullptr, "DeactivateMigrationService"}, | ||
| 921 | {500, nullptr, "DisableSleepTillShutdown"}, | ||
| 922 | {501, nullptr, "SuppressDisablingSleepTemporarily"}, | ||
| 923 | {502, nullptr, "IsSleepEnabled"}, | ||
| 924 | {503, nullptr, "IsDisablingSleepSuppressed"}, | ||
| 925 | {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, | ||
| 926 | }; | ||
| 927 | // clang-format on | ||
| 928 | |||
| 929 | RegisterHandlers(functions); | ||
| 930 | |||
| 931 | sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent"); | ||
| 932 | |||
| 933 | // Configure applets to be in foreground state | ||
| 934 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 935 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 936 | } | ||
| 937 | |||
| 938 | ICommonStateGetter::~ICommonStateGetter() { | ||
| 939 | service_context.CloseEvent(sleep_lock_event); | ||
| 940 | }; | ||
| 941 | |||
| 942 | void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { | ||
| 943 | LOG_DEBUG(Service_AM, "called"); | ||
| 944 | |||
| 945 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 946 | rb.Push(ResultSuccess); | ||
| 947 | rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode | ||
| 948 | } | ||
| 949 | |||
| 950 | void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { | ||
| 951 | LOG_DEBUG(Service_AM, "called"); | ||
| 952 | |||
| 953 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 954 | rb.Push(ResultSuccess); | ||
| 955 | rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent()); | ||
| 956 | } | ||
| 957 | |||
| 958 | void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { | ||
| 959 | LOG_DEBUG(Service_AM, "called"); | ||
| 960 | |||
| 961 | const auto message = msg_queue->PopMessage(); | ||
| 962 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 963 | |||
| 964 | if (message == AppletMessageQueue::AppletMessage::None) { | ||
| 965 | LOG_ERROR(Service_AM, "Message queue is empty"); | ||
| 966 | rb.Push(AM::ResultNoMessages); | ||
| 967 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 968 | return; | ||
| 969 | } | ||
| 970 | |||
| 971 | rb.Push(ResultSuccess); | ||
| 972 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 973 | } | ||
| 974 | |||
| 975 | void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { | ||
| 976 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 977 | |||
| 978 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 979 | rb.Push(ResultSuccess); | ||
| 980 | rb.Push(static_cast<u8>(FocusState::InFocus)); | ||
| 981 | } | ||
| 982 | |||
| 983 | void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { | ||
| 984 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 985 | |||
| 986 | // Sleep lock is acquired immediately. | ||
| 987 | sleep_lock_event->Signal(); | ||
| 988 | |||
| 989 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 990 | rb.Push(ResultSuccess); | ||
| 991 | } | ||
| 992 | |||
| 993 | void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) { | ||
| 994 | IPC::RequestParser rp{ctx}; | ||
| 995 | const auto unknown = rp.Pop<u32>(); | ||
| 996 | |||
| 997 | LOG_INFO(Service_AM, "called, unknown={}", unknown); | ||
| 998 | |||
| 999 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1000 | |||
| 1001 | rb.Push(ResultSuccess); | ||
| 1002 | rb.PushIpcInterface<ILockAccessor>(system); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { | ||
| 1006 | LOG_WARNING(Service_AM, "called"); | ||
| 1007 | |||
| 1008 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1009 | rb.Push(ResultSuccess); | ||
| 1010 | rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { | ||
| 1014 | LOG_DEBUG(Service_AM, "called"); | ||
| 1015 | |||
| 1016 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1017 | rb.Push(ResultSuccess); | ||
| 1018 | rb.Push(vr_mode_state); | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { | ||
| 1022 | IPC::RequestParser rp{ctx}; | ||
| 1023 | vr_mode_state = rp.Pop<bool>(); | ||
| 1024 | |||
| 1025 | LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); | ||
| 1026 | |||
| 1027 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1028 | rb.Push(ResultSuccess); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { | ||
| 1032 | IPC::RequestParser rp{ctx}; | ||
| 1033 | const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); | ||
| 1034 | |||
| 1035 | LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", | ||
| 1036 | is_lcd_backlight_off_enabled); | ||
| 1037 | |||
| 1038 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1039 | rb.Push(ResultSuccess); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { | ||
| 1043 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1044 | |||
| 1045 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1046 | rb.Push(ResultSuccess); | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { | ||
| 1050 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1051 | |||
| 1052 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1053 | rb.Push(ResultSuccess); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { | ||
| 1057 | LOG_DEBUG(Service_AM, "called"); | ||
| 1058 | |||
| 1059 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1060 | rb.Push(ResultSuccess); | ||
| 1061 | rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { | ||
| 1065 | LOG_DEBUG(Service_AM, "called"); | ||
| 1066 | |||
| 1067 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1068 | rb.Push(ResultSuccess); | ||
| 1069 | |||
| 1070 | if (Settings::IsDockedMode()) { | ||
| 1071 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||
| 1072 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||
| 1073 | } else { | ||
| 1074 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||
| 1075 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||
| 1076 | } | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { | ||
| 1080 | LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); | ||
| 1081 | |||
| 1082 | const auto& sm = system.ServiceManager(); | ||
| 1083 | const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); | ||
| 1084 | ASSERT(apm_sys != nullptr); | ||
| 1085 | |||
| 1086 | apm_sys->SetCpuBoostMode(ctx); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) { | ||
| 1090 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1091 | |||
| 1092 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1093 | rb.Push(ResultSuccess); | ||
| 1094 | rb.Push(0); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { | ||
| 1098 | IPC::RequestParser rp{ctx}; | ||
| 1099 | const auto system_button{rp.PopEnum<SystemButtonType>()}; | ||
| 1100 | |||
| 1101 | LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button); | ||
| 1102 | |||
| 1103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1104 | rb.Push(ResultSuccess); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { | ||
| 1108 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1109 | |||
| 1110 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1111 | rb.Push(ResultSuccess); | ||
| 1112 | rb.PushEnum(SysPlatformRegion::Global); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( | ||
| 1116 | HLERequestContext& ctx) { | ||
| 1117 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1118 | |||
| 1119 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1120 | rb.Push(ResultSuccess); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | IStorageImpl::~IStorageImpl() = default; | ||
| 1124 | |||
| 1125 | class StorageDataImpl final : public IStorageImpl { | ||
| 1126 | public: | ||
| 1127 | explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {} | ||
| 1128 | |||
| 1129 | std::vector<u8>& GetData() override { | ||
| 1130 | return buffer; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | const std::vector<u8>& GetData() const override { | ||
| 1134 | return buffer; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | std::size_t GetSize() const override { | ||
| 1138 | return buffer.size(); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | private: | ||
| 1142 | std::vector<u8> buffer; | ||
| 1143 | }; | ||
| 1144 | |||
| 1145 | IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer) | ||
| 1146 | : ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>( | ||
| 1147 | std::move(buffer))} { | ||
| 1148 | Register(); | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | void IStorage::Register() { | ||
| 1152 | // clang-format off | ||
| 1153 | static const FunctionInfo functions[] = { | ||
| 1154 | {0, &IStorage::Open, "Open"}, | ||
| 1155 | {1, nullptr, "OpenTransferStorage"}, | ||
| 1156 | }; | ||
| 1157 | // clang-format on | ||
| 1158 | |||
| 1159 | RegisterHandlers(functions); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | IStorage::~IStorage() = default; | ||
| 1163 | |||
| 1164 | void IStorage::Open(HLERequestContext& ctx) { | ||
| 1165 | LOG_DEBUG(Service_AM, "called"); | ||
| 1166 | |||
| 1167 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1168 | |||
| 1169 | rb.Push(ResultSuccess); | ||
| 1170 | rb.PushIpcInterface<IStorageAccessor>(system, *this); | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { | ||
| 1174 | const bool use_docked_mode{Settings::IsDockedMode()}; | ||
| 1175 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | ||
| 1176 | |||
| 1177 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1178 | rb.Push(ResultSuccess); | ||
| 1179 | rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { | ||
| 1183 | LOG_DEBUG(Service_AM, "called"); | ||
| 1184 | |||
| 1185 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1186 | rb.Push(ResultSuccess); | ||
| 1187 | rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode()); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { | ||
| 1191 | public: | ||
| 1192 | explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_) | ||
| 1193 | : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { | ||
| 1194 | // clang-format off | ||
| 1195 | static const FunctionInfo functions[] = { | ||
| 1196 | {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, | ||
| 1197 | {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, | ||
| 1198 | {10, &ILibraryAppletAccessor::Start, "Start"}, | ||
| 1199 | {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, | ||
| 1200 | {25, nullptr, "Terminate"}, | ||
| 1201 | {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, | ||
| 1202 | {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, | ||
| 1203 | {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"}, | ||
| 1204 | {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, | ||
| 1205 | {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, | ||
| 1206 | {102, nullptr, "PushExtraStorage"}, | ||
| 1207 | {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, | ||
| 1208 | {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, | ||
| 1209 | {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, | ||
| 1210 | {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, | ||
| 1211 | {110, nullptr, "NeedsToExitProcess"}, | ||
| 1212 | {120, nullptr, "GetLibraryAppletInfo"}, | ||
| 1213 | {150, nullptr, "RequestForAppletToGetForeground"}, | ||
| 1214 | {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"}, | ||
| 1215 | }; | ||
| 1216 | // clang-format on | ||
| 1217 | |||
| 1218 | RegisterHandlers(functions); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | private: | ||
| 1222 | void GetAppletStateChangedEvent(HLERequestContext& ctx) { | ||
| 1223 | LOG_DEBUG(Service_AM, "called"); | ||
| 1224 | |||
| 1225 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1226 | rb.Push(ResultSuccess); | ||
| 1227 | rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | void IsCompleted(HLERequestContext& ctx) { | ||
| 1231 | LOG_DEBUG(Service_AM, "called"); | ||
| 1232 | |||
| 1233 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1234 | rb.Push(ResultSuccess); | ||
| 1235 | rb.Push<u32>(applet->TransactionComplete()); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | void GetResult(HLERequestContext& ctx) { | ||
| 1239 | LOG_DEBUG(Service_AM, "called"); | ||
| 1240 | |||
| 1241 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1242 | rb.Push(applet->GetStatus()); | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { | ||
| 1246 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1247 | |||
| 1248 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1249 | rb.Push(ResultSuccess); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | void Start(HLERequestContext& ctx) { | ||
| 1253 | LOG_DEBUG(Service_AM, "called"); | ||
| 1254 | |||
| 1255 | ASSERT(applet != nullptr); | ||
| 1256 | |||
| 1257 | applet->Initialize(); | ||
| 1258 | applet->Execute(); | ||
| 1259 | |||
| 1260 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1261 | rb.Push(ResultSuccess); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | void RequestExit(HLERequestContext& ctx) { | ||
| 1265 | LOG_DEBUG(Service_AM, "called"); | ||
| 1266 | |||
| 1267 | ASSERT(applet != nullptr); | ||
| 1268 | |||
| 1269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1270 | rb.Push(applet->RequestExit()); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | void PushInData(HLERequestContext& ctx) { | ||
| 1274 | LOG_DEBUG(Service_AM, "called"); | ||
| 1275 | |||
| 1276 | IPC::RequestParser rp{ctx}; | ||
| 1277 | applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 1278 | |||
| 1279 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1280 | rb.Push(ResultSuccess); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | void PopOutData(HLERequestContext& ctx) { | ||
| 1284 | LOG_DEBUG(Service_AM, "called"); | ||
| 1285 | |||
| 1286 | auto storage = applet->GetBroker().PopNormalDataToGame(); | ||
| 1287 | if (storage == nullptr) { | ||
| 1288 | LOG_DEBUG(Service_AM, | ||
| 1289 | "storage is a nullptr. There is no data in the current normal channel"); | ||
| 1290 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1291 | rb.Push(AM::ResultNoDataInChannel); | ||
| 1292 | return; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1296 | rb.Push(ResultSuccess); | ||
| 1297 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | void PushInteractiveInData(HLERequestContext& ctx) { | ||
| 1301 | LOG_DEBUG(Service_AM, "called"); | ||
| 1302 | |||
| 1303 | IPC::RequestParser rp{ctx}; | ||
| 1304 | applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock()); | ||
| 1305 | |||
| 1306 | ASSERT(applet->IsInitialized()); | ||
| 1307 | applet->ExecuteInteractive(); | ||
| 1308 | applet->Execute(); | ||
| 1309 | |||
| 1310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1311 | rb.Push(ResultSuccess); | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | void PopInteractiveOutData(HLERequestContext& ctx) { | ||
| 1315 | LOG_DEBUG(Service_AM, "called"); | ||
| 1316 | |||
| 1317 | auto storage = applet->GetBroker().PopInteractiveDataToGame(); | ||
| 1318 | if (storage == nullptr) { | ||
| 1319 | LOG_DEBUG(Service_AM, | ||
| 1320 | "storage is a nullptr. There is no data in the current interactive channel"); | ||
| 1321 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1322 | rb.Push(AM::ResultNoDataInChannel); | ||
| 1323 | return; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1327 | rb.Push(ResultSuccess); | ||
| 1328 | rb.PushIpcInterface<IStorage>(std::move(storage)); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | void GetPopOutDataEvent(HLERequestContext& ctx) { | ||
| 1332 | LOG_DEBUG(Service_AM, "called"); | ||
| 1333 | |||
| 1334 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1335 | rb.Push(ResultSuccess); | ||
| 1336 | rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | void GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { | ||
| 1340 | LOG_DEBUG(Service_AM, "called"); | ||
| 1341 | |||
| 1342 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 1343 | rb.Push(ResultSuccess); | ||
| 1344 | rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | void GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { | ||
| 1348 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1349 | |||
| 1350 | // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is | ||
| 1351 | // actually used anywhere | ||
| 1352 | constexpr u64 handle = 0xdeadbeef; | ||
| 1353 | |||
| 1354 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1355 | rb.Push(ResultSuccess); | ||
| 1356 | rb.Push(handle); | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | std::shared_ptr<Applets::Applet> applet; | ||
| 1360 | }; | ||
| 1361 | |||
| 1362 | IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_) | ||
| 1363 | : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} { | ||
| 1364 | // clang-format off | ||
| 1365 | static const FunctionInfo functions[] = { | ||
| 1366 | {0, &IStorageAccessor::GetSize, "GetSize"}, | ||
| 1367 | {10, &IStorageAccessor::Write, "Write"}, | ||
| 1368 | {11, &IStorageAccessor::Read, "Read"}, | ||
| 1369 | }; | ||
| 1370 | // clang-format on | ||
| 1371 | |||
| 1372 | RegisterHandlers(functions); | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | IStorageAccessor::~IStorageAccessor() = default; | ||
| 1376 | |||
| 1377 | void IStorageAccessor::GetSize(HLERequestContext& ctx) { | ||
| 1378 | LOG_DEBUG(Service_AM, "called"); | ||
| 1379 | |||
| 1380 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1381 | |||
| 1382 | rb.Push(ResultSuccess); | ||
| 1383 | rb.Push(static_cast<u64>(backing.GetSize())); | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | void IStorageAccessor::Write(HLERequestContext& ctx) { | ||
| 1387 | IPC::RequestParser rp{ctx}; | ||
| 1388 | |||
| 1389 | const u64 offset{rp.Pop<u64>()}; | ||
| 1390 | const auto data{ctx.ReadBuffer()}; | ||
| 1391 | const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; | ||
| 1392 | |||
| 1393 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 1394 | |||
| 1395 | if (offset > backing.GetSize()) { | ||
| 1396 | LOG_ERROR(Service_AM, | ||
| 1397 | "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", | ||
| 1398 | backing.GetSize(), size, offset); | ||
| 1399 | |||
| 1400 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1401 | rb.Push(AM::ResultInvalidOffset); | ||
| 1402 | return; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | std::memcpy(backing.GetData().data() + offset, data.data(), size); | ||
| 1406 | |||
| 1407 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1408 | rb.Push(ResultSuccess); | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | void IStorageAccessor::Read(HLERequestContext& ctx) { | ||
| 1412 | IPC::RequestParser rp{ctx}; | ||
| 1413 | |||
| 1414 | const u64 offset{rp.Pop<u64>()}; | ||
| 1415 | const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; | ||
| 1416 | |||
| 1417 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | ||
| 1418 | |||
| 1419 | if (offset > backing.GetSize()) { | ||
| 1420 | LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", | ||
| 1421 | backing.GetSize(), size, offset); | ||
| 1422 | |||
| 1423 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1424 | rb.Push(AM::ResultInvalidOffset); | ||
| 1425 | return; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | ctx.WriteBuffer(backing.GetData().data() + offset, size); | ||
| 1429 | |||
| 1430 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1431 | rb.Push(ResultSuccess); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) | ||
| 1435 | : ServiceFramework{system_, "ILibraryAppletCreator"} { | ||
| 1436 | static const FunctionInfo functions[] = { | ||
| 1437 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, | ||
| 1438 | {1, nullptr, "TerminateAllLibraryApplets"}, | ||
| 1439 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, | ||
| 1440 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, | ||
| 1441 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, | ||
| 1442 | {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, | ||
| 1443 | }; | ||
| 1444 | RegisterHandlers(functions); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | ILibraryAppletCreator::~ILibraryAppletCreator() = default; | ||
| 1448 | |||
| 1449 | void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { | ||
| 1450 | IPC::RequestParser rp{ctx}; | ||
| 1451 | |||
| 1452 | const auto applet_id = rp.PopRaw<Applets::AppletId>(); | ||
| 1453 | const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>(); | ||
| 1454 | |||
| 1455 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 1456 | applet_mode); | ||
| 1457 | |||
| 1458 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 1459 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 1460 | |||
| 1461 | if (applet == nullptr) { | ||
| 1462 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 1463 | |||
| 1464 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1465 | rb.Push(ResultUnknown); | ||
| 1466 | return; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1470 | |||
| 1471 | rb.Push(ResultSuccess); | ||
| 1472 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { | ||
| 1476 | IPC::RequestParser rp{ctx}; | ||
| 1477 | |||
| 1478 | const s64 size{rp.Pop<s64>()}; | ||
| 1479 | |||
| 1480 | LOG_DEBUG(Service_AM, "called, size={}", size); | ||
| 1481 | |||
| 1482 | if (size <= 0) { | ||
| 1483 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1484 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1485 | rb.Push(ResultUnknown); | ||
| 1486 | return; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | std::vector<u8> buffer(size); | ||
| 1490 | |||
| 1491 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1492 | rb.Push(ResultSuccess); | ||
| 1493 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { | ||
| 1497 | IPC::RequestParser rp{ctx}; | ||
| 1498 | |||
| 1499 | struct Parameters { | ||
| 1500 | u8 permissions; | ||
| 1501 | s64 size; | ||
| 1502 | }; | ||
| 1503 | |||
| 1504 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1505 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 1506 | |||
| 1507 | LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, | ||
| 1508 | parameters.size, handle); | ||
| 1509 | |||
| 1510 | if (parameters.size <= 0) { | ||
| 1511 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1513 | rb.Push(ResultUnknown); | ||
| 1514 | return; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 1518 | |||
| 1519 | if (transfer_mem.IsNull()) { | ||
| 1520 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 1521 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1522 | rb.Push(ResultUnknown); | ||
| 1523 | return; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 1527 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 1528 | |||
| 1529 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1530 | rb.Push(ResultSuccess); | ||
| 1531 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | ||
| 1535 | IPC::RequestParser rp{ctx}; | ||
| 1536 | |||
| 1537 | const s64 size{rp.Pop<s64>()}; | ||
| 1538 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 1539 | |||
| 1540 | LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); | ||
| 1541 | |||
| 1542 | if (size <= 0) { | ||
| 1543 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 1544 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1545 | rb.Push(ResultUnknown); | ||
| 1546 | return; | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 1550 | |||
| 1551 | if (transfer_mem.IsNull()) { | ||
| 1552 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 1553 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1554 | rb.Push(ResultUnknown); | ||
| 1555 | return; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | std::vector<u8> memory(transfer_mem->GetSize()); | ||
| 1559 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); | ||
| 1560 | |||
| 1561 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1562 | rb.Push(ResultSuccess); | ||
| 1563 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) | ||
| 1567 | : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { | ||
| 1568 | // clang-format off | ||
| 1569 | static const FunctionInfo functions[] = { | ||
| 1570 | {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, | ||
| 1571 | {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, | ||
| 1572 | {2, nullptr, "PopInteractiveInData"}, | ||
| 1573 | {3, nullptr, "PushInteractiveOutData"}, | ||
| 1574 | {5, nullptr, "GetPopInDataEvent"}, | ||
| 1575 | {6, nullptr, "GetPopInteractiveInDataEvent"}, | ||
| 1576 | {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, | ||
| 1577 | {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, | ||
| 1578 | {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, | ||
| 1579 | {13, nullptr, "CanUseApplicationCore"}, | ||
| 1580 | {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, | ||
| 1581 | {15, nullptr, "GetMainAppletApplicationControlProperty"}, | ||
| 1582 | {16, nullptr, "GetMainAppletStorageId"}, | ||
| 1583 | {17, nullptr, "GetCallerAppletIdentityInfoStack"}, | ||
| 1584 | {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, | ||
| 1585 | {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"}, | ||
| 1586 | {20, nullptr, "PopExtraStorage"}, | ||
| 1587 | {25, nullptr, "GetPopExtraStorageEvent"}, | ||
| 1588 | {30, nullptr, "UnpopInData"}, | ||
| 1589 | {31, nullptr, "UnpopExtraStorage"}, | ||
| 1590 | {40, nullptr, "GetIndirectLayerProducerHandle"}, | ||
| 1591 | {50, nullptr, "ReportVisibleError"}, | ||
| 1592 | {51, nullptr, "ReportVisibleErrorWithErrorContext"}, | ||
| 1593 | {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, | ||
| 1594 | {70, nullptr, "GetCurrentApplicationId"}, | ||
| 1595 | {80, nullptr, "RequestExitToSelf"}, | ||
| 1596 | {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, | ||
| 1597 | {100, nullptr, "CreateGameMovieTrimmer"}, | ||
| 1598 | {101, nullptr, "ReserveResourceForMovieOperation"}, | ||
| 1599 | {102, nullptr, "UnreserveResourceForMovieOperation"}, | ||
| 1600 | {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"}, | ||
| 1601 | {120, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 1602 | {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, | ||
| 1603 | {140, nullptr, "SetApplicationMemoryReservation"}, | ||
| 1604 | {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, | ||
| 1605 | }; | ||
| 1606 | // clang-format on | ||
| 1607 | RegisterHandlers(functions); | ||
| 1608 | |||
| 1609 | switch (system.GetAppletManager().GetCurrentAppletId()) { | ||
| 1610 | case Applets::AppletId::Cabinet: | ||
| 1611 | PushInShowCabinetData(); | ||
| 1612 | break; | ||
| 1613 | case Applets::AppletId::MiiEdit: | ||
| 1614 | PushInShowMiiEditData(); | ||
| 1615 | break; | ||
| 1616 | case Applets::AppletId::PhotoViewer: | ||
| 1617 | PushInShowAlbum(); | ||
| 1618 | break; | ||
| 1619 | case Applets::AppletId::SoftwareKeyboard: | ||
| 1620 | PushInShowSoftwareKeyboard(); | ||
| 1621 | break; | ||
| 1622 | case Applets::AppletId::Controller: | ||
| 1623 | PushInShowController(); | ||
| 1624 | break; | ||
| 1625 | default: | ||
| 1626 | break; | ||
| 1627 | } | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | ||
| 1631 | void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { | ||
| 1632 | LOG_INFO(Service_AM, "called"); | ||
| 1633 | |||
| 1634 | if (queue_data.empty()) { | ||
| 1635 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1636 | rb.Push(ResultNoDataInChannel); | ||
| 1637 | return; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | auto data = queue_data.front(); | ||
| 1641 | queue_data.pop_front(); | ||
| 1642 | |||
| 1643 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 1644 | rb.Push(ResultSuccess); | ||
| 1645 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { | ||
| 1649 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1650 | |||
| 1651 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1652 | rb.Push(ResultSuccess); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { | ||
| 1656 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1657 | |||
| 1658 | system.Exit(); | ||
| 1659 | |||
| 1660 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1661 | rb.Push(ResultSuccess); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { | ||
| 1665 | struct LibraryAppletInfo { | ||
| 1666 | Applets::AppletId applet_id; | ||
| 1667 | Applets::LibraryAppletMode library_applet_mode; | ||
| 1668 | }; | ||
| 1669 | |||
| 1670 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1671 | |||
| 1672 | const LibraryAppletInfo applet_info{ | ||
| 1673 | .applet_id = system.GetAppletManager().GetCurrentAppletId(), | ||
| 1674 | .library_applet_mode = Applets::LibraryAppletMode::AllForeground, | ||
| 1675 | }; | ||
| 1676 | |||
| 1677 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1678 | rb.Push(ResultSuccess); | ||
| 1679 | rb.PushRaw(applet_info); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 1683 | struct AppletIdentityInfo { | ||
| 1684 | Applets::AppletId applet_id; | ||
| 1685 | INSERT_PADDING_BYTES(0x4); | ||
| 1686 | u64 application_id; | ||
| 1687 | }; | ||
| 1688 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 1689 | |||
| 1690 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1691 | |||
| 1692 | const AppletIdentityInfo applet_info{ | ||
| 1693 | .applet_id = Applets::AppletId::QLaunch, | ||
| 1694 | .application_id = 0x0100000000001000ull, | ||
| 1695 | }; | ||
| 1696 | |||
| 1697 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1698 | rb.Push(ResultSuccess); | ||
| 1699 | rb.PushRaw(applet_info); | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 1703 | struct AppletIdentityInfo { | ||
| 1704 | Applets::AppletId applet_id; | ||
| 1705 | INSERT_PADDING_BYTES(0x4); | ||
| 1706 | u64 application_id; | ||
| 1707 | }; | ||
| 1708 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 1709 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1710 | |||
| 1711 | const AppletIdentityInfo applet_info{ | ||
| 1712 | .applet_id = Applets::AppletId::QLaunch, | ||
| 1713 | .application_id = 0x0100000000001000ull, | ||
| 1714 | }; | ||
| 1715 | |||
| 1716 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1717 | rb.Push(ResultSuccess); | ||
| 1718 | rb.PushRaw(applet_info); | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { | ||
| 1722 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1723 | |||
| 1724 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1725 | rb.Push(ResultSuccess); | ||
| 1726 | rb.Push<u32>(0); | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { | ||
| 1730 | const Service::Account::ProfileManager manager{}; | ||
| 1731 | bool is_empty{true}; | ||
| 1732 | s32 user_count{-1}; | ||
| 1733 | |||
| 1734 | LOG_INFO(Service_AM, "called"); | ||
| 1735 | |||
| 1736 | if (manager.GetUserCount() > 0) { | ||
| 1737 | is_empty = false; | ||
| 1738 | user_count = static_cast<s32>(manager.GetUserCount()); | ||
| 1739 | ctx.WriteBuffer(manager.GetAllUsers()); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1743 | rb.Push(ResultSuccess); | ||
| 1744 | rb.Push<u8>(is_empty); | ||
| 1745 | rb.Push(user_count); | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) { | ||
| 1749 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1750 | |||
| 1751 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1752 | rb.Push(ResultSuccess); | ||
| 1753 | rb.Push<u8>(0); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | void ILibraryAppletSelfAccessor::PushInShowAlbum() { | ||
| 1757 | const Applets::CommonArguments arguments{ | ||
| 1758 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1759 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1760 | .library_version = 1, | ||
| 1761 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1762 | .play_startup_sound = true, | ||
| 1763 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1764 | }; | ||
| 1765 | |||
| 1766 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1767 | std::vector<u8> settings_data{2}; | ||
| 1768 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1769 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1770 | queue_data.emplace_back(std::move(settings_data)); | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | void ILibraryAppletSelfAccessor::PushInShowController() { | ||
| 1774 | const Applets::CommonArguments common_args = { | ||
| 1775 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1776 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1777 | .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8), | ||
| 1778 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1779 | .play_startup_sound = true, | ||
| 1780 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1781 | }; | ||
| 1782 | |||
| 1783 | Applets::ControllerSupportArgNew user_args = { | ||
| 1784 | .header = {.player_count_min = 1, | ||
| 1785 | .player_count_max = 4, | ||
| 1786 | .enable_take_over_connection = true, | ||
| 1787 | .enable_left_justify = false, | ||
| 1788 | .enable_permit_joy_dual = true, | ||
| 1789 | .enable_single_mode = false, | ||
| 1790 | .enable_identification_color = false}, | ||
| 1791 | .identification_colors = {}, | ||
| 1792 | .enable_explain_text = false, | ||
| 1793 | .explain_text = {}, | ||
| 1794 | }; | ||
| 1795 | |||
| 1796 | Applets::ControllerSupportArgPrivate private_args = { | ||
| 1797 | .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate), | ||
| 1798 | .arg_size = sizeof(Applets::ControllerSupportArgNew), | ||
| 1799 | .is_home_menu = true, | ||
| 1800 | .flag_1 = true, | ||
| 1801 | .mode = Applets::ControllerSupportMode::ShowControllerSupport, | ||
| 1802 | .caller = Applets::ControllerSupportCaller:: | ||
| 1803 | Application, // switchbrew: Always zero except with | ||
| 1804 | // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, | ||
| 1805 | // which sets this to the input param | ||
| 1806 | .style_set = Core::HID::NpadStyleSet::None, | ||
| 1807 | .joy_hold_type = 0, | ||
| 1808 | }; | ||
| 1809 | std::vector<u8> common_args_data(sizeof(common_args)); | ||
| 1810 | std::vector<u8> private_args_data(sizeof(private_args)); | ||
| 1811 | std::vector<u8> user_args_data(sizeof(user_args)); | ||
| 1812 | |||
| 1813 | std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); | ||
| 1814 | std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); | ||
| 1815 | std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); | ||
| 1816 | |||
| 1817 | queue_data.emplace_back(std::move(common_args_data)); | ||
| 1818 | queue_data.emplace_back(std::move(private_args_data)); | ||
| 1819 | queue_data.emplace_back(std::move(user_args_data)); | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | void ILibraryAppletSelfAccessor::PushInShowCabinetData() { | ||
| 1823 | const Applets::CommonArguments arguments{ | ||
| 1824 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1825 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1826 | .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1), | ||
| 1827 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1828 | .play_startup_sound = true, | ||
| 1829 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1830 | }; | ||
| 1831 | |||
| 1832 | const Applets::StartParamForAmiiboSettings amiibo_settings{ | ||
| 1833 | .param_1 = 0, | ||
| 1834 | .applet_mode = system.GetAppletManager().GetCabinetMode(), | ||
| 1835 | .flags = Applets::CabinetFlags::None, | ||
| 1836 | .amiibo_settings_1 = 0, | ||
| 1837 | .device_handle = 0, | ||
| 1838 | .tag_info{}, | ||
| 1839 | .register_info{}, | ||
| 1840 | .amiibo_settings_3{}, | ||
| 1841 | }; | ||
| 1842 | |||
| 1843 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1844 | std::vector<u8> settings_data(sizeof(amiibo_settings)); | ||
| 1845 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1846 | std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); | ||
| 1847 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1848 | queue_data.emplace_back(std::move(settings_data)); | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { | ||
| 1852 | struct MiiEditV3 { | ||
| 1853 | Applets::MiiEditAppletInputCommon common; | ||
| 1854 | Applets::MiiEditAppletInputV3 input; | ||
| 1855 | }; | ||
| 1856 | static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size."); | ||
| 1857 | |||
| 1858 | MiiEditV3 mii_arguments{ | ||
| 1859 | .common = | ||
| 1860 | { | ||
| 1861 | .version = Applets::MiiEditAppletVersion::Version3, | ||
| 1862 | .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit, | ||
| 1863 | }, | ||
| 1864 | .input{}, | ||
| 1865 | }; | ||
| 1866 | |||
| 1867 | std::vector<u8> argument_data(sizeof(mii_arguments)); | ||
| 1868 | std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); | ||
| 1869 | |||
| 1870 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() { | ||
| 1874 | const Applets::CommonArguments arguments{ | ||
| 1875 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1876 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1877 | .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301), | ||
| 1878 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1879 | .play_startup_sound = true, | ||
| 1880 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1881 | }; | ||
| 1882 | |||
| 1883 | std::vector<char16_t> initial_string(0); | ||
| 1884 | |||
| 1885 | const Applets::SwkbdConfigCommon swkbd_config{ | ||
| 1886 | .type = Applets::SwkbdType::Qwerty, | ||
| 1887 | .ok_text{}, | ||
| 1888 | .left_optional_symbol_key{}, | ||
| 1889 | .right_optional_symbol_key{}, | ||
| 1890 | .use_prediction = false, | ||
| 1891 | .key_disable_flags{}, | ||
| 1892 | .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start, | ||
| 1893 | .header_text{}, | ||
| 1894 | .sub_text{}, | ||
| 1895 | .guide_text{}, | ||
| 1896 | .max_text_length = 500, | ||
| 1897 | .min_text_length = 0, | ||
| 1898 | .password_mode = Applets::SwkbdPasswordMode::Disabled, | ||
| 1899 | .text_draw_type = Applets::SwkbdTextDrawType::Box, | ||
| 1900 | .enable_return_button = true, | ||
| 1901 | .use_utf8 = false, | ||
| 1902 | .use_blur_background = true, | ||
| 1903 | .initial_string_offset{}, | ||
| 1904 | .initial_string_length = static_cast<u32>(initial_string.size()), | ||
| 1905 | .user_dictionary_offset{}, | ||
| 1906 | .user_dictionary_entries{}, | ||
| 1907 | .use_text_check = false, | ||
| 1908 | }; | ||
| 1909 | |||
| 1910 | Applets::SwkbdConfigNew swkbd_config_new{}; | ||
| 1911 | |||
| 1912 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1913 | std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new)); | ||
| 1914 | std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 1915 | |||
| 1916 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1917 | std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config)); | ||
| 1918 | std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new, | ||
| 1919 | sizeof(Applets::SwkbdConfigNew)); | ||
| 1920 | std::memcpy(work_buffer.data(), initial_string.data(), | ||
| 1921 | swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 1922 | |||
| 1923 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1924 | queue_data.emplace_back(std::move(swkbd_data)); | ||
| 1925 | queue_data.emplace_back(std::move(work_buffer)); | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) | ||
| 1929 | : ServiceFramework{system_, "IAppletCommonFunctions"} { | ||
| 1930 | // clang-format off | ||
| 1931 | static const FunctionInfo functions[] = { | ||
| 1932 | {0, nullptr, "SetTerminateResult"}, | ||
| 1933 | {10, nullptr, "ReadThemeStorage"}, | ||
| 1934 | {11, nullptr, "WriteThemeStorage"}, | ||
| 1935 | {20, nullptr, "PushToAppletBoundChannel"}, | ||
| 1936 | {21, nullptr, "TryPopFromAppletBoundChannel"}, | ||
| 1937 | {40, nullptr, "GetDisplayLogicalResolution"}, | ||
| 1938 | {42, nullptr, "SetDisplayMagnification"}, | ||
| 1939 | {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, | ||
| 1940 | {51, nullptr, "GetHomeButtonDoubleClickEnabled"}, | ||
| 1941 | {52, nullptr, "IsHomeButtonShortPressedBlocked"}, | ||
| 1942 | {60, nullptr, "IsVrModeCurtainRequired"}, | ||
| 1943 | {61, nullptr, "IsSleepRequiredByHighTemperature"}, | ||
| 1944 | {62, nullptr, "IsSleepRequiredByLowBattery"}, | ||
| 1945 | {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"}, | ||
| 1946 | {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, | ||
| 1947 | {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, | ||
| 1948 | {90, nullptr, "OpenNamedChannelAsParent"}, | ||
| 1949 | {91, nullptr, "OpenNamedChannelAsChild"}, | ||
| 1950 | {100, nullptr, "SetApplicationCoreUsageMode"}, | ||
| 1951 | }; | ||
| 1952 | // clang-format on | ||
| 1953 | |||
| 1954 | RegisterHandlers(functions); | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | IAppletCommonFunctions::~IAppletCommonFunctions() = default; | ||
| 1958 | |||
| 1959 | void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { | ||
| 1960 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1961 | |||
| 1962 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1963 | rb.Push(ResultSuccess); | ||
| 1964 | } | ||
| 1965 | |||
| 1966 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | ||
| 1967 | : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, | ||
| 1968 | "IApplicationFunctions"} { | ||
| 1969 | // clang-format off | ||
| 1970 | static const FunctionInfo functions[] = { | ||
| 1971 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | ||
| 1972 | {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, | ||
| 1973 | {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, | ||
| 1974 | {12, nullptr, "CreateApplicationAndRequestToStart"}, | ||
| 1975 | {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, | ||
| 1976 | {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, | ||
| 1977 | {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, | ||
| 1978 | {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, | ||
| 1979 | {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, | ||
| 1980 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | ||
| 1981 | {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"}, | ||
| 1982 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 1983 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | ||
| 1984 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | ||
| 1985 | {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, | ||
| 1986 | {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, | ||
| 1987 | {29, nullptr, "GetCacheStorageMax"}, | ||
| 1988 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | ||
| 1989 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | ||
| 1990 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | ||
| 1991 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, | ||
| 1992 | {34, nullptr, "SelectApplicationLicense"}, | ||
| 1993 | {35, nullptr, "GetDeviceSaveDataSizeMax"}, | ||
| 1994 | {36, nullptr, "GetLimitedApplicationLicense"}, | ||
| 1995 | {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, | ||
| 1996 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 1997 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, | ||
| 1998 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, | ||
| 1999 | {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"}, | ||
| 2000 | {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, | ||
| 2001 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 2002 | {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, | ||
| 2003 | {70, nullptr, "RequestToShutdown"}, | ||
| 2004 | {71, nullptr, "RequestToReboot"}, | ||
| 2005 | {72, nullptr, "RequestToSleep"}, | ||
| 2006 | {80, nullptr, "ExitAndRequestToShowThanksMessage"}, | ||
| 2007 | {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, | ||
| 2008 | {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, | ||
| 2009 | {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, | ||
| 2010 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, | ||
| 2011 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, | ||
| 2012 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, | ||
| 2013 | {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, | ||
| 2014 | {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, | ||
| 2015 | {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, | ||
| 2016 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | ||
| 2017 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 2018 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | ||
| 2019 | {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, | ||
| 2020 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | ||
| 2021 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, | ||
| 2022 | {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, | ||
| 2023 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, | ||
| 2024 | {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, | ||
| 2025 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | ||
| 2026 | {180, nullptr, "GetLaunchRequiredVersion"}, | ||
| 2027 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | ||
| 2028 | {190, nullptr, "SendServerMaintenanceOverlayNotification"}, | ||
| 2029 | {200, nullptr, "GetLastApplicationExitReason"}, | ||
| 2030 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | ||
| 2031 | {1000, nullptr, "CreateMovieMaker"}, | ||
| 2032 | {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, | ||
| 2033 | }; | ||
| 2034 | // clang-format on | ||
| 2035 | |||
| 2036 | RegisterHandlers(functions); | ||
| 2037 | |||
| 2038 | gpu_error_detected_event = | ||
| 2039 | service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent"); | ||
| 2040 | friend_invitation_storage_channel_event = | ||
| 2041 | service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent"); | ||
| 2042 | notification_storage_channel_event = | ||
| 2043 | service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent"); | ||
| 2044 | health_warning_disappeared_system_event = | ||
| 2045 | service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent"); | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | IApplicationFunctions::~IApplicationFunctions() { | ||
| 2049 | service_context.CloseEvent(gpu_error_detected_event); | ||
| 2050 | service_context.CloseEvent(friend_invitation_storage_channel_event); | ||
| 2051 | service_context.CloseEvent(notification_storage_channel_event); | ||
| 2052 | service_context.CloseEvent(health_warning_disappeared_system_event); | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { | ||
| 2056 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2057 | |||
| 2058 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2059 | rb.Push(ResultSuccess); | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { | ||
| 2063 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2064 | |||
| 2065 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2066 | rb.Push(ResultSuccess); | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { | ||
| 2070 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2071 | |||
| 2072 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2073 | rb.Push(ResultSuccess); | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { | ||
| 2077 | IPC::RequestParser rp{ctx}; | ||
| 2078 | const auto is_visible = rp.Pop<bool>(); | ||
| 2079 | |||
| 2080 | LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible); | ||
| 2081 | |||
| 2082 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2083 | rb.Push(ResultSuccess); | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 2087 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2088 | |||
| 2089 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2090 | rb.Push(ResultSuccess); | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 2094 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2095 | |||
| 2096 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2097 | rb.Push(ResultSuccess); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { | ||
| 2101 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2102 | |||
| 2103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2104 | rb.Push(ResultSuccess); | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { | ||
| 2108 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2109 | |||
| 2110 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2111 | rb.Push(ResultSuccess); | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { | ||
| 2115 | IPC::RequestParser rp{ctx}; | ||
| 2116 | const auto kind = rp.PopEnum<LaunchParameterKind>(); | ||
| 2117 | |||
| 2118 | LOG_INFO(Service_AM, "called, kind={:08X}", kind); | ||
| 2119 | |||
| 2120 | if (kind == LaunchParameterKind::UserChannel) { | ||
| 2121 | auto channel = system.GetUserChannel(); | ||
| 2122 | if (channel.empty()) { | ||
| 2123 | LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!"); | ||
| 2124 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2125 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2126 | return; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | auto data = channel.back(); | ||
| 2130 | channel.pop_back(); | ||
| 2131 | |||
| 2132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2133 | rb.Push(ResultSuccess); | ||
| 2134 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 2135 | } else if (kind == LaunchParameterKind::AccountPreselectedUser && | ||
| 2136 | !launch_popped_account_preselect) { | ||
| 2137 | // TODO: Verify this is hw-accurate | ||
| 2138 | LaunchParameterAccountPreselectedUser params{}; | ||
| 2139 | |||
| 2140 | params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC; | ||
| 2141 | params.is_account_selected = 1; | ||
| 2142 | |||
| 2143 | Account::ProfileManager profile_manager{}; | ||
| 2144 | const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user)); | ||
| 2145 | ASSERT(uuid.has_value() && uuid->IsValid()); | ||
| 2146 | params.current_user = *uuid; | ||
| 2147 | |||
| 2148 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2149 | rb.Push(ResultSuccess); | ||
| 2150 | |||
| 2151 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | ||
| 2152 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | ||
| 2153 | |||
| 2154 | rb.PushIpcInterface<IStorage>(system, std::move(buffer)); | ||
| 2155 | launch_popped_account_preselect = true; | ||
| 2156 | } else { | ||
| 2157 | LOG_ERROR(Service_AM, "Unknown launch parameter kind."); | ||
| 2158 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2159 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2160 | } | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { | ||
| 2164 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2165 | |||
| 2166 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2167 | rb.Push(ResultSuccess); | ||
| 2168 | } | ||
| 2169 | |||
| 2170 | void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | ||
| 2171 | IPC::RequestParser rp{ctx}; | ||
| 2172 | u128 user_id = rp.PopRaw<u128>(); | ||
| 2173 | |||
| 2174 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); | ||
| 2175 | |||
| 2176 | FileSys::SaveDataAttribute attribute{}; | ||
| 2177 | attribute.title_id = system.GetApplicationProcessProgramID(); | ||
| 2178 | attribute.user_id = user_id; | ||
| 2179 | attribute.type = FileSys::SaveDataType::SaveData; | ||
| 2180 | |||
| 2181 | FileSys::VirtualDir save_data{}; | ||
| 2182 | const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( | ||
| 2183 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); | ||
| 2184 | |||
| 2185 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2186 | rb.Push(res); | ||
| 2187 | rb.Push<u64>(0); | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { | ||
| 2191 | // Takes an input u32 Result, no output. | ||
| 2192 | // For example, in some cases official apps use this with error 0x2A2 then | ||
| 2193 | // uses svcBreak. | ||
| 2194 | |||
| 2195 | IPC::RequestParser rp{ctx}; | ||
| 2196 | u32 result = rp.Pop<u32>(); | ||
| 2197 | LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); | ||
| 2198 | |||
| 2199 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2200 | rb.Push(ResultSuccess); | ||
| 2201 | } | ||
| 2202 | |||
| 2203 | void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { | ||
| 2204 | LOG_DEBUG(Service_AM, "called"); | ||
| 2205 | |||
| 2206 | std::array<u8, 0x10> version_string{}; | ||
| 2207 | |||
| 2208 | const auto res = [this] { | ||
| 2209 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 2210 | |||
| 2211 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 2212 | system.GetContentProvider()}; | ||
| 2213 | auto metadata = pm.GetControlMetadata(); | ||
| 2214 | if (metadata.first != nullptr) { | ||
| 2215 | return metadata; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 2219 | system.GetFileSystemController(), | ||
| 2220 | system.GetContentProvider()}; | ||
| 2221 | return pm_update.GetControlMetadata(); | ||
| 2222 | }(); | ||
| 2223 | |||
| 2224 | if (res.first != nullptr) { | ||
| 2225 | const auto& version = res.first->GetVersionString(); | ||
| 2226 | std::copy(version.begin(), version.end(), version_string.begin()); | ||
| 2227 | } else { | ||
| 2228 | static constexpr char default_version[]{"1.0.0"}; | ||
| 2229 | std::memcpy(version_string.data(), default_version, sizeof(default_version)); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2233 | rb.Push(ResultSuccess); | ||
| 2234 | rb.PushRaw(version_string); | ||
| 2235 | } | ||
| 2236 | |||
| 2237 | void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | ||
| 2238 | // TODO(bunnei): This should be configurable | ||
| 2239 | LOG_DEBUG(Service_AM, "called"); | ||
| 2240 | |||
| 2241 | // Get supported languages from NACP, if possible | ||
| 2242 | // Default to 0 (all languages supported) | ||
| 2243 | u32 supported_languages = 0; | ||
| 2244 | |||
| 2245 | const auto res = [this] { | ||
| 2246 | const auto title_id = system.GetApplicationProcessProgramID(); | ||
| 2247 | |||
| 2248 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 2249 | system.GetContentProvider()}; | ||
| 2250 | auto metadata = pm.GetControlMetadata(); | ||
| 2251 | if (metadata.first != nullptr) { | ||
| 2252 | return metadata; | ||
| 2253 | } | ||
| 2254 | |||
| 2255 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | ||
| 2256 | system.GetFileSystemController(), | ||
| 2257 | system.GetContentProvider()}; | ||
| 2258 | return pm_update.GetControlMetadata(); | ||
| 2259 | }(); | ||
| 2260 | |||
| 2261 | if (res.first != nullptr) { | ||
| 2262 | supported_languages = res.first->GetSupportedLanguages(); | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | // Call IApplicationManagerInterface implementation. | ||
| 2266 | auto& service_manager = system.ServiceManager(); | ||
| 2267 | auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); | ||
| 2268 | auto app_man = ns_am2->GetApplicationManagerInterface(); | ||
| 2269 | |||
| 2270 | // Get desired application language | ||
| 2271 | u8 desired_language{}; | ||
| 2272 | const auto res_lang = | ||
| 2273 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 2274 | if (res_lang != ResultSuccess) { | ||
| 2275 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2276 | rb.Push(res_lang); | ||
| 2277 | return; | ||
| 2278 | } | ||
| 2279 | |||
| 2280 | // Convert to settings language code. | ||
| 2281 | u64 language_code{}; | ||
| 2282 | const auto res_code = | ||
| 2283 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 2284 | if (res_code != ResultSuccess) { | ||
| 2285 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2286 | rb.Push(res_code); | ||
| 2287 | return; | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); | ||
| 2291 | |||
| 2292 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2293 | rb.Push(ResultSuccess); | ||
| 2294 | rb.Push(language_code); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | ||
| 2298 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2299 | |||
| 2300 | constexpr bool gameplay_recording_supported = false; | ||
| 2301 | |||
| 2302 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2303 | rb.Push(ResultSuccess); | ||
| 2304 | rb.Push(gameplay_recording_supported); | ||
| 2305 | } | ||
| 2306 | |||
| 2307 | void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { | ||
| 2308 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2309 | |||
| 2310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2311 | rb.Push(ResultSuccess); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { | ||
| 2315 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2316 | |||
| 2317 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2318 | rb.Push(ResultSuccess); | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { | ||
| 2322 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2323 | |||
| 2324 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2325 | rb.Push(ResultSuccess); | ||
| 2326 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { | ||
| 2330 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2331 | |||
| 2332 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2333 | rb.Push(ResultSuccess); | ||
| 2334 | |||
| 2335 | // Returns a 128-bit UUID | ||
| 2336 | rb.Push<u64>(0); | ||
| 2337 | rb.Push<u64>(0); | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { | ||
| 2341 | struct Parameters { | ||
| 2342 | FileSys::SaveDataType type; | ||
| 2343 | u128 user_id; | ||
| 2344 | u64 new_normal_size; | ||
| 2345 | u64 new_journal_size; | ||
| 2346 | }; | ||
| 2347 | static_assert(sizeof(Parameters) == 40); | ||
| 2348 | |||
| 2349 | IPC::RequestParser rp{ctx}; | ||
| 2350 | const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>(); | ||
| 2351 | |||
| 2352 | LOG_DEBUG(Service_AM, | ||
| 2353 | "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, " | ||
| 2354 | "new_journal={:016X}", | ||
| 2355 | static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); | ||
| 2356 | |||
| 2357 | system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( | ||
| 2358 | type, system.GetApplicationProcessProgramID(), user_id, | ||
| 2359 | {new_normal_size, new_journal_size}); | ||
| 2360 | |||
| 2361 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 2362 | rb.Push(ResultSuccess); | ||
| 2363 | |||
| 2364 | // The following value is used upon failure to help the system recover. | ||
| 2365 | // Since we always succeed, this should be 0. | ||
| 2366 | rb.Push<u64>(0); | ||
| 2367 | } | ||
| 2368 | |||
| 2369 | void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { | ||
| 2370 | struct Parameters { | ||
| 2371 | FileSys::SaveDataType type; | ||
| 2372 | u128 user_id; | ||
| 2373 | }; | ||
| 2374 | static_assert(sizeof(Parameters) == 24); | ||
| 2375 | |||
| 2376 | IPC::RequestParser rp{ctx}; | ||
| 2377 | const auto [type, user_id] = rp.PopRaw<Parameters>(); | ||
| 2378 | |||
| 2379 | LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], | ||
| 2380 | user_id[0]); | ||
| 2381 | |||
| 2382 | const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( | ||
| 2383 | type, system.GetApplicationProcessProgramID(), user_id); | ||
| 2384 | |||
| 2385 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2386 | rb.Push(ResultSuccess); | ||
| 2387 | rb.Push(size.normal); | ||
| 2388 | rb.Push(size.journal); | ||
| 2389 | } | ||
| 2390 | |||
| 2391 | void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { | ||
| 2392 | struct InputParameters { | ||
| 2393 | u16 index; | ||
| 2394 | s64 size; | ||
| 2395 | s64 journal_size; | ||
| 2396 | }; | ||
| 2397 | static_assert(sizeof(InputParameters) == 24); | ||
| 2398 | |||
| 2399 | struct OutputParameters { | ||
| 2400 | u32 storage_target; | ||
| 2401 | u64 required_size; | ||
| 2402 | }; | ||
| 2403 | static_assert(sizeof(OutputParameters) == 16); | ||
| 2404 | |||
| 2405 | IPC::RequestParser rp{ctx}; | ||
| 2406 | const auto params = rp.PopRaw<InputParameters>(); | ||
| 2407 | |||
| 2408 | LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", | ||
| 2409 | params.index, params.size, params.journal_size); | ||
| 2410 | |||
| 2411 | const OutputParameters resp{ | ||
| 2412 | .storage_target = 1, | ||
| 2413 | .required_size = 0, | ||
| 2414 | }; | ||
| 2415 | |||
| 2416 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2417 | rb.Push(ResultSuccess); | ||
| 2418 | rb.PushRaw(resp); | ||
| 2419 | } | ||
| 2420 | |||
| 2421 | void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { | ||
| 2422 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2423 | |||
| 2424 | constexpr u64 size_max_normal = 0xFFFFFFF; | ||
| 2425 | constexpr u64 size_max_journal = 0xFFFFFFF; | ||
| 2426 | |||
| 2427 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2428 | rb.Push(ResultSuccess); | ||
| 2429 | rb.Push(size_max_normal); | ||
| 2430 | rb.Push(size_max_journal); | ||
| 2431 | } | ||
| 2432 | |||
| 2433 | void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { | ||
| 2434 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2435 | |||
| 2436 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2437 | rb.Push(ResultSuccess); | ||
| 2438 | rb.Push<u32>(0); | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { | ||
| 2442 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2443 | |||
| 2444 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2445 | rb.Push(ResultSuccess); | ||
| 2446 | rb.Push<u32>(0); | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { | ||
| 2450 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2451 | |||
| 2452 | IPC::RequestParser rp{ctx}; | ||
| 2453 | [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); | ||
| 2454 | [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); | ||
| 2455 | const auto program_index = rp.Pop<u64>(); | ||
| 2456 | |||
| 2457 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2458 | rb.Push(ResultSuccess); | ||
| 2459 | |||
| 2460 | system.ExecuteProgram(program_index); | ||
| 2461 | } | ||
| 2462 | |||
| 2463 | void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { | ||
| 2464 | LOG_DEBUG(Service_AM, "called"); | ||
| 2465 | |||
| 2466 | system.GetUserChannel().clear(); | ||
| 2467 | |||
| 2468 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2469 | rb.Push(ResultSuccess); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { | ||
| 2473 | LOG_DEBUG(Service_AM, "called"); | ||
| 2474 | |||
| 2475 | IPC::RequestParser rp{ctx}; | ||
| 2476 | const auto storage = rp.PopIpcInterface<IStorage>().lock(); | ||
| 2477 | if (storage) { | ||
| 2478 | system.GetUserChannel().push_back(storage->GetData()); | ||
| 2479 | } | ||
| 2480 | |||
| 2481 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2482 | rb.Push(ResultSuccess); | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { | ||
| 2486 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2487 | |||
| 2488 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2489 | rb.Push(ResultSuccess); | ||
| 2490 | rb.Push<s32>(previous_program_index); | ||
| 2491 | } | ||
| 2492 | |||
| 2493 | void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { | ||
| 2494 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2495 | |||
| 2496 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2497 | rb.Push(ResultSuccess); | ||
| 2498 | rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); | ||
| 2499 | } | ||
| 2500 | |||
| 2501 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 2502 | LOG_DEBUG(Service_AM, "called"); | ||
| 2503 | |||
| 2504 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2505 | rb.Push(ResultSuccess); | ||
| 2506 | rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); | ||
| 2507 | } | ||
| 2508 | |||
| 2509 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { | ||
| 2510 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 2511 | |||
| 2512 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2513 | rb.Push(AM::ResultNoDataInChannel); | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 2517 | LOG_DEBUG(Service_AM, "called"); | ||
| 2518 | |||
| 2519 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2520 | rb.Push(ResultSuccess); | ||
| 2521 | rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent()); | ||
| 2522 | } | ||
| 2523 | |||
| 2524 | void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { | ||
| 2525 | LOG_DEBUG(Service_AM, "called"); | ||
| 2526 | |||
| 2527 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2528 | rb.Push(ResultSuccess); | ||
| 2529 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { | ||
| 2533 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2534 | |||
| 2535 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2536 | rb.Push(ResultSuccess); | ||
| 2537 | } | ||
| 2538 | |||
| 2539 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 14 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { |
| 2540 | auto message_queue = std::make_shared<AppletMessageQueue>(system); | ||
| 2541 | auto server_manager = std::make_unique<ServerManager>(system); | 15 | auto server_manager = std::make_unique<ServerManager>(system); |
| 2542 | 16 | ||
| 2543 | server_manager->RegisterNamedService( | 17 | server_manager->RegisterNamedService("appletAE", |
| 2544 | "appletAE", std::make_shared<AppletAE>(nvnflinger, message_queue, system)); | 18 | std::make_shared<AppletAE>(nvnflinger, system)); |
| 2545 | server_manager->RegisterNamedService( | 19 | server_manager->RegisterNamedService("appletOE", |
| 2546 | "appletOE", std::make_shared<AppletOE>(nvnflinger, message_queue, system)); | 20 | std::make_shared<AppletOE>(nvnflinger, system)); |
| 2547 | server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system)); | 21 | server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system)); |
| 2548 | server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system)); | 22 | server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system)); |
| 2549 | server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system)); | 23 | server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system)); |
| 2550 | ServerManager::RunServer(std::move(server_manager)); | 24 | ServerManager::RunServer(std::move(server_manager)); |
| 2551 | } | 25 | } |
| 2552 | 26 | ||
| 2553 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | ||
| 2554 | : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system, | ||
| 2555 | "IHomeMenuFunctions"} { | ||
| 2556 | // clang-format off | ||
| 2557 | static const FunctionInfo functions[] = { | ||
| 2558 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, | ||
| 2559 | {11, nullptr, "LockForeground"}, | ||
| 2560 | {12, nullptr, "UnlockForeground"}, | ||
| 2561 | {20, nullptr, "PopFromGeneralChannel"}, | ||
| 2562 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, | ||
| 2563 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, | ||
| 2564 | {31, nullptr, "GetWriterLockAccessorEx"}, | ||
| 2565 | {40, nullptr, "IsSleepEnabled"}, | ||
| 2566 | {41, nullptr, "IsRebootEnabled"}, | ||
| 2567 | {50, nullptr, "LaunchSystemApplet"}, | ||
| 2568 | {51, nullptr, "LaunchStarter"}, | ||
| 2569 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, | ||
| 2570 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, | ||
| 2571 | {200, nullptr, "LaunchDevMenu"}, | ||
| 2572 | {1000, nullptr, "SetLastApplicationExitReason"}, | ||
| 2573 | }; | ||
| 2574 | // clang-format on | ||
| 2575 | |||
| 2576 | RegisterHandlers(functions); | ||
| 2577 | |||
| 2578 | pop_from_general_channel_event = | ||
| 2579 | service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent"); | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | IHomeMenuFunctions::~IHomeMenuFunctions() { | ||
| 2583 | service_context.CloseEvent(pop_from_general_channel_event); | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { | ||
| 2587 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2588 | |||
| 2589 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2590 | rb.Push(ResultSuccess); | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { | ||
| 2594 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2595 | |||
| 2596 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2597 | rb.Push(ResultSuccess); | ||
| 2598 | rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); | ||
| 2599 | } | ||
| 2600 | |||
| 2601 | IGlobalStateController::IGlobalStateController(Core::System& system_) | ||
| 2602 | : ServiceFramework{system_, "IGlobalStateController"} { | ||
| 2603 | // clang-format off | ||
| 2604 | static const FunctionInfo functions[] = { | ||
| 2605 | {0, nullptr, "RequestToEnterSleep"}, | ||
| 2606 | {1, nullptr, "EnterSleep"}, | ||
| 2607 | {2, nullptr, "StartSleepSequence"}, | ||
| 2608 | {3, nullptr, "StartShutdownSequence"}, | ||
| 2609 | {4, nullptr, "StartRebootSequence"}, | ||
| 2610 | {9, nullptr, "IsAutoPowerDownRequested"}, | ||
| 2611 | {10, nullptr, "LoadAndApplyIdlePolicySettings"}, | ||
| 2612 | {11, nullptr, "NotifyCecSettingsChanged"}, | ||
| 2613 | {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, | ||
| 2614 | {13, nullptr, "UpdateDefaultDisplayResolution"}, | ||
| 2615 | {14, nullptr, "ShouldSleepOnBoot"}, | ||
| 2616 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, | ||
| 2617 | {30, nullptr, "OpenCradleFirmwareUpdater"}, | ||
| 2618 | }; | ||
| 2619 | // clang-format on | ||
| 2620 | |||
| 2621 | RegisterHandlers(functions); | ||
| 2622 | } | ||
| 2623 | |||
| 2624 | IGlobalStateController::~IGlobalStateController() = default; | ||
| 2625 | |||
| 2626 | IApplicationCreator::IApplicationCreator(Core::System& system_) | ||
| 2627 | : ServiceFramework{system_, "IApplicationCreator"} { | ||
| 2628 | // clang-format off | ||
| 2629 | static const FunctionInfo functions[] = { | ||
| 2630 | {0, nullptr, "CreateApplication"}, | ||
| 2631 | {1, nullptr, "PopLaunchRequestedApplication"}, | ||
| 2632 | {10, nullptr, "CreateSystemApplication"}, | ||
| 2633 | {100, nullptr, "PopFloatingApplicationForDevelopment"}, | ||
| 2634 | }; | ||
| 2635 | // clang-format on | ||
| 2636 | |||
| 2637 | RegisterHandlers(functions); | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | IApplicationCreator::~IApplicationCreator() = default; | ||
| 2641 | |||
| 2642 | IProcessWindingController::IProcessWindingController(Core::System& system_) | ||
| 2643 | : ServiceFramework{system_, "IProcessWindingController"} { | ||
| 2644 | // clang-format off | ||
| 2645 | static const FunctionInfo functions[] = { | ||
| 2646 | {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, | ||
| 2647 | {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"}, | ||
| 2648 | {21, nullptr, "PushContext"}, | ||
| 2649 | {22, nullptr, "PopContext"}, | ||
| 2650 | {23, nullptr, "CancelWindingReservation"}, | ||
| 2651 | {30, nullptr, "WindAndDoReserved"}, | ||
| 2652 | {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, | ||
| 2653 | {41, nullptr, "ReserveToStartAndWait"}, | ||
| 2654 | }; | ||
| 2655 | // clang-format on | ||
| 2656 | |||
| 2657 | RegisterHandlers(functions); | ||
| 2658 | } | ||
| 2659 | |||
| 2660 | IProcessWindingController::~IProcessWindingController() = default; | ||
| 2661 | |||
| 2662 | void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { | ||
| 2663 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 2664 | |||
| 2665 | struct AppletProcessLaunchReason { | ||
| 2666 | u8 flag; | ||
| 2667 | INSERT_PADDING_BYTES(3); | ||
| 2668 | }; | ||
| 2669 | static_assert(sizeof(AppletProcessLaunchReason) == 0x4, | ||
| 2670 | "AppletProcessLaunchReason is an invalid size"); | ||
| 2671 | |||
| 2672 | AppletProcessLaunchReason reason{ | ||
| 2673 | .flag = 0, | ||
| 2674 | }; | ||
| 2675 | |||
| 2676 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2677 | rb.Push(ResultSuccess); | ||
| 2678 | rb.PushRaw(reason); | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { | ||
| 2682 | const auto applet_id = system.GetAppletManager().GetCurrentAppletId(); | ||
| 2683 | const auto applet_mode = Applets::LibraryAppletMode::AllForeground; | ||
| 2684 | |||
| 2685 | LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 2686 | applet_mode); | ||
| 2687 | |||
| 2688 | const auto& applet_manager{system.GetAppletManager()}; | ||
| 2689 | const auto applet = applet_manager.GetApplet(applet_id, applet_mode); | ||
| 2690 | |||
| 2691 | if (applet == nullptr) { | ||
| 2692 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 2693 | |||
| 2694 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 2695 | rb.Push(ResultUnknown); | ||
| 2696 | return; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 2700 | rb.Push(ResultSuccess); | ||
| 2701 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | } // namespace Service::AM | 27 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 905a71b9f..4a2d797bd 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -1,20 +1,11 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <chrono> | 6 | namespace Core { |
| 7 | #include <memory> | 7 | class System; |
| 8 | #include <queue> | 8 | } |
| 9 | |||
| 10 | #include "core/hle/service/kernel_helpers.h" | ||
| 11 | #include "core/hle/service/service.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | class KernelCore; | ||
| 15 | class KReadableEvent; | ||
| 16 | class KTransferMemory; | ||
| 17 | } // namespace Kernel | ||
| 18 | 9 | ||
| 19 | namespace Service::Nvnflinger { | 10 | namespace Service::Nvnflinger { |
| 20 | class Nvnflinger; | 11 | class Nvnflinger; |
| @@ -22,443 +13,6 @@ class Nvnflinger; | |||
| 22 | 13 | ||
| 23 | namespace Service::AM { | 14 | namespace Service::AM { |
| 24 | 15 | ||
| 25 | class AppletMessageQueue { | ||
| 26 | public: | ||
| 27 | // This is nn::am::AppletMessage | ||
| 28 | enum class AppletMessage : u32 { | ||
| 29 | None = 0, | ||
| 30 | ChangeIntoForeground = 1, | ||
| 31 | ChangeIntoBackground = 2, | ||
| 32 | Exit = 4, | ||
| 33 | ApplicationExited = 6, | ||
| 34 | FocusStateChanged = 15, | ||
| 35 | Resume = 16, | ||
| 36 | DetectShortPressingHomeButton = 20, | ||
| 37 | DetectLongPressingHomeButton = 21, | ||
| 38 | DetectShortPressingPowerButton = 22, | ||
| 39 | DetectMiddlePressingPowerButton = 23, | ||
| 40 | DetectLongPressingPowerButton = 24, | ||
| 41 | RequestToPrepareSleep = 25, | ||
| 42 | FinishedSleepSequence = 26, | ||
| 43 | SleepRequiredByHighTemperature = 27, | ||
| 44 | SleepRequiredByLowBattery = 28, | ||
| 45 | AutoPowerDown = 29, | ||
| 46 | OperationModeChanged = 30, | ||
| 47 | PerformanceModeChanged = 31, | ||
| 48 | DetectReceivingCecSystemStandby = 32, | ||
| 49 | SdCardRemoved = 33, | ||
| 50 | LaunchApplicationRequested = 50, | ||
| 51 | RequestToDisplay = 51, | ||
| 52 | ShowApplicationLogo = 55, | ||
| 53 | HideApplicationLogo = 56, | ||
| 54 | ForceHideApplicationLogo = 57, | ||
| 55 | FloatingApplicationDetected = 60, | ||
| 56 | DetectShortPressingCaptureButton = 90, | ||
| 57 | AlbumScreenShotTaken = 92, | ||
| 58 | AlbumRecordingSaved = 93, | ||
| 59 | }; | ||
| 60 | |||
| 61 | explicit AppletMessageQueue(Core::System& system); | ||
| 62 | ~AppletMessageQueue(); | ||
| 63 | |||
| 64 | Kernel::KReadableEvent& GetMessageReceiveEvent(); | ||
| 65 | Kernel::KReadableEvent& GetOperationModeChangedEvent(); | ||
| 66 | void PushMessage(AppletMessage msg); | ||
| 67 | AppletMessage PopMessage(); | ||
| 68 | std::size_t GetMessageCount() const; | ||
| 69 | void RequestExit(); | ||
| 70 | void RequestResume(); | ||
| 71 | void FocusStateChanged(); | ||
| 72 | void OperationModeChanged(); | ||
| 73 | |||
| 74 | private: | ||
| 75 | KernelHelpers::ServiceContext service_context; | ||
| 76 | |||
| 77 | Kernel::KEvent* on_new_message; | ||
| 78 | Kernel::KEvent* on_operation_mode_changed; | ||
| 79 | |||
| 80 | std::queue<AppletMessage> messages; | ||
| 81 | }; | ||
| 82 | |||
| 83 | class IWindowController final : public ServiceFramework<IWindowController> { | ||
| 84 | public: | ||
| 85 | explicit IWindowController(Core::System& system_); | ||
| 86 | ~IWindowController() override; | ||
| 87 | |||
| 88 | private: | ||
| 89 | void GetAppletResourceUserId(HLERequestContext& ctx); | ||
| 90 | void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); | ||
| 91 | void AcquireForegroundRights(HLERequestContext& ctx); | ||
| 92 | }; | ||
| 93 | |||
| 94 | class IAudioController final : public ServiceFramework<IAudioController> { | ||
| 95 | public: | ||
| 96 | explicit IAudioController(Core::System& system_); | ||
| 97 | ~IAudioController() override; | ||
| 98 | |||
| 99 | private: | ||
| 100 | void SetExpectedMasterVolume(HLERequestContext& ctx); | ||
| 101 | void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 102 | void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 103 | void ChangeMainAppletMasterVolume(HLERequestContext& ctx); | ||
| 104 | void SetTransparentAudioRate(HLERequestContext& ctx); | ||
| 105 | |||
| 106 | static constexpr float min_allowed_volume = 0.0f; | ||
| 107 | static constexpr float max_allowed_volume = 1.0f; | ||
| 108 | |||
| 109 | float main_applet_volume{0.25f}; | ||
| 110 | float library_applet_volume{max_allowed_volume}; | ||
| 111 | float transparent_volume_rate{min_allowed_volume}; | ||
| 112 | |||
| 113 | // Volume transition fade time in nanoseconds. | ||
| 114 | // e.g. If the main applet volume was 0% and was changed to 50% | ||
| 115 | // with a fade of 50ns, then over the course of 50ns, | ||
| 116 | // the volume will gradually fade up to 50% | ||
| 117 | std::chrono::nanoseconds fade_time_ns{0}; | ||
| 118 | }; | ||
| 119 | |||
| 120 | class IDisplayController final : public ServiceFramework<IDisplayController> { | ||
| 121 | public: | ||
| 122 | explicit IDisplayController(Core::System& system_); | ||
| 123 | ~IDisplayController() override; | ||
| 124 | |||
| 125 | private: | ||
| 126 | void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); | ||
| 127 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); | ||
| 128 | void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 129 | void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 130 | void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 131 | void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 132 | }; | ||
| 133 | |||
| 134 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { | ||
| 135 | public: | ||
| 136 | explicit IDebugFunctions(Core::System& system_); | ||
| 137 | ~IDebugFunctions() override; | ||
| 138 | }; | ||
| 139 | |||
| 140 | class ISelfController final : public ServiceFramework<ISelfController> { | ||
| 141 | public: | ||
| 142 | explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 143 | ~ISelfController() override; | ||
| 144 | |||
| 145 | private: | ||
| 146 | void Exit(HLERequestContext& ctx); | ||
| 147 | void LockExit(HLERequestContext& ctx); | ||
| 148 | void UnlockExit(HLERequestContext& ctx); | ||
| 149 | void EnterFatalSection(HLERequestContext& ctx); | ||
| 150 | void LeaveFatalSection(HLERequestContext& ctx); | ||
| 151 | void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); | ||
| 152 | void SetScreenShotPermission(HLERequestContext& ctx); | ||
| 153 | void SetOperationModeChangedNotification(HLERequestContext& ctx); | ||
| 154 | void SetPerformanceModeChangedNotification(HLERequestContext& ctx); | ||
| 155 | void SetFocusHandlingMode(HLERequestContext& ctx); | ||
| 156 | void SetRestartMessageEnabled(HLERequestContext& ctx); | ||
| 157 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); | ||
| 158 | void SetAlbumImageOrientation(HLERequestContext& ctx); | ||
| 159 | void IsSystemBufferSharingEnabled(HLERequestContext& ctx); | ||
| 160 | void GetSystemSharedBufferHandle(HLERequestContext& ctx); | ||
| 161 | void GetSystemSharedLayerHandle(HLERequestContext& ctx); | ||
| 162 | void CreateManagedDisplayLayer(HLERequestContext& ctx); | ||
| 163 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); | ||
| 164 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); | ||
| 165 | void ApproveToDisplay(HLERequestContext& ctx); | ||
| 166 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 167 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 168 | void ReportUserIsActive(HLERequestContext& ctx); | ||
| 169 | void SetAutoSleepDisabled(HLERequestContext& ctx); | ||
| 170 | void IsAutoSleepDisabled(HLERequestContext& ctx); | ||
| 171 | void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); | ||
| 172 | void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); | ||
| 173 | void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); | ||
| 174 | void SaveCurrentScreenshot(HLERequestContext& ctx); | ||
| 175 | void SetRecordVolumeMuted(HLERequestContext& ctx); | ||
| 176 | |||
| 177 | Result EnsureBufferSharingEnabled(); | ||
| 178 | |||
| 179 | enum class ScreenshotPermission : u32 { | ||
| 180 | Inherit = 0, | ||
| 181 | Enable = 1, | ||
| 182 | Disable = 2, | ||
| 183 | }; | ||
| 184 | |||
| 185 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 186 | |||
| 187 | KernelHelpers::ServiceContext service_context; | ||
| 188 | |||
| 189 | Kernel::KEvent* launchable_event; | ||
| 190 | Kernel::KEvent* accumulated_suspended_tick_changed_event; | ||
| 191 | |||
| 192 | u32 idle_time_detection_extension = 0; | ||
| 193 | u64 num_fatal_sections_entered = 0; | ||
| 194 | u64 system_shared_buffer_id = 0; | ||
| 195 | u64 system_shared_layer_id = 0; | ||
| 196 | bool is_auto_sleep_disabled = false; | ||
| 197 | bool buffer_sharing_enabled = false; | ||
| 198 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | ||
| 199 | }; | ||
| 200 | |||
| 201 | class ILockAccessor final : public ServiceFramework<ILockAccessor> { | ||
| 202 | public: | ||
| 203 | explicit ILockAccessor(Core::System& system_); | ||
| 204 | ~ILockAccessor() override; | ||
| 205 | |||
| 206 | private: | ||
| 207 | void TryLock(HLERequestContext& ctx); | ||
| 208 | void Unlock(HLERequestContext& ctx); | ||
| 209 | void GetEvent(HLERequestContext& ctx); | ||
| 210 | void IsLocked(HLERequestContext& ctx); | ||
| 211 | |||
| 212 | bool is_locked{}; | ||
| 213 | |||
| 214 | Kernel::KEvent* lock_event; | ||
| 215 | KernelHelpers::ServiceContext service_context; | ||
| 216 | }; | ||
| 217 | |||
| 218 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||
| 219 | public: | ||
| 220 | explicit ICommonStateGetter(Core::System& system_, | ||
| 221 | std::shared_ptr<AppletMessageQueue> msg_queue_); | ||
| 222 | ~ICommonStateGetter() override; | ||
| 223 | |||
| 224 | private: | ||
| 225 | // This is nn::oe::FocusState | ||
| 226 | enum class FocusState : u8 { | ||
| 227 | InFocus = 1, | ||
| 228 | NotInFocus = 2, | ||
| 229 | Background = 3, | ||
| 230 | }; | ||
| 231 | |||
| 232 | // This is nn::oe::OperationMode | ||
| 233 | enum class OperationMode : u8 { | ||
| 234 | Handheld = 0, | ||
| 235 | Docked = 1, | ||
| 236 | }; | ||
| 237 | |||
| 238 | // This is nn::am::service::SystemButtonType | ||
| 239 | enum class SystemButtonType { | ||
| 240 | None, | ||
| 241 | HomeButtonShortPressing, | ||
| 242 | HomeButtonLongPressing, | ||
| 243 | PowerButtonShortPressing, | ||
| 244 | PowerButtonLongPressing, | ||
| 245 | ShutdownSystem, | ||
| 246 | CaptureButtonShortPressing, | ||
| 247 | CaptureButtonLongPressing, | ||
| 248 | }; | ||
| 249 | |||
| 250 | enum class SysPlatformRegion : s32 { | ||
| 251 | Global = 1, | ||
| 252 | Terra = 2, | ||
| 253 | }; | ||
| 254 | |||
| 255 | void GetEventHandle(HLERequestContext& ctx); | ||
| 256 | void ReceiveMessage(HLERequestContext& ctx); | ||
| 257 | void GetCurrentFocusState(HLERequestContext& ctx); | ||
| 258 | void RequestToAcquireSleepLock(HLERequestContext& ctx); | ||
| 259 | void GetAcquiredSleepLockEvent(HLERequestContext& ctx); | ||
| 260 | void GetReaderLockAccessorEx(HLERequestContext& ctx); | ||
| 261 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); | ||
| 262 | void GetOperationMode(HLERequestContext& ctx); | ||
| 263 | void GetPerformanceMode(HLERequestContext& ctx); | ||
| 264 | void GetBootMode(HLERequestContext& ctx); | ||
| 265 | void IsVrModeEnabled(HLERequestContext& ctx); | ||
| 266 | void SetVrModeEnabled(HLERequestContext& ctx); | ||
| 267 | void SetLcdBacklighOffEnabled(HLERequestContext& ctx); | ||
| 268 | void BeginVrModeEx(HLERequestContext& ctx); | ||
| 269 | void EndVrModeEx(HLERequestContext& ctx); | ||
| 270 | void GetDefaultDisplayResolution(HLERequestContext& ctx); | ||
| 271 | void SetCpuBoostMode(HLERequestContext& ctx); | ||
| 272 | void GetBuiltInDisplayType(HLERequestContext& ctx); | ||
| 273 | void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); | ||
| 274 | void GetSettingsPlatformRegion(HLERequestContext& ctx); | ||
| 275 | void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); | ||
| 276 | |||
| 277 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 278 | bool vr_mode_state{}; | ||
| 279 | Kernel::KEvent* sleep_lock_event; | ||
| 280 | KernelHelpers::ServiceContext service_context; | ||
| 281 | }; | ||
| 282 | |||
| 283 | class IStorageImpl { | ||
| 284 | public: | ||
| 285 | virtual ~IStorageImpl(); | ||
| 286 | virtual std::vector<u8>& GetData() = 0; | ||
| 287 | virtual const std::vector<u8>& GetData() const = 0; | ||
| 288 | virtual std::size_t GetSize() const = 0; | ||
| 289 | }; | ||
| 290 | |||
| 291 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 292 | public: | ||
| 293 | explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); | ||
| 294 | ~IStorage() override; | ||
| 295 | |||
| 296 | std::vector<u8>& GetData() { | ||
| 297 | return impl->GetData(); | ||
| 298 | } | ||
| 299 | |||
| 300 | const std::vector<u8>& GetData() const { | ||
| 301 | return impl->GetData(); | ||
| 302 | } | ||
| 303 | |||
| 304 | std::size_t GetSize() const { | ||
| 305 | return impl->GetSize(); | ||
| 306 | } | ||
| 307 | |||
| 308 | private: | ||
| 309 | void Register(); | ||
| 310 | void Open(HLERequestContext& ctx); | ||
| 311 | |||
| 312 | std::shared_ptr<IStorageImpl> impl; | ||
| 313 | }; | ||
| 314 | |||
| 315 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | ||
| 316 | public: | ||
| 317 | explicit IStorageAccessor(Core::System& system_, IStorage& backing_); | ||
| 318 | ~IStorageAccessor() override; | ||
| 319 | |||
| 320 | private: | ||
| 321 | void GetSize(HLERequestContext& ctx); | ||
| 322 | void Write(HLERequestContext& ctx); | ||
| 323 | void Read(HLERequestContext& ctx); | ||
| 324 | |||
| 325 | IStorage& backing; | ||
| 326 | }; | ||
| 327 | |||
| 328 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | ||
| 329 | public: | ||
| 330 | explicit ILibraryAppletCreator(Core::System& system_); | ||
| 331 | ~ILibraryAppletCreator() override; | ||
| 332 | |||
| 333 | private: | ||
| 334 | void CreateLibraryApplet(HLERequestContext& ctx); | ||
| 335 | void CreateStorage(HLERequestContext& ctx); | ||
| 336 | void CreateTransferMemoryStorage(HLERequestContext& ctx); | ||
| 337 | void CreateHandleStorage(HLERequestContext& ctx); | ||
| 338 | }; | ||
| 339 | |||
| 340 | class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { | ||
| 341 | public: | ||
| 342 | explicit ILibraryAppletSelfAccessor(Core::System& system_); | ||
| 343 | ~ILibraryAppletSelfAccessor() override; | ||
| 344 | |||
| 345 | private: | ||
| 346 | void PopInData(HLERequestContext& ctx); | ||
| 347 | void PushOutData(HLERequestContext& ctx); | ||
| 348 | void GetLibraryAppletInfo(HLERequestContext& ctx); | ||
| 349 | void GetMainAppletIdentityInfo(HLERequestContext& ctx); | ||
| 350 | void ExitProcessAndReturn(HLERequestContext& ctx); | ||
| 351 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); | ||
| 352 | void GetDesirableKeyboardLayout(HLERequestContext& ctx); | ||
| 353 | void GetMainAppletAvailableUsers(HLERequestContext& ctx); | ||
| 354 | void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); | ||
| 355 | |||
| 356 | void PushInShowAlbum(); | ||
| 357 | void PushInShowCabinetData(); | ||
| 358 | void PushInShowMiiEditData(); | ||
| 359 | void PushInShowSoftwareKeyboard(); | ||
| 360 | void PushInShowController(); | ||
| 361 | |||
| 362 | std::deque<std::vector<u8>> queue_data; | ||
| 363 | }; | ||
| 364 | |||
| 365 | class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { | ||
| 366 | public: | ||
| 367 | explicit IAppletCommonFunctions(Core::System& system_); | ||
| 368 | ~IAppletCommonFunctions() override; | ||
| 369 | |||
| 370 | private: | ||
| 371 | void SetCpuBoostRequestPriority(HLERequestContext& ctx); | ||
| 372 | }; | ||
| 373 | |||
| 374 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 375 | public: | ||
| 376 | explicit IApplicationFunctions(Core::System& system_); | ||
| 377 | ~IApplicationFunctions() override; | ||
| 378 | |||
| 379 | private: | ||
| 380 | void PopLaunchParameter(HLERequestContext& ctx); | ||
| 381 | void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); | ||
| 382 | void EnsureSaveData(HLERequestContext& ctx); | ||
| 383 | void SetTerminateResult(HLERequestContext& ctx); | ||
| 384 | void GetDisplayVersion(HLERequestContext& ctx); | ||
| 385 | void GetDesiredLanguage(HLERequestContext& ctx); | ||
| 386 | void IsGamePlayRecordingSupported(HLERequestContext& ctx); | ||
| 387 | void InitializeGamePlayRecording(HLERequestContext& ctx); | ||
| 388 | void SetGamePlayRecordingState(HLERequestContext& ctx); | ||
| 389 | void NotifyRunning(HLERequestContext& ctx); | ||
| 390 | void GetPseudoDeviceId(HLERequestContext& ctx); | ||
| 391 | void ExtendSaveData(HLERequestContext& ctx); | ||
| 392 | void GetSaveDataSize(HLERequestContext& ctx); | ||
| 393 | void CreateCacheStorage(HLERequestContext& ctx); | ||
| 394 | void GetSaveDataSizeMax(HLERequestContext& ctx); | ||
| 395 | void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 396 | void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 397 | void BeginBlockingHomeButton(HLERequestContext& ctx); | ||
| 398 | void EndBlockingHomeButton(HLERequestContext& ctx); | ||
| 399 | void EnableApplicationCrashReport(HLERequestContext& ctx); | ||
| 400 | void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); | ||
| 401 | void SetApplicationCopyrightImage(HLERequestContext& ctx); | ||
| 402 | void SetApplicationCopyrightVisibility(HLERequestContext& ctx); | ||
| 403 | void QueryApplicationPlayStatistics(HLERequestContext& ctx); | ||
| 404 | void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); | ||
| 405 | void ExecuteProgram(HLERequestContext& ctx); | ||
| 406 | void ClearUserChannel(HLERequestContext& ctx); | ||
| 407 | void UnpopToUserChannel(HLERequestContext& ctx); | ||
| 408 | void GetPreviousProgramIndex(HLERequestContext& ctx); | ||
| 409 | void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); | ||
| 410 | void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); | ||
| 411 | void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); | ||
| 412 | void GetNotificationStorageChannelEvent(HLERequestContext& ctx); | ||
| 413 | void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); | ||
| 414 | void PrepareForJit(HLERequestContext& ctx); | ||
| 415 | |||
| 416 | KernelHelpers::ServiceContext service_context; | ||
| 417 | |||
| 418 | bool launch_popped_account_preselect = false; | ||
| 419 | s32 previous_program_index{-1}; | ||
| 420 | Kernel::KEvent* gpu_error_detected_event; | ||
| 421 | Kernel::KEvent* friend_invitation_storage_channel_event; | ||
| 422 | Kernel::KEvent* notification_storage_channel_event; | ||
| 423 | Kernel::KEvent* health_warning_disappeared_system_event; | ||
| 424 | }; | ||
| 425 | |||
| 426 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | ||
| 427 | public: | ||
| 428 | explicit IHomeMenuFunctions(Core::System& system_); | ||
| 429 | ~IHomeMenuFunctions() override; | ||
| 430 | |||
| 431 | private: | ||
| 432 | void RequestToGetForeground(HLERequestContext& ctx); | ||
| 433 | void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); | ||
| 434 | |||
| 435 | KernelHelpers::ServiceContext service_context; | ||
| 436 | |||
| 437 | Kernel::KEvent* pop_from_general_channel_event; | ||
| 438 | }; | ||
| 439 | |||
| 440 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { | ||
| 441 | public: | ||
| 442 | explicit IGlobalStateController(Core::System& system_); | ||
| 443 | ~IGlobalStateController() override; | ||
| 444 | }; | ||
| 445 | |||
| 446 | class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | ||
| 447 | public: | ||
| 448 | explicit IApplicationCreator(Core::System& system_); | ||
| 449 | ~IApplicationCreator() override; | ||
| 450 | }; | ||
| 451 | |||
| 452 | class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { | ||
| 453 | public: | ||
| 454 | explicit IProcessWindingController(Core::System& system_); | ||
| 455 | ~IProcessWindingController() override; | ||
| 456 | |||
| 457 | private: | ||
| 458 | void GetLaunchReason(HLERequestContext& ctx); | ||
| 459 | void OpenCallingLibraryApplet(HLERequestContext& ctx); | ||
| 460 | }; | ||
| 461 | |||
| 462 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); | 16 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); |
| 463 | 17 | ||
| 464 | } // namespace Service::AM | 18 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h new file mode 100644 index 000000000..a2afc9eec --- /dev/null +++ b/src/core/hle/service/am/am_results.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | ||
| 11 | constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | ||
| 12 | constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | ||
| 13 | constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511}; | ||
| 14 | constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512}; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h new file mode 100644 index 000000000..a2b852b12 --- /dev/null +++ b/src/core/hle/service/am/am_types.h | |||
| @@ -0,0 +1,178 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | namespace Frontend { | ||
| 12 | class FrontendApplet; | ||
| 13 | } | ||
| 14 | |||
| 15 | enum class AppletType { | ||
| 16 | Application, | ||
| 17 | LibraryApplet, | ||
| 18 | SystemApplet, | ||
| 19 | }; | ||
| 20 | |||
| 21 | enum class GameplayRecordingState : u32 { | ||
| 22 | Disabled, | ||
| 23 | Enabled, | ||
| 24 | }; | ||
| 25 | |||
| 26 | // This is nn::oe::FocusState | ||
| 27 | enum class FocusState : u8 { | ||
| 28 | InFocus = 1, | ||
| 29 | NotInFocus = 2, | ||
| 30 | Background = 3, | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::oe::OperationMode | ||
| 34 | enum class OperationMode : u8 { | ||
| 35 | Handheld = 0, | ||
| 36 | Docked = 1, | ||
| 37 | }; | ||
| 38 | |||
| 39 | // This is nn::am::service::SystemButtonType | ||
| 40 | enum class SystemButtonType { | ||
| 41 | None, | ||
| 42 | HomeButtonShortPressing, | ||
| 43 | HomeButtonLongPressing, | ||
| 44 | PowerButtonShortPressing, | ||
| 45 | PowerButtonLongPressing, | ||
| 46 | ShutdownSystem, | ||
| 47 | CaptureButtonShortPressing, | ||
| 48 | CaptureButtonLongPressing, | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum class SysPlatformRegion : s32 { | ||
| 52 | Global = 1, | ||
| 53 | Terra = 2, | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct AppletProcessLaunchReason { | ||
| 57 | u8 flag; | ||
| 58 | INSERT_PADDING_BYTES(3); | ||
| 59 | }; | ||
| 60 | static_assert(sizeof(AppletProcessLaunchReason) == 0x4, | ||
| 61 | "AppletProcessLaunchReason is an invalid size"); | ||
| 62 | |||
| 63 | enum class ScreenshotPermission : u32 { | ||
| 64 | Inherit = 0, | ||
| 65 | Enable = 1, | ||
| 66 | Disable = 2, | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct FocusHandlingMode { | ||
| 70 | bool unknown0; | ||
| 71 | bool unknown1; | ||
| 72 | bool unknown2; | ||
| 73 | bool unknown3; | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum class IdleTimeDetectionExtension : u32 { | ||
| 77 | Disabled = 0, | ||
| 78 | Extended = 1, | ||
| 79 | ExtendedUnsafe = 2, | ||
| 80 | }; | ||
| 81 | |||
| 82 | enum class AppletId : u32 { | ||
| 83 | None = 0x00, | ||
| 84 | Application = 0x01, | ||
| 85 | OverlayDisplay = 0x02, | ||
| 86 | QLaunch = 0x03, | ||
| 87 | Starter = 0x04, | ||
| 88 | Auth = 0x0A, | ||
| 89 | Cabinet = 0x0B, | ||
| 90 | Controller = 0x0C, | ||
| 91 | DataErase = 0x0D, | ||
| 92 | Error = 0x0E, | ||
| 93 | NetConnect = 0x0F, | ||
| 94 | ProfileSelect = 0x10, | ||
| 95 | SoftwareKeyboard = 0x11, | ||
| 96 | MiiEdit = 0x12, | ||
| 97 | Web = 0x13, | ||
| 98 | Shop = 0x14, | ||
| 99 | PhotoViewer = 0x15, | ||
| 100 | Settings = 0x16, | ||
| 101 | OfflineWeb = 0x17, | ||
| 102 | LoginShare = 0x18, | ||
| 103 | WebAuth = 0x19, | ||
| 104 | MyPage = 0x1A, | ||
| 105 | }; | ||
| 106 | |||
| 107 | enum class AppletProgramId : u64 { | ||
| 108 | QLaunch = 0x0100000000001000ull, | ||
| 109 | Auth = 0x0100000000001001ull, | ||
| 110 | Cabinet = 0x0100000000001002ull, | ||
| 111 | Controller = 0x0100000000001003ull, | ||
| 112 | DataErase = 0x0100000000001004ull, | ||
| 113 | Error = 0x0100000000001005ull, | ||
| 114 | NetConnect = 0x0100000000001006ull, | ||
| 115 | ProfileSelect = 0x0100000000001007ull, | ||
| 116 | SoftwareKeyboard = 0x0100000000001008ull, | ||
| 117 | MiiEdit = 0x0100000000001009ull, | ||
| 118 | Web = 0x010000000000100Aull, | ||
| 119 | Shop = 0x010000000000100Bull, | ||
| 120 | OverlayDisplay = 0x010000000000100Cull, | ||
| 121 | PhotoViewer = 0x010000000000100Dull, | ||
| 122 | Settings = 0x010000000000100Eull, | ||
| 123 | OfflineWeb = 0x010000000000100Full, | ||
| 124 | LoginShare = 0x0100000000001010ull, | ||
| 125 | WebAuth = 0x0100000000001011ull, | ||
| 126 | Starter = 0x0100000000001012ull, | ||
| 127 | MyPage = 0x0100000000001013ull, | ||
| 128 | MaxProgramId = 0x0100000000001FFFull, | ||
| 129 | }; | ||
| 130 | |||
| 131 | enum class LibraryAppletMode : u32 { | ||
| 132 | AllForeground = 0, | ||
| 133 | Background = 1, | ||
| 134 | NoUI = 2, | ||
| 135 | BackgroundIndirectDisplay = 3, | ||
| 136 | AllForegroundInitiallyHidden = 4, | ||
| 137 | }; | ||
| 138 | |||
| 139 | enum class CommonArgumentVersion : u32 { | ||
| 140 | Version0, | ||
| 141 | Version1, | ||
| 142 | Version2, | ||
| 143 | Version3, | ||
| 144 | }; | ||
| 145 | |||
| 146 | enum class CommonArgumentSize : u32 { | ||
| 147 | Version3 = 0x20, | ||
| 148 | }; | ||
| 149 | |||
| 150 | enum class ThemeColor : u32 { | ||
| 151 | BasicWhite = 0, | ||
| 152 | BasicBlack = 3, | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct CommonArguments { | ||
| 156 | CommonArgumentVersion arguments_version; | ||
| 157 | CommonArgumentSize size; | ||
| 158 | u32 library_version; | ||
| 159 | ThemeColor theme_color; | ||
| 160 | bool play_startup_sound; | ||
| 161 | u64 system_tick; | ||
| 162 | }; | ||
| 163 | static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); | ||
| 164 | |||
| 165 | struct AppletIdentityInfo { | ||
| 166 | AppletId applet_id; | ||
| 167 | INSERT_PADDING_BYTES(0x4); | ||
| 168 | u64 application_id; | ||
| 169 | }; | ||
| 170 | static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); | ||
| 171 | |||
| 172 | using AppletResourceUserId = u64; | ||
| 173 | using ProgramId = u64; | ||
| 174 | |||
| 175 | struct Applet; | ||
| 176 | class AppletDataBroker; | ||
| 177 | |||
| 178 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp new file mode 100644 index 000000000..5b9056c12 --- /dev/null +++ b/src/core/hle/service/am/applet.cpp | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/scope_exit.h" | ||
| 5 | |||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/hle/service/am/am_results.h" | ||
| 8 | #include "core/hle/service/am/applet.h" | ||
| 9 | #include "core/hle/service/am/applet_manager.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | Applet::Applet(Core::System& system, std::unique_ptr<Process> process_) | ||
| 14 | : context(system, "Applet"), message_queue(system), process(std::move(process_)), | ||
| 15 | hid_registration(system, *process), gpu_error_detected_event(context), | ||
| 16 | friend_invitation_storage_channel_event(context), notification_storage_channel_event(context), | ||
| 17 | health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context), | ||
| 18 | pop_from_general_channel_event(context), library_applet_launchable_event(context), | ||
| 19 | accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) { | ||
| 20 | |||
| 21 | aruid = process->GetProcessId(); | ||
| 22 | program_id = process->GetProgramId(); | ||
| 23 | } | ||
| 24 | |||
| 25 | Applet::~Applet() = default; | ||
| 26 | |||
| 27 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h new file mode 100644 index 000000000..bce6f9050 --- /dev/null +++ b/src/core/hle/service/am/applet.h | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <list> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/math_util.h" | ||
| 10 | #include "core/hle/service/apm/apm_controller.h" | ||
| 11 | #include "core/hle/service/caps/caps_types.h" | ||
| 12 | #include "core/hle/service/event.h" | ||
| 13 | #include "core/hle/service/kernel_helpers.h" | ||
| 14 | #include "core/hle/service/service.h" | ||
| 15 | |||
| 16 | #include "core/hle/service/am/am_types.h" | ||
| 17 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 18 | #include "core/hle/service/am/hid_registration.h" | ||
| 19 | #include "core/hle/service/am/managed_layer_holder.h" | ||
| 20 | #include "core/hle/service/am/process.h" | ||
| 21 | #include "core/hle/service/am/storage.h" | ||
| 22 | #include "core/hle/service/am/system_buffer_manager.h" | ||
| 23 | |||
| 24 | namespace Service::AM { | ||
| 25 | |||
| 26 | struct Applet { | ||
| 27 | explicit Applet(Core::System& system, std::unique_ptr<Process> process_); | ||
| 28 | ~Applet(); | ||
| 29 | |||
| 30 | // Lock | ||
| 31 | std::mutex lock{}; | ||
| 32 | |||
| 33 | // Event creation helper | ||
| 34 | KernelHelpers::ServiceContext context; | ||
| 35 | |||
| 36 | // Applet message queue | ||
| 37 | AppletMessageQueue message_queue; | ||
| 38 | |||
| 39 | // Process | ||
| 40 | std::unique_ptr<Process> process; | ||
| 41 | |||
| 42 | // Creation state | ||
| 43 | AppletId applet_id{}; | ||
| 44 | AppletResourceUserId aruid{}; | ||
| 45 | AppletProcessLaunchReason launch_reason{}; | ||
| 46 | AppletType type{}; | ||
| 47 | ProgramId program_id{}; | ||
| 48 | LibraryAppletMode library_applet_mode{}; | ||
| 49 | s32 previous_program_index{-1}; | ||
| 50 | ScreenshotPermission previous_screenshot_permission{ScreenshotPermission::Enable}; | ||
| 51 | |||
| 52 | // TODO: some fields above can be AppletIdentityInfo | ||
| 53 | AppletIdentityInfo screen_shot_identity; | ||
| 54 | |||
| 55 | // hid state | ||
| 56 | HidRegistration hid_registration; | ||
| 57 | |||
| 58 | // vi state | ||
| 59 | SystemBufferManager system_buffer_manager{}; | ||
| 60 | ManagedLayerHolder managed_layer_holder{}; | ||
| 61 | |||
| 62 | // Applet common functions | ||
| 63 | Result terminate_result{}; | ||
| 64 | s32 display_logical_width{}; | ||
| 65 | s32 display_logical_height{}; | ||
| 66 | Common::Rectangle<f32> display_magnification{0, 0, 1, 1}; | ||
| 67 | bool home_button_double_click_enabled{}; | ||
| 68 | bool home_button_short_pressed_blocked{}; | ||
| 69 | bool home_button_long_pressed_blocked{}; | ||
| 70 | bool vr_mode_curtain_required{}; | ||
| 71 | bool sleep_required_by_high_temperature{}; | ||
| 72 | bool sleep_required_by_low_battery{}; | ||
| 73 | s32 cpu_boost_request_priority{-1}; | ||
| 74 | bool handling_capture_button_short_pressed_message_enabled_for_applet{}; | ||
| 75 | bool handling_capture_button_long_pressed_message_enabled_for_applet{}; | ||
| 76 | u32 application_core_usage_mode{}; | ||
| 77 | |||
| 78 | // Application functions | ||
| 79 | bool gameplay_recording_supported{}; | ||
| 80 | GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled}; | ||
| 81 | bool jit_service_launched{}; | ||
| 82 | bool is_running{}; | ||
| 83 | bool application_crash_report_enabled{}; | ||
| 84 | |||
| 85 | // Common state | ||
| 86 | FocusState focus_state{}; | ||
| 87 | bool sleep_lock_enabled{}; | ||
| 88 | bool vr_mode_enabled{}; | ||
| 89 | bool lcd_backlight_off_enabled{}; | ||
| 90 | APM::CpuBoostMode boost_mode{}; | ||
| 91 | bool request_exit_to_library_applet_at_execute_next_program_enabled{}; | ||
| 92 | |||
| 93 | // Channels | ||
| 94 | std::deque<std::vector<u8>> user_channel_launch_parameter{}; | ||
| 95 | std::deque<std::vector<u8>> preselected_user_launch_parameter{}; | ||
| 96 | |||
| 97 | // Caller applet | ||
| 98 | std::weak_ptr<Applet> caller_applet{}; | ||
| 99 | std::shared_ptr<AppletDataBroker> caller_applet_broker{}; | ||
| 100 | |||
| 101 | // Self state | ||
| 102 | bool exit_locked{}; | ||
| 103 | s32 fatal_section_count{}; | ||
| 104 | bool operation_mode_changed_notification_enabled{true}; | ||
| 105 | bool performance_mode_changed_notification_enabled{true}; | ||
| 106 | FocusHandlingMode focus_handling_mode{}; | ||
| 107 | bool restart_message_enabled{}; | ||
| 108 | bool out_of_focus_suspension_enabled{true}; | ||
| 109 | Capture::AlbumImageOrientation album_image_orientation{}; | ||
| 110 | bool handles_request_to_display{}; | ||
| 111 | ScreenshotPermission screenshot_permission{}; | ||
| 112 | IdleTimeDetectionExtension idle_time_detection_extension{}; | ||
| 113 | bool auto_sleep_disabled{}; | ||
| 114 | u64 suspended_ticks{}; | ||
| 115 | bool album_image_taken_notification_enabled{}; | ||
| 116 | bool record_volume_muted{}; | ||
| 117 | |||
| 118 | // Events | ||
| 119 | Event gpu_error_detected_event; | ||
| 120 | Event friend_invitation_storage_channel_event; | ||
| 121 | Event notification_storage_channel_event; | ||
| 122 | Event health_warning_disappeared_system_event; | ||
| 123 | Event acquired_sleep_lock_event; | ||
| 124 | Event pop_from_general_channel_event; | ||
| 125 | Event library_applet_launchable_event; | ||
| 126 | Event accumulated_suspended_tick_changed_event; | ||
| 127 | Event sleep_lock_event; | ||
| 128 | |||
| 129 | // Frontend state | ||
| 130 | std::shared_ptr<Frontend::FrontendApplet> frontend{}; | ||
| 131 | }; | ||
| 132 | |||
| 133 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index e30e6478a..1b715dea6 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp | |||
| @@ -1,311 +1,73 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hle/service/am/am.h" | ||
| 7 | #include "core/hle/service/am/applet_ae.h" | 4 | #include "core/hle/service/am/applet_ae.h" |
| 5 | #include "core/hle/service/am/applet_manager.h" | ||
| 6 | #include "core/hle/service/am/library_applet_proxy.h" | ||
| 7 | #include "core/hle/service/am/system_applet_proxy.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 10 | 9 | ||
| 11 | namespace Service::AM { | 10 | namespace Service::AM { |
| 12 | 11 | ||
| 13 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | 12 | AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) |
| 14 | public: | 13 | : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} { |
| 15 | explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | 14 | // clang-format off |
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue_, | 15 | static const FunctionInfo functions[] = { |
| 17 | Core::System& system_) | 16 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, |
| 18 | : ServiceFramework{system_, "ILibraryAppletProxy"}, | 17 | {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"}, |
| 19 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | 18 | {201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"}, |
| 20 | // clang-format off | 19 | {300, nullptr, "OpenOverlayAppletProxy"}, |
| 21 | static const FunctionInfo functions[] = { | 20 | {350, nullptr, "OpenSystemApplicationProxy"}, |
| 22 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | 21 | {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, |
| 23 | {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, | 22 | {410, nullptr, "GetSystemAppletControllerForDebug"}, |
| 24 | {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, | 23 | {1000, nullptr, "GetDebugFunctions"}, |
| 25 | {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, | 24 | }; |
| 26 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, | 25 | // clang-format on |
| 27 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 28 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 29 | {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, | ||
| 30 | {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 31 | {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 32 | {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 33 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 34 | }; | ||
| 35 | // clang-format on | ||
| 36 | |||
| 37 | RegisterHandlers(functions); | ||
| 38 | } | ||
| 39 | |||
| 40 | private: | ||
| 41 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 42 | LOG_DEBUG(Service_AM, "called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 47 | } | ||
| 48 | |||
| 49 | void GetSelfController(HLERequestContext& ctx) { | ||
| 50 | LOG_DEBUG(Service_AM, "called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 55 | } | ||
| 56 | |||
| 57 | void GetWindowController(HLERequestContext& ctx) { | ||
| 58 | LOG_DEBUG(Service_AM, "called"); | ||
| 59 | |||
| 60 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 61 | rb.Push(ResultSuccess); | ||
| 62 | rb.PushIpcInterface<IWindowController>(system); | ||
| 63 | } | ||
| 64 | |||
| 65 | void GetAudioController(HLERequestContext& ctx) { | ||
| 66 | LOG_DEBUG(Service_AM, "called"); | ||
| 67 | |||
| 68 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 69 | rb.Push(ResultSuccess); | ||
| 70 | rb.PushIpcInterface<IAudioController>(system); | ||
| 71 | } | ||
| 72 | |||
| 73 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 74 | LOG_DEBUG(Service_AM, "called"); | ||
| 75 | |||
| 76 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 77 | rb.Push(ResultSuccess); | ||
| 78 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 79 | } | ||
| 80 | |||
| 81 | void GetProcessWindingController(HLERequestContext& ctx) { | ||
| 82 | LOG_DEBUG(Service_AM, "called"); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | rb.PushIpcInterface<IProcessWindingController>(system); | ||
| 87 | } | ||
| 88 | |||
| 89 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 90 | LOG_DEBUG(Service_AM, "called"); | ||
| 91 | |||
| 92 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 93 | rb.Push(ResultSuccess); | ||
| 94 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 95 | } | ||
| 96 | |||
| 97 | void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_AM, "called"); | ||
| 99 | |||
| 100 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 101 | rb.Push(ResultSuccess); | ||
| 102 | rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); | ||
| 103 | } | ||
| 104 | |||
| 105 | void GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 106 | LOG_DEBUG(Service_AM, "called"); | ||
| 107 | |||
| 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 109 | rb.Push(ResultSuccess); | ||
| 110 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | ||
| 111 | } | ||
| 112 | |||
| 113 | void GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 114 | LOG_DEBUG(Service_AM, "called"); | ||
| 115 | |||
| 116 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 117 | rb.Push(ResultSuccess); | ||
| 118 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 119 | } | ||
| 120 | |||
| 121 | void GetGlobalStateController(HLERequestContext& ctx) { | ||
| 122 | LOG_DEBUG(Service_AM, "called"); | ||
| 123 | |||
| 124 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 125 | rb.Push(ResultSuccess); | ||
| 126 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 127 | } | ||
| 128 | |||
| 129 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 130 | LOG_DEBUG(Service_AM, "called"); | ||
| 131 | |||
| 132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 133 | rb.Push(ResultSuccess); | ||
| 134 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 135 | } | ||
| 136 | |||
| 137 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 138 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 139 | }; | ||
| 140 | |||
| 141 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | ||
| 142 | public: | ||
| 143 | explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 144 | std::shared_ptr<AppletMessageQueue> msg_queue_, | ||
| 145 | Core::System& system_) | ||
| 146 | : ServiceFramework{system_, "ISystemAppletProxy"}, | ||
| 147 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | ||
| 148 | // clang-format off | ||
| 149 | static const FunctionInfo functions[] = { | ||
| 150 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 151 | {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 152 | {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 153 | {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 154 | {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 155 | {10, nullptr, "GetProcessWindingController"}, | ||
| 156 | {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 157 | {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 158 | {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 159 | {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, | ||
| 160 | {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 161 | {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 162 | }; | ||
| 163 | // clang-format on | ||
| 164 | |||
| 165 | RegisterHandlers(functions); | ||
| 166 | } | ||
| 167 | |||
| 168 | private: | ||
| 169 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 170 | LOG_DEBUG(Service_AM, "called"); | ||
| 171 | |||
| 172 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 173 | rb.Push(ResultSuccess); | ||
| 174 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 175 | } | ||
| 176 | |||
| 177 | void GetSelfController(HLERequestContext& ctx) { | ||
| 178 | LOG_DEBUG(Service_AM, "called"); | ||
| 179 | |||
| 180 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 181 | rb.Push(ResultSuccess); | ||
| 182 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 183 | } | ||
| 184 | |||
| 185 | void GetWindowController(HLERequestContext& ctx) { | ||
| 186 | LOG_DEBUG(Service_AM, "called"); | ||
| 187 | |||
| 188 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 189 | rb.Push(ResultSuccess); | ||
| 190 | rb.PushIpcInterface<IWindowController>(system); | ||
| 191 | } | ||
| 192 | |||
| 193 | void GetAudioController(HLERequestContext& ctx) { | ||
| 194 | LOG_DEBUG(Service_AM, "called"); | ||
| 195 | |||
| 196 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 197 | rb.Push(ResultSuccess); | ||
| 198 | rb.PushIpcInterface<IAudioController>(system); | ||
| 199 | } | ||
| 200 | |||
| 201 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 202 | LOG_DEBUG(Service_AM, "called"); | ||
| 203 | |||
| 204 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 205 | rb.Push(ResultSuccess); | ||
| 206 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 207 | } | ||
| 208 | 26 | ||
| 209 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | 27 | RegisterHandlers(functions); |
| 210 | LOG_DEBUG(Service_AM, "called"); | 28 | } |
| 211 | 29 | ||
| 212 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 30 | AppletAE::~AppletAE() = default; |
| 213 | rb.Push(ResultSuccess); | ||
| 214 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | ||
| 215 | } | ||
| 216 | 31 | ||
| 217 | void GetHomeMenuFunctions(HLERequestContext& ctx) { | 32 | void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { |
| 218 | LOG_DEBUG(Service_AM, "called"); | 33 | LOG_DEBUG(Service_AM, "called"); |
| 219 | 34 | ||
| 35 | if (const auto applet = GetAppletFromContext(ctx)) { | ||
| 220 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 36 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 221 | rb.Push(ResultSuccess); | 37 | rb.Push(ResultSuccess); |
| 222 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | 38 | rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, applet, system); |
| 223 | } | 39 | } else { |
| 224 | 40 | UNIMPLEMENTED(); | |
| 225 | void GetGlobalStateController(HLERequestContext& ctx) { | ||
| 226 | LOG_DEBUG(Service_AM, "called"); | ||
| 227 | 41 | ||
| 228 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 42 | IPC::ResponseBuilder rb{ctx, 2}; |
| 229 | rb.Push(ResultSuccess); | 43 | rb.Push(ResultUnknown); |
| 230 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 231 | } | ||
| 232 | |||
| 233 | void GetApplicationCreator(HLERequestContext& ctx) { | ||
| 234 | LOG_DEBUG(Service_AM, "called"); | ||
| 235 | |||
| 236 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 237 | rb.Push(ResultSuccess); | ||
| 238 | rb.PushIpcInterface<IApplicationCreator>(system); | ||
| 239 | } | 44 | } |
| 45 | } | ||
| 240 | 46 | ||
| 241 | void GetAppletCommonFunctions(HLERequestContext& ctx) { | 47 | void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { |
| 242 | LOG_DEBUG(Service_AM, "called"); | 48 | LOG_DEBUG(Service_AM, "called"); |
| 243 | 49 | ||
| 50 | if (const auto applet = GetAppletFromContext(ctx)) { | ||
| 244 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 51 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 245 | rb.Push(ResultSuccess); | 52 | rb.Push(ResultSuccess); |
| 246 | rb.PushIpcInterface<IAppletCommonFunctions>(system); | 53 | rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, applet, system); |
| 247 | } | 54 | } else { |
| 248 | 55 | UNIMPLEMENTED(); | |
| 249 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 250 | LOG_DEBUG(Service_AM, "called"); | ||
| 251 | 56 | ||
| 252 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 57 | IPC::ResponseBuilder rb{ctx, 2}; |
| 253 | rb.Push(ResultSuccess); | 58 | rb.Push(ResultUnknown); |
| 254 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 255 | } | 59 | } |
| 256 | |||
| 257 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 258 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 259 | }; | ||
| 260 | |||
| 261 | void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { | ||
| 262 | LOG_DEBUG(Service_AM, "called"); | ||
| 263 | |||
| 264 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 265 | rb.Push(ResultSuccess); | ||
| 266 | rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, msg_queue, system); | ||
| 267 | } | ||
| 268 | |||
| 269 | void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { | ||
| 270 | LOG_DEBUG(Service_AM, "called"); | ||
| 271 | |||
| 272 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 273 | rb.Push(ResultSuccess); | ||
| 274 | rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system); | ||
| 275 | } | 60 | } |
| 276 | 61 | ||
| 277 | void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { | 62 | void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { |
| 278 | LOG_DEBUG(Service_AM, "called"); | 63 | LOG_DEBUG(Service_AM, "called"); |
| 279 | 64 | ||
| 280 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 65 | return OpenLibraryAppletProxy(ctx); |
| 281 | rb.Push(ResultSuccess); | ||
| 282 | rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system); | ||
| 283 | } | 66 | } |
| 284 | 67 | ||
| 285 | AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, | 68 | std::shared_ptr<Applet> AppletAE::GetAppletFromContext(HLERequestContext& ctx) { |
| 286 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) | 69 | const auto aruid = ctx.GetPID(); |
| 287 | : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{ | 70 | return system.GetAppletManager().GetByAppletResourceUserId(aruid); |
| 288 | std::move(msg_queue_)} { | ||
| 289 | // clang-format off | ||
| 290 | static const FunctionInfo functions[] = { | ||
| 291 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, | ||
| 292 | {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"}, | ||
| 293 | {201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"}, | ||
| 294 | {300, nullptr, "OpenOverlayAppletProxy"}, | ||
| 295 | {350, nullptr, "OpenSystemApplicationProxy"}, | ||
| 296 | {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, | ||
| 297 | {410, nullptr, "GetSystemAppletControllerForDebug"}, | ||
| 298 | {1000, nullptr, "GetDebugFunctions"}, | ||
| 299 | }; | ||
| 300 | // clang-format on | ||
| 301 | |||
| 302 | RegisterHandlers(functions); | ||
| 303 | } | ||
| 304 | |||
| 305 | AppletAE::~AppletAE() = default; | ||
| 306 | |||
| 307 | const std::shared_ptr<AppletMessageQueue>& AppletAE::GetMessageQueue() const { | ||
| 308 | return msg_queue; | ||
| 309 | } | 71 | } |
| 310 | 72 | ||
| 311 | } // namespace Service::AM | 73 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 538ce2903..3d7961fa1 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h | |||
| @@ -18,23 +18,21 @@ class Nvnflinger; | |||
| 18 | 18 | ||
| 19 | namespace AM { | 19 | namespace AM { |
| 20 | 20 | ||
| 21 | class AppletMessageQueue; | 21 | struct Applet; |
| 22 | 22 | ||
| 23 | class AppletAE final : public ServiceFramework<AppletAE> { | 23 | class AppletAE final : public ServiceFramework<AppletAE> { |
| 24 | public: | 24 | public: |
| 25 | explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, | 25 | explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); |
| 26 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); | ||
| 27 | ~AppletAE() override; | 26 | ~AppletAE() override; |
| 28 | 27 | ||
| 29 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; | ||
| 30 | |||
| 31 | private: | 28 | private: |
| 32 | void OpenSystemAppletProxy(HLERequestContext& ctx); | 29 | void OpenSystemAppletProxy(HLERequestContext& ctx); |
| 33 | void OpenLibraryAppletProxy(HLERequestContext& ctx); | 30 | void OpenLibraryAppletProxy(HLERequestContext& ctx); |
| 34 | void OpenLibraryAppletProxyOld(HLERequestContext& ctx); | 31 | void OpenLibraryAppletProxyOld(HLERequestContext& ctx); |
| 35 | 32 | ||
| 33 | std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx); | ||
| 34 | |||
| 36 | Nvnflinger::Nvnflinger& nvnflinger; | 35 | Nvnflinger::Nvnflinger& nvnflinger; |
| 37 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 38 | }; | 36 | }; |
| 39 | 37 | ||
| 40 | } // namespace AM | 38 | } // namespace AM |
diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp new file mode 100644 index 000000000..130614ae5 --- /dev/null +++ b/src/core/hle/service/am/applet_common_functions.cpp | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet.h" | ||
| 5 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, | ||
| 11 | std::shared_ptr<Applet> applet_) | ||
| 12 | : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} { | ||
| 13 | // clang-format off | ||
| 14 | static const FunctionInfo functions[] = { | ||
| 15 | {0, nullptr, "SetTerminateResult"}, | ||
| 16 | {10, nullptr, "ReadThemeStorage"}, | ||
| 17 | {11, nullptr, "WriteThemeStorage"}, | ||
| 18 | {20, nullptr, "PushToAppletBoundChannel"}, | ||
| 19 | {21, nullptr, "TryPopFromAppletBoundChannel"}, | ||
| 20 | {40, nullptr, "GetDisplayLogicalResolution"}, | ||
| 21 | {42, nullptr, "SetDisplayMagnification"}, | ||
| 22 | {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, | ||
| 23 | {51, nullptr, "GetHomeButtonDoubleClickEnabled"}, | ||
| 24 | {52, nullptr, "IsHomeButtonShortPressedBlocked"}, | ||
| 25 | {60, nullptr, "IsVrModeCurtainRequired"}, | ||
| 26 | {61, nullptr, "IsSleepRequiredByHighTemperature"}, | ||
| 27 | {62, nullptr, "IsSleepRequiredByLowBattery"}, | ||
| 28 | {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"}, | ||
| 29 | {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, | ||
| 30 | {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, | ||
| 31 | {90, nullptr, "OpenNamedChannelAsParent"}, | ||
| 32 | {91, nullptr, "OpenNamedChannelAsChild"}, | ||
| 33 | {100, nullptr, "SetApplicationCoreUsageMode"}, | ||
| 34 | {300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"}, | ||
| 35 | }; | ||
| 36 | // clang-format on | ||
| 37 | |||
| 38 | RegisterHandlers(functions); | ||
| 39 | } | ||
| 40 | |||
| 41 | IAppletCommonFunctions::~IAppletCommonFunctions() = default; | ||
| 42 | |||
| 43 | void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { | ||
| 44 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 45 | |||
| 46 | IPC::RequestParser rp{ctx}; | ||
| 47 | |||
| 48 | std::scoped_lock lk{applet->lock}; | ||
| 49 | applet->cpu_boost_request_priority = rp.Pop<s32>(); | ||
| 50 | |||
| 51 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 52 | rb.Push(ResultSuccess); | ||
| 53 | } | ||
| 54 | |||
| 55 | void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) { | ||
| 56 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 59 | rb.Push(ResultSuccess); | ||
| 60 | rb.Push<u64>(system.GetApplicationProcessProgramID() & ~0xFFFULL); | ||
| 61 | } | ||
| 62 | |||
| 63 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h new file mode 100644 index 000000000..b86adf5cb --- /dev/null +++ b/src/core/hle/service/am/applet_common_functions.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { | ||
| 13 | public: | ||
| 14 | explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 15 | ~IAppletCommonFunctions() override; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void SetCpuBoostRequestPriority(HLERequestContext& ctx); | ||
| 19 | void GetCurrentApplicationId(HLERequestContext& ctx); | ||
| 20 | |||
| 21 | const std::shared_ptr<Applet> applet; | ||
| 22 | }; | ||
| 23 | |||
| 24 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp new file mode 100644 index 000000000..4d58c4db5 --- /dev/null +++ b/src/core/hle/service/am/applet_data_broker.cpp | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/scope_exit.h" | ||
| 5 | |||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/hle/service/am/am_results.h" | ||
| 8 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 9 | #include "core/hle/service/am/applet_manager.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context) | ||
| 14 | : m_event(context) {} | ||
| 15 | AppletStorageChannel::~AppletStorageChannel() = default; | ||
| 16 | |||
| 17 | void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) { | ||
| 18 | std::scoped_lock lk{m_lock}; | ||
| 19 | |||
| 20 | m_data.emplace_back(std::move(storage)); | ||
| 21 | m_event.Signal(); | ||
| 22 | } | ||
| 23 | |||
| 24 | Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) { | ||
| 25 | std::scoped_lock lk{m_lock}; | ||
| 26 | |||
| 27 | SCOPE_EXIT({ | ||
| 28 | if (m_data.empty()) { | ||
| 29 | m_event.Clear(); | ||
| 30 | } | ||
| 31 | }); | ||
| 32 | |||
| 33 | R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel); | ||
| 34 | |||
| 35 | *out_storage = std::move(m_data.front()); | ||
| 36 | m_data.pop_front(); | ||
| 37 | |||
| 38 | R_SUCCEED(); | ||
| 39 | } | ||
| 40 | |||
| 41 | Kernel::KReadableEvent* AppletStorageChannel::GetEvent() { | ||
| 42 | return m_event.GetHandle(); | ||
| 43 | } | ||
| 44 | |||
| 45 | AppletDataBroker::AppletDataBroker(Core::System& system_) | ||
| 46 | : system(system_), context(system_, "AppletDataBroker"), in_data(context), | ||
| 47 | interactive_in_data(context), out_data(context), interactive_out_data(context), | ||
| 48 | state_changed_event(context), is_completed(false) {} | ||
| 49 | |||
| 50 | AppletDataBroker::~AppletDataBroker() = default; | ||
| 51 | |||
| 52 | void AppletDataBroker::SignalCompletion() { | ||
| 53 | { | ||
| 54 | std::scoped_lock lk{lock}; | ||
| 55 | |||
| 56 | if (is_completed) { | ||
| 57 | return; | ||
| 58 | } | ||
| 59 | |||
| 60 | is_completed = true; | ||
| 61 | state_changed_event.Signal(); | ||
| 62 | } | ||
| 63 | |||
| 64 | system.GetAppletManager().FocusStateChanged(); | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_data_broker.h b/src/core/hle/service/am/applet_data_broker.h new file mode 100644 index 000000000..12326fd04 --- /dev/null +++ b/src/core/hle/service/am/applet_data_broker.h | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <deque> | ||
| 7 | #include <memory> | ||
| 8 | #include <mutex> | ||
| 9 | |||
| 10 | #include "core/hle/service/event.h" | ||
| 11 | #include "core/hle/service/kernel_helpers.h" | ||
| 12 | |||
| 13 | union Result; | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | struct Applet; | ||
| 18 | class IStorage; | ||
| 19 | |||
| 20 | class AppletStorageChannel { | ||
| 21 | public: | ||
| 22 | explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx); | ||
| 23 | ~AppletStorageChannel(); | ||
| 24 | |||
| 25 | void Push(std::shared_ptr<IStorage> storage); | ||
| 26 | Result Pop(std::shared_ptr<IStorage>* out_storage); | ||
| 27 | Kernel::KReadableEvent* GetEvent(); | ||
| 28 | |||
| 29 | private: | ||
| 30 | std::mutex m_lock{}; | ||
| 31 | std::deque<std::shared_ptr<IStorage>> m_data{}; | ||
| 32 | Event m_event; | ||
| 33 | }; | ||
| 34 | |||
| 35 | class AppletDataBroker { | ||
| 36 | public: | ||
| 37 | explicit AppletDataBroker(Core::System& system_); | ||
| 38 | ~AppletDataBroker(); | ||
| 39 | |||
| 40 | AppletStorageChannel& GetInData() { | ||
| 41 | return in_data; | ||
| 42 | } | ||
| 43 | |||
| 44 | AppletStorageChannel& GetInteractiveInData() { | ||
| 45 | return interactive_in_data; | ||
| 46 | } | ||
| 47 | |||
| 48 | AppletStorageChannel& GetOutData() { | ||
| 49 | return out_data; | ||
| 50 | } | ||
| 51 | |||
| 52 | AppletStorageChannel& GetInteractiveOutData() { | ||
| 53 | return interactive_out_data; | ||
| 54 | } | ||
| 55 | |||
| 56 | Event& GetStateChangedEvent() { | ||
| 57 | return state_changed_event; | ||
| 58 | } | ||
| 59 | |||
| 60 | bool IsCompleted() const { | ||
| 61 | return is_completed; | ||
| 62 | } | ||
| 63 | |||
| 64 | void SignalCompletion(); | ||
| 65 | |||
| 66 | private: | ||
| 67 | Core::System& system; | ||
| 68 | KernelHelpers::ServiceContext context; | ||
| 69 | |||
| 70 | AppletStorageChannel in_data; | ||
| 71 | AppletStorageChannel interactive_in_data; | ||
| 72 | AppletStorageChannel out_data; | ||
| 73 | AppletStorageChannel interactive_out_data; | ||
| 74 | Event state_changed_event; | ||
| 75 | |||
| 76 | std::mutex lock; | ||
| 77 | bool is_completed; | ||
| 78 | }; | ||
| 79 | |||
| 80 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp new file mode 100644 index 000000000..52200d5b2 --- /dev/null +++ b/src/core/hle/service/am/applet_manager.cpp | |||
| @@ -0,0 +1,361 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "common/uuid.h" | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/hle/service/acc/profile_manager.h" | ||
| 9 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 10 | #include "core/hle/service/am/applet_manager.h" | ||
| 11 | #include "core/hle/service/am/frontend/applet_cabinet.h" | ||
| 12 | #include "core/hle/service/am/frontend/applet_controller.h" | ||
| 13 | #include "core/hle/service/am/frontend/applet_mii_edit_types.h" | ||
| 14 | #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" | ||
| 15 | #include "hid_core/hid_types.h" | ||
| 16 | |||
| 17 | namespace Service::AM { | ||
| 18 | |||
| 19 | namespace { | ||
| 20 | |||
| 21 | constexpr u32 LaunchParameterAccountPreselectedUserMagic = 0xC79497CA; | ||
| 22 | |||
| 23 | struct LaunchParameterAccountPreselectedUser { | ||
| 24 | u32 magic; | ||
| 25 | u32 is_account_selected; | ||
| 26 | Common::UUID current_user; | ||
| 27 | INSERT_PADDING_BYTES(0x70); | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); | ||
| 30 | |||
| 31 | AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, | ||
| 32 | std::shared_ptr<Applet>& applet) { | ||
| 33 | applet->caller_applet_broker = std::make_shared<AppletDataBroker>(system); | ||
| 34 | return applet->caller_applet_broker->GetInData(); | ||
| 35 | } | ||
| 36 | |||
| 37 | void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { | ||
| 38 | const CommonArguments arguments{ | ||
| 39 | .arguments_version = CommonArgumentVersion::Version3, | ||
| 40 | .size = CommonArgumentSize::Version3, | ||
| 41 | .library_version = 1, | ||
| 42 | .theme_color = ThemeColor::BasicBlack, | ||
| 43 | .play_startup_sound = true, | ||
| 44 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 45 | }; | ||
| 46 | |||
| 47 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 48 | std::vector<u8> settings_data{2}; | ||
| 49 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 50 | channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); | ||
| 51 | channel.Push(std::make_shared<IStorage>(system, std::move(settings_data))); | ||
| 52 | } | ||
| 53 | |||
| 54 | void PushInShowController(Core::System& system, AppletStorageChannel& channel) { | ||
| 55 | const CommonArguments common_args = { | ||
| 56 | .arguments_version = CommonArgumentVersion::Version3, | ||
| 57 | .size = CommonArgumentSize::Version3, | ||
| 58 | .library_version = static_cast<u32>(Frontend::ControllerAppletVersion::Version8), | ||
| 59 | .theme_color = ThemeColor::BasicBlack, | ||
| 60 | .play_startup_sound = true, | ||
| 61 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 62 | }; | ||
| 63 | |||
| 64 | Frontend::ControllerSupportArgNew user_args = { | ||
| 65 | .header = {.player_count_min = 1, | ||
| 66 | .player_count_max = 4, | ||
| 67 | .enable_take_over_connection = true, | ||
| 68 | .enable_left_justify = false, | ||
| 69 | .enable_permit_joy_dual = true, | ||
| 70 | .enable_single_mode = false, | ||
| 71 | .enable_identification_color = false}, | ||
| 72 | .identification_colors = {}, | ||
| 73 | .enable_explain_text = false, | ||
| 74 | .explain_text = {}, | ||
| 75 | }; | ||
| 76 | |||
| 77 | Frontend::ControllerSupportArgPrivate private_args = { | ||
| 78 | .arg_private_size = sizeof(Frontend::ControllerSupportArgPrivate), | ||
| 79 | .arg_size = sizeof(Frontend::ControllerSupportArgNew), | ||
| 80 | .is_home_menu = true, | ||
| 81 | .flag_1 = true, | ||
| 82 | .mode = Frontend::ControllerSupportMode::ShowControllerSupport, | ||
| 83 | .caller = Frontend::ControllerSupportCaller:: | ||
| 84 | Application, // switchbrew: Always zero except with | ||
| 85 | // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, | ||
| 86 | // which sets this to the input param | ||
| 87 | .style_set = Core::HID::NpadStyleSet::None, | ||
| 88 | .joy_hold_type = 0, | ||
| 89 | }; | ||
| 90 | std::vector<u8> common_args_data(sizeof(common_args)); | ||
| 91 | std::vector<u8> private_args_data(sizeof(private_args)); | ||
| 92 | std::vector<u8> user_args_data(sizeof(user_args)); | ||
| 93 | |||
| 94 | std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); | ||
| 95 | std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); | ||
| 96 | std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); | ||
| 97 | |||
| 98 | channel.Push(std::make_shared<IStorage>(system, std::move(common_args_data))); | ||
| 99 | channel.Push(std::make_shared<IStorage>(system, std::move(private_args_data))); | ||
| 100 | channel.Push(std::make_shared<IStorage>(system, std::move(user_args_data))); | ||
| 101 | } | ||
| 102 | |||
| 103 | void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) { | ||
| 104 | const CommonArguments arguments{ | ||
| 105 | .arguments_version = CommonArgumentVersion::Version3, | ||
| 106 | .size = CommonArgumentSize::Version3, | ||
| 107 | .library_version = static_cast<u32>(Frontend::CabinetAppletVersion::Version1), | ||
| 108 | .theme_color = ThemeColor::BasicBlack, | ||
| 109 | .play_startup_sound = true, | ||
| 110 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 111 | }; | ||
| 112 | |||
| 113 | const Frontend::StartParamForAmiiboSettings amiibo_settings{ | ||
| 114 | .param_1 = 0, | ||
| 115 | .applet_mode = system.GetFrontendAppletHolder().GetCabinetMode(), | ||
| 116 | .flags = Frontend::CabinetFlags::None, | ||
| 117 | .amiibo_settings_1 = 0, | ||
| 118 | .device_handle = 0, | ||
| 119 | .tag_info{}, | ||
| 120 | .register_info{}, | ||
| 121 | .amiibo_settings_3{}, | ||
| 122 | }; | ||
| 123 | |||
| 124 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 125 | std::vector<u8> settings_data(sizeof(amiibo_settings)); | ||
| 126 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 127 | std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); | ||
| 128 | channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); | ||
| 129 | channel.Push(std::make_shared<IStorage>(system, std::move(settings_data))); | ||
| 130 | } | ||
| 131 | |||
| 132 | void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) { | ||
| 133 | struct MiiEditV3 { | ||
| 134 | Frontend::MiiEditAppletInputCommon common; | ||
| 135 | Frontend::MiiEditAppletInputV3 input; | ||
| 136 | }; | ||
| 137 | static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size."); | ||
| 138 | |||
| 139 | MiiEditV3 mii_arguments{ | ||
| 140 | .common = | ||
| 141 | { | ||
| 142 | .version = Frontend::MiiEditAppletVersion::Version3, | ||
| 143 | .applet_mode = Frontend::MiiEditAppletMode::ShowMiiEdit, | ||
| 144 | }, | ||
| 145 | .input{}, | ||
| 146 | }; | ||
| 147 | |||
| 148 | std::vector<u8> argument_data(sizeof(mii_arguments)); | ||
| 149 | std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); | ||
| 150 | |||
| 151 | channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); | ||
| 152 | } | ||
| 153 | |||
| 154 | void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) { | ||
| 155 | const CommonArguments arguments{ | ||
| 156 | .arguments_version = CommonArgumentVersion::Version3, | ||
| 157 | .size = CommonArgumentSize::Version3, | ||
| 158 | .library_version = static_cast<u32>(Frontend::SwkbdAppletVersion::Version524301), | ||
| 159 | .theme_color = ThemeColor::BasicBlack, | ||
| 160 | .play_startup_sound = true, | ||
| 161 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 162 | }; | ||
| 163 | |||
| 164 | std::vector<char16_t> initial_string(0); | ||
| 165 | |||
| 166 | const Frontend::SwkbdConfigCommon swkbd_config{ | ||
| 167 | .type = Frontend::SwkbdType::Qwerty, | ||
| 168 | .ok_text{}, | ||
| 169 | .left_optional_symbol_key{}, | ||
| 170 | .right_optional_symbol_key{}, | ||
| 171 | .use_prediction = false, | ||
| 172 | .key_disable_flags{}, | ||
| 173 | .initial_cursor_position = Frontend::SwkbdInitialCursorPosition::Start, | ||
| 174 | .header_text{}, | ||
| 175 | .sub_text{}, | ||
| 176 | .guide_text{}, | ||
| 177 | .max_text_length = 500, | ||
| 178 | .min_text_length = 0, | ||
| 179 | .password_mode = Frontend::SwkbdPasswordMode::Disabled, | ||
| 180 | .text_draw_type = Frontend::SwkbdTextDrawType::Box, | ||
| 181 | .enable_return_button = true, | ||
| 182 | .use_utf8 = false, | ||
| 183 | .use_blur_background = true, | ||
| 184 | .initial_string_offset{}, | ||
| 185 | .initial_string_length = static_cast<u32>(initial_string.size()), | ||
| 186 | .user_dictionary_offset{}, | ||
| 187 | .user_dictionary_entries{}, | ||
| 188 | .use_text_check = false, | ||
| 189 | }; | ||
| 190 | |||
| 191 | Frontend::SwkbdConfigNew swkbd_config_new{}; | ||
| 192 | |||
| 193 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 194 | std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new)); | ||
| 195 | std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 196 | |||
| 197 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 198 | std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config)); | ||
| 199 | std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new, | ||
| 200 | sizeof(Frontend::SwkbdConfigNew)); | ||
| 201 | std::memcpy(work_buffer.data(), initial_string.data(), | ||
| 202 | swkbd_config.initial_string_length * sizeof(char16_t)); | ||
| 203 | |||
| 204 | channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); | ||
| 205 | channel.Push(std::make_shared<IStorage>(system, std::move(swkbd_data))); | ||
| 206 | channel.Push(std::make_shared<IStorage>(system, std::move(work_buffer))); | ||
| 207 | } | ||
| 208 | |||
| 209 | } // namespace | ||
| 210 | |||
| 211 | AppletManager::AppletManager(Core::System& system) : m_system(system) {} | ||
| 212 | AppletManager::~AppletManager() { | ||
| 213 | this->Reset(); | ||
| 214 | } | ||
| 215 | |||
| 216 | void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) { | ||
| 217 | std::scoped_lock lk{m_lock}; | ||
| 218 | |||
| 219 | m_applets.emplace(applet->aruid, std::move(applet)); | ||
| 220 | } | ||
| 221 | |||
| 222 | void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) { | ||
| 223 | std::shared_ptr<Applet> applet; | ||
| 224 | bool should_stop = false; | ||
| 225 | { | ||
| 226 | std::scoped_lock lk{m_lock}; | ||
| 227 | |||
| 228 | const auto it = m_applets.find(aruid); | ||
| 229 | if (it == m_applets.end()) { | ||
| 230 | return; | ||
| 231 | } | ||
| 232 | |||
| 233 | applet = it->second; | ||
| 234 | m_applets.erase(it); | ||
| 235 | |||
| 236 | should_stop = m_applets.empty(); | ||
| 237 | } | ||
| 238 | |||
| 239 | // Terminate process. | ||
| 240 | applet->process->Terminate(); | ||
| 241 | |||
| 242 | // If there were no applets left, stop emulation. | ||
| 243 | if (should_stop) { | ||
| 244 | m_system.Exit(); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | void AppletManager::CreateAndInsertByFrontendAppletParameters( | ||
| 249 | AppletResourceUserId aruid, const FrontendAppletParameters& params) { | ||
| 250 | // TODO: this should be run inside AM so that the events will have a parent process | ||
| 251 | // TODO: have am create the guest process | ||
| 252 | auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system)); | ||
| 253 | |||
| 254 | applet->aruid = aruid; | ||
| 255 | applet->program_id = params.program_id; | ||
| 256 | applet->applet_id = params.applet_id; | ||
| 257 | applet->type = params.applet_type; | ||
| 258 | applet->previous_program_index = params.previous_program_index; | ||
| 259 | |||
| 260 | // Push UserChannel data from previous application | ||
| 261 | if (params.launch_type == LaunchType::ApplicationInitiated) { | ||
| 262 | applet->user_channel_launch_parameter.swap(m_system.GetUserChannel()); | ||
| 263 | } | ||
| 264 | |||
| 265 | // TODO: Read whether we need a preselected user from NACP? | ||
| 266 | // TODO: This can be done quite easily from loader | ||
| 267 | { | ||
| 268 | LaunchParameterAccountPreselectedUser lp{}; | ||
| 269 | |||
| 270 | lp.magic = LaunchParameterAccountPreselectedUserMagic; | ||
| 271 | lp.is_account_selected = 1; | ||
| 272 | |||
| 273 | Account::ProfileManager profile_manager{}; | ||
| 274 | const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user)); | ||
| 275 | ASSERT(uuid.has_value() && uuid->IsValid()); | ||
| 276 | lp.current_user = *uuid; | ||
| 277 | |||
| 278 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | ||
| 279 | std::memcpy(buffer.data(), &lp, buffer.size()); | ||
| 280 | |||
| 281 | applet->preselected_user_launch_parameter.push_back(std::move(buffer)); | ||
| 282 | } | ||
| 283 | |||
| 284 | // Starting from frontend, some applets require input data. | ||
| 285 | switch (applet->applet_id) { | ||
| 286 | case AppletId::Cabinet: | ||
| 287 | PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet)); | ||
| 288 | break; | ||
| 289 | case AppletId::MiiEdit: | ||
| 290 | PushInShowMiiEditData(m_system, InitializeFakeCallerApplet(m_system, applet)); | ||
| 291 | break; | ||
| 292 | case AppletId::PhotoViewer: | ||
| 293 | PushInShowAlbum(m_system, InitializeFakeCallerApplet(m_system, applet)); | ||
| 294 | break; | ||
| 295 | case AppletId::SoftwareKeyboard: | ||
| 296 | PushInShowSoftwareKeyboard(m_system, InitializeFakeCallerApplet(m_system, applet)); | ||
| 297 | break; | ||
| 298 | case AppletId::Controller: | ||
| 299 | PushInShowController(m_system, InitializeFakeCallerApplet(m_system, applet)); | ||
| 300 | break; | ||
| 301 | default: | ||
| 302 | break; | ||
| 303 | } | ||
| 304 | |||
| 305 | // Applet was started by frontend, so it is foreground. | ||
| 306 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 307 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 308 | applet->focus_state = FocusState::InFocus; | ||
| 309 | |||
| 310 | this->InsertApplet(std::move(applet)); | ||
| 311 | } | ||
| 312 | |||
| 313 | std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const { | ||
| 314 | std::scoped_lock lk{m_lock}; | ||
| 315 | |||
| 316 | if (const auto it = m_applets.find(aruid); it != m_applets.end()) { | ||
| 317 | return it->second; | ||
| 318 | } | ||
| 319 | |||
| 320 | return {}; | ||
| 321 | } | ||
| 322 | |||
| 323 | void AppletManager::Reset() { | ||
| 324 | std::scoped_lock lk{m_lock}; | ||
| 325 | |||
| 326 | m_applets.clear(); | ||
| 327 | } | ||
| 328 | |||
| 329 | void AppletManager::RequestExit() { | ||
| 330 | std::scoped_lock lk{m_lock}; | ||
| 331 | |||
| 332 | for (const auto& [aruid, applet] : m_applets) { | ||
| 333 | applet->message_queue.RequestExit(); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | void AppletManager::RequestResume() { | ||
| 338 | std::scoped_lock lk{m_lock}; | ||
| 339 | |||
| 340 | for (const auto& [aruid, applet] : m_applets) { | ||
| 341 | applet->message_queue.RequestResume(); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | void AppletManager::OperationModeChanged() { | ||
| 346 | std::scoped_lock lk{m_lock}; | ||
| 347 | |||
| 348 | for (const auto& [aruid, applet] : m_applets) { | ||
| 349 | applet->message_queue.OperationModeChanged(); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | void AppletManager::FocusStateChanged() { | ||
| 354 | std::scoped_lock lk{m_lock}; | ||
| 355 | |||
| 356 | for (const auto& [aruid, applet] : m_applets) { | ||
| 357 | applet->message_queue.FocusStateChanged(); | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_manager.h b/src/core/hle/service/am/applet_manager.h new file mode 100644 index 000000000..4875de309 --- /dev/null +++ b/src/core/hle/service/am/applet_manager.h | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <map> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "core/hle/service/am/applet.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | enum class LaunchType { | ||
| 18 | FrontendInitiated, | ||
| 19 | ApplicationInitiated, | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct FrontendAppletParameters { | ||
| 23 | ProgramId program_id{}; | ||
| 24 | AppletId applet_id{}; | ||
| 25 | AppletType applet_type{}; | ||
| 26 | LaunchType launch_type{}; | ||
| 27 | s32 program_index{}; | ||
| 28 | s32 previous_program_index{-1}; | ||
| 29 | }; | ||
| 30 | |||
| 31 | class AppletManager { | ||
| 32 | public: | ||
| 33 | explicit AppletManager(Core::System& system); | ||
| 34 | ~AppletManager(); | ||
| 35 | |||
| 36 | void InsertApplet(std::shared_ptr<Applet> applet); | ||
| 37 | void TerminateAndRemoveApplet(AppletResourceUserId aruid); | ||
| 38 | |||
| 39 | void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid, | ||
| 40 | const FrontendAppletParameters& params); | ||
| 41 | std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const; | ||
| 42 | |||
| 43 | void Reset(); | ||
| 44 | |||
| 45 | void RequestExit(); | ||
| 46 | void RequestResume(); | ||
| 47 | void OperationModeChanged(); | ||
| 48 | void FocusStateChanged(); | ||
| 49 | |||
| 50 | private: | ||
| 51 | Core::System& m_system; | ||
| 52 | |||
| 53 | mutable std::mutex m_lock{}; | ||
| 54 | std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{}; | ||
| 55 | |||
| 56 | // AudioController state goes here | ||
| 57 | }; | ||
| 58 | |||
| 59 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp new file mode 100644 index 000000000..5ed996b70 --- /dev/null +++ b/src/core/hle/service/am/applet_message_queue.cpp | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | AppletMessageQueue::AppletMessageQueue(Core::System& system) | ||
| 10 | : service_context{system, "AppletMessageQueue"} { | ||
| 11 | on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); | ||
| 12 | on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged"); | ||
| 13 | } | ||
| 14 | |||
| 15 | AppletMessageQueue::~AppletMessageQueue() { | ||
| 16 | service_context.CloseEvent(on_new_message); | ||
| 17 | service_context.CloseEvent(on_operation_mode_changed); | ||
| 18 | } | ||
| 19 | |||
| 20 | Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() { | ||
| 21 | return on_new_message->GetReadableEvent(); | ||
| 22 | } | ||
| 23 | |||
| 24 | Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { | ||
| 25 | return on_operation_mode_changed->GetReadableEvent(); | ||
| 26 | } | ||
| 27 | |||
| 28 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | ||
| 29 | { | ||
| 30 | std::scoped_lock lk{lock}; | ||
| 31 | messages.push(msg); | ||
| 32 | } | ||
| 33 | on_new_message->Signal(); | ||
| 34 | } | ||
| 35 | |||
| 36 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | ||
| 37 | std::scoped_lock lk{lock}; | ||
| 38 | if (messages.empty()) { | ||
| 39 | on_new_message->Clear(); | ||
| 40 | return AppletMessage::None; | ||
| 41 | } | ||
| 42 | auto msg = messages.front(); | ||
| 43 | messages.pop(); | ||
| 44 | if (messages.empty()) { | ||
| 45 | on_new_message->Clear(); | ||
| 46 | } | ||
| 47 | return msg; | ||
| 48 | } | ||
| 49 | |||
| 50 | std::size_t AppletMessageQueue::GetMessageCount() const { | ||
| 51 | std::scoped_lock lk{lock}; | ||
| 52 | return messages.size(); | ||
| 53 | } | ||
| 54 | |||
| 55 | void AppletMessageQueue::RequestExit() { | ||
| 56 | PushMessage(AppletMessage::Exit); | ||
| 57 | } | ||
| 58 | |||
| 59 | void AppletMessageQueue::RequestResume() { | ||
| 60 | PushMessage(AppletMessage::Resume); | ||
| 61 | } | ||
| 62 | |||
| 63 | void AppletMessageQueue::FocusStateChanged() { | ||
| 64 | PushMessage(AppletMessage::FocusStateChanged); | ||
| 65 | } | ||
| 66 | |||
| 67 | void AppletMessageQueue::OperationModeChanged() { | ||
| 68 | PushMessage(AppletMessage::OperationModeChanged); | ||
| 69 | PushMessage(AppletMessage::PerformanceModeChanged); | ||
| 70 | on_operation_mode_changed->Signal(); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h new file mode 100644 index 000000000..5cb236d47 --- /dev/null +++ b/src/core/hle/service/am/applet_message_queue.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <queue> | ||
| 7 | |||
| 8 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | class KReadableEvent; | ||
| 13 | } // namespace Kernel | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | class AppletMessageQueue { | ||
| 18 | public: | ||
| 19 | // This is nn::am::AppletMessage | ||
| 20 | enum class AppletMessage : u32 { | ||
| 21 | None = 0, | ||
| 22 | ChangeIntoForeground = 1, | ||
| 23 | ChangeIntoBackground = 2, | ||
| 24 | Exit = 4, | ||
| 25 | ApplicationExited = 6, | ||
| 26 | FocusStateChanged = 15, | ||
| 27 | Resume = 16, | ||
| 28 | DetectShortPressingHomeButton = 20, | ||
| 29 | DetectLongPressingHomeButton = 21, | ||
| 30 | DetectShortPressingPowerButton = 22, | ||
| 31 | DetectMiddlePressingPowerButton = 23, | ||
| 32 | DetectLongPressingPowerButton = 24, | ||
| 33 | RequestToPrepareSleep = 25, | ||
| 34 | FinishedSleepSequence = 26, | ||
| 35 | SleepRequiredByHighTemperature = 27, | ||
| 36 | SleepRequiredByLowBattery = 28, | ||
| 37 | AutoPowerDown = 29, | ||
| 38 | OperationModeChanged = 30, | ||
| 39 | PerformanceModeChanged = 31, | ||
| 40 | DetectReceivingCecSystemStandby = 32, | ||
| 41 | SdCardRemoved = 33, | ||
| 42 | LaunchApplicationRequested = 50, | ||
| 43 | RequestToDisplay = 51, | ||
| 44 | ShowApplicationLogo = 55, | ||
| 45 | HideApplicationLogo = 56, | ||
| 46 | ForceHideApplicationLogo = 57, | ||
| 47 | FloatingApplicationDetected = 60, | ||
| 48 | DetectShortPressingCaptureButton = 90, | ||
| 49 | AlbumScreenShotTaken = 92, | ||
| 50 | AlbumRecordingSaved = 93, | ||
| 51 | }; | ||
| 52 | |||
| 53 | explicit AppletMessageQueue(Core::System& system); | ||
| 54 | ~AppletMessageQueue(); | ||
| 55 | |||
| 56 | Kernel::KReadableEvent& GetMessageReceiveEvent(); | ||
| 57 | Kernel::KReadableEvent& GetOperationModeChangedEvent(); | ||
| 58 | void PushMessage(AppletMessage msg); | ||
| 59 | AppletMessage PopMessage(); | ||
| 60 | std::size_t GetMessageCount() const; | ||
| 61 | void RequestExit(); | ||
| 62 | void RequestResume(); | ||
| 63 | void FocusStateChanged(); | ||
| 64 | void OperationModeChanged(); | ||
| 65 | |||
| 66 | private: | ||
| 67 | KernelHelpers::ServiceContext service_context; | ||
| 68 | |||
| 69 | Kernel::KEvent* on_new_message; | ||
| 70 | Kernel::KEvent* on_operation_mode_changed; | ||
| 71 | |||
| 72 | mutable std::mutex lock; | ||
| 73 | std::queue<AppletMessage> messages; | ||
| 74 | }; | ||
| 75 | |||
| 76 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index d6c565d85..56bafd162 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -1,129 +1,42 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/hle/service/am/am.h" | 4 | #include "core/hle/service/am/am.h" |
| 5 | #include "core/hle/service/am/applet_manager.h" | ||
| 6 | #include "core/hle/service/am/applet_oe.h" | 6 | #include "core/hle/service/am/applet_oe.h" |
| 7 | #include "core/hle/service/am/application_proxy.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 8 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 9 | 9 | ||
| 10 | namespace Service::AM { | 10 | namespace Service::AM { |
| 11 | 11 | ||
| 12 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | 12 | AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) |
| 13 | public: | 13 | : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} { |
| 14 | explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | 14 | static const FunctionInfo functions[] = { |
| 15 | std::shared_ptr<AppletMessageQueue> msg_queue_, | 15 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, |
| 16 | Core::System& system_) | 16 | }; |
| 17 | : ServiceFramework{system_, "IApplicationProxy"}, | 17 | RegisterHandlers(functions); |
| 18 | nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} { | 18 | } |
| 19 | // clang-format off | ||
| 20 | static const FunctionInfo functions[] = { | ||
| 21 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 22 | {1, &IApplicationProxy::GetSelfController, "GetSelfController"}, | ||
| 23 | {2, &IApplicationProxy::GetWindowController, "GetWindowController"}, | ||
| 24 | {3, &IApplicationProxy::GetAudioController, "GetAudioController"}, | ||
| 25 | {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"}, | ||
| 26 | {10, nullptr, "GetProcessWindingController"}, | ||
| 27 | {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 28 | {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"}, | ||
| 29 | {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 30 | }; | ||
| 31 | // clang-format on | ||
| 32 | |||
| 33 | RegisterHandlers(functions); | ||
| 34 | } | ||
| 35 | |||
| 36 | private: | ||
| 37 | void GetAudioController(HLERequestContext& ctx) { | ||
| 38 | LOG_DEBUG(Service_AM, "called"); | ||
| 39 | |||
| 40 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 41 | rb.Push(ResultSuccess); | ||
| 42 | rb.PushIpcInterface<IAudioController>(system); | ||
| 43 | } | ||
| 44 | |||
| 45 | void GetDisplayController(HLERequestContext& ctx) { | ||
| 46 | LOG_DEBUG(Service_AM, "called"); | ||
| 47 | |||
| 48 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 49 | rb.Push(ResultSuccess); | ||
| 50 | rb.PushIpcInterface<IDisplayController>(system); | ||
| 51 | } | ||
| 52 | |||
| 53 | void GetDebugFunctions(HLERequestContext& ctx) { | ||
| 54 | LOG_DEBUG(Service_AM, "called"); | ||
| 55 | |||
| 56 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 57 | rb.Push(ResultSuccess); | ||
| 58 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 59 | } | ||
| 60 | |||
| 61 | void GetWindowController(HLERequestContext& ctx) { | ||
| 62 | LOG_DEBUG(Service_AM, "called"); | ||
| 63 | |||
| 64 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 65 | rb.Push(ResultSuccess); | ||
| 66 | rb.PushIpcInterface<IWindowController>(system); | ||
| 67 | } | ||
| 68 | |||
| 69 | void GetSelfController(HLERequestContext& ctx) { | ||
| 70 | LOG_DEBUG(Service_AM, "called"); | ||
| 71 | |||
| 72 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 73 | rb.Push(ResultSuccess); | ||
| 74 | rb.PushIpcInterface<ISelfController>(system, nvnflinger); | ||
| 75 | } | ||
| 76 | |||
| 77 | void GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 78 | LOG_DEBUG(Service_AM, "called"); | ||
| 79 | 19 | ||
| 80 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 20 | AppletOE::~AppletOE() = default; |
| 81 | rb.Push(ResultSuccess); | ||
| 82 | rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue); | ||
| 83 | } | ||
| 84 | 21 | ||
| 85 | void GetLibraryAppletCreator(HLERequestContext& ctx) { | 22 | void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { |
| 86 | LOG_DEBUG(Service_AM, "called"); | 23 | LOG_DEBUG(Service_AM, "called"); |
| 87 | 24 | ||
| 25 | if (const auto applet = GetAppletFromContext(ctx)) { | ||
| 88 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 26 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 89 | rb.Push(ResultSuccess); | 27 | rb.Push(ResultSuccess); |
| 90 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | 28 | rb.PushIpcInterface<IApplicationProxy>(nvnflinger, applet, system); |
| 91 | } | 29 | } else { |
| 92 | 30 | UNIMPLEMENTED(); | |
| 93 | void GetApplicationFunctions(HLERequestContext& ctx) { | ||
| 94 | LOG_DEBUG(Service_AM, "called"); | ||
| 95 | 31 | ||
| 96 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 32 | IPC::ResponseBuilder rb{ctx, 2}; |
| 97 | rb.Push(ResultSuccess); | 33 | rb.Push(ResultUnknown); |
| 98 | rb.PushIpcInterface<IApplicationFunctions>(system); | ||
| 99 | } | 34 | } |
| 100 | |||
| 101 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 102 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 103 | }; | ||
| 104 | |||
| 105 | void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { | ||
| 106 | LOG_DEBUG(Service_AM, "called"); | ||
| 107 | |||
| 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 109 | rb.Push(ResultSuccess); | ||
| 110 | rb.PushIpcInterface<IApplicationProxy>(nvnflinger, msg_queue, system); | ||
| 111 | } | ||
| 112 | |||
| 113 | AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 114 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_) | ||
| 115 | : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, msg_queue{ | ||
| 116 | std::move(msg_queue_)} { | ||
| 117 | static const FunctionInfo functions[] = { | ||
| 118 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, | ||
| 119 | }; | ||
| 120 | RegisterHandlers(functions); | ||
| 121 | } | 35 | } |
| 122 | 36 | ||
| 123 | AppletOE::~AppletOE() = default; | 37 | std::shared_ptr<Applet> AppletOE::GetAppletFromContext(HLERequestContext& ctx) { |
| 124 | 38 | const auto aruid = ctx.GetPID(); | |
| 125 | const std::shared_ptr<AppletMessageQueue>& AppletOE::GetMessageQueue() const { | 39 | return system.GetAppletManager().GetByAppletResourceUserId(aruid); |
| 126 | return msg_queue; | ||
| 127 | } | 40 | } |
| 128 | 41 | ||
| 129 | } // namespace Service::AM | 42 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 39eccc4ab..f2ba1c924 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h | |||
| @@ -18,21 +18,19 @@ class Nvnflinger; | |||
| 18 | 18 | ||
| 19 | namespace AM { | 19 | namespace AM { |
| 20 | 20 | ||
| 21 | class AppletMessageQueue; | 21 | struct Applet; |
| 22 | 22 | ||
| 23 | class AppletOE final : public ServiceFramework<AppletOE> { | 23 | class AppletOE final : public ServiceFramework<AppletOE> { |
| 24 | public: | 24 | public: |
| 25 | explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, | 25 | explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); |
| 26 | std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); | ||
| 27 | ~AppletOE() override; | 26 | ~AppletOE() override; |
| 28 | 27 | ||
| 29 | const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; | ||
| 30 | |||
| 31 | private: | 28 | private: |
| 32 | void OpenApplicationProxy(HLERequestContext& ctx); | 29 | void OpenApplicationProxy(HLERequestContext& ctx); |
| 33 | 30 | ||
| 31 | std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx); | ||
| 32 | |||
| 34 | Nvnflinger::Nvnflinger& nvnflinger; | 33 | Nvnflinger::Nvnflinger& nvnflinger; |
| 35 | std::shared_ptr<AppletMessageQueue> msg_queue; | ||
| 36 | }; | 34 | }; |
| 37 | 35 | ||
| 38 | } // namespace AM | 36 | } // namespace AM |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp deleted file mode 100644 index 89d5434af..000000000 --- a/src/core/hle/service/am/applets/applets.cpp +++ /dev/null | |||
| @@ -1,338 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | |||
| 6 | #include "common/assert.h" | ||
| 7 | #include "core/core.h" | ||
| 8 | #include "core/frontend/applets/cabinet.h" | ||
| 9 | #include "core/frontend/applets/controller.h" | ||
| 10 | #include "core/frontend/applets/error.h" | ||
| 11 | #include "core/frontend/applets/general_frontend.h" | ||
| 12 | #include "core/frontend/applets/mii_edit.h" | ||
| 13 | #include "core/frontend/applets/profile_select.h" | ||
| 14 | #include "core/frontend/applets/software_keyboard.h" | ||
| 15 | #include "core/frontend/applets/web_browser.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | ||
| 17 | #include "core/hle/service/am/am.h" | ||
| 18 | #include "core/hle/service/am/applet_ae.h" | ||
| 19 | #include "core/hle/service/am/applet_oe.h" | ||
| 20 | #include "core/hle/service/am/applets/applet_cabinet.h" | ||
| 21 | #include "core/hle/service/am/applets/applet_controller.h" | ||
| 22 | #include "core/hle/service/am/applets/applet_error.h" | ||
| 23 | #include "core/hle/service/am/applets/applet_general_backend.h" | ||
| 24 | #include "core/hle/service/am/applets/applet_mii_edit.h" | ||
| 25 | #include "core/hle/service/am/applets/applet_profile_select.h" | ||
| 26 | #include "core/hle/service/am/applets/applet_software_keyboard.h" | ||
| 27 | #include "core/hle/service/am/applets/applet_web_browser.h" | ||
| 28 | #include "core/hle/service/am/applets/applets.h" | ||
| 29 | #include "core/hle/service/sm/sm.h" | ||
| 30 | |||
| 31 | namespace Service::AM::Applets { | ||
| 32 | |||
| 33 | AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) | ||
| 34 | : system{system_}, applet_mode{applet_mode_}, service_context{system, | ||
| 35 | "ILibraryAppletAccessor"} { | ||
| 36 | state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent"); | ||
| 37 | pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent"); | ||
| 38 | pop_interactive_out_data_event = | ||
| 39 | service_context.CreateEvent("ILibraryAppletAccessor:PopInteractiveDataOutEvent"); | ||
| 40 | } | ||
| 41 | |||
| 42 | AppletDataBroker::~AppletDataBroker() { | ||
| 43 | service_context.CloseEvent(state_changed_event); | ||
| 44 | service_context.CloseEvent(pop_out_data_event); | ||
| 45 | service_context.CloseEvent(pop_interactive_out_data_event); | ||
| 46 | } | ||
| 47 | |||
| 48 | AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const { | ||
| 49 | std::vector<std::vector<u8>> out_normal; | ||
| 50 | |||
| 51 | for (const auto& storage : in_channel) { | ||
| 52 | out_normal.push_back(storage->GetData()); | ||
| 53 | } | ||
| 54 | |||
| 55 | std::vector<std::vector<u8>> out_interactive; | ||
| 56 | |||
| 57 | for (const auto& storage : in_interactive_channel) { | ||
| 58 | out_interactive.push_back(storage->GetData()); | ||
| 59 | } | ||
| 60 | |||
| 61 | return {std::move(out_normal), std::move(out_interactive)}; | ||
| 62 | } | ||
| 63 | |||
| 64 | std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { | ||
| 65 | if (out_channel.empty()) | ||
| 66 | return nullptr; | ||
| 67 | |||
| 68 | auto out = std::move(out_channel.front()); | ||
| 69 | out_channel.pop_front(); | ||
| 70 | pop_out_data_event->Clear(); | ||
| 71 | return out; | ||
| 72 | } | ||
| 73 | |||
| 74 | std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() { | ||
| 75 | if (in_channel.empty()) | ||
| 76 | return nullptr; | ||
| 77 | |||
| 78 | auto out = std::move(in_channel.front()); | ||
| 79 | in_channel.pop_front(); | ||
| 80 | return out; | ||
| 81 | } | ||
| 82 | |||
| 83 | std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { | ||
| 84 | if (out_interactive_channel.empty()) | ||
| 85 | return nullptr; | ||
| 86 | |||
| 87 | auto out = std::move(out_interactive_channel.front()); | ||
| 88 | out_interactive_channel.pop_front(); | ||
| 89 | pop_interactive_out_data_event->Clear(); | ||
| 90 | return out; | ||
| 91 | } | ||
| 92 | |||
| 93 | std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() { | ||
| 94 | if (in_interactive_channel.empty()) | ||
| 95 | return nullptr; | ||
| 96 | |||
| 97 | auto out = std::move(in_interactive_channel.front()); | ||
| 98 | in_interactive_channel.pop_front(); | ||
| 99 | return out; | ||
| 100 | } | ||
| 101 | |||
| 102 | void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage) { | ||
| 103 | in_channel.emplace_back(std::move(storage)); | ||
| 104 | } | ||
| 105 | |||
| 106 | void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { | ||
| 107 | out_channel.emplace_back(std::move(storage)); | ||
| 108 | pop_out_data_event->Signal(); | ||
| 109 | } | ||
| 110 | |||
| 111 | void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { | ||
| 112 | in_interactive_channel.emplace_back(std::move(storage)); | ||
| 113 | } | ||
| 114 | |||
| 115 | void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { | ||
| 116 | out_interactive_channel.emplace_back(std::move(storage)); | ||
| 117 | pop_interactive_out_data_event->Signal(); | ||
| 118 | } | ||
| 119 | |||
| 120 | void AppletDataBroker::SignalStateChanged() { | ||
| 121 | state_changed_event->Signal(); | ||
| 122 | |||
| 123 | switch (applet_mode) { | ||
| 124 | case LibraryAppletMode::AllForeground: | ||
| 125 | case LibraryAppletMode::AllForegroundInitiallyHidden: { | ||
| 126 | auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE"); | ||
| 127 | auto applet_ae = system.ServiceManager().GetService<AppletAE>("appletAE"); | ||
| 128 | |||
| 129 | if (applet_oe) { | ||
| 130 | applet_oe->GetMessageQueue()->FocusStateChanged(); | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (applet_ae) { | ||
| 135 | applet_ae->GetMessageQueue()->FocusStateChanged(); | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | default: | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | Kernel::KReadableEvent& AppletDataBroker::GetNormalDataEvent() { | ||
| 146 | return pop_out_data_event->GetReadableEvent(); | ||
| 147 | } | ||
| 148 | |||
| 149 | Kernel::KReadableEvent& AppletDataBroker::GetInteractiveDataEvent() { | ||
| 150 | return pop_interactive_out_data_event->GetReadableEvent(); | ||
| 151 | } | ||
| 152 | |||
| 153 | Kernel::KReadableEvent& AppletDataBroker::GetStateChangedEvent() { | ||
| 154 | return state_changed_event->GetReadableEvent(); | ||
| 155 | } | ||
| 156 | |||
| 157 | Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_) | ||
| 158 | : broker{system_, applet_mode_}, applet_mode{applet_mode_} {} | ||
| 159 | |||
| 160 | Applet::~Applet() = default; | ||
| 161 | |||
| 162 | void Applet::Initialize() { | ||
| 163 | const auto common = broker.PopNormalDataToApplet(); | ||
| 164 | ASSERT(common != nullptr); | ||
| 165 | |||
| 166 | const auto common_data = common->GetData(); | ||
| 167 | |||
| 168 | ASSERT(common_data.size() >= sizeof(CommonArguments)); | ||
| 169 | std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments)); | ||
| 170 | |||
| 171 | initialized = true; | ||
| 172 | } | ||
| 173 | |||
| 174 | AppletFrontendSet::AppletFrontendSet() = default; | ||
| 175 | |||
| 176 | AppletFrontendSet::AppletFrontendSet(CabinetApplet cabinet_applet, | ||
| 177 | ControllerApplet controller_applet, ErrorApplet error_applet, | ||
| 178 | MiiEdit mii_edit_, | ||
| 179 | ParentalControlsApplet parental_controls_applet, | ||
| 180 | PhotoViewer photo_viewer_, ProfileSelect profile_select_, | ||
| 181 | SoftwareKeyboard software_keyboard_, WebBrowser web_browser_) | ||
| 182 | : cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)}, | ||
| 183 | error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)}, | ||
| 184 | parental_controls{std::move(parental_controls_applet)}, | ||
| 185 | photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)}, | ||
| 186 | software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {} | ||
| 187 | |||
| 188 | AppletFrontendSet::~AppletFrontendSet() = default; | ||
| 189 | |||
| 190 | AppletFrontendSet::AppletFrontendSet(AppletFrontendSet&&) noexcept = default; | ||
| 191 | |||
| 192 | AppletFrontendSet& AppletFrontendSet::operator=(AppletFrontendSet&&) noexcept = default; | ||
| 193 | |||
| 194 | AppletManager::AppletManager(Core::System& system_) : system{system_} {} | ||
| 195 | |||
| 196 | AppletManager::~AppletManager() = default; | ||
| 197 | |||
| 198 | const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const { | ||
| 199 | return frontend; | ||
| 200 | } | ||
| 201 | |||
| 202 | NFP::CabinetMode AppletManager::GetCabinetMode() const { | ||
| 203 | return cabinet_mode; | ||
| 204 | } | ||
| 205 | |||
| 206 | AppletId AppletManager::GetCurrentAppletId() const { | ||
| 207 | return current_applet_id; | ||
| 208 | } | ||
| 209 | |||
| 210 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | ||
| 211 | if (set.cabinet != nullptr) { | ||
| 212 | frontend.cabinet = std::move(set.cabinet); | ||
| 213 | } | ||
| 214 | |||
| 215 | if (set.controller != nullptr) { | ||
| 216 | frontend.controller = std::move(set.controller); | ||
| 217 | } | ||
| 218 | |||
| 219 | if (set.error != nullptr) { | ||
| 220 | frontend.error = std::move(set.error); | ||
| 221 | } | ||
| 222 | |||
| 223 | if (set.mii_edit != nullptr) { | ||
| 224 | frontend.mii_edit = std::move(set.mii_edit); | ||
| 225 | } | ||
| 226 | |||
| 227 | if (set.parental_controls != nullptr) { | ||
| 228 | frontend.parental_controls = std::move(set.parental_controls); | ||
| 229 | } | ||
| 230 | |||
| 231 | if (set.photo_viewer != nullptr) { | ||
| 232 | frontend.photo_viewer = std::move(set.photo_viewer); | ||
| 233 | } | ||
| 234 | |||
| 235 | if (set.profile_select != nullptr) { | ||
| 236 | frontend.profile_select = std::move(set.profile_select); | ||
| 237 | } | ||
| 238 | |||
| 239 | if (set.software_keyboard != nullptr) { | ||
| 240 | frontend.software_keyboard = std::move(set.software_keyboard); | ||
| 241 | } | ||
| 242 | |||
| 243 | if (set.web_browser != nullptr) { | ||
| 244 | frontend.web_browser = std::move(set.web_browser); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | void AppletManager::SetCabinetMode(NFP::CabinetMode mode) { | ||
| 249 | cabinet_mode = mode; | ||
| 250 | } | ||
| 251 | |||
| 252 | void AppletManager::SetCurrentAppletId(AppletId applet_id) { | ||
| 253 | current_applet_id = applet_id; | ||
| 254 | } | ||
| 255 | |||
| 256 | void AppletManager::SetDefaultAppletFrontendSet() { | ||
| 257 | ClearAll(); | ||
| 258 | SetDefaultAppletsIfMissing(); | ||
| 259 | } | ||
| 260 | |||
| 261 | void AppletManager::SetDefaultAppletsIfMissing() { | ||
| 262 | if (frontend.cabinet == nullptr) { | ||
| 263 | frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>(); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (frontend.controller == nullptr) { | ||
| 267 | frontend.controller = | ||
| 268 | std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore()); | ||
| 269 | } | ||
| 270 | |||
| 271 | if (frontend.error == nullptr) { | ||
| 272 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); | ||
| 273 | } | ||
| 274 | |||
| 275 | if (frontend.mii_edit == nullptr) { | ||
| 276 | frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>(); | ||
| 277 | } | ||
| 278 | |||
| 279 | if (frontend.parental_controls == nullptr) { | ||
| 280 | frontend.parental_controls = | ||
| 281 | std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (frontend.photo_viewer == nullptr) { | ||
| 285 | frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (frontend.profile_select == nullptr) { | ||
| 289 | frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>(); | ||
| 290 | } | ||
| 291 | |||
| 292 | if (frontend.software_keyboard == nullptr) { | ||
| 293 | frontend.software_keyboard = | ||
| 294 | std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>(); | ||
| 295 | } | ||
| 296 | |||
| 297 | if (frontend.web_browser == nullptr) { | ||
| 298 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | void AppletManager::ClearAll() { | ||
| 303 | frontend = {}; | ||
| 304 | } | ||
| 305 | |||
| 306 | std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const { | ||
| 307 | switch (id) { | ||
| 308 | case AppletId::Auth: | ||
| 309 | return std::make_shared<Auth>(system, mode, *frontend.parental_controls); | ||
| 310 | case AppletId::Cabinet: | ||
| 311 | return std::make_shared<Cabinet>(system, mode, *frontend.cabinet); | ||
| 312 | case AppletId::Controller: | ||
| 313 | return std::make_shared<Controller>(system, mode, *frontend.controller); | ||
| 314 | case AppletId::Error: | ||
| 315 | return std::make_shared<Error>(system, mode, *frontend.error); | ||
| 316 | case AppletId::ProfileSelect: | ||
| 317 | return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select); | ||
| 318 | case AppletId::SoftwareKeyboard: | ||
| 319 | return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard); | ||
| 320 | case AppletId::MiiEdit: | ||
| 321 | return std::make_shared<MiiEdit>(system, mode, *frontend.mii_edit); | ||
| 322 | case AppletId::Web: | ||
| 323 | case AppletId::Shop: | ||
| 324 | case AppletId::OfflineWeb: | ||
| 325 | case AppletId::LoginShare: | ||
| 326 | case AppletId::WebAuth: | ||
| 327 | return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser); | ||
| 328 | case AppletId::PhotoViewer: | ||
| 329 | return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer); | ||
| 330 | default: | ||
| 331 | UNIMPLEMENTED_MSG( | ||
| 332 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", | ||
| 333 | static_cast<u8>(id)); | ||
| 334 | return std::make_shared<StubApplet>(system, id, mode); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | } // namespace Service::AM::Applets | ||
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h deleted file mode 100644 index 0bf2598b7..000000000 --- a/src/core/hle/service/am/applets/applets.h +++ /dev/null | |||
| @@ -1,289 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <queue> | ||
| 8 | |||
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/hle/service/kernel_helpers.h" | ||
| 11 | |||
| 12 | union Result; | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Core::Frontend { | ||
| 19 | class CabinetApplet; | ||
| 20 | class ControllerApplet; | ||
| 21 | class ECommerceApplet; | ||
| 22 | class ErrorApplet; | ||
| 23 | class MiiEditApplet; | ||
| 24 | class ParentalControlsApplet; | ||
| 25 | class PhotoViewerApplet; | ||
| 26 | class ProfileSelectApplet; | ||
| 27 | class SoftwareKeyboardApplet; | ||
| 28 | class WebBrowserApplet; | ||
| 29 | } // namespace Core::Frontend | ||
| 30 | |||
| 31 | namespace Kernel { | ||
| 32 | class KernelCore; | ||
| 33 | class KEvent; | ||
| 34 | class KReadableEvent; | ||
| 35 | } // namespace Kernel | ||
| 36 | |||
| 37 | namespace Service::NFP { | ||
| 38 | enum class CabinetMode : u8; | ||
| 39 | } // namespace Service::NFP | ||
| 40 | |||
| 41 | namespace Service::AM { | ||
| 42 | |||
| 43 | class IStorage; | ||
| 44 | |||
| 45 | namespace Applets { | ||
| 46 | |||
| 47 | enum class AppletId : u32 { | ||
| 48 | None = 0x00, | ||
| 49 | Application = 0x01, | ||
| 50 | OverlayDisplay = 0x02, | ||
| 51 | QLaunch = 0x03, | ||
| 52 | Starter = 0x04, | ||
| 53 | Auth = 0x0A, | ||
| 54 | Cabinet = 0x0B, | ||
| 55 | Controller = 0x0C, | ||
| 56 | DataErase = 0x0D, | ||
| 57 | Error = 0x0E, | ||
| 58 | NetConnect = 0x0F, | ||
| 59 | ProfileSelect = 0x10, | ||
| 60 | SoftwareKeyboard = 0x11, | ||
| 61 | MiiEdit = 0x12, | ||
| 62 | Web = 0x13, | ||
| 63 | Shop = 0x14, | ||
| 64 | PhotoViewer = 0x15, | ||
| 65 | Settings = 0x16, | ||
| 66 | OfflineWeb = 0x17, | ||
| 67 | LoginShare = 0x18, | ||
| 68 | WebAuth = 0x19, | ||
| 69 | MyPage = 0x1A, | ||
| 70 | }; | ||
| 71 | |||
| 72 | enum class AppletProgramId : u64 { | ||
| 73 | QLaunch = 0x0100000000001000ull, | ||
| 74 | Auth = 0x0100000000001001ull, | ||
| 75 | Cabinet = 0x0100000000001002ull, | ||
| 76 | Controller = 0x0100000000001003ull, | ||
| 77 | DataErase = 0x0100000000001004ull, | ||
| 78 | Error = 0x0100000000001005ull, | ||
| 79 | NetConnect = 0x0100000000001006ull, | ||
| 80 | ProfileSelect = 0x0100000000001007ull, | ||
| 81 | SoftwareKeyboard = 0x0100000000001008ull, | ||
| 82 | MiiEdit = 0x0100000000001009ull, | ||
| 83 | Web = 0x010000000000100Aull, | ||
| 84 | Shop = 0x010000000000100Bull, | ||
| 85 | OverlayDisplay = 0x010000000000100Cull, | ||
| 86 | PhotoViewer = 0x010000000000100Dull, | ||
| 87 | Settings = 0x010000000000100Eull, | ||
| 88 | OfflineWeb = 0x010000000000100Full, | ||
| 89 | LoginShare = 0x0100000000001010ull, | ||
| 90 | WebAuth = 0x0100000000001011ull, | ||
| 91 | Starter = 0x0100000000001012ull, | ||
| 92 | MyPage = 0x0100000000001013ull, | ||
| 93 | MaxProgramId = 0x0100000000001FFFull, | ||
| 94 | }; | ||
| 95 | |||
| 96 | enum class LibraryAppletMode : u32 { | ||
| 97 | AllForeground = 0, | ||
| 98 | Background = 1, | ||
| 99 | NoUI = 2, | ||
| 100 | BackgroundIndirectDisplay = 3, | ||
| 101 | AllForegroundInitiallyHidden = 4, | ||
| 102 | }; | ||
| 103 | |||
| 104 | enum class CommonArgumentVersion : u32 { | ||
| 105 | Version0, | ||
| 106 | Version1, | ||
| 107 | Version2, | ||
| 108 | Version3, | ||
| 109 | }; | ||
| 110 | |||
| 111 | enum class CommonArgumentSize : u32 { | ||
| 112 | Version3 = 0x20, | ||
| 113 | }; | ||
| 114 | |||
| 115 | enum class ThemeColor : u32 { | ||
| 116 | BasicWhite = 0, | ||
| 117 | BasicBlack = 3, | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct CommonArguments { | ||
| 121 | CommonArgumentVersion arguments_version; | ||
| 122 | CommonArgumentSize size; | ||
| 123 | u32 library_version; | ||
| 124 | ThemeColor theme_color; | ||
| 125 | bool play_startup_sound; | ||
| 126 | u64_le system_tick; | ||
| 127 | }; | ||
| 128 | static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); | ||
| 129 | |||
| 130 | class AppletDataBroker final { | ||
| 131 | public: | ||
| 132 | explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_); | ||
| 133 | ~AppletDataBroker(); | ||
| 134 | |||
| 135 | struct RawChannelData { | ||
| 136 | std::vector<std::vector<u8>> normal; | ||
| 137 | std::vector<std::vector<u8>> interactive; | ||
| 138 | }; | ||
| 139 | |||
| 140 | // Retrieves but does not pop the data sent to applet. | ||
| 141 | RawChannelData PeekDataToAppletForDebug() const; | ||
| 142 | |||
| 143 | std::shared_ptr<IStorage> PopNormalDataToGame(); | ||
| 144 | std::shared_ptr<IStorage> PopNormalDataToApplet(); | ||
| 145 | |||
| 146 | std::shared_ptr<IStorage> PopInteractiveDataToGame(); | ||
| 147 | std::shared_ptr<IStorage> PopInteractiveDataToApplet(); | ||
| 148 | |||
| 149 | void PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage); | ||
| 150 | void PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage); | ||
| 151 | |||
| 152 | void PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage); | ||
| 153 | void PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage); | ||
| 154 | |||
| 155 | void SignalStateChanged(); | ||
| 156 | |||
| 157 | Kernel::KReadableEvent& GetNormalDataEvent(); | ||
| 158 | Kernel::KReadableEvent& GetInteractiveDataEvent(); | ||
| 159 | Kernel::KReadableEvent& GetStateChangedEvent(); | ||
| 160 | |||
| 161 | private: | ||
| 162 | Core::System& system; | ||
| 163 | LibraryAppletMode applet_mode; | ||
| 164 | |||
| 165 | KernelHelpers::ServiceContext service_context; | ||
| 166 | |||
| 167 | // Queues are named from applet's perspective | ||
| 168 | |||
| 169 | // PopNormalDataToApplet and PushNormalDataFromGame | ||
| 170 | std::deque<std::shared_ptr<IStorage>> in_channel; | ||
| 171 | |||
| 172 | // PopNormalDataToGame and PushNormalDataFromApplet | ||
| 173 | std::deque<std::shared_ptr<IStorage>> out_channel; | ||
| 174 | |||
| 175 | // PopInteractiveDataToApplet and PushInteractiveDataFromGame | ||
| 176 | std::deque<std::shared_ptr<IStorage>> in_interactive_channel; | ||
| 177 | |||
| 178 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet | ||
| 179 | std::deque<std::shared_ptr<IStorage>> out_interactive_channel; | ||
| 180 | |||
| 181 | Kernel::KEvent* state_changed_event; | ||
| 182 | |||
| 183 | // Signaled on PushNormalDataFromApplet | ||
| 184 | Kernel::KEvent* pop_out_data_event; | ||
| 185 | |||
| 186 | // Signaled on PushInteractiveDataFromApplet | ||
| 187 | Kernel::KEvent* pop_interactive_out_data_event; | ||
| 188 | }; | ||
| 189 | |||
| 190 | class Applet { | ||
| 191 | public: | ||
| 192 | explicit Applet(Core::System& system_, LibraryAppletMode applet_mode_); | ||
| 193 | virtual ~Applet(); | ||
| 194 | |||
| 195 | virtual void Initialize(); | ||
| 196 | |||
| 197 | virtual bool TransactionComplete() const = 0; | ||
| 198 | virtual Result GetStatus() const = 0; | ||
| 199 | virtual void ExecuteInteractive() = 0; | ||
| 200 | virtual void Execute() = 0; | ||
| 201 | virtual Result RequestExit() = 0; | ||
| 202 | |||
| 203 | AppletDataBroker& GetBroker() { | ||
| 204 | return broker; | ||
| 205 | } | ||
| 206 | |||
| 207 | const AppletDataBroker& GetBroker() const { | ||
| 208 | return broker; | ||
| 209 | } | ||
| 210 | |||
| 211 | LibraryAppletMode GetLibraryAppletMode() const { | ||
| 212 | return applet_mode; | ||
| 213 | } | ||
| 214 | |||
| 215 | bool IsInitialized() const { | ||
| 216 | return initialized; | ||
| 217 | } | ||
| 218 | |||
| 219 | protected: | ||
| 220 | CommonArguments common_args{}; | ||
| 221 | AppletDataBroker broker; | ||
| 222 | LibraryAppletMode applet_mode; | ||
| 223 | bool initialized = false; | ||
| 224 | }; | ||
| 225 | |||
| 226 | struct AppletFrontendSet { | ||
| 227 | using CabinetApplet = std::unique_ptr<Core::Frontend::CabinetApplet>; | ||
| 228 | using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>; | ||
| 229 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; | ||
| 230 | using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>; | ||
| 231 | using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; | ||
| 232 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; | ||
| 233 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; | ||
| 234 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; | ||
| 235 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; | ||
| 236 | |||
| 237 | AppletFrontendSet(); | ||
| 238 | AppletFrontendSet(CabinetApplet cabinet_applet, ControllerApplet controller_applet, | ||
| 239 | ErrorApplet error_applet, MiiEdit mii_edit_, | ||
| 240 | ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_, | ||
| 241 | ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_, | ||
| 242 | WebBrowser web_browser_); | ||
| 243 | ~AppletFrontendSet(); | ||
| 244 | |||
| 245 | AppletFrontendSet(const AppletFrontendSet&) = delete; | ||
| 246 | AppletFrontendSet& operator=(const AppletFrontendSet&) = delete; | ||
| 247 | |||
| 248 | AppletFrontendSet(AppletFrontendSet&&) noexcept; | ||
| 249 | AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; | ||
| 250 | |||
| 251 | CabinetApplet cabinet; | ||
| 252 | ControllerApplet controller; | ||
| 253 | ErrorApplet error; | ||
| 254 | MiiEdit mii_edit; | ||
| 255 | ParentalControlsApplet parental_controls; | ||
| 256 | PhotoViewer photo_viewer; | ||
| 257 | ProfileSelect profile_select; | ||
| 258 | SoftwareKeyboard software_keyboard; | ||
| 259 | WebBrowser web_browser; | ||
| 260 | }; | ||
| 261 | |||
| 262 | class AppletManager { | ||
| 263 | public: | ||
| 264 | explicit AppletManager(Core::System& system_); | ||
| 265 | ~AppletManager(); | ||
| 266 | |||
| 267 | const AppletFrontendSet& GetAppletFrontendSet() const; | ||
| 268 | NFP::CabinetMode GetCabinetMode() const; | ||
| 269 | AppletId GetCurrentAppletId() const; | ||
| 270 | |||
| 271 | void SetAppletFrontendSet(AppletFrontendSet set); | ||
| 272 | void SetCabinetMode(NFP::CabinetMode mode); | ||
| 273 | void SetCurrentAppletId(AppletId applet_id); | ||
| 274 | void SetDefaultAppletFrontendSet(); | ||
| 275 | void SetDefaultAppletsIfMissing(); | ||
| 276 | void ClearAll(); | ||
| 277 | |||
| 278 | std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const; | ||
| 279 | |||
| 280 | private: | ||
| 281 | AppletId current_applet_id{}; | ||
| 282 | NFP::CabinetMode cabinet_mode{}; | ||
| 283 | |||
| 284 | AppletFrontendSet frontend; | ||
| 285 | Core::System& system; | ||
| 286 | }; | ||
| 287 | |||
| 288 | } // namespace Applets | ||
| 289 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp new file mode 100644 index 000000000..79ea045a3 --- /dev/null +++ b/src/core/hle/service/am/application_creator.cpp | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/application_creator.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IApplicationCreator::IApplicationCreator(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IApplicationCreator"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "CreateApplication"}, | ||
| 14 | {1, nullptr, "PopLaunchRequestedApplication"}, | ||
| 15 | {10, nullptr, "CreateSystemApplication"}, | ||
| 16 | {100, nullptr, "PopFloatingApplicationForDevelopment"}, | ||
| 17 | }; | ||
| 18 | // clang-format on | ||
| 19 | |||
| 20 | RegisterHandlers(functions); | ||
| 21 | } | ||
| 22 | |||
| 23 | IApplicationCreator::~IApplicationCreator() = default; | ||
| 24 | |||
| 25 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h new file mode 100644 index 000000000..375a3c476 --- /dev/null +++ b/src/core/hle/service/am/application_creator.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | ||
| 11 | public: | ||
| 12 | explicit IApplicationCreator(Core::System& system_); | ||
| 13 | ~IApplicationCreator() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp new file mode 100644 index 000000000..51c5be2d1 --- /dev/null +++ b/src/core/hle/service/am/application_functions.cpp | |||
| @@ -0,0 +1,594 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "common/uuid.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | ||
| 7 | #include "core/file_sys/patch_manager.h" | ||
| 8 | #include "core/file_sys/registered_cache.h" | ||
| 9 | #include "core/file_sys/savedata_factory.h" | ||
| 10 | #include "core/hle/service/acc/profile_manager.h" | ||
| 11 | #include "core/hle/service/am/am_results.h" | ||
| 12 | #include "core/hle/service/am/applet.h" | ||
| 13 | #include "core/hle/service/am/application_functions.h" | ||
| 14 | #include "core/hle/service/am/storage.h" | ||
| 15 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 16 | #include "core/hle/service/filesystem/save_data_controller.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | ||
| 18 | #include "core/hle/service/ns/ns.h" | ||
| 19 | #include "core/hle/service/sm/sm.h" | ||
| 20 | |||
| 21 | namespace Service::AM { | ||
| 22 | |||
| 23 | enum class LaunchParameterKind : u32 { | ||
| 24 | UserChannel = 1, | ||
| 25 | AccountPreselectedUser = 2, | ||
| 26 | }; | ||
| 27 | |||
| 28 | IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_) | ||
| 29 | : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} { | ||
| 30 | // clang-format off | ||
| 31 | static const FunctionInfo functions[] = { | ||
| 32 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | ||
| 33 | {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, | ||
| 34 | {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, | ||
| 35 | {12, nullptr, "CreateApplicationAndRequestToStart"}, | ||
| 36 | {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, | ||
| 37 | {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, | ||
| 38 | {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, | ||
| 39 | {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, | ||
| 40 | {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, | ||
| 41 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | ||
| 42 | {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"}, | ||
| 43 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 44 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | ||
| 45 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | ||
| 46 | {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, | ||
| 47 | {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, | ||
| 48 | {29, nullptr, "GetCacheStorageMax"}, | ||
| 49 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | ||
| 50 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | ||
| 51 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | ||
| 52 | {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, | ||
| 53 | {34, nullptr, "SelectApplicationLicense"}, | ||
| 54 | {35, nullptr, "GetDeviceSaveDataSizeMax"}, | ||
| 55 | {36, nullptr, "GetLimitedApplicationLicense"}, | ||
| 56 | {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, | ||
| 57 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 58 | {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, | ||
| 59 | {60, nullptr, "SetMediaPlaybackStateForApplication"}, | ||
| 60 | {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"}, | ||
| 61 | {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, | ||
| 62 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 63 | {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, | ||
| 64 | {70, nullptr, "RequestToShutdown"}, | ||
| 65 | {71, nullptr, "RequestToReboot"}, | ||
| 66 | {72, nullptr, "RequestToSleep"}, | ||
| 67 | {80, nullptr, "ExitAndRequestToShowThanksMessage"}, | ||
| 68 | {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, | ||
| 69 | {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, | ||
| 70 | {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, | ||
| 71 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, | ||
| 72 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, | ||
| 73 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, | ||
| 74 | {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, | ||
| 75 | {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, | ||
| 76 | {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, | ||
| 77 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | ||
| 78 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 79 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | ||
| 80 | {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, | ||
| 81 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | ||
| 82 | {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, | ||
| 83 | {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, | ||
| 84 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, | ||
| 85 | {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, | ||
| 86 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | ||
| 87 | {180, nullptr, "GetLaunchRequiredVersion"}, | ||
| 88 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | ||
| 89 | {190, nullptr, "SendServerMaintenanceOverlayNotification"}, | ||
| 90 | {200, nullptr, "GetLastApplicationExitReason"}, | ||
| 91 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | ||
| 92 | {1000, nullptr, "CreateMovieMaker"}, | ||
| 93 | {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, | ||
| 94 | }; | ||
| 95 | // clang-format on | ||
| 96 | |||
| 97 | RegisterHandlers(functions); | ||
| 98 | } | ||
| 99 | |||
| 100 | IApplicationFunctions::~IApplicationFunctions() = default; | ||
| 101 | |||
| 102 | void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { | ||
| 103 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 104 | |||
| 105 | std::scoped_lock lk{applet->lock}; | ||
| 106 | applet->application_crash_report_enabled = true; | ||
| 107 | |||
| 108 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 109 | rb.Push(ResultSuccess); | ||
| 110 | } | ||
| 111 | |||
| 112 | void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { | ||
| 113 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 114 | |||
| 115 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 116 | rb.Push(ResultSuccess); | ||
| 117 | } | ||
| 118 | |||
| 119 | void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { | ||
| 120 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | } | ||
| 125 | |||
| 126 | void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { | ||
| 127 | IPC::RequestParser rp{ctx}; | ||
| 128 | const auto is_visible = rp.Pop<bool>(); | ||
| 129 | |||
| 130 | LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible); | ||
| 131 | |||
| 132 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 133 | rb.Push(ResultSuccess); | ||
| 134 | } | ||
| 135 | |||
| 136 | void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 137 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 138 | |||
| 139 | std::scoped_lock lk{applet->lock}; | ||
| 140 | applet->home_button_long_pressed_blocked = true; | ||
| 141 | applet->home_button_short_pressed_blocked = true; | ||
| 142 | |||
| 143 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 144 | rb.Push(ResultSuccess); | ||
| 145 | } | ||
| 146 | |||
| 147 | void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { | ||
| 148 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 149 | |||
| 150 | std::scoped_lock lk{applet->lock}; | ||
| 151 | applet->home_button_long_pressed_blocked = false; | ||
| 152 | applet->home_button_short_pressed_blocked = false; | ||
| 153 | |||
| 154 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 155 | rb.Push(ResultSuccess); | ||
| 156 | } | ||
| 157 | |||
| 158 | void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { | ||
| 159 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 160 | |||
| 161 | std::scoped_lock lk{applet->lock}; | ||
| 162 | applet->home_button_long_pressed_blocked = true; | ||
| 163 | applet->home_button_short_pressed_blocked = true; | ||
| 164 | applet->home_button_double_click_enabled = true; | ||
| 165 | |||
| 166 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 167 | rb.Push(ResultSuccess); | ||
| 168 | } | ||
| 169 | |||
| 170 | void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { | ||
| 171 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 172 | |||
| 173 | std::scoped_lock lk{applet->lock}; | ||
| 174 | applet->home_button_long_pressed_blocked = false; | ||
| 175 | applet->home_button_short_pressed_blocked = false; | ||
| 176 | applet->home_button_double_click_enabled = false; | ||
| 177 | |||
| 178 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 179 | rb.Push(ResultSuccess); | ||
| 180 | } | ||
| 181 | |||
| 182 | void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { | ||
| 183 | IPC::RequestParser rp{ctx}; | ||
| 184 | const auto kind = rp.PopEnum<LaunchParameterKind>(); | ||
| 185 | |||
| 186 | LOG_INFO(Service_AM, "called, kind={:08X}", kind); | ||
| 187 | |||
| 188 | std::scoped_lock lk{applet->lock}; | ||
| 189 | |||
| 190 | auto& channel = kind == LaunchParameterKind::UserChannel | ||
| 191 | ? applet->user_channel_launch_parameter | ||
| 192 | : applet->preselected_user_launch_parameter; | ||
| 193 | |||
| 194 | if (channel.empty()) { | ||
| 195 | LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind); | ||
| 196 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 197 | rb.Push(AM::ResultNoDataInChannel); | ||
| 198 | return; | ||
| 199 | } | ||
| 200 | |||
| 201 | auto data = channel.back(); | ||
| 202 | channel.pop_back(); | ||
| 203 | |||
| 204 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 205 | rb.Push(ResultSuccess); | ||
| 206 | rb.PushIpcInterface<IStorage>(system, std::move(data)); | ||
| 207 | } | ||
| 208 | |||
| 209 | void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { | ||
| 210 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 211 | |||
| 212 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 213 | rb.Push(ResultSuccess); | ||
| 214 | } | ||
| 215 | |||
| 216 | void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | ||
| 217 | IPC::RequestParser rp{ctx}; | ||
| 218 | u128 user_id = rp.PopRaw<u128>(); | ||
| 219 | |||
| 220 | LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); | ||
| 221 | |||
| 222 | FileSys::SaveDataAttribute attribute{}; | ||
| 223 | attribute.title_id = applet->program_id; | ||
| 224 | attribute.user_id = user_id; | ||
| 225 | attribute.type = FileSys::SaveDataType::SaveData; | ||
| 226 | |||
| 227 | FileSys::VirtualDir save_data{}; | ||
| 228 | const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( | ||
| 229 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); | ||
| 230 | |||
| 231 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 232 | rb.Push(res); | ||
| 233 | rb.Push<u64>(0); | ||
| 234 | } | ||
| 235 | |||
| 236 | void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { | ||
| 237 | // Takes an input u32 Result, no output. | ||
| 238 | // For example, in some cases official apps use this with error 0x2A2 then | ||
| 239 | // uses svcBreak. | ||
| 240 | |||
| 241 | IPC::RequestParser rp{ctx}; | ||
| 242 | u32 result = rp.Pop<u32>(); | ||
| 243 | LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); | ||
| 244 | |||
| 245 | std::scoped_lock lk{applet->lock}; | ||
| 246 | applet->terminate_result = Result(result); | ||
| 247 | |||
| 248 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 249 | rb.Push(ResultSuccess); | ||
| 250 | } | ||
| 251 | |||
| 252 | void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { | ||
| 253 | LOG_DEBUG(Service_AM, "called"); | ||
| 254 | |||
| 255 | std::array<u8, 0x10> version_string{}; | ||
| 256 | |||
| 257 | const auto res = [this] { | ||
| 258 | const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), | ||
| 259 | system.GetContentProvider()}; | ||
| 260 | auto metadata = pm.GetControlMetadata(); | ||
| 261 | if (metadata.first != nullptr) { | ||
| 262 | return metadata; | ||
| 263 | } | ||
| 264 | |||
| 265 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), | ||
| 266 | system.GetFileSystemController(), | ||
| 267 | system.GetContentProvider()}; | ||
| 268 | return pm_update.GetControlMetadata(); | ||
| 269 | }(); | ||
| 270 | |||
| 271 | if (res.first != nullptr) { | ||
| 272 | const auto& version = res.first->GetVersionString(); | ||
| 273 | std::copy(version.begin(), version.end(), version_string.begin()); | ||
| 274 | } else { | ||
| 275 | static constexpr char default_version[]{"1.0.0"}; | ||
| 276 | std::memcpy(version_string.data(), default_version, sizeof(default_version)); | ||
| 277 | } | ||
| 278 | |||
| 279 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 280 | rb.Push(ResultSuccess); | ||
| 281 | rb.PushRaw(version_string); | ||
| 282 | } | ||
| 283 | |||
| 284 | void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | ||
| 285 | // TODO(bunnei): This should be configurable | ||
| 286 | LOG_DEBUG(Service_AM, "called"); | ||
| 287 | |||
| 288 | // Get supported languages from NACP, if possible | ||
| 289 | // Default to 0 (all languages supported) | ||
| 290 | u32 supported_languages = 0; | ||
| 291 | |||
| 292 | const auto res = [this] { | ||
| 293 | const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), | ||
| 294 | system.GetContentProvider()}; | ||
| 295 | auto metadata = pm.GetControlMetadata(); | ||
| 296 | if (metadata.first != nullptr) { | ||
| 297 | return metadata; | ||
| 298 | } | ||
| 299 | |||
| 300 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), | ||
| 301 | system.GetFileSystemController(), | ||
| 302 | system.GetContentProvider()}; | ||
| 303 | return pm_update.GetControlMetadata(); | ||
| 304 | }(); | ||
| 305 | |||
| 306 | if (res.first != nullptr) { | ||
| 307 | supported_languages = res.first->GetSupportedLanguages(); | ||
| 308 | } | ||
| 309 | |||
| 310 | // Call IApplicationManagerInterface implementation. | ||
| 311 | auto& service_manager = system.ServiceManager(); | ||
| 312 | auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); | ||
| 313 | auto app_man = ns_am2->GetApplicationManagerInterface(); | ||
| 314 | |||
| 315 | // Get desired application language | ||
| 316 | u8 desired_language{}; | ||
| 317 | const auto res_lang = | ||
| 318 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 319 | if (res_lang != ResultSuccess) { | ||
| 320 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 321 | rb.Push(res_lang); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | |||
| 325 | // Convert to settings language code. | ||
| 326 | u64 language_code{}; | ||
| 327 | const auto res_code = | ||
| 328 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 329 | if (res_code != ResultSuccess) { | ||
| 330 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 331 | rb.Push(res_code); | ||
| 332 | return; | ||
| 333 | } | ||
| 334 | |||
| 335 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); | ||
| 336 | |||
| 337 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 338 | rb.Push(ResultSuccess); | ||
| 339 | rb.Push(language_code); | ||
| 340 | } | ||
| 341 | |||
| 342 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | ||
| 343 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 344 | |||
| 345 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 346 | rb.Push(ResultSuccess); | ||
| 347 | rb.Push(applet->gameplay_recording_supported); | ||
| 348 | } | ||
| 349 | |||
| 350 | void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { | ||
| 351 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 352 | |||
| 353 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 354 | rb.Push(ResultSuccess); | ||
| 355 | } | ||
| 356 | |||
| 357 | void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { | ||
| 358 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 359 | |||
| 360 | IPC::RequestParser rp{ctx}; | ||
| 361 | |||
| 362 | std::scoped_lock lk{applet->lock}; | ||
| 363 | applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>(); | ||
| 364 | |||
| 365 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 366 | rb.Push(ResultSuccess); | ||
| 367 | } | ||
| 368 | |||
| 369 | void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { | ||
| 370 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 371 | |||
| 372 | std::scoped_lock lk{applet->lock}; | ||
| 373 | applet->is_running = true; | ||
| 374 | |||
| 375 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 376 | rb.Push(ResultSuccess); | ||
| 377 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 378 | } | ||
| 379 | |||
| 380 | void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { | ||
| 381 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 382 | |||
| 383 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 384 | rb.Push(ResultSuccess); | ||
| 385 | |||
| 386 | // Returns a 128-bit UUID | ||
| 387 | rb.Push<u64>(0); | ||
| 388 | rb.Push<u64>(0); | ||
| 389 | } | ||
| 390 | |||
| 391 | void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { | ||
| 392 | struct Parameters { | ||
| 393 | FileSys::SaveDataType type; | ||
| 394 | u128 user_id; | ||
| 395 | u64 new_normal_size; | ||
| 396 | u64 new_journal_size; | ||
| 397 | }; | ||
| 398 | static_assert(sizeof(Parameters) == 40); | ||
| 399 | |||
| 400 | IPC::RequestParser rp{ctx}; | ||
| 401 | const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>(); | ||
| 402 | |||
| 403 | LOG_DEBUG(Service_AM, | ||
| 404 | "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, " | ||
| 405 | "new_journal={:016X}", | ||
| 406 | static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); | ||
| 407 | |||
| 408 | system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( | ||
| 409 | type, applet->program_id, user_id, {new_normal_size, new_journal_size}); | ||
| 410 | |||
| 411 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 412 | rb.Push(ResultSuccess); | ||
| 413 | |||
| 414 | // The following value is used upon failure to help the system recover. | ||
| 415 | // Since we always succeed, this should be 0. | ||
| 416 | rb.Push<u64>(0); | ||
| 417 | } | ||
| 418 | |||
| 419 | void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { | ||
| 420 | struct Parameters { | ||
| 421 | FileSys::SaveDataType type; | ||
| 422 | u128 user_id; | ||
| 423 | }; | ||
| 424 | static_assert(sizeof(Parameters) == 24); | ||
| 425 | |||
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | const auto [type, user_id] = rp.PopRaw<Parameters>(); | ||
| 428 | |||
| 429 | LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], | ||
| 430 | user_id[0]); | ||
| 431 | |||
| 432 | const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( | ||
| 433 | type, applet->program_id, user_id); | ||
| 434 | |||
| 435 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 436 | rb.Push(ResultSuccess); | ||
| 437 | rb.Push(size.normal); | ||
| 438 | rb.Push(size.journal); | ||
| 439 | } | ||
| 440 | |||
| 441 | void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { | ||
| 442 | struct InputParameters { | ||
| 443 | u16 index; | ||
| 444 | s64 size; | ||
| 445 | s64 journal_size; | ||
| 446 | }; | ||
| 447 | static_assert(sizeof(InputParameters) == 24); | ||
| 448 | |||
| 449 | struct OutputParameters { | ||
| 450 | u32 storage_target; | ||
| 451 | u64 required_size; | ||
| 452 | }; | ||
| 453 | static_assert(sizeof(OutputParameters) == 16); | ||
| 454 | |||
| 455 | IPC::RequestParser rp{ctx}; | ||
| 456 | const auto params = rp.PopRaw<InputParameters>(); | ||
| 457 | |||
| 458 | LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", | ||
| 459 | params.index, params.size, params.journal_size); | ||
| 460 | |||
| 461 | const OutputParameters resp{ | ||
| 462 | .storage_target = 1, | ||
| 463 | .required_size = 0, | ||
| 464 | }; | ||
| 465 | |||
| 466 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 467 | rb.Push(ResultSuccess); | ||
| 468 | rb.PushRaw(resp); | ||
| 469 | } | ||
| 470 | |||
| 471 | void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { | ||
| 472 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 473 | |||
| 474 | constexpr u64 size_max_normal = 0xFFFFFFF; | ||
| 475 | constexpr u64 size_max_journal = 0xFFFFFFF; | ||
| 476 | |||
| 477 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 478 | rb.Push(ResultSuccess); | ||
| 479 | rb.Push(size_max_normal); | ||
| 480 | rb.Push(size_max_journal); | ||
| 481 | } | ||
| 482 | |||
| 483 | void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { | ||
| 484 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 485 | |||
| 486 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 487 | rb.Push(ResultSuccess); | ||
| 488 | rb.Push<u32>(0); | ||
| 489 | } | ||
| 490 | |||
| 491 | void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { | ||
| 492 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 493 | |||
| 494 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 495 | rb.Push(ResultSuccess); | ||
| 496 | rb.Push<u32>(0); | ||
| 497 | } | ||
| 498 | |||
| 499 | void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { | ||
| 500 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 501 | |||
| 502 | IPC::RequestParser rp{ctx}; | ||
| 503 | [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); | ||
| 504 | [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); | ||
| 505 | const auto program_index = rp.Pop<u64>(); | ||
| 506 | |||
| 507 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 508 | rb.Push(ResultSuccess); | ||
| 509 | |||
| 510 | // Swap user channel ownership into the system so that it will be preserved | ||
| 511 | system.GetUserChannel().swap(applet->user_channel_launch_parameter); | ||
| 512 | system.ExecuteProgram(program_index); | ||
| 513 | } | ||
| 514 | |||
| 515 | void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { | ||
| 516 | LOG_DEBUG(Service_AM, "called"); | ||
| 517 | |||
| 518 | applet->user_channel_launch_parameter.clear(); | ||
| 519 | |||
| 520 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 521 | rb.Push(ResultSuccess); | ||
| 522 | } | ||
| 523 | |||
| 524 | void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { | ||
| 525 | LOG_DEBUG(Service_AM, "called"); | ||
| 526 | |||
| 527 | IPC::RequestParser rp{ctx}; | ||
| 528 | const auto storage = rp.PopIpcInterface<IStorage>().lock(); | ||
| 529 | if (storage) { | ||
| 530 | applet->user_channel_launch_parameter.push_back(storage->GetData()); | ||
| 531 | } | ||
| 532 | |||
| 533 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 534 | rb.Push(ResultSuccess); | ||
| 535 | } | ||
| 536 | |||
| 537 | void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { | ||
| 538 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 539 | |||
| 540 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 541 | rb.Push(ResultSuccess); | ||
| 542 | rb.Push<s32>(applet->previous_program_index); | ||
| 543 | } | ||
| 544 | |||
| 545 | void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { | ||
| 546 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 547 | |||
| 548 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 549 | rb.Push(ResultSuccess); | ||
| 550 | rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle()); | ||
| 551 | } | ||
| 552 | |||
| 553 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 554 | LOG_DEBUG(Service_AM, "called"); | ||
| 555 | |||
| 556 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 557 | rb.Push(ResultSuccess); | ||
| 558 | rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle()); | ||
| 559 | } | ||
| 560 | |||
| 561 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { | ||
| 562 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 563 | |||
| 564 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 565 | rb.Push(AM::ResultNoDataInChannel); | ||
| 566 | } | ||
| 567 | |||
| 568 | void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { | ||
| 569 | LOG_DEBUG(Service_AM, "called"); | ||
| 570 | |||
| 571 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 572 | rb.Push(ResultSuccess); | ||
| 573 | rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle()); | ||
| 574 | } | ||
| 575 | |||
| 576 | void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { | ||
| 577 | LOG_DEBUG(Service_AM, "called"); | ||
| 578 | |||
| 579 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 580 | rb.Push(ResultSuccess); | ||
| 581 | rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle()); | ||
| 582 | } | ||
| 583 | |||
| 584 | void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { | ||
| 585 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 586 | |||
| 587 | std::scoped_lock lk{applet->lock}; | ||
| 588 | applet->jit_service_launched = true; | ||
| 589 | |||
| 590 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 591 | rb.Push(ResultSuccess); | ||
| 592 | } | ||
| 593 | |||
| 594 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h new file mode 100644 index 000000000..55eb21d39 --- /dev/null +++ b/src/core/hle/service/am/application_functions.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | struct Applet; | ||
| 12 | |||
| 13 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | ||
| 14 | public: | ||
| 15 | explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 16 | ~IApplicationFunctions() override; | ||
| 17 | |||
| 18 | private: | ||
| 19 | void PopLaunchParameter(HLERequestContext& ctx); | ||
| 20 | void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); | ||
| 21 | void EnsureSaveData(HLERequestContext& ctx); | ||
| 22 | void SetTerminateResult(HLERequestContext& ctx); | ||
| 23 | void GetDisplayVersion(HLERequestContext& ctx); | ||
| 24 | void GetDesiredLanguage(HLERequestContext& ctx); | ||
| 25 | void IsGamePlayRecordingSupported(HLERequestContext& ctx); | ||
| 26 | void InitializeGamePlayRecording(HLERequestContext& ctx); | ||
| 27 | void SetGamePlayRecordingState(HLERequestContext& ctx); | ||
| 28 | void NotifyRunning(HLERequestContext& ctx); | ||
| 29 | void GetPseudoDeviceId(HLERequestContext& ctx); | ||
| 30 | void ExtendSaveData(HLERequestContext& ctx); | ||
| 31 | void GetSaveDataSize(HLERequestContext& ctx); | ||
| 32 | void CreateCacheStorage(HLERequestContext& ctx); | ||
| 33 | void GetSaveDataSizeMax(HLERequestContext& ctx); | ||
| 34 | void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 35 | void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); | ||
| 36 | void BeginBlockingHomeButton(HLERequestContext& ctx); | ||
| 37 | void EndBlockingHomeButton(HLERequestContext& ctx); | ||
| 38 | void EnableApplicationCrashReport(HLERequestContext& ctx); | ||
| 39 | void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); | ||
| 40 | void SetApplicationCopyrightImage(HLERequestContext& ctx); | ||
| 41 | void SetApplicationCopyrightVisibility(HLERequestContext& ctx); | ||
| 42 | void QueryApplicationPlayStatistics(HLERequestContext& ctx); | ||
| 43 | void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); | ||
| 44 | void ExecuteProgram(HLERequestContext& ctx); | ||
| 45 | void ClearUserChannel(HLERequestContext& ctx); | ||
| 46 | void UnpopToUserChannel(HLERequestContext& ctx); | ||
| 47 | void GetPreviousProgramIndex(HLERequestContext& ctx); | ||
| 48 | void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); | ||
| 49 | void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); | ||
| 50 | void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); | ||
| 51 | void GetNotificationStorageChannelEvent(HLERequestContext& ctx); | ||
| 52 | void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); | ||
| 53 | void PrepareForJit(HLERequestContext& ctx); | ||
| 54 | |||
| 55 | const std::shared_ptr<Applet> applet; | ||
| 56 | }; | ||
| 57 | |||
| 58 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp new file mode 100644 index 000000000..a6fd6d37f --- /dev/null +++ b/src/core/hle/service/am/application_proxy.cpp | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/application_functions.h" | ||
| 6 | #include "core/hle/service/am/application_proxy.h" | ||
| 7 | #include "core/hle/service/am/audio_controller.h" | ||
| 8 | #include "core/hle/service/am/common_state_getter.h" | ||
| 9 | #include "core/hle/service/am/debug_functions.h" | ||
| 10 | #include "core/hle/service/am/display_controller.h" | ||
| 11 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 12 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 13 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 14 | #include "core/hle/service/am/self_controller.h" | ||
| 15 | #include "core/hle/service/am/window_controller.h" | ||
| 16 | #include "core/hle/service/ipc_helpers.h" | ||
| 17 | |||
| 18 | namespace Service::AM { | ||
| 19 | |||
| 20 | IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 21 | std::shared_ptr<Applet> applet_, Core::System& system_) | ||
| 22 | : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move( | ||
| 23 | applet_)} { | ||
| 24 | // clang-format off | ||
| 25 | static const FunctionInfo functions[] = { | ||
| 26 | {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 27 | {1, &IApplicationProxy::GetSelfController, "GetSelfController"}, | ||
| 28 | {2, &IApplicationProxy::GetWindowController, "GetWindowController"}, | ||
| 29 | {3, &IApplicationProxy::GetAudioController, "GetAudioController"}, | ||
| 30 | {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"}, | ||
| 31 | {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 32 | {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 33 | {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"}, | ||
| 34 | {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 35 | }; | ||
| 36 | // clang-format on | ||
| 37 | |||
| 38 | RegisterHandlers(functions); | ||
| 39 | } | ||
| 40 | |||
| 41 | IApplicationProxy::~IApplicationProxy() = default; | ||
| 42 | |||
| 43 | void IApplicationProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 44 | LOG_DEBUG(Service_AM, "called"); | ||
| 45 | |||
| 46 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 47 | rb.Push(ResultSuccess); | ||
| 48 | rb.PushIpcInterface<IAudioController>(system); | ||
| 49 | } | ||
| 50 | |||
| 51 | void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 52 | LOG_DEBUG(Service_AM, "called"); | ||
| 53 | |||
| 54 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 55 | rb.Push(ResultSuccess); | ||
| 56 | rb.PushIpcInterface<IDisplayController>(system, applet); | ||
| 57 | } | ||
| 58 | |||
| 59 | void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) { | ||
| 60 | LOG_DEBUG(Service_AM, "called"); | ||
| 61 | |||
| 62 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 63 | rb.Push(ResultSuccess); | ||
| 64 | rb.PushIpcInterface<IProcessWindingController>(system, applet); | ||
| 65 | } | ||
| 66 | |||
| 67 | void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 68 | LOG_DEBUG(Service_AM, "called"); | ||
| 69 | |||
| 70 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 71 | rb.Push(ResultSuccess); | ||
| 72 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 73 | } | ||
| 74 | |||
| 75 | void IApplicationProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 76 | LOG_DEBUG(Service_AM, "called"); | ||
| 77 | |||
| 78 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 79 | rb.Push(ResultSuccess); | ||
| 80 | rb.PushIpcInterface<IWindowController>(system, applet); | ||
| 81 | } | ||
| 82 | |||
| 83 | void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 84 | LOG_DEBUG(Service_AM, "called"); | ||
| 85 | |||
| 86 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 87 | rb.Push(ResultSuccess); | ||
| 88 | rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); | ||
| 89 | } | ||
| 90 | |||
| 91 | void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 92 | LOG_DEBUG(Service_AM, "called"); | ||
| 93 | |||
| 94 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 95 | rb.Push(ResultSuccess); | ||
| 96 | rb.PushIpcInterface<ICommonStateGetter>(system, applet); | ||
| 97 | } | ||
| 98 | |||
| 99 | void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 100 | LOG_DEBUG(Service_AM, "called"); | ||
| 101 | |||
| 102 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 103 | rb.Push(ResultSuccess); | ||
| 104 | rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); | ||
| 105 | } | ||
| 106 | |||
| 107 | void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { | ||
| 108 | LOG_DEBUG(Service_AM, "called"); | ||
| 109 | |||
| 110 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 111 | rb.Push(ResultSuccess); | ||
| 112 | rb.PushIpcInterface<IApplicationFunctions>(system, applet); | ||
| 113 | } | ||
| 114 | |||
| 115 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h new file mode 100644 index 000000000..eb98b095c --- /dev/null +++ b/src/core/hle/service/am/application_proxy.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | ||
| 13 | public: | ||
| 14 | explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 15 | std::shared_ptr<Applet> msg_queue_, Core::System& system_); | ||
| 16 | ~IApplicationProxy(); | ||
| 17 | |||
| 18 | private: | ||
| 19 | void GetAudioController(HLERequestContext& ctx); | ||
| 20 | void GetDisplayController(HLERequestContext& ctx); | ||
| 21 | void GetProcessWindingController(HLERequestContext& ctx); | ||
| 22 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 23 | void GetWindowController(HLERequestContext& ctx); | ||
| 24 | void GetSelfController(HLERequestContext& ctx); | ||
| 25 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 26 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 27 | void GetApplicationFunctions(HLERequestContext& ctx); | ||
| 28 | |||
| 29 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 30 | std::shared_ptr<Applet> applet; | ||
| 31 | }; | ||
| 32 | |||
| 33 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp new file mode 100644 index 000000000..ae75db174 --- /dev/null +++ b/src/core/hle/service/am/audio_controller.cpp | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/audio_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IAudioController::IAudioController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IAudioController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, | ||
| 14 | {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"}, | ||
| 15 | {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"}, | ||
| 16 | {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"}, | ||
| 17 | {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"}, | ||
| 18 | }; | ||
| 19 | // clang-format on | ||
| 20 | |||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | IAudioController::~IAudioController() = default; | ||
| 25 | |||
| 26 | void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 27 | IPC::RequestParser rp{ctx}; | ||
| 28 | const float main_applet_volume_tmp = rp.Pop<float>(); | ||
| 29 | const float library_applet_volume_tmp = rp.Pop<float>(); | ||
| 30 | |||
| 31 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", | ||
| 32 | main_applet_volume_tmp, library_applet_volume_tmp); | ||
| 33 | |||
| 34 | // Ensure the volume values remain within the 0-100% range | ||
| 35 | main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 36 | library_applet_volume = | ||
| 37 | std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume); | ||
| 38 | |||
| 39 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 40 | rb.Push(ResultSuccess); | ||
| 41 | } | ||
| 42 | |||
| 43 | void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 44 | LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | rb.Push(main_applet_volume); | ||
| 48 | } | ||
| 49 | |||
| 50 | void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { | ||
| 51 | LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); | ||
| 52 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.Push(library_applet_volume); | ||
| 55 | } | ||
| 56 | |||
| 57 | void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { | ||
| 58 | struct Parameters { | ||
| 59 | float volume; | ||
| 60 | s64 fade_time_ns; | ||
| 61 | }; | ||
| 62 | static_assert(sizeof(Parameters) == 16); | ||
| 63 | |||
| 64 | IPC::RequestParser rp{ctx}; | ||
| 65 | const auto parameters = rp.PopRaw<Parameters>(); | ||
| 66 | |||
| 67 | LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume, | ||
| 68 | parameters.fade_time_ns); | ||
| 69 | |||
| 70 | main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume); | ||
| 71 | fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns}; | ||
| 72 | |||
| 73 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 74 | rb.Push(ResultSuccess); | ||
| 75 | } | ||
| 76 | |||
| 77 | void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { | ||
| 78 | IPC::RequestParser rp{ctx}; | ||
| 79 | const float transparent_volume_rate_tmp = rp.Pop<float>(); | ||
| 80 | |||
| 81 | LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp); | ||
| 82 | |||
| 83 | // Clamp volume range to 0-100%. | ||
| 84 | transparent_volume_rate = | ||
| 85 | std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume); | ||
| 86 | |||
| 87 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 88 | rb.Push(ResultSuccess); | ||
| 89 | } | ||
| 90 | |||
| 91 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h new file mode 100644 index 000000000..a47e3bad8 --- /dev/null +++ b/src/core/hle/service/am/audio_controller.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IAudioController final : public ServiceFramework<IAudioController> { | ||
| 11 | public: | ||
| 12 | explicit IAudioController(Core::System& system_); | ||
| 13 | ~IAudioController() override; | ||
| 14 | |||
| 15 | private: | ||
| 16 | void SetExpectedMasterVolume(HLERequestContext& ctx); | ||
| 17 | void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 18 | void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); | ||
| 19 | void ChangeMainAppletMasterVolume(HLERequestContext& ctx); | ||
| 20 | void SetTransparentAudioRate(HLERequestContext& ctx); | ||
| 21 | |||
| 22 | static constexpr float min_allowed_volume = 0.0f; | ||
| 23 | static constexpr float max_allowed_volume = 1.0f; | ||
| 24 | |||
| 25 | float main_applet_volume{0.25f}; | ||
| 26 | float library_applet_volume{max_allowed_volume}; | ||
| 27 | float transparent_volume_rate{min_allowed_volume}; | ||
| 28 | |||
| 29 | // Volume transition fade time in nanoseconds. | ||
| 30 | // e.g. If the main applet volume was 0% and was changed to 50% | ||
| 31 | // with a fade of 50ns, then over the course of 50ns, | ||
| 32 | // the volume will gradually fade up to 50% | ||
| 33 | std::chrono::nanoseconds fade_time_ns{0}; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp new file mode 100644 index 000000000..937ac0beb --- /dev/null +++ b/src/core/hle/service/am/common_state_getter.cpp | |||
| @@ -0,0 +1,314 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/hle/service/am/am_results.h" | ||
| 6 | #include "core/hle/service/am/applet.h" | ||
| 7 | #include "core/hle/service/am/common_state_getter.h" | ||
| 8 | #include "core/hle/service/am/lock_accessor.h" | ||
| 9 | #include "core/hle/service/apm/apm_controller.h" | ||
| 10 | #include "core/hle/service/apm/apm_interface.h" | ||
| 11 | #include "core/hle/service/ipc_helpers.h" | ||
| 12 | #include "core/hle/service/pm/pm.h" | ||
| 13 | #include "core/hle/service/sm/sm.h" | ||
| 14 | #include "core/hle/service/vi/vi.h" | ||
| 15 | |||
| 16 | namespace Service::AM { | ||
| 17 | |||
| 18 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_) | ||
| 19 | : ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} { | ||
| 20 | // clang-format off | ||
| 21 | static const FunctionInfo functions[] = { | ||
| 22 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | ||
| 23 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | ||
| 24 | {2, nullptr, "GetThisAppletKind"}, | ||
| 25 | {3, nullptr, "AllowToEnterSleep"}, | ||
| 26 | {4, nullptr, "DisallowToEnterSleep"}, | ||
| 27 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 28 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 29 | {7, nullptr, "GetCradleStatus"}, | ||
| 30 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, | ||
| 31 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | ||
| 32 | {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, | ||
| 33 | {11, nullptr, "ReleaseSleepLock"}, | ||
| 34 | {12, nullptr, "ReleaseSleepLockTransiently"}, | ||
| 35 | {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, | ||
| 36 | {14, nullptr, "GetWakeupCount"}, | ||
| 37 | {20, nullptr, "PushToGeneralChannel"}, | ||
| 38 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | ||
| 39 | {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"}, | ||
| 40 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 41 | {40, nullptr, "GetCradleFwVersion"}, | ||
| 42 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | ||
| 43 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | ||
| 44 | {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, | ||
| 45 | {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, | ||
| 46 | {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, | ||
| 47 | {55, nullptr, "IsInControllerFirmwareUpdateSection"}, | ||
| 48 | {59, nullptr, "SetVrPositionForDebug"}, | ||
| 49 | {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, | ||
| 50 | {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, | ||
| 51 | {62, nullptr, "GetHdcpAuthenticationState"}, | ||
| 52 | {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, | ||
| 53 | {64, nullptr, "SetTvPowerStateMatchingMode"}, | ||
| 54 | {65, nullptr, "GetApplicationIdByContentActionName"}, | ||
| 55 | {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, | ||
| 56 | {67, nullptr, "CancelCpuBoostMode"}, | ||
| 57 | {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"}, | ||
| 58 | {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"}, | ||
| 59 | {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, | ||
| 60 | {91, nullptr, "GetCurrentPerformanceConfiguration"}, | ||
| 61 | {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, | ||
| 62 | {110, nullptr, "OpenMyGpuErrorHandler"}, | ||
| 63 | {120, &ICommonStateGetter::GetAppletLaunchedHistory, "GetAppletLaunchedHistory"}, | ||
| 64 | {200, nullptr, "GetOperationModeSystemInfo"}, | ||
| 65 | {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"}, | ||
| 66 | {400, nullptr, "ActivateMigrationService"}, | ||
| 67 | {401, nullptr, "DeactivateMigrationService"}, | ||
| 68 | {500, nullptr, "DisableSleepTillShutdown"}, | ||
| 69 | {501, nullptr, "SuppressDisablingSleepTemporarily"}, | ||
| 70 | {502, nullptr, "IsSleepEnabled"}, | ||
| 71 | {503, nullptr, "IsDisablingSleepSuppressed"}, | ||
| 72 | {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, | ||
| 73 | }; | ||
| 74 | // clang-format on | ||
| 75 | |||
| 76 | RegisterHandlers(functions); | ||
| 77 | } | ||
| 78 | |||
| 79 | ICommonStateGetter::~ICommonStateGetter() = default; | ||
| 80 | |||
| 81 | void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { | ||
| 82 | LOG_DEBUG(Service_AM, "called"); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode | ||
| 87 | } | ||
| 88 | |||
| 89 | void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { | ||
| 90 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 91 | |||
| 92 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 93 | rb.Push(ResultSuccess); | ||
| 94 | rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent()); | ||
| 95 | } | ||
| 96 | |||
| 97 | void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_AM, "called"); | ||
| 99 | |||
| 100 | const auto message = applet->message_queue.PopMessage(); | ||
| 101 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 102 | |||
| 103 | if (message == AppletMessageQueue::AppletMessage::None) { | ||
| 104 | LOG_ERROR(Service_AM, "Message queue is empty"); | ||
| 105 | rb.Push(AM::ResultNoMessages); | ||
| 106 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | |||
| 110 | rb.Push(ResultSuccess); | ||
| 111 | rb.PushEnum<AppletMessageQueue::AppletMessage>(message); | ||
| 112 | } | ||
| 113 | |||
| 114 | void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { | ||
| 115 | LOG_DEBUG(Service_AM, "(STUBBED) called"); | ||
| 116 | |||
| 117 | std::scoped_lock lk{applet->lock}; | ||
| 118 | |||
| 119 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 120 | rb.Push(ResultSuccess); | ||
| 121 | rb.Push(static_cast<u8>(applet->focus_state)); | ||
| 122 | } | ||
| 123 | |||
| 124 | void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { | ||
| 125 | const bool use_docked_mode{Settings::IsDockedMode()}; | ||
| 126 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | ||
| 127 | |||
| 128 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 129 | rb.Push(ResultSuccess); | ||
| 130 | rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); | ||
| 131 | } | ||
| 132 | |||
| 133 | void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { | ||
| 134 | LOG_DEBUG(Service_AM, "called"); | ||
| 135 | |||
| 136 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 137 | rb.Push(ResultSuccess); | ||
| 138 | rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode()); | ||
| 139 | } | ||
| 140 | |||
| 141 | void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { | ||
| 142 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 143 | |||
| 144 | // Sleep lock is acquired immediately. | ||
| 145 | applet->sleep_lock_event.Signal(); | ||
| 146 | |||
| 147 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 148 | rb.Push(ResultSuccess); | ||
| 149 | } | ||
| 150 | |||
| 151 | void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) { | ||
| 152 | IPC::RequestParser rp{ctx}; | ||
| 153 | const auto unknown = rp.Pop<u32>(); | ||
| 154 | |||
| 155 | LOG_INFO(Service_AM, "called, unknown={}", unknown); | ||
| 156 | |||
| 157 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 158 | |||
| 159 | rb.Push(ResultSuccess); | ||
| 160 | rb.PushIpcInterface<ILockAccessor>(system); | ||
| 161 | } | ||
| 162 | |||
| 163 | void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { | ||
| 164 | LOG_WARNING(Service_AM, "called"); | ||
| 165 | |||
| 166 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 167 | rb.Push(ResultSuccess); | ||
| 168 | rb.PushCopyObjects(applet->sleep_lock_event.GetHandle()); | ||
| 169 | } | ||
| 170 | |||
| 171 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { | ||
| 172 | LOG_DEBUG(Service_AM, "called"); | ||
| 173 | |||
| 174 | std::scoped_lock lk{applet->lock}; | ||
| 175 | |||
| 176 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 177 | rb.Push(ResultSuccess); | ||
| 178 | rb.Push(applet->vr_mode_enabled); | ||
| 179 | } | ||
| 180 | |||
| 181 | void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { | ||
| 182 | IPC::RequestParser rp{ctx}; | ||
| 183 | |||
| 184 | std::scoped_lock lk{applet->lock}; | ||
| 185 | applet->vr_mode_enabled = rp.Pop<bool>(); | ||
| 186 | LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off"); | ||
| 187 | |||
| 188 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 189 | rb.Push(ResultSuccess); | ||
| 190 | } | ||
| 191 | |||
| 192 | void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { | ||
| 193 | IPC::RequestParser rp{ctx}; | ||
| 194 | const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); | ||
| 195 | |||
| 196 | LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", | ||
| 197 | is_lcd_backlight_off_enabled); | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 200 | rb.Push(ResultSuccess); | ||
| 201 | } | ||
| 202 | |||
| 203 | void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { | ||
| 204 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 205 | |||
| 206 | std::scoped_lock lk{applet->lock}; | ||
| 207 | applet->vr_mode_enabled = true; | ||
| 208 | |||
| 209 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 210 | rb.Push(ResultSuccess); | ||
| 211 | } | ||
| 212 | |||
| 213 | void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { | ||
| 214 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 215 | |||
| 216 | std::scoped_lock lk{applet->lock}; | ||
| 217 | applet->vr_mode_enabled = false; | ||
| 218 | |||
| 219 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 220 | rb.Push(ResultSuccess); | ||
| 221 | } | ||
| 222 | |||
| 223 | void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { | ||
| 224 | LOG_DEBUG(Service_AM, "called"); | ||
| 225 | |||
| 226 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 227 | rb.Push(ResultSuccess); | ||
| 228 | rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent()); | ||
| 229 | } | ||
| 230 | |||
| 231 | void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { | ||
| 232 | LOG_DEBUG(Service_AM, "called"); | ||
| 233 | |||
| 234 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 235 | rb.Push(ResultSuccess); | ||
| 236 | |||
| 237 | if (Settings::IsDockedMode()) { | ||
| 238 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||
| 239 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||
| 240 | } else { | ||
| 241 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||
| 242 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { | ||
| 247 | LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); | ||
| 248 | |||
| 249 | const auto& sm = system.ServiceManager(); | ||
| 250 | const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); | ||
| 251 | ASSERT(apm_sys != nullptr); | ||
| 252 | |||
| 253 | apm_sys->SetCpuBoostMode(ctx); | ||
| 254 | } | ||
| 255 | |||
| 256 | void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) { | ||
| 257 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 258 | |||
| 259 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 260 | rb.Push(ResultSuccess); | ||
| 261 | rb.Push(0); | ||
| 262 | } | ||
| 263 | |||
| 264 | void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { | ||
| 265 | IPC::RequestParser rp{ctx}; | ||
| 266 | const auto system_button{rp.PopEnum<SystemButtonType>()}; | ||
| 267 | |||
| 268 | LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button); | ||
| 269 | |||
| 270 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 271 | rb.Push(ResultSuccess); | ||
| 272 | } | ||
| 273 | |||
| 274 | void ICommonStateGetter::GetAppletLaunchedHistory(HLERequestContext& ctx) { | ||
| 275 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 276 | |||
| 277 | std::shared_ptr<Applet> current_applet = applet; | ||
| 278 | std::vector<AppletId> result; | ||
| 279 | |||
| 280 | const size_t count = ctx.GetWriteBufferNumElements<AppletId>(); | ||
| 281 | size_t i; | ||
| 282 | |||
| 283 | for (i = 0; i < count && current_applet != nullptr; i++) { | ||
| 284 | result.push_back(current_applet->applet_id); | ||
| 285 | current_applet = current_applet->caller_applet.lock(); | ||
| 286 | } | ||
| 287 | |||
| 288 | ctx.WriteBuffer(result); | ||
| 289 | |||
| 290 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 291 | rb.Push(ResultSuccess); | ||
| 292 | rb.Push(static_cast<u32>(i)); | ||
| 293 | } | ||
| 294 | |||
| 295 | void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { | ||
| 296 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 297 | |||
| 298 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 299 | rb.Push(ResultSuccess); | ||
| 300 | rb.PushEnum(SysPlatformRegion::Global); | ||
| 301 | } | ||
| 302 | |||
| 303 | void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( | ||
| 304 | HLERequestContext& ctx) { | ||
| 305 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 306 | |||
| 307 | std::scoped_lock lk{applet->lock}; | ||
| 308 | applet->request_exit_to_library_applet_at_execute_next_program_enabled = true; | ||
| 309 | |||
| 310 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 311 | rb.Push(ResultSuccess); | ||
| 312 | } | ||
| 313 | |||
| 314 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h new file mode 100644 index 000000000..bf652790c --- /dev/null +++ b/src/core/hle/service/am/common_state_getter.h | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | struct Applet; | ||
| 14 | |||
| 15 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | ||
| 16 | public: | ||
| 17 | explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 18 | ~ICommonStateGetter() override; | ||
| 19 | |||
| 20 | private: | ||
| 21 | // This is nn::oe::FocusState | ||
| 22 | enum class FocusState : u8 { | ||
| 23 | InFocus = 1, | ||
| 24 | NotInFocus = 2, | ||
| 25 | Background = 3, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // This is nn::oe::OperationMode | ||
| 29 | enum class OperationMode : u8 { | ||
| 30 | Handheld = 0, | ||
| 31 | Docked = 1, | ||
| 32 | }; | ||
| 33 | |||
| 34 | // This is nn::am::service::SystemButtonType | ||
| 35 | enum class SystemButtonType { | ||
| 36 | None, | ||
| 37 | HomeButtonShortPressing, | ||
| 38 | HomeButtonLongPressing, | ||
| 39 | PowerButtonShortPressing, | ||
| 40 | PowerButtonLongPressing, | ||
| 41 | ShutdownSystem, | ||
| 42 | CaptureButtonShortPressing, | ||
| 43 | CaptureButtonLongPressing, | ||
| 44 | }; | ||
| 45 | |||
| 46 | enum class SysPlatformRegion : s32 { | ||
| 47 | Global = 1, | ||
| 48 | Terra = 2, | ||
| 49 | }; | ||
| 50 | |||
| 51 | void GetEventHandle(HLERequestContext& ctx); | ||
| 52 | void ReceiveMessage(HLERequestContext& ctx); | ||
| 53 | void GetCurrentFocusState(HLERequestContext& ctx); | ||
| 54 | void RequestToAcquireSleepLock(HLERequestContext& ctx); | ||
| 55 | void GetAcquiredSleepLockEvent(HLERequestContext& ctx); | ||
| 56 | void GetReaderLockAccessorEx(HLERequestContext& ctx); | ||
| 57 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); | ||
| 58 | void GetOperationMode(HLERequestContext& ctx); | ||
| 59 | void GetPerformanceMode(HLERequestContext& ctx); | ||
| 60 | void GetBootMode(HLERequestContext& ctx); | ||
| 61 | void IsVrModeEnabled(HLERequestContext& ctx); | ||
| 62 | void SetVrModeEnabled(HLERequestContext& ctx); | ||
| 63 | void SetLcdBacklighOffEnabled(HLERequestContext& ctx); | ||
| 64 | void BeginVrModeEx(HLERequestContext& ctx); | ||
| 65 | void EndVrModeEx(HLERequestContext& ctx); | ||
| 66 | void GetDefaultDisplayResolution(HLERequestContext& ctx); | ||
| 67 | void SetCpuBoostMode(HLERequestContext& ctx); | ||
| 68 | void GetBuiltInDisplayType(HLERequestContext& ctx); | ||
| 69 | void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); | ||
| 70 | void GetAppletLaunchedHistory(HLERequestContext& ctx); | ||
| 71 | void GetSettingsPlatformRegion(HLERequestContext& ctx); | ||
| 72 | void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); | ||
| 73 | |||
| 74 | const std::shared_ptr<Applet> applet; | ||
| 75 | }; | ||
| 76 | |||
| 77 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp new file mode 100644 index 000000000..f80b970f2 --- /dev/null +++ b/src/core/hle/service/am/debug_functions.cpp | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/debug_functions.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IDebugFunctions::IDebugFunctions(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IDebugFunctions"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | ||
| 14 | {1, nullptr, "OpenMainApplication"}, | ||
| 15 | {10, nullptr, "PerformSystemButtonPressing"}, | ||
| 16 | {20, nullptr, "InvalidateTransitionLayer"}, | ||
| 17 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | ||
| 18 | {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, | ||
| 19 | {40, nullptr, "GetAppletResourceUsageInfo"}, | ||
| 20 | {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, | ||
| 21 | {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, | ||
| 22 | {100, nullptr, "SetCpuBoostModeForApplet"}, | ||
| 23 | {101, nullptr, "CancelCpuBoostModeForApplet"}, | ||
| 24 | {110, nullptr, "PushToAppletBoundChannelForDebug"}, | ||
| 25 | {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, | ||
| 26 | {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, | ||
| 27 | {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, | ||
| 28 | {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, | ||
| 29 | {130, nullptr, "FriendInvitationSetApplicationParameter"}, | ||
| 30 | {131, nullptr, "FriendInvitationClearApplicationParameter"}, | ||
| 31 | {132, nullptr, "FriendInvitationPushApplicationParameter"}, | ||
| 32 | {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, | ||
| 33 | {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, | ||
| 34 | {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, | ||
| 35 | {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, | ||
| 36 | }; | ||
| 37 | // clang-format on | ||
| 38 | |||
| 39 | RegisterHandlers(functions); | ||
| 40 | } | ||
| 41 | |||
| 42 | IDebugFunctions::~IDebugFunctions() = default; | ||
| 43 | |||
| 44 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/debug_functions.h new file mode 100644 index 000000000..d55968743 --- /dev/null +++ b/src/core/hle/service/am/debug_functions.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { | ||
| 11 | public: | ||
| 12 | explicit IDebugFunctions(Core::System& system_); | ||
| 13 | ~IDebugFunctions() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp new file mode 100644 index 000000000..4d6858348 --- /dev/null +++ b/src/core/hle/service/am/display_controller.cpp | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet.h" | ||
| 5 | #include "core/hle/service/am/display_controller.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | namespace { | ||
| 11 | struct OutputParameters { | ||
| 12 | bool was_written; | ||
| 13 | s32 fbshare_layer_index; | ||
| 14 | }; | ||
| 15 | |||
| 16 | static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size"); | ||
| 17 | } // namespace | ||
| 18 | |||
| 19 | IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_) | ||
| 20 | : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) { | ||
| 21 | // clang-format off | ||
| 22 | static const FunctionInfo functions[] = { | ||
| 23 | {0, nullptr, "GetLastForegroundCaptureImage"}, | ||
| 24 | {1, nullptr, "UpdateLastForegroundCaptureImage"}, | ||
| 25 | {2, nullptr, "GetLastApplicationCaptureImage"}, | ||
| 26 | {3, nullptr, "GetCallerAppletCaptureImage"}, | ||
| 27 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, | ||
| 28 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | ||
| 29 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | ||
| 30 | {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, | ||
| 31 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, | ||
| 32 | {9, nullptr, "CopyBetweenCaptureBuffers"}, | ||
| 33 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | ||
| 34 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | ||
| 35 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | ||
| 36 | {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, | ||
| 37 | {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, | ||
| 38 | {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, | ||
| 39 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | ||
| 40 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | ||
| 41 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | ||
| 42 | {20, nullptr, "ClearCaptureBuffer"}, | ||
| 43 | {21, nullptr, "ClearAppletTransitionBuffer"}, | ||
| 44 | {22, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"}, | ||
| 45 | {23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "ReleaseLastApplicationCaptureSharedBuffer"}, | ||
| 46 | {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, | ||
| 47 | {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, | ||
| 48 | {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, | ||
| 49 | {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, | ||
| 50 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | ||
| 51 | }; | ||
| 52 | // clang-format on | ||
| 53 | |||
| 54 | RegisterHandlers(functions); | ||
| 55 | } | ||
| 56 | |||
| 57 | IDisplayController::~IDisplayController() = default; | ||
| 58 | |||
| 59 | void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { | ||
| 60 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 61 | |||
| 62 | OutputParameters params{}; | ||
| 63 | const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( | ||
| 64 | ¶ms.was_written, ¶ms.fbshare_layer_index); | ||
| 65 | |||
| 66 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 67 | rb.Push(res); | ||
| 68 | rb.PushRaw(params); | ||
| 69 | } | ||
| 70 | |||
| 71 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | ||
| 72 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 73 | |||
| 74 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 75 | rb.Push(ResultSuccess); | ||
| 76 | } | ||
| 77 | |||
| 78 | void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 79 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 80 | |||
| 81 | OutputParameters params{}; | ||
| 82 | const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( | ||
| 83 | ¶ms.was_written, ¶ms.fbshare_layer_index); | ||
| 84 | |||
| 85 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 86 | rb.Push(res); | ||
| 87 | rb.PushRaw(params); | ||
| 88 | } | ||
| 89 | |||
| 90 | void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 91 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 94 | rb.Push(ResultSuccess); | ||
| 95 | } | ||
| 96 | |||
| 97 | void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 98 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 99 | |||
| 100 | OutputParameters params{}; | ||
| 101 | const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( | ||
| 102 | ¶ms.was_written, ¶ms.fbshare_layer_index); | ||
| 103 | |||
| 104 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 105 | rb.Push(res); | ||
| 106 | rb.PushRaw(params); | ||
| 107 | } | ||
| 108 | |||
| 109 | void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 110 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 111 | |||
| 112 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 113 | rb.Push(ResultSuccess); | ||
| 114 | } | ||
| 115 | |||
| 116 | void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 117 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 118 | |||
| 119 | OutputParameters params{}; | ||
| 120 | const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( | ||
| 121 | ¶ms.was_written, ¶ms.fbshare_layer_index); | ||
| 122 | |||
| 123 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 124 | rb.Push(res); | ||
| 125 | rb.PushRaw(params); | ||
| 126 | } | ||
| 127 | |||
| 128 | void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 129 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 130 | |||
| 131 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 132 | rb.Push(ResultSuccess); | ||
| 133 | } | ||
| 134 | |||
| 135 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h new file mode 100644 index 000000000..75172580c --- /dev/null +++ b/src/core/hle/service/am/display_controller.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class IDisplayController final : public ServiceFramework<IDisplayController> { | ||
| 13 | public: | ||
| 14 | explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 15 | ~IDisplayController() override; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); | ||
| 19 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); | ||
| 20 | void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 21 | void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 22 | void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 23 | void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 24 | void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 25 | void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 26 | |||
| 27 | const std::shared_ptr<Applet> applet; | ||
| 28 | }; | ||
| 29 | |||
| 30 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/frontend/applet_cabinet.cpp index c2ff444a6..0862c81b6 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/frontend/applet_cabinet.cpp | |||
| @@ -8,16 +8,17 @@ | |||
| 8 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 9 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applets/applet_cabinet.h" | 11 | #include "core/hle/service/am/frontend/applet_cabinet.h" |
| 12 | #include "core/hle/service/am/storage.h" | ||
| 12 | #include "core/hle/service/mii/mii_manager.h" | 13 | #include "core/hle/service/mii/mii_manager.h" |
| 13 | #include "core/hle/service/nfc/common/device.h" | 14 | #include "core/hle/service/nfc/common/device.h" |
| 14 | #include "hid_core/hid_core.h" | 15 | #include "hid_core/hid_core.h" |
| 15 | 16 | ||
| 16 | namespace Service::AM::Applets { | 17 | namespace Service::AM::Frontend { |
| 17 | 18 | ||
| 18 | Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, | 19 | Cabinet::Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 19 | const Core::Frontend::CabinetApplet& frontend_) | 20 | LibraryAppletMode applet_mode_, const Core::Frontend::CabinetApplet& frontend_) |
| 20 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{ | 21 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_}, service_context{ |
| 21 | system_, | 22 | system_, |
| 22 | "CabinetApplet"} { | 23 | "CabinetApplet"} { |
| 23 | 24 | ||
| @@ -30,7 +31,7 @@ Cabinet::~Cabinet() { | |||
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | void Cabinet::Initialize() { | 33 | void Cabinet::Initialize() { |
| 33 | Applet::Initialize(); | 34 | FrontendApplet::Initialize(); |
| 34 | 35 | ||
| 35 | LOG_INFO(Service_HID, "Initializing Cabinet Applet."); | 36 | LOG_INFO(Service_HID, "Initializing Cabinet Applet."); |
| 36 | 37 | ||
| @@ -41,7 +42,7 @@ void Cabinet::Initialize() { | |||
| 41 | common_args.play_startup_sound, common_args.size, common_args.system_tick, | 42 | common_args.play_startup_sound, common_args.size, common_args.system_tick, |
| 42 | common_args.theme_color); | 43 | common_args.theme_color); |
| 43 | 44 | ||
| 44 | const auto storage = broker.PopNormalDataToApplet(); | 45 | std::shared_ptr<IStorage> storage = PopInData(); |
| 45 | ASSERT(storage != nullptr); | 46 | ASSERT(storage != nullptr); |
| 46 | 47 | ||
| 47 | const auto applet_input_data = storage->GetData(); | 48 | const auto applet_input_data = storage->GetData(); |
| @@ -51,10 +52,6 @@ void Cabinet::Initialize() { | |||
| 51 | sizeof(StartParamForAmiiboSettings)); | 52 | sizeof(StartParamForAmiiboSettings)); |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | bool Cabinet::TransactionComplete() const { | ||
| 55 | return is_complete; | ||
| 56 | } | ||
| 57 | |||
| 58 | Result Cabinet::GetStatus() const { | 55 | Result Cabinet::GetStatus() const { |
| 59 | return ResultSuccess; | 56 | return ResultSuccess; |
| 60 | } | 57 | } |
| @@ -160,8 +157,8 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) | |||
| 160 | 157 | ||
| 161 | is_complete = true; | 158 | is_complete = true; |
| 162 | 159 | ||
| 163 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 160 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 164 | broker.SignalStateChanged(); | 161 | Exit(); |
| 165 | } | 162 | } |
| 166 | 163 | ||
| 167 | void Cabinet::Cancel() { | 164 | void Cabinet::Cancel() { |
| @@ -175,8 +172,8 @@ void Cabinet::Cancel() { | |||
| 175 | 172 | ||
| 176 | is_complete = true; | 173 | is_complete = true; |
| 177 | 174 | ||
| 178 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 175 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 179 | broker.SignalStateChanged(); | 176 | Exit(); |
| 180 | } | 177 | } |
| 181 | 178 | ||
| 182 | Result Cabinet::RequestExit() { | 179 | Result Cabinet::RequestExit() { |
| @@ -184,4 +181,4 @@ Result Cabinet::RequestExit() { | |||
| 184 | R_SUCCEED(); | 181 | R_SUCCEED(); |
| 185 | } | 182 | } |
| 186 | 183 | ||
| 187 | } // namespace Service::AM::Applets | 184 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/frontend/applet_cabinet.h index f498796f7..3a211ed37 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/frontend/applet_cabinet.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <array> | 6 | #include <array> |
| 7 | 7 | ||
| 8 | #include "core/hle/result.h" | 8 | #include "core/hle/result.h" |
| 9 | #include "core/hle/service/am/applets/applets.h" | 9 | #include "core/hle/service/am/frontend/applets.h" |
| 10 | #include "core/hle/service/kernel_helpers.h" | 10 | #include "core/hle/service/kernel_helpers.h" |
| 11 | #include "core/hle/service/nfp/nfp_types.h" | 11 | #include "core/hle/service/nfp/nfp_types.h" |
| 12 | 12 | ||
| @@ -23,7 +23,7 @@ namespace Service::NFC { | |||
| 23 | class NfcDevice; | 23 | class NfcDevice; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | namespace Service::AM::Applets { | 26 | namespace Service::AM::Frontend { |
| 27 | 27 | ||
| 28 | enum class CabinetAppletVersion : u32 { | 28 | enum class CabinetAppletVersion : u32 { |
| 29 | Version1 = 0x1, | 29 | Version1 = 0x1, |
| @@ -84,15 +84,15 @@ static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x188, | |||
| 84 | "ReturnValueForAmiiboSettings is an invalid size"); | 84 | "ReturnValueForAmiiboSettings is an invalid size"); |
| 85 | #pragma pack(pop) | 85 | #pragma pack(pop) |
| 86 | 86 | ||
| 87 | class Cabinet final : public Applet { | 87 | class Cabinet final : public FrontendApplet { |
| 88 | public: | 88 | public: |
| 89 | explicit Cabinet(Core::System& system_, LibraryAppletMode applet_mode_, | 89 | explicit Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 90 | LibraryAppletMode applet_mode_, | ||
| 90 | const Core::Frontend::CabinetApplet& frontend_); | 91 | const Core::Frontend::CabinetApplet& frontend_); |
| 91 | ~Cabinet() override; | 92 | ~Cabinet() override; |
| 92 | 93 | ||
| 93 | void Initialize() override; | 94 | void Initialize() override; |
| 94 | 95 | ||
| 95 | bool TransactionComplete() const override; | ||
| 96 | Result GetStatus() const override; | 96 | Result GetStatus() const override; |
| 97 | void ExecuteInteractive() override; | 97 | void ExecuteInteractive() override; |
| 98 | void Execute() override; | 98 | void Execute() override; |
| @@ -102,7 +102,6 @@ public: | |||
| 102 | 102 | ||
| 103 | private: | 103 | private: |
| 104 | const Core::Frontend::CabinetApplet& frontend; | 104 | const Core::Frontend::CabinetApplet& frontend; |
| 105 | Core::System& system; | ||
| 106 | 105 | ||
| 107 | bool is_complete{false}; | 106 | bool is_complete{false}; |
| 108 | std::shared_ptr<Service::NFC::NfcDevice> nfp_device; | 107 | std::shared_ptr<Service::NFC::NfcDevice> nfp_device; |
| @@ -111,4 +110,4 @@ private: | |||
| 111 | StartParamForAmiiboSettings applet_input_common{}; | 110 | StartParamForAmiiboSettings applet_input_common{}; |
| 112 | }; | 111 | }; |
| 113 | 112 | ||
| 114 | } // namespace Service::AM::Applets | 113 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/frontend/applet_controller.cpp index 0e4d9cc39..bd3e49fc4 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/frontend/applet_controller.cpp | |||
| @@ -11,13 +11,14 @@ | |||
| 11 | #include "core/frontend/applets/controller.h" | 11 | #include "core/frontend/applets/controller.h" |
| 12 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 13 | #include "core/hle/service/am/am.h" | 13 | #include "core/hle/service/am/am.h" |
| 14 | #include "core/hle/service/am/applets/applet_controller.h" | 14 | #include "core/hle/service/am/frontend/applet_controller.h" |
| 15 | #include "core/hle/service/am/storage.h" | ||
| 15 | #include "hid_core/frontend/emulated_controller.h" | 16 | #include "hid_core/frontend/emulated_controller.h" |
| 16 | #include "hid_core/hid_core.h" | 17 | #include "hid_core/hid_core.h" |
| 17 | #include "hid_core/hid_types.h" | 18 | #include "hid_core/hid_types.h" |
| 18 | #include "hid_core/resources/npad/npad.h" | 19 | #include "hid_core/resources/npad/npad.h" |
| 19 | 20 | ||
| 20 | namespace Service::AM::Applets { | 21 | namespace Service::AM::Frontend { |
| 21 | 22 | ||
| 22 | [[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101}; | 23 | [[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101}; |
| 23 | [[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID, | 24 | [[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID, |
| @@ -46,14 +47,15 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( | |||
| 46 | }; | 47 | }; |
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_, | 50 | Controller::Controller(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 51 | LibraryAppletMode applet_mode_, | ||
| 50 | const Core::Frontend::ControllerApplet& frontend_) | 52 | const Core::Frontend::ControllerApplet& frontend_) |
| 51 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 53 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 52 | 54 | ||
| 53 | Controller::~Controller() = default; | 55 | Controller::~Controller() = default; |
| 54 | 56 | ||
| 55 | void Controller::Initialize() { | 57 | void Controller::Initialize() { |
| 56 | Applet::Initialize(); | 58 | FrontendApplet::Initialize(); |
| 57 | 59 | ||
| 58 | LOG_INFO(Service_HID, "Initializing Controller Applet."); | 60 | LOG_INFO(Service_HID, "Initializing Controller Applet."); |
| 59 | 61 | ||
| @@ -66,7 +68,7 @@ void Controller::Initialize() { | |||
| 66 | 68 | ||
| 67 | controller_applet_version = ControllerAppletVersion{common_args.library_version}; | 69 | controller_applet_version = ControllerAppletVersion{common_args.library_version}; |
| 68 | 70 | ||
| 69 | const auto private_arg_storage = broker.PopNormalDataToApplet(); | 71 | const std::shared_ptr<IStorage> private_arg_storage = PopInData(); |
| 70 | ASSERT(private_arg_storage != nullptr); | 72 | ASSERT(private_arg_storage != nullptr); |
| 71 | 73 | ||
| 72 | const auto& private_arg = private_arg_storage->GetData(); | 74 | const auto& private_arg = private_arg_storage->GetData(); |
| @@ -116,7 +118,7 @@ void Controller::Initialize() { | |||
| 116 | switch (controller_private_arg.mode) { | 118 | switch (controller_private_arg.mode) { |
| 117 | case ControllerSupportMode::ShowControllerSupport: | 119 | case ControllerSupportMode::ShowControllerSupport: |
| 118 | case ControllerSupportMode::ShowControllerStrapGuide: { | 120 | case ControllerSupportMode::ShowControllerStrapGuide: { |
| 119 | const auto user_arg_storage = broker.PopNormalDataToApplet(); | 121 | const std::shared_ptr<IStorage> user_arg_storage = PopInData(); |
| 120 | ASSERT(user_arg_storage != nullptr); | 122 | ASSERT(user_arg_storage != nullptr); |
| 121 | 123 | ||
| 122 | const auto& user_arg = user_arg_storage->GetData(); | 124 | const auto& user_arg = user_arg_storage->GetData(); |
| @@ -142,7 +144,7 @@ void Controller::Initialize() { | |||
| 142 | break; | 144 | break; |
| 143 | } | 145 | } |
| 144 | case ControllerSupportMode::ShowControllerFirmwareUpdate: { | 146 | case ControllerSupportMode::ShowControllerFirmwareUpdate: { |
| 145 | const auto update_arg_storage = broker.PopNormalDataToApplet(); | 147 | const std::shared_ptr<IStorage> update_arg_storage = PopInData(); |
| 146 | ASSERT(update_arg_storage != nullptr); | 148 | ASSERT(update_arg_storage != nullptr); |
| 147 | 149 | ||
| 148 | const auto& update_arg = update_arg_storage->GetData(); | 150 | const auto& update_arg = update_arg_storage->GetData(); |
| @@ -152,7 +154,7 @@ void Controller::Initialize() { | |||
| 152 | break; | 154 | break; |
| 153 | } | 155 | } |
| 154 | case ControllerSupportMode::ShowControllerKeyRemappingForSystem: { | 156 | case ControllerSupportMode::ShowControllerKeyRemappingForSystem: { |
| 155 | const auto remapping_arg_storage = broker.PopNormalDataToApplet(); | 157 | const std::shared_ptr<IStorage> remapping_arg_storage = PopInData(); |
| 156 | ASSERT(remapping_arg_storage != nullptr); | 158 | ASSERT(remapping_arg_storage != nullptr); |
| 157 | 159 | ||
| 158 | const auto& remapping_arg = remapping_arg_storage->GetData(); | 160 | const auto& remapping_arg = remapping_arg_storage->GetData(); |
| @@ -168,10 +170,6 @@ void Controller::Initialize() { | |||
| 168 | } | 170 | } |
| 169 | } | 171 | } |
| 170 | 172 | ||
| 171 | bool Controller::TransactionComplete() const { | ||
| 172 | return complete; | ||
| 173 | } | ||
| 174 | |||
| 175 | Result Controller::GetStatus() const { | 173 | Result Controller::GetStatus() const { |
| 176 | return status; | 174 | return status; |
| 177 | } | 175 | } |
| @@ -260,8 +258,9 @@ void Controller::ConfigurationComplete(bool is_success) { | |||
| 260 | complete = true; | 258 | complete = true; |
| 261 | out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo)); | 259 | out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo)); |
| 262 | std::memcpy(out_data.data(), &result_info, out_data.size()); | 260 | std::memcpy(out_data.data(), &result_info, out_data.size()); |
| 263 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 261 | |
| 264 | broker.SignalStateChanged(); | 262 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 263 | Exit(); | ||
| 265 | } | 264 | } |
| 266 | 265 | ||
| 267 | Result Controller::RequestExit() { | 266 | Result Controller::RequestExit() { |
| @@ -269,4 +268,4 @@ Result Controller::RequestExit() { | |||
| 269 | R_SUCCEED(); | 268 | R_SUCCEED(); |
| 270 | } | 269 | } |
| 271 | 270 | ||
| 272 | } // namespace Service::AM::Applets | 271 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/frontend/applet_controller.h index 9f839f3d7..2f219429c 100644 --- a/src/core/hle/service/am/applets/applet_controller.h +++ b/src/core/hle/service/am/frontend/applet_controller.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 12 | #include "core/hle/service/am/applets/applets.h" | 12 | #include "core/hle/service/am/frontend/applets.h" |
| 13 | 13 | ||
| 14 | namespace Core { | 14 | namespace Core { |
| 15 | class System; | 15 | class System; |
| @@ -19,7 +19,7 @@ namespace Core::HID { | |||
| 19 | enum class NpadStyleSet : u32; | 19 | enum class NpadStyleSet : u32; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | namespace Service::AM::Applets { | 22 | namespace Service::AM::Frontend { |
| 23 | 23 | ||
| 24 | using IdentificationColor = std::array<u8, 4>; | 24 | using IdentificationColor = std::array<u8, 4>; |
| 25 | using ExplainText = std::array<char, 0x81>; | 25 | using ExplainText = std::array<char, 0x81>; |
| @@ -122,15 +122,15 @@ struct ControllerSupportResultInfo { | |||
| 122 | static_assert(sizeof(ControllerSupportResultInfo) == 0xC, | 122 | static_assert(sizeof(ControllerSupportResultInfo) == 0xC, |
| 123 | "ControllerSupportResultInfo has incorrect size."); | 123 | "ControllerSupportResultInfo has incorrect size."); |
| 124 | 124 | ||
| 125 | class Controller final : public Applet { | 125 | class Controller final : public FrontendApplet { |
| 126 | public: | 126 | public: |
| 127 | explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_, | 127 | explicit Controller(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 128 | LibraryAppletMode applet_mode_, | ||
| 128 | const Core::Frontend::ControllerApplet& frontend_); | 129 | const Core::Frontend::ControllerApplet& frontend_); |
| 129 | ~Controller() override; | 130 | ~Controller() override; |
| 130 | 131 | ||
| 131 | void Initialize() override; | 132 | void Initialize() override; |
| 132 | 133 | ||
| 133 | bool TransactionComplete() const override; | ||
| 134 | Result GetStatus() const override; | 134 | Result GetStatus() const override; |
| 135 | void ExecuteInteractive() override; | 135 | void ExecuteInteractive() override; |
| 136 | void Execute() override; | 136 | void Execute() override; |
| @@ -140,7 +140,6 @@ public: | |||
| 140 | 140 | ||
| 141 | private: | 141 | private: |
| 142 | const Core::Frontend::ControllerApplet& frontend; | 142 | const Core::Frontend::ControllerApplet& frontend; |
| 143 | Core::System& system; | ||
| 144 | 143 | ||
| 145 | ControllerAppletVersion controller_applet_version; | 144 | ControllerAppletVersion controller_applet_version; |
| 146 | ControllerSupportArgPrivate controller_private_arg; | 145 | ControllerSupportArgPrivate controller_private_arg; |
| @@ -154,4 +153,4 @@ private: | |||
| 154 | std::vector<u8> out_data; | 153 | std::vector<u8> out_data; |
| 155 | }; | 154 | }; |
| 156 | 155 | ||
| 157 | } // namespace Service::AM::Applets | 156 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/frontend/applet_error.cpp index 084bc138c..b97a5f3ea 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/frontend/applet_error.cpp | |||
| @@ -9,10 +9,11 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/frontend/applets/error.h" | 10 | #include "core/frontend/applets/error.h" |
| 11 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_error.h" | 12 | #include "core/hle/service/am/frontend/applet_error.h" |
| 13 | #include "core/hle/service/am/storage.h" | ||
| 13 | #include "core/reporter.h" | 14 | #include "core/reporter.h" |
| 14 | 15 | ||
| 15 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Frontend { |
| 16 | 17 | ||
| 17 | struct ErrorCode { | 18 | struct ErrorCode { |
| 18 | u32 error_category{}; | 19 | u32 error_category{}; |
| @@ -103,18 +104,18 @@ Result Decode64BitError(u64 error) { | |||
| 103 | 104 | ||
| 104 | } // Anonymous namespace | 105 | } // Anonymous namespace |
| 105 | 106 | ||
| 106 | Error::Error(Core::System& system_, LibraryAppletMode applet_mode_, | 107 | Error::Error(Core::System& system_, std::shared_ptr<Applet> applet_, LibraryAppletMode applet_mode_, |
| 107 | const Core::Frontend::ErrorApplet& frontend_) | 108 | const Core::Frontend::ErrorApplet& frontend_) |
| 108 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 109 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 109 | 110 | ||
| 110 | Error::~Error() = default; | 111 | Error::~Error() = default; |
| 111 | 112 | ||
| 112 | void Error::Initialize() { | 113 | void Error::Initialize() { |
| 113 | Applet::Initialize(); | 114 | FrontendApplet::Initialize(); |
| 114 | args = std::make_unique<ErrorArguments>(); | 115 | args = std::make_unique<ErrorArguments>(); |
| 115 | complete = false; | 116 | complete = false; |
| 116 | 117 | ||
| 117 | const auto storage = broker.PopNormalDataToApplet(); | 118 | const std::shared_ptr<IStorage> storage = PopInData(); |
| 118 | ASSERT(storage != nullptr); | 119 | ASSERT(storage != nullptr); |
| 119 | const auto data = storage->GetData(); | 120 | const auto data = storage->GetData(); |
| 120 | 121 | ||
| @@ -152,10 +153,6 @@ void Error::Initialize() { | |||
| 152 | } | 153 | } |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | bool Error::TransactionComplete() const { | ||
| 156 | return complete; | ||
| 157 | } | ||
| 158 | |||
| 159 | Result Error::GetStatus() const { | 156 | Result Error::GetStatus() const { |
| 160 | return ResultSuccess; | 157 | return ResultSuccess; |
| 161 | } | 158 | } |
| @@ -210,8 +207,8 @@ void Error::Execute() { | |||
| 210 | 207 | ||
| 211 | void Error::DisplayCompleted() { | 208 | void Error::DisplayCompleted() { |
| 212 | complete = true; | 209 | complete = true; |
| 213 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{})); | 210 | PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); |
| 214 | broker.SignalStateChanged(); | 211 | Exit(); |
| 215 | } | 212 | } |
| 216 | 213 | ||
| 217 | Result Error::RequestExit() { | 214 | Result Error::RequestExit() { |
| @@ -219,4 +216,4 @@ Result Error::RequestExit() { | |||
| 219 | R_SUCCEED(); | 216 | R_SUCCEED(); |
| 220 | } | 217 | } |
| 221 | 218 | ||
| 222 | } // namespace Service::AM::Applets | 219 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_error.h b/src/core/hle/service/am/frontend/applet_error.h index d822a32bb..678bf33fa 100644 --- a/src/core/hle/service/am/applets/applet_error.h +++ b/src/core/hle/service/am/frontend/applet_error.h | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/result.h" | 6 | #include "core/hle/result.h" |
| 7 | #include "core/hle/service/am/applets/applets.h" | 7 | #include "core/hle/service/am/frontend/applets.h" |
| 8 | 8 | ||
| 9 | namespace Core { | 9 | namespace Core { |
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::AM::Applets { | 13 | namespace Service::AM::Frontend { |
| 14 | 14 | ||
| 15 | enum class ErrorAppletMode : u8 { | 15 | enum class ErrorAppletMode : u8 { |
| 16 | ShowError = 0, | 16 | ShowError = 0, |
| @@ -22,15 +22,14 @@ enum class ErrorAppletMode : u8 { | |||
| 22 | ShowUpdateEula = 8, | 22 | ShowUpdateEula = 8, |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | class Error final : public Applet { | 25 | class Error final : public FrontendApplet { |
| 26 | public: | 26 | public: |
| 27 | explicit Error(Core::System& system_, LibraryAppletMode applet_mode_, | 27 | explicit Error(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 28 | const Core::Frontend::ErrorApplet& frontend_); | 28 | LibraryAppletMode applet_mode_, const Core::Frontend::ErrorApplet& frontend_); |
| 29 | ~Error() override; | 29 | ~Error() override; |
| 30 | 30 | ||
| 31 | void Initialize() override; | 31 | void Initialize() override; |
| 32 | 32 | ||
| 33 | bool TransactionComplete() const override; | ||
| 34 | Result GetStatus() const override; | 33 | Result GetStatus() const override; |
| 35 | void ExecuteInteractive() override; | 34 | void ExecuteInteractive() override; |
| 36 | void Execute() override; | 35 | void Execute() override; |
| @@ -47,7 +46,6 @@ private: | |||
| 47 | std::unique_ptr<ErrorArguments> args; | 46 | std::unique_ptr<ErrorArguments> args; |
| 48 | 47 | ||
| 49 | bool complete = false; | 48 | bool complete = false; |
| 50 | Core::System& system; | ||
| 51 | }; | 49 | }; |
| 52 | 50 | ||
| 53 | } // namespace Service::AM::Applets | 51 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/frontend/applet_general.cpp index c0032f652..3c091a602 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/frontend/applet_general.cpp | |||
| @@ -5,27 +5,28 @@ | |||
| 5 | #include "common/hex_util.h" | 5 | #include "common/hex_util.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/frontend/applets/general_frontend.h" | 8 | #include "core/frontend/applets/general.h" |
| 9 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applets/applet_general_backend.h" | 11 | #include "core/hle/service/am/applet_data_broker.h" |
| 12 | #include "core/hle/service/am/frontend/applet_general.h" | ||
| 13 | #include "core/hle/service/am/storage.h" | ||
| 12 | #include "core/reporter.h" | 14 | #include "core/reporter.h" |
| 13 | 15 | ||
| 14 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Frontend { |
| 15 | 17 | ||
| 16 | constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; | 18 | constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; |
| 17 | 19 | ||
| 18 | static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { | 20 | static void LogCurrentStorage(std::shared_ptr<Applet> applet, std::string_view prefix) { |
| 19 | std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet(); | 21 | std::shared_ptr<IStorage> storage; |
| 20 | for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { | 22 | while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(&storage))) { |
| 21 | const auto data = storage->GetData(); | 23 | const auto data = storage->GetData(); |
| 22 | LOG_INFO(Service_AM, | 24 | LOG_INFO(Service_AM, |
| 23 | "called (STUBBED), during {} received normal data with size={:08X}, data={}", | 25 | "called (STUBBED), during {} received normal data with size={:08X}, data={}", |
| 24 | prefix, data.size(), Common::HexToString(data)); | 26 | prefix, data.size(), Common::HexToString(data)); |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | storage = broker.PopInteractiveDataToApplet(); | 29 | while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(&storage))) { |
| 28 | for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) { | ||
| 29 | const auto data = storage->GetData(); | 30 | const auto data = storage->GetData(); |
| 30 | LOG_INFO(Service_AM, | 31 | LOG_INFO(Service_AM, |
| 31 | "called (STUBBED), during {} received interactive data with size={:08X}, data={}", | 32 | "called (STUBBED), during {} received interactive data with size={:08X}, data={}", |
| @@ -33,17 +34,17 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) | |||
| 33 | } | 34 | } |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_, | 37 | Auth::Auth(Core::System& system_, std::shared_ptr<Applet> applet_, LibraryAppletMode applet_mode_, |
| 37 | Core::Frontend::ParentalControlsApplet& frontend_) | 38 | Core::Frontend::ParentalControlsApplet& frontend_) |
| 38 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 39 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 39 | 40 | ||
| 40 | Auth::~Auth() = default; | 41 | Auth::~Auth() = default; |
| 41 | 42 | ||
| 42 | void Auth::Initialize() { | 43 | void Auth::Initialize() { |
| 43 | Applet::Initialize(); | 44 | FrontendApplet::Initialize(); |
| 44 | complete = false; | 45 | complete = false; |
| 45 | 46 | ||
| 46 | const auto storage = broker.PopNormalDataToApplet(); | 47 | const std::shared_ptr<IStorage> storage = PopInData(); |
| 47 | ASSERT(storage != nullptr); | 48 | ASSERT(storage != nullptr); |
| 48 | const auto data = storage->GetData(); | 49 | const auto data = storage->GetData(); |
| 49 | ASSERT(data.size() >= 0xC); | 50 | ASSERT(data.size() >= 0xC); |
| @@ -67,10 +68,6 @@ void Auth::Initialize() { | |||
| 67 | arg2 = arg.arg2; | 68 | arg2 = arg.arg2; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | bool Auth::TransactionComplete() const { | ||
| 71 | return complete; | ||
| 72 | } | ||
| 73 | |||
| 74 | Result Auth::GetStatus() const { | 71 | Result Auth::GetStatus() const { |
| 75 | return successful ? ResultSuccess : ERROR_INVALID_PIN; | 72 | return successful ? ResultSuccess : ERROR_INVALID_PIN; |
| 76 | } | 73 | } |
| @@ -146,8 +143,8 @@ void Auth::AuthFinished(bool is_successful) { | |||
| 146 | std::vector<u8> out(sizeof(Return)); | 143 | std::vector<u8> out(sizeof(Return)); |
| 147 | std::memcpy(out.data(), &return_, sizeof(Return)); | 144 | std::memcpy(out.data(), &return_, sizeof(Return)); |
| 148 | 145 | ||
| 149 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out))); | 146 | PushOutData(std::make_shared<IStorage>(system, std::move(out))); |
| 150 | broker.SignalStateChanged(); | 147 | Exit(); |
| 151 | } | 148 | } |
| 152 | 149 | ||
| 153 | Result Auth::RequestExit() { | 150 | Result Auth::RequestExit() { |
| @@ -155,27 +152,24 @@ Result Auth::RequestExit() { | |||
| 155 | R_SUCCEED(); | 152 | R_SUCCEED(); |
| 156 | } | 153 | } |
| 157 | 154 | ||
| 158 | PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, | 155 | PhotoViewer::PhotoViewer(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 156 | LibraryAppletMode applet_mode_, | ||
| 159 | const Core::Frontend::PhotoViewerApplet& frontend_) | 157 | const Core::Frontend::PhotoViewerApplet& frontend_) |
| 160 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 158 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 161 | 159 | ||
| 162 | PhotoViewer::~PhotoViewer() = default; | 160 | PhotoViewer::~PhotoViewer() = default; |
| 163 | 161 | ||
| 164 | void PhotoViewer::Initialize() { | 162 | void PhotoViewer::Initialize() { |
| 165 | Applet::Initialize(); | 163 | FrontendApplet::Initialize(); |
| 166 | complete = false; | 164 | complete = false; |
| 167 | 165 | ||
| 168 | const auto storage = broker.PopNormalDataToApplet(); | 166 | const std::shared_ptr<IStorage> storage = PopInData(); |
| 169 | ASSERT(storage != nullptr); | 167 | ASSERT(storage != nullptr); |
| 170 | const auto data = storage->GetData(); | 168 | const auto data = storage->GetData(); |
| 171 | ASSERT(!data.empty()); | 169 | ASSERT(!data.empty()); |
| 172 | mode = static_cast<PhotoViewerAppletMode>(data[0]); | 170 | mode = static_cast<PhotoViewerAppletMode>(data[0]); |
| 173 | } | 171 | } |
| 174 | 172 | ||
| 175 | bool PhotoViewer::TransactionComplete() const { | ||
| 176 | return complete; | ||
| 177 | } | ||
| 178 | |||
| 179 | Result PhotoViewer::GetStatus() const { | 173 | Result PhotoViewer::GetStatus() const { |
| 180 | return ResultSuccess; | 174 | return ResultSuccess; |
| 181 | } | 175 | } |
| @@ -203,8 +197,8 @@ void PhotoViewer::Execute() { | |||
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | void PhotoViewer::ViewFinished() { | 199 | void PhotoViewer::ViewFinished() { |
| 206 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{})); | 200 | PushOutData(std::make_shared<IStorage>(system, std::vector<u8>{})); |
| 207 | broker.SignalStateChanged(); | 201 | Exit(); |
| 208 | } | 202 | } |
| 209 | 203 | ||
| 210 | Result PhotoViewer::RequestExit() { | 204 | Result PhotoViewer::RequestExit() { |
| @@ -212,27 +206,17 @@ Result PhotoViewer::RequestExit() { | |||
| 212 | R_SUCCEED(); | 206 | R_SUCCEED(); |
| 213 | } | 207 | } |
| 214 | 208 | ||
| 215 | StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) | 209 | StubApplet::StubApplet(Core::System& system_, std::shared_ptr<Applet> applet_, AppletId id_, |
| 216 | : Applet{system_, applet_mode_}, id{id_}, system{system_} {} | 210 | LibraryAppletMode applet_mode_) |
| 211 | : FrontendApplet{system_, applet_, applet_mode_}, id{id_} {} | ||
| 217 | 212 | ||
| 218 | StubApplet::~StubApplet() = default; | 213 | StubApplet::~StubApplet() = default; |
| 219 | 214 | ||
| 220 | void StubApplet::Initialize() { | 215 | void StubApplet::Initialize() { |
| 221 | LOG_WARNING(Service_AM, "called (STUBBED)"); | 216 | LOG_WARNING(Service_AM, "called (STUBBED)"); |
| 222 | Applet::Initialize(); | 217 | FrontendApplet::Initialize(); |
| 223 | 218 | ||
| 224 | const auto data = broker.PeekDataToAppletForDebug(); | 219 | LogCurrentStorage(applet.lock(), "Initialize"); |
| 225 | system.GetReporter().SaveUnimplementedAppletReport( | ||
| 226 | static_cast<u32>(id), static_cast<u32>(common_args.arguments_version), | ||
| 227 | common_args.library_version, static_cast<u32>(common_args.theme_color), | ||
| 228 | common_args.play_startup_sound, common_args.system_tick, data.normal, data.interactive); | ||
| 229 | |||
| 230 | LogCurrentStorage(broker, "Initialize"); | ||
| 231 | } | ||
| 232 | |||
| 233 | bool StubApplet::TransactionComplete() const { | ||
| 234 | LOG_WARNING(Service_AM, "called (STUBBED)"); | ||
| 235 | return true; | ||
| 236 | } | 220 | } |
| 237 | 221 | ||
| 238 | Result StubApplet::GetStatus() const { | 222 | Result StubApplet::GetStatus() const { |
| @@ -242,22 +226,20 @@ Result StubApplet::GetStatus() const { | |||
| 242 | 226 | ||
| 243 | void StubApplet::ExecuteInteractive() { | 227 | void StubApplet::ExecuteInteractive() { |
| 244 | LOG_WARNING(Service_AM, "called (STUBBED)"); | 228 | LOG_WARNING(Service_AM, "called (STUBBED)"); |
| 245 | LogCurrentStorage(broker, "ExecuteInteractive"); | 229 | LogCurrentStorage(applet.lock(), "ExecuteInteractive"); |
| 246 | 230 | ||
| 247 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); | 231 | PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); |
| 248 | broker.PushInteractiveDataFromApplet( | 232 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); |
| 249 | std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); | 233 | Exit(); |
| 250 | broker.SignalStateChanged(); | ||
| 251 | } | 234 | } |
| 252 | 235 | ||
| 253 | void StubApplet::Execute() { | 236 | void StubApplet::Execute() { |
| 254 | LOG_WARNING(Service_AM, "called (STUBBED)"); | 237 | LOG_WARNING(Service_AM, "called (STUBBED)"); |
| 255 | LogCurrentStorage(broker, "Execute"); | 238 | LogCurrentStorage(applet.lock(), "Execute"); |
| 256 | 239 | ||
| 257 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); | 240 | PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); |
| 258 | broker.PushInteractiveDataFromApplet( | 241 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); |
| 259 | std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); | 242 | Exit(); |
| 260 | broker.SignalStateChanged(); | ||
| 261 | } | 243 | } |
| 262 | 244 | ||
| 263 | Result StubApplet::RequestExit() { | 245 | Result StubApplet::RequestExit() { |
| @@ -265,4 +247,4 @@ Result StubApplet::RequestExit() { | |||
| 265 | R_SUCCEED(); | 247 | R_SUCCEED(); |
| 266 | } | 248 | } |
| 267 | 249 | ||
| 268 | } // namespace Service::AM::Applets | 250 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_general_backend.h b/src/core/hle/service/am/frontend/applet_general.h index 34ecaebb9..eaa7ae25f 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.h +++ b/src/core/hle/service/am/frontend/applet_general.h | |||
| @@ -3,13 +3,13 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/am/applets/applets.h" | 6 | #include "core/hle/service/am/frontend/applets.h" |
| 7 | 7 | ||
| 8 | namespace Core { | 8 | namespace Core { |
| 9 | class System; | 9 | class System; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | namespace Service::AM::Applets { | 12 | namespace Service::AM::Frontend { |
| 13 | 13 | ||
| 14 | enum class AuthAppletType : u32 { | 14 | enum class AuthAppletType : u32 { |
| 15 | ShowParentalAuthentication, | 15 | ShowParentalAuthentication, |
| @@ -17,14 +17,14 @@ enum class AuthAppletType : u32 { | |||
| 17 | ChangeParentalPasscode, | 17 | ChangeParentalPasscode, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | class Auth final : public Applet { | 20 | class Auth final : public FrontendApplet { |
| 21 | public: | 21 | public: |
| 22 | explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_, | 22 | explicit Auth(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 23 | LibraryAppletMode applet_mode_, | ||
| 23 | Core::Frontend::ParentalControlsApplet& frontend_); | 24 | Core::Frontend::ParentalControlsApplet& frontend_); |
| 24 | ~Auth() override; | 25 | ~Auth() override; |
| 25 | 26 | ||
| 26 | void Initialize() override; | 27 | void Initialize() override; |
| 27 | bool TransactionComplete() const override; | ||
| 28 | Result GetStatus() const override; | 28 | Result GetStatus() const override; |
| 29 | void ExecuteInteractive() override; | 29 | void ExecuteInteractive() override; |
| 30 | void Execute() override; | 30 | void Execute() override; |
| @@ -34,7 +34,6 @@ public: | |||
| 34 | 34 | ||
| 35 | private: | 35 | private: |
| 36 | Core::Frontend::ParentalControlsApplet& frontend; | 36 | Core::Frontend::ParentalControlsApplet& frontend; |
| 37 | Core::System& system; | ||
| 38 | bool complete = false; | 37 | bool complete = false; |
| 39 | bool successful = false; | 38 | bool successful = false; |
| 40 | 39 | ||
| @@ -49,14 +48,14 @@ enum class PhotoViewerAppletMode : u8 { | |||
| 49 | AllApps = 1, | 48 | AllApps = 1, |
| 50 | }; | 49 | }; |
| 51 | 50 | ||
| 52 | class PhotoViewer final : public Applet { | 51 | class PhotoViewer final : public FrontendApplet { |
| 53 | public: | 52 | public: |
| 54 | explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, | 53 | explicit PhotoViewer(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 54 | LibraryAppletMode applet_mode_, | ||
| 55 | const Core::Frontend::PhotoViewerApplet& frontend_); | 55 | const Core::Frontend::PhotoViewerApplet& frontend_); |
| 56 | ~PhotoViewer() override; | 56 | ~PhotoViewer() override; |
| 57 | 57 | ||
| 58 | void Initialize() override; | 58 | void Initialize() override; |
| 59 | bool TransactionComplete() const override; | ||
| 60 | Result GetStatus() const override; | 59 | Result GetStatus() const override; |
| 61 | void ExecuteInteractive() override; | 60 | void ExecuteInteractive() override; |
| 62 | void Execute() override; | 61 | void Execute() override; |
| @@ -68,17 +67,16 @@ private: | |||
| 68 | const Core::Frontend::PhotoViewerApplet& frontend; | 67 | const Core::Frontend::PhotoViewerApplet& frontend; |
| 69 | bool complete = false; | 68 | bool complete = false; |
| 70 | PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; | 69 | PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; |
| 71 | Core::System& system; | ||
| 72 | }; | 70 | }; |
| 73 | 71 | ||
| 74 | class StubApplet final : public Applet { | 72 | class StubApplet final : public FrontendApplet { |
| 75 | public: | 73 | public: |
| 76 | explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_); | 74 | explicit StubApplet(Core::System& system_, std::shared_ptr<Applet> applet_, AppletId id_, |
| 75 | LibraryAppletMode applet_mode_); | ||
| 77 | ~StubApplet() override; | 76 | ~StubApplet() override; |
| 78 | 77 | ||
| 79 | void Initialize() override; | 78 | void Initialize() override; |
| 80 | 79 | ||
| 81 | bool TransactionComplete() const override; | ||
| 82 | Result GetStatus() const override; | 80 | Result GetStatus() const override; |
| 83 | void ExecuteInteractive() override; | 81 | void ExecuteInteractive() override; |
| 84 | void Execute() override; | 82 | void Execute() override; |
| @@ -86,7 +84,6 @@ public: | |||
| 86 | 84 | ||
| 87 | private: | 85 | private: |
| 88 | AppletId id; | 86 | AppletId id; |
| 89 | Core::System& system; | ||
| 90 | }; | 87 | }; |
| 91 | 88 | ||
| 92 | } // namespace Service::AM::Applets | 89 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/frontend/applet_mii_edit.cpp index e83e931c5..e3d19fb3d 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.cpp +++ b/src/core/hle/service/am/frontend/applet_mii_edit.cpp | |||
| @@ -6,16 +6,17 @@ | |||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/frontend/applets/mii_edit.h" | 7 | #include "core/frontend/applets/mii_edit.h" |
| 8 | #include "core/hle/service/am/am.h" | 8 | #include "core/hle/service/am/am.h" |
| 9 | #include "core/hle/service/am/applets/applet_mii_edit.h" | 9 | #include "core/hle/service/am/frontend/applet_mii_edit.h" |
| 10 | #include "core/hle/service/am/storage.h" | ||
| 10 | #include "core/hle/service/mii/mii.h" | 11 | #include "core/hle/service/mii/mii.h" |
| 11 | #include "core/hle/service/mii/mii_manager.h" | 12 | #include "core/hle/service/mii/mii_manager.h" |
| 12 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
| 13 | 14 | ||
| 14 | namespace Service::AM::Applets { | 15 | namespace Service::AM::Frontend { |
| 15 | 16 | ||
| 16 | MiiEdit::MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_, | 17 | MiiEdit::MiiEdit(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 17 | const Core::Frontend::MiiEditApplet& frontend_) | 18 | LibraryAppletMode applet_mode_, const Core::Frontend::MiiEditApplet& frontend_) |
| 18 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 19 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 19 | 20 | ||
| 20 | MiiEdit::~MiiEdit() = default; | 21 | MiiEdit::~MiiEdit() = default; |
| 21 | 22 | ||
| @@ -24,7 +25,7 @@ void MiiEdit::Initialize() { | |||
| 24 | // Instead, it is initialized by an AppletInput storage with size 0x100 bytes. | 25 | // Instead, it is initialized by an AppletInput storage with size 0x100 bytes. |
| 25 | // Do NOT call Applet::Initialize() here. | 26 | // Do NOT call Applet::Initialize() here. |
| 26 | 27 | ||
| 27 | const auto storage = broker.PopNormalDataToApplet(); | 28 | const std::shared_ptr<IStorage> storage = PopInData(); |
| 28 | ASSERT(storage != nullptr); | 29 | ASSERT(storage != nullptr); |
| 29 | 30 | ||
| 30 | const auto applet_input_data = storage->GetData(); | 31 | const auto applet_input_data = storage->GetData(); |
| @@ -66,10 +67,6 @@ void MiiEdit::Initialize() { | |||
| 66 | manager->Initialize(metadata); | 67 | manager->Initialize(metadata); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | bool MiiEdit::TransactionComplete() const { | ||
| 70 | return is_complete; | ||
| 71 | } | ||
| 72 | |||
| 73 | Result MiiEdit::GetStatus() const { | 70 | Result MiiEdit::GetStatus() const { |
| 74 | return ResultSuccess; | 71 | return ResultSuccess; |
| 75 | } | 72 | } |
| @@ -152,8 +149,8 @@ void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) { | |||
| 152 | 149 | ||
| 153 | is_complete = true; | 150 | is_complete = true; |
| 154 | 151 | ||
| 155 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 152 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 156 | broker.SignalStateChanged(); | 153 | Exit(); |
| 157 | } | 154 | } |
| 158 | 155 | ||
| 159 | void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result, | 156 | void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result, |
| @@ -168,8 +165,8 @@ void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result, | |||
| 168 | 165 | ||
| 169 | is_complete = true; | 166 | is_complete = true; |
| 170 | 167 | ||
| 171 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 168 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 172 | broker.SignalStateChanged(); | 169 | Exit(); |
| 173 | } | 170 | } |
| 174 | 171 | ||
| 175 | Result MiiEdit::RequestExit() { | 172 | Result MiiEdit::RequestExit() { |
| @@ -177,4 +174,4 @@ Result MiiEdit::RequestExit() { | |||
| 177 | R_SUCCEED(); | 174 | R_SUCCEED(); |
| 178 | } | 175 | } |
| 179 | 176 | ||
| 180 | } // namespace Service::AM::Applets | 177 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/frontend/applet_mii_edit.h index 7ff34af49..5db792f7d 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit.h +++ b/src/core/hle/service/am/frontend/applet_mii_edit.h | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/result.h" | 6 | #include "core/hle/result.h" |
| 7 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" | 7 | #include "core/hle/service/am/frontend/applet_mii_edit_types.h" |
| 8 | #include "core/hle/service/am/applets/applets.h" | 8 | #include "core/hle/service/am/frontend/applets.h" |
| 9 | 9 | ||
| 10 | namespace Core { | 10 | namespace Core { |
| 11 | class System; | 11 | class System; |
| @@ -16,17 +16,17 @@ struct DatabaseSessionMetadata; | |||
| 16 | class MiiManager; | 16 | class MiiManager; |
| 17 | } // namespace Service::Mii | 17 | } // namespace Service::Mii |
| 18 | 18 | ||
| 19 | namespace Service::AM::Applets { | 19 | namespace Service::AM::Frontend { |
| 20 | 20 | ||
| 21 | class MiiEdit final : public Applet { | 21 | class MiiEdit final : public FrontendApplet { |
| 22 | public: | 22 | public: |
| 23 | explicit MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_, | 23 | explicit MiiEdit(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 24 | LibraryAppletMode applet_mode_, | ||
| 24 | const Core::Frontend::MiiEditApplet& frontend_); | 25 | const Core::Frontend::MiiEditApplet& frontend_); |
| 25 | ~MiiEdit() override; | 26 | ~MiiEdit() override; |
| 26 | 27 | ||
| 27 | void Initialize() override; | 28 | void Initialize() override; |
| 28 | 29 | ||
| 29 | bool TransactionComplete() const override; | ||
| 30 | Result GetStatus() const override; | 30 | Result GetStatus() const override; |
| 31 | void ExecuteInteractive() override; | 31 | void ExecuteInteractive() override; |
| 32 | void Execute() override; | 32 | void Execute() override; |
| @@ -38,7 +38,6 @@ public: | |||
| 38 | 38 | ||
| 39 | private: | 39 | private: |
| 40 | const Core::Frontend::MiiEditApplet& frontend; | 40 | const Core::Frontend::MiiEditApplet& frontend; |
| 41 | Core::System& system; | ||
| 42 | 41 | ||
| 43 | MiiEditAppletInputCommon applet_input_common{}; | 42 | MiiEditAppletInputCommon applet_input_common{}; |
| 44 | MiiEditAppletInputV3 applet_input_v3{}; | 43 | MiiEditAppletInputV3 applet_input_v3{}; |
| @@ -49,4 +48,4 @@ private: | |||
| 49 | Mii::DatabaseSessionMetadata metadata{}; | 48 | Mii::DatabaseSessionMetadata metadata{}; |
| 50 | }; | 49 | }; |
| 51 | 50 | ||
| 52 | } // namespace Service::AM::Applets | 51 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_mii_edit_types.h b/src/core/hle/service/am/frontend/applet_mii_edit_types.h index f3d764073..23d9d7a69 100644 --- a/src/core/hle/service/am/applets/applet_mii_edit_types.h +++ b/src/core/hle/service/am/frontend/applet_mii_edit_types.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "common/uuid.h" | 10 | #include "common/uuid.h" |
| 11 | #include "core/hle/service/mii/types/char_info.h" | 11 | #include "core/hle/service/mii/types/char_info.h" |
| 12 | 12 | ||
| 13 | namespace Service::AM::Applets { | 13 | namespace Service::AM::Frontend { |
| 14 | 14 | ||
| 15 | enum class MiiEditAppletVersion : s32 { | 15 | enum class MiiEditAppletVersion : s32 { |
| 16 | Version3 = 0x3, // 1.0.0 - 10.1.1 | 16 | Version3 = 0x3, // 1.0.0 - 10.1.1 |
| @@ -80,4 +80,4 @@ struct MiiEditAppletOutputForCharInfoEditing { | |||
| 80 | static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80, | 80 | static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80, |
| 81 | "MiiEditAppletOutputForCharInfoEditing has incorrect size."); | 81 | "MiiEditAppletOutputForCharInfoEditing has incorrect size."); |
| 82 | 82 | ||
| 83 | } // namespace Service::AM::Applets | 83 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/frontend/applet_profile_select.cpp index 89cb323e9..efb4053b8 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.cpp +++ b/src/core/hle/service/am/frontend/applet_profile_select.cpp | |||
| @@ -9,13 +9,15 @@ | |||
| 9 | #include "core/frontend/applets/profile_select.h" | 9 | #include "core/frontend/applets/profile_select.h" |
| 10 | #include "core/hle/service/acc/errors.h" | 10 | #include "core/hle/service/acc/errors.h" |
| 11 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_profile_select.h" | 12 | #include "core/hle/service/am/frontend/applet_profile_select.h" |
| 13 | #include "core/hle/service/am/storage.h" | ||
| 13 | 14 | ||
| 14 | namespace Service::AM::Applets { | 15 | namespace Service::AM::Frontend { |
| 15 | 16 | ||
| 16 | ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, | 17 | ProfileSelect::ProfileSelect(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 18 | LibraryAppletMode applet_mode_, | ||
| 17 | const Core::Frontend::ProfileSelectApplet& frontend_) | 19 | const Core::Frontend::ProfileSelectApplet& frontend_) |
| 18 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 20 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 19 | 21 | ||
| 20 | ProfileSelect::~ProfileSelect() = default; | 22 | ProfileSelect::~ProfileSelect() = default; |
| 21 | 23 | ||
| @@ -24,10 +26,10 @@ void ProfileSelect::Initialize() { | |||
| 24 | status = ResultSuccess; | 26 | status = ResultSuccess; |
| 25 | final_data.clear(); | 27 | final_data.clear(); |
| 26 | 28 | ||
| 27 | Applet::Initialize(); | 29 | FrontendApplet::Initialize(); |
| 28 | profile_select_version = ProfileSelectAppletVersion{common_args.library_version}; | 30 | profile_select_version = ProfileSelectAppletVersion{common_args.library_version}; |
| 29 | 31 | ||
| 30 | const auto user_config_storage = broker.PopNormalDataToApplet(); | 32 | const std::shared_ptr<IStorage> user_config_storage = PopInData(); |
| 31 | ASSERT(user_config_storage != nullptr); | 33 | ASSERT(user_config_storage != nullptr); |
| 32 | const auto& user_config = user_config_storage->GetData(); | 34 | const auto& user_config = user_config_storage->GetData(); |
| 33 | 35 | ||
| @@ -50,10 +52,6 @@ void ProfileSelect::Initialize() { | |||
| 50 | } | 52 | } |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | bool ProfileSelect::TransactionComplete() const { | ||
| 54 | return complete; | ||
| 55 | } | ||
| 56 | |||
| 57 | Result ProfileSelect::GetStatus() const { | 55 | Result ProfileSelect::GetStatus() const { |
| 58 | return status; | 56 | return status; |
| 59 | } | 57 | } |
| @@ -64,7 +62,8 @@ void ProfileSelect::ExecuteInteractive() { | |||
| 64 | 62 | ||
| 65 | void ProfileSelect::Execute() { | 63 | void ProfileSelect::Execute() { |
| 66 | if (complete) { | 64 | if (complete) { |
| 67 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); | 65 | PushOutData(std::make_shared<IStorage>(system, std::move(final_data))); |
| 66 | Exit(); | ||
| 68 | return; | 67 | return; |
| 69 | } | 68 | } |
| 70 | 69 | ||
| @@ -111,8 +110,9 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { | |||
| 111 | 110 | ||
| 112 | final_data = std::vector<u8>(sizeof(UiReturnArg)); | 111 | final_data = std::vector<u8>(sizeof(UiReturnArg)); |
| 113 | std::memcpy(final_data.data(), &output, final_data.size()); | 112 | std::memcpy(final_data.data(), &output, final_data.size()); |
| 114 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); | 113 | |
| 115 | broker.SignalStateChanged(); | 114 | PushOutData(std::make_shared<IStorage>(system, std::move(final_data))); |
| 115 | Exit(); | ||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | Result ProfileSelect::RequestExit() { | 118 | Result ProfileSelect::RequestExit() { |
| @@ -120,4 +120,4 @@ Result ProfileSelect::RequestExit() { | |||
| 120 | R_SUCCEED(); | 120 | R_SUCCEED(); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | } // namespace Service::AM::Applets | 123 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/frontend/applet_profile_select.h index 673eed516..674e7afe1 100644 --- a/src/core/hle/service/am/applets/applet_profile_select.h +++ b/src/core/hle/service/am/frontend/applet_profile_select.h | |||
| @@ -8,13 +8,13 @@ | |||
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/uuid.h" | 9 | #include "common/uuid.h" |
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 11 | #include "core/hle/service/am/applets/applets.h" | 11 | #include "core/hle/service/am/frontend/applets.h" |
| 12 | 12 | ||
| 13 | namespace Core { | 13 | namespace Core { |
| 14 | class System; | 14 | class System; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace Service::AM::Applets { | 17 | namespace Service::AM::Frontend { |
| 18 | 18 | ||
| 19 | enum class ProfileSelectAppletVersion : u32 { | 19 | enum class ProfileSelectAppletVersion : u32 { |
| 20 | Version1 = 0x1, // 1.0.0+ | 20 | Version1 = 0x1, // 1.0.0+ |
| @@ -111,15 +111,15 @@ struct UiReturnArg { | |||
| 111 | }; | 111 | }; |
| 112 | static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size."); | 112 | static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size."); |
| 113 | 113 | ||
| 114 | class ProfileSelect final : public Applet { | 114 | class ProfileSelect final : public FrontendApplet { |
| 115 | public: | 115 | public: |
| 116 | explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, | 116 | explicit ProfileSelect(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 117 | LibraryAppletMode applet_mode_, | ||
| 117 | const Core::Frontend::ProfileSelectApplet& frontend_); | 118 | const Core::Frontend::ProfileSelectApplet& frontend_); |
| 118 | ~ProfileSelect() override; | 119 | ~ProfileSelect() override; |
| 119 | 120 | ||
| 120 | void Initialize() override; | 121 | void Initialize() override; |
| 121 | 122 | ||
| 122 | bool TransactionComplete() const override; | ||
| 123 | Result GetStatus() const override; | 123 | Result GetStatus() const override; |
| 124 | void ExecuteInteractive() override; | 124 | void ExecuteInteractive() override; |
| 125 | void Execute() override; | 125 | void Execute() override; |
| @@ -137,7 +137,6 @@ private: | |||
| 137 | bool complete = false; | 137 | bool complete = false; |
| 138 | Result status = ResultSuccess; | 138 | Result status = ResultSuccess; |
| 139 | std::vector<u8> final_data; | 139 | std::vector<u8> final_data; |
| 140 | Core::System& system; | ||
| 141 | }; | 140 | }; |
| 142 | 141 | ||
| 143 | } // namespace Service::AM::Applets | 142 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp index 4145bb84f..fbf75d379 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp | |||
| @@ -5,9 +5,10 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/frontend/applets/software_keyboard.h" | 6 | #include "core/frontend/applets/software_keyboard.h" |
| 7 | #include "core/hle/service/am/am.h" | 7 | #include "core/hle/service/am/am.h" |
| 8 | #include "core/hle/service/am/applets/applet_software_keyboard.h" | 8 | #include "core/hle/service/am/frontend/applet_software_keyboard.h" |
| 9 | #include "core/hle/service/am/storage.h" | ||
| 9 | 10 | ||
| 10 | namespace Service::AM::Applets { | 11 | namespace Service::AM::Frontend { |
| 11 | 12 | ||
| 12 | namespace { | 13 | namespace { |
| 13 | 14 | ||
| @@ -41,14 +42,15 @@ void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply | |||
| 41 | 42 | ||
| 42 | } // Anonymous namespace | 43 | } // Anonymous namespace |
| 43 | 44 | ||
| 44 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, | 45 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 46 | LibraryAppletMode applet_mode_, | ||
| 45 | Core::Frontend::SoftwareKeyboardApplet& frontend_) | 47 | Core::Frontend::SoftwareKeyboardApplet& frontend_) |
| 46 | : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} | 48 | : FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {} |
| 47 | 49 | ||
| 48 | SoftwareKeyboard::~SoftwareKeyboard() = default; | 50 | SoftwareKeyboard::~SoftwareKeyboard() = default; |
| 49 | 51 | ||
| 50 | void SoftwareKeyboard::Initialize() { | 52 | void SoftwareKeyboard::Initialize() { |
| 51 | Applet::Initialize(); | 53 | FrontendApplet::Initialize(); |
| 52 | 54 | ||
| 53 | LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}", | 55 | LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}", |
| 54 | applet_mode); | 56 | applet_mode); |
| @@ -76,10 +78,6 @@ void SoftwareKeyboard::Initialize() { | |||
| 76 | } | 78 | } |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | bool SoftwareKeyboard::TransactionComplete() const { | ||
| 80 | return complete; | ||
| 81 | } | ||
| 82 | |||
| 83 | Result SoftwareKeyboard::GetStatus() const { | 81 | Result SoftwareKeyboard::GetStatus() const { |
| 84 | return status; | 82 | return status; |
| 85 | } | 83 | } |
| @@ -184,7 +182,7 @@ void SoftwareKeyboard::InitializeForeground() { | |||
| 184 | 182 | ||
| 185 | is_background = false; | 183 | is_background = false; |
| 186 | 184 | ||
| 187 | const auto swkbd_config_storage = broker.PopNormalDataToApplet(); | 185 | const auto swkbd_config_storage = PopInData(); |
| 188 | ASSERT(swkbd_config_storage != nullptr); | 186 | ASSERT(swkbd_config_storage != nullptr); |
| 189 | 187 | ||
| 190 | const auto& swkbd_config_data = swkbd_config_storage->GetData(); | 188 | const auto& swkbd_config_data = swkbd_config_storage->GetData(); |
| @@ -221,7 +219,7 @@ void SoftwareKeyboard::InitializeForeground() { | |||
| 221 | break; | 219 | break; |
| 222 | } | 220 | } |
| 223 | 221 | ||
| 224 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); | 222 | const auto work_buffer_storage = PopInData(); |
| 225 | ASSERT(work_buffer_storage != nullptr); | 223 | ASSERT(work_buffer_storage != nullptr); |
| 226 | 224 | ||
| 227 | if (swkbd_config_common.initial_string_length == 0) { | 225 | if (swkbd_config_common.initial_string_length == 0) { |
| @@ -250,7 +248,7 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod | |||
| 250 | 248 | ||
| 251 | is_background = true; | 249 | is_background = true; |
| 252 | 250 | ||
| 253 | const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet(); | 251 | const auto swkbd_inline_initialize_arg_storage = PopInData(); |
| 254 | ASSERT(swkbd_inline_initialize_arg_storage != nullptr); | 252 | ASSERT(swkbd_inline_initialize_arg_storage != nullptr); |
| 255 | 253 | ||
| 256 | const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData(); | 254 | const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData(); |
| @@ -267,7 +265,7 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod | |||
| 267 | } | 265 | } |
| 268 | 266 | ||
| 269 | void SoftwareKeyboard::ProcessTextCheck() { | 267 | void SoftwareKeyboard::ProcessTextCheck() { |
| 270 | const auto text_check_storage = broker.PopInteractiveDataToApplet(); | 268 | const auto text_check_storage = PopInteractiveInData(); |
| 271 | ASSERT(text_check_storage != nullptr); | 269 | ASSERT(text_check_storage != nullptr); |
| 272 | 270 | ||
| 273 | const auto& text_check_data = text_check_storage->GetData(); | 271 | const auto& text_check_data = text_check_storage->GetData(); |
| @@ -314,7 +312,7 @@ void SoftwareKeyboard::ProcessTextCheck() { | |||
| 314 | } | 312 | } |
| 315 | 313 | ||
| 316 | void SoftwareKeyboard::ProcessInlineKeyboardRequest() { | 314 | void SoftwareKeyboard::ProcessInlineKeyboardRequest() { |
| 317 | const auto request_data_storage = broker.PopInteractiveDataToApplet(); | 315 | const auto request_data_storage = PopInteractiveInData(); |
| 318 | ASSERT(request_data_storage != nullptr); | 316 | ASSERT(request_data_storage != nullptr); |
| 319 | 317 | ||
| 320 | const auto& request_data = request_data_storage->GetData(); | 318 | const auto& request_data = request_data_storage->GetData(); |
| @@ -377,7 +375,7 @@ void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result, | |||
| 377 | submitted_text.size() * sizeof(char16_t)); | 375 | submitted_text.size() * sizeof(char16_t)); |
| 378 | } | 376 | } |
| 379 | 377 | ||
| 380 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 378 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 381 | 379 | ||
| 382 | ExitKeyboard(); | 380 | ExitKeyboard(); |
| 383 | } | 381 | } |
| @@ -410,7 +408,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) { | |||
| 410 | current_text.size() * sizeof(char16_t)); | 408 | current_text.size() * sizeof(char16_t)); |
| 411 | } | 409 | } |
| 412 | 410 | ||
| 413 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 411 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 414 | } | 412 | } |
| 415 | 413 | ||
| 416 | void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) { | 414 | void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) { |
| @@ -767,7 +765,7 @@ void SoftwareKeyboard::ExitKeyboard() { | |||
| 767 | 765 | ||
| 768 | frontend.ExitKeyboard(); | 766 | frontend.ExitKeyboard(); |
| 769 | 767 | ||
| 770 | broker.SignalStateChanged(); | 768 | Exit(); |
| 771 | } | 769 | } |
| 772 | 770 | ||
| 773 | Result SoftwareKeyboard::RequestExit() { | 771 | Result SoftwareKeyboard::RequestExit() { |
| @@ -967,7 +965,7 @@ void SoftwareKeyboard::ReplyFinishedInitialize() { | |||
| 967 | 965 | ||
| 968 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize); | 966 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize); |
| 969 | 967 | ||
| 970 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 968 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 971 | } | 969 | } |
| 972 | 970 | ||
| 973 | void SoftwareKeyboard::ReplyDefault() { | 971 | void SoftwareKeyboard::ReplyDefault() { |
| @@ -977,7 +975,7 @@ void SoftwareKeyboard::ReplyDefault() { | |||
| 977 | 975 | ||
| 978 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default); | 976 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default); |
| 979 | 977 | ||
| 980 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 978 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 981 | } | 979 | } |
| 982 | 980 | ||
| 983 | void SoftwareKeyboard::ReplyChangedString() { | 981 | void SoftwareKeyboard::ReplyChangedString() { |
| @@ -999,7 +997,7 @@ void SoftwareKeyboard::ReplyChangedString() { | |||
| 999 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, | 997 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, |
| 1000 | sizeof(SwkbdChangedStringArg)); | 998 | sizeof(SwkbdChangedStringArg)); |
| 1001 | 999 | ||
| 1002 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1000 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1003 | } | 1001 | } |
| 1004 | 1002 | ||
| 1005 | void SoftwareKeyboard::ReplyMovedCursor() { | 1003 | void SoftwareKeyboard::ReplyMovedCursor() { |
| @@ -1019,7 +1017,7 @@ void SoftwareKeyboard::ReplyMovedCursor() { | |||
| 1019 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, | 1017 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, |
| 1020 | sizeof(SwkbdMovedCursorArg)); | 1018 | sizeof(SwkbdMovedCursorArg)); |
| 1021 | 1019 | ||
| 1022 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1020 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1023 | } | 1021 | } |
| 1024 | 1022 | ||
| 1025 | void SoftwareKeyboard::ReplyMovedTab() { | 1023 | void SoftwareKeyboard::ReplyMovedTab() { |
| @@ -1039,7 +1037,7 @@ void SoftwareKeyboard::ReplyMovedTab() { | |||
| 1039 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg, | 1037 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg, |
| 1040 | sizeof(SwkbdMovedTabArg)); | 1038 | sizeof(SwkbdMovedTabArg)); |
| 1041 | 1039 | ||
| 1042 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1040 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1043 | } | 1041 | } |
| 1044 | 1042 | ||
| 1045 | void SoftwareKeyboard::ReplyDecidedEnter() { | 1043 | void SoftwareKeyboard::ReplyDecidedEnter() { |
| @@ -1058,7 +1056,7 @@ void SoftwareKeyboard::ReplyDecidedEnter() { | |||
| 1058 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg, | 1056 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg, |
| 1059 | sizeof(SwkbdDecidedEnterArg)); | 1057 | sizeof(SwkbdDecidedEnterArg)); |
| 1060 | 1058 | ||
| 1061 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1059 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1062 | 1060 | ||
| 1063 | HideInlineKeyboard(); | 1061 | HideInlineKeyboard(); |
| 1064 | } | 1062 | } |
| @@ -1070,7 +1068,7 @@ void SoftwareKeyboard::ReplyDecidedCancel() { | |||
| 1070 | 1068 | ||
| 1071 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel); | 1069 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel); |
| 1072 | 1070 | ||
| 1073 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1071 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1074 | 1072 | ||
| 1075 | HideInlineKeyboard(); | 1073 | HideInlineKeyboard(); |
| 1076 | } | 1074 | } |
| @@ -1095,7 +1093,7 @@ void SoftwareKeyboard::ReplyChangedStringUtf8() { | |||
| 1095 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, | 1093 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, |
| 1096 | sizeof(SwkbdChangedStringArg)); | 1094 | sizeof(SwkbdChangedStringArg)); |
| 1097 | 1095 | ||
| 1098 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1096 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1099 | } | 1097 | } |
| 1100 | 1098 | ||
| 1101 | void SoftwareKeyboard::ReplyMovedCursorUtf8() { | 1099 | void SoftwareKeyboard::ReplyMovedCursorUtf8() { |
| @@ -1116,7 +1114,7 @@ void SoftwareKeyboard::ReplyMovedCursorUtf8() { | |||
| 1116 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, | 1114 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, |
| 1117 | sizeof(SwkbdMovedCursorArg)); | 1115 | sizeof(SwkbdMovedCursorArg)); |
| 1118 | 1116 | ||
| 1119 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1117 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1120 | } | 1118 | } |
| 1121 | 1119 | ||
| 1122 | void SoftwareKeyboard::ReplyDecidedEnterUtf8() { | 1120 | void SoftwareKeyboard::ReplyDecidedEnterUtf8() { |
| @@ -1136,7 +1134,7 @@ void SoftwareKeyboard::ReplyDecidedEnterUtf8() { | |||
| 1136 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg, | 1134 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg, |
| 1137 | sizeof(SwkbdDecidedEnterArg)); | 1135 | sizeof(SwkbdDecidedEnterArg)); |
| 1138 | 1136 | ||
| 1139 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1137 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1140 | 1138 | ||
| 1141 | HideInlineKeyboard(); | 1139 | HideInlineKeyboard(); |
| 1142 | } | 1140 | } |
| @@ -1148,7 +1146,7 @@ void SoftwareKeyboard::ReplyUnsetCustomizeDic() { | |||
| 1148 | 1146 | ||
| 1149 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic); | 1147 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic); |
| 1150 | 1148 | ||
| 1151 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1149 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1152 | } | 1150 | } |
| 1153 | 1151 | ||
| 1154 | void SoftwareKeyboard::ReplyReleasedUserWordInfo() { | 1152 | void SoftwareKeyboard::ReplyReleasedUserWordInfo() { |
| @@ -1158,7 +1156,7 @@ void SoftwareKeyboard::ReplyReleasedUserWordInfo() { | |||
| 1158 | 1156 | ||
| 1159 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo); | 1157 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo); |
| 1160 | 1158 | ||
| 1161 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1159 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1162 | } | 1160 | } |
| 1163 | 1161 | ||
| 1164 | void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() { | 1162 | void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() { |
| @@ -1168,7 +1166,7 @@ void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() { | |||
| 1168 | 1166 | ||
| 1169 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries); | 1167 | SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries); |
| 1170 | 1168 | ||
| 1171 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1169 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1172 | } | 1170 | } |
| 1173 | 1171 | ||
| 1174 | void SoftwareKeyboard::ReplyChangedStringV2() { | 1172 | void SoftwareKeyboard::ReplyChangedStringV2() { |
| @@ -1194,7 +1192,7 @@ void SoftwareKeyboard::ReplyChangedStringV2() { | |||
| 1194 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg), | 1192 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg), |
| 1195 | &flag, 1); | 1193 | &flag, 1); |
| 1196 | 1194 | ||
| 1197 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1195 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1198 | } | 1196 | } |
| 1199 | 1197 | ||
| 1200 | void SoftwareKeyboard::ReplyMovedCursorV2() { | 1198 | void SoftwareKeyboard::ReplyMovedCursorV2() { |
| @@ -1218,7 +1216,7 @@ void SoftwareKeyboard::ReplyMovedCursorV2() { | |||
| 1218 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg), | 1216 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg), |
| 1219 | &flag, 1); | 1217 | &flag, 1); |
| 1220 | 1218 | ||
| 1221 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1219 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1222 | } | 1220 | } |
| 1223 | 1221 | ||
| 1224 | void SoftwareKeyboard::ReplyChangedStringUtf8V2() { | 1222 | void SoftwareKeyboard::ReplyChangedStringUtf8V2() { |
| @@ -1245,7 +1243,7 @@ void SoftwareKeyboard::ReplyChangedStringUtf8V2() { | |||
| 1245 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg), | 1243 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg), |
| 1246 | &flag, 1); | 1244 | &flag, 1); |
| 1247 | 1245 | ||
| 1248 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1246 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1249 | } | 1247 | } |
| 1250 | 1248 | ||
| 1251 | void SoftwareKeyboard::ReplyMovedCursorUtf8V2() { | 1249 | void SoftwareKeyboard::ReplyMovedCursorUtf8V2() { |
| @@ -1270,7 +1268,7 @@ void SoftwareKeyboard::ReplyMovedCursorUtf8V2() { | |||
| 1270 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg), | 1268 | std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg), |
| 1271 | &flag, 1); | 1269 | &flag, 1); |
| 1272 | 1270 | ||
| 1273 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply))); | 1271 | PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply))); |
| 1274 | } | 1272 | } |
| 1275 | 1273 | ||
| 1276 | } // namespace Service::AM::Applets | 1274 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/frontend/applet_software_keyboard.h index 2e919811b..f464b7e15 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard.h +++ b/src/core/hle/service/am/frontend/applet_software_keyboard.h | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "core/hle/result.h" | 7 | #include "core/hle/result.h" |
| 8 | #include "core/hle/service/am/applets/applet_software_keyboard_types.h" | 8 | #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" |
| 9 | #include "core/hle/service/am/applets/applets.h" | 9 | #include "core/hle/service/am/frontend/applets.h" |
| 10 | 10 | ||
| 11 | namespace Core { | 11 | namespace Core { |
| 12 | class System; | 12 | class System; |
| @@ -17,17 +17,17 @@ struct KeyboardInitializeParameters; | |||
| 17 | struct InlineAppearParameters; | 17 | struct InlineAppearParameters; |
| 18 | } // namespace Core::Frontend | 18 | } // namespace Core::Frontend |
| 19 | 19 | ||
| 20 | namespace Service::AM::Applets { | 20 | namespace Service::AM::Frontend { |
| 21 | 21 | ||
| 22 | class SoftwareKeyboard final : public Applet { | 22 | class SoftwareKeyboard final : public FrontendApplet { |
| 23 | public: | 23 | public: |
| 24 | explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, | 24 | explicit SoftwareKeyboard(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 25 | LibraryAppletMode applet_mode_, | ||
| 25 | Core::Frontend::SoftwareKeyboardApplet& frontend_); | 26 | Core::Frontend::SoftwareKeyboardApplet& frontend_); |
| 26 | ~SoftwareKeyboard() override; | 27 | ~SoftwareKeyboard() override; |
| 27 | 28 | ||
| 28 | void Initialize() override; | 29 | void Initialize() override; |
| 29 | 30 | ||
| 30 | bool TransactionComplete() const override; | ||
| 31 | Result GetStatus() const override; | 31 | Result GetStatus() const override; |
| 32 | void ExecuteInteractive() override; | 32 | void ExecuteInteractive() override; |
| 33 | void Execute() override; | 33 | void Execute() override; |
| @@ -156,7 +156,6 @@ private: | |||
| 156 | void ReplyMovedCursorUtf8V2(); | 156 | void ReplyMovedCursorUtf8V2(); |
| 157 | 157 | ||
| 158 | Core::Frontend::SoftwareKeyboardApplet& frontend; | 158 | Core::Frontend::SoftwareKeyboardApplet& frontend; |
| 159 | Core::System& system; | ||
| 160 | 159 | ||
| 161 | SwkbdAppletVersion swkbd_applet_version; | 160 | SwkbdAppletVersion swkbd_applet_version; |
| 162 | 161 | ||
| @@ -184,4 +183,4 @@ private: | |||
| 184 | Result status{ResultSuccess}; | 183 | Result status{ResultSuccess}; |
| 185 | }; | 184 | }; |
| 186 | 185 | ||
| 187 | } // namespace Service::AM::Applets | 186 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard_types.h b/src/core/hle/service/am/frontend/applet_software_keyboard_types.h index 1f696900e..a25ff2a6d 100644 --- a/src/core/hle/service/am/applets/applet_software_keyboard_types.h +++ b/src/core/hle/service/am/frontend/applet_software_keyboard_types.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 12 | #include "common/uuid.h" | 12 | #include "common/uuid.h" |
| 13 | 13 | ||
| 14 | namespace Service::AM::Applets { | 14 | namespace Service::AM::Frontend { |
| 15 | 15 | ||
| 16 | constexpr std::size_t MAX_OK_TEXT_LENGTH = 8; | 16 | constexpr std::size_t MAX_OK_TEXT_LENGTH = 8; |
| 17 | constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64; | 17 | constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64; |
| @@ -351,4 +351,4 @@ struct SwkbdDecidedEnterArg { | |||
| 351 | }; | 351 | }; |
| 352 | static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size."); | 352 | static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size."); |
| 353 | 353 | ||
| 354 | } // namespace Service::AM::Applets | 354 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp index 19057ad7b..6ee4caf34 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp | |||
| @@ -19,12 +19,13 @@ | |||
| 19 | #include "core/frontend/applets/web_browser.h" | 19 | #include "core/frontend/applets/web_browser.h" |
| 20 | #include "core/hle/result.h" | 20 | #include "core/hle/result.h" |
| 21 | #include "core/hle/service/am/am.h" | 21 | #include "core/hle/service/am/am.h" |
| 22 | #include "core/hle/service/am/applets/applet_web_browser.h" | 22 | #include "core/hle/service/am/frontend/applet_web_browser.h" |
| 23 | #include "core/hle/service/am/storage.h" | ||
| 23 | #include "core/hle/service/filesystem/filesystem.h" | 24 | #include "core/hle/service/filesystem/filesystem.h" |
| 24 | #include "core/hle/service/ns/iplatform_service_manager.h" | 25 | #include "core/hle/service/ns/iplatform_service_manager.h" |
| 25 | #include "core/loader/loader.h" | 26 | #include "core/loader/loader.h" |
| 26 | 27 | ||
| 27 | namespace Service::AM::Applets { | 28 | namespace Service::AM::Frontend { |
| 28 | 29 | ||
| 29 | namespace { | 30 | namespace { |
| 30 | 31 | ||
| @@ -223,14 +224,15 @@ void ExtractSharedFonts(Core::System& system) { | |||
| 223 | 224 | ||
| 224 | } // namespace | 225 | } // namespace |
| 225 | 226 | ||
| 226 | WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, | 227 | WebBrowser::WebBrowser(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 228 | LibraryAppletMode applet_mode_, | ||
| 227 | const Core::Frontend::WebBrowserApplet& frontend_) | 229 | const Core::Frontend::WebBrowserApplet& frontend_) |
| 228 | : Applet{system_, applet_mode_}, frontend(frontend_), system{system_} {} | 230 | : FrontendApplet{system_, applet_, applet_mode_}, frontend(frontend_) {} |
| 229 | 231 | ||
| 230 | WebBrowser::~WebBrowser() = default; | 232 | WebBrowser::~WebBrowser() = default; |
| 231 | 233 | ||
| 232 | void WebBrowser::Initialize() { | 234 | void WebBrowser::Initialize() { |
| 233 | Applet::Initialize(); | 235 | FrontendApplet::Initialize(); |
| 234 | 236 | ||
| 235 | LOG_INFO(Service_AM, "Initializing Web Browser Applet."); | 237 | LOG_INFO(Service_AM, "Initializing Web Browser Applet."); |
| 236 | 238 | ||
| @@ -243,7 +245,7 @@ void WebBrowser::Initialize() { | |||
| 243 | 245 | ||
| 244 | web_applet_version = WebAppletVersion{common_args.library_version}; | 246 | web_applet_version = WebAppletVersion{common_args.library_version}; |
| 245 | 247 | ||
| 246 | const auto web_arg_storage = broker.PopNormalDataToApplet(); | 248 | const auto web_arg_storage = PopInData(); |
| 247 | ASSERT(web_arg_storage != nullptr); | 249 | ASSERT(web_arg_storage != nullptr); |
| 248 | 250 | ||
| 249 | const auto& web_arg = web_arg_storage->GetData(); | 251 | const auto& web_arg = web_arg_storage->GetData(); |
| @@ -284,10 +286,6 @@ void WebBrowser::Initialize() { | |||
| 284 | } | 286 | } |
| 285 | } | 287 | } |
| 286 | 288 | ||
| 287 | bool WebBrowser::TransactionComplete() const { | ||
| 288 | return complete; | ||
| 289 | } | ||
| 290 | |||
| 291 | Result WebBrowser::GetStatus() const { | 289 | Result WebBrowser::GetStatus() const { |
| 292 | return status; | 290 | return status; |
| 293 | } | 291 | } |
| @@ -358,8 +356,8 @@ void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url) | |||
| 358 | complete = true; | 356 | complete = true; |
| 359 | std::vector<u8> out_data(sizeof(WebCommonReturnValue)); | 357 | std::vector<u8> out_data(sizeof(WebCommonReturnValue)); |
| 360 | std::memcpy(out_data.data(), &web_common_return_value, out_data.size()); | 358 | std::memcpy(out_data.data(), &web_common_return_value, out_data.size()); |
| 361 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); | 359 | PushOutData(std::make_shared<IStorage>(system, std::move(out_data))); |
| 362 | broker.SignalStateChanged(); | 360 | Exit(); |
| 363 | } | 361 | } |
| 364 | 362 | ||
| 365 | Result WebBrowser::RequestExit() { | 363 | Result WebBrowser::RequestExit() { |
| @@ -504,4 +502,4 @@ void WebBrowser::ExecuteLobby() { | |||
| 504 | LOG_WARNING(Service_AM, "(STUBBED) called, Lobby Applet is not implemented"); | 502 | LOG_WARNING(Service_AM, "(STUBBED) called, Lobby Applet is not implemented"); |
| 505 | WebBrowserExit(WebExitReason::EndButtonPressed); | 503 | WebBrowserExit(WebExitReason::EndButtonPressed); |
| 506 | } | 504 | } |
| 507 | } // namespace Service::AM::Applets | 505 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/frontend/applet_web_browser.h index 36adb2510..ba20b7a4c 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.h +++ b/src/core/hle/service/am/frontend/applet_web_browser.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/file_sys/vfs/vfs_types.h" | 10 | #include "core/file_sys/vfs/vfs_types.h" |
| 11 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 12 | #include "core/hle/service/am/applets/applet_web_browser_types.h" | 12 | #include "core/hle/service/am/frontend/applet_web_browser_types.h" |
| 13 | #include "core/hle/service/am/applets/applets.h" | 13 | #include "core/hle/service/am/frontend/applets.h" |
| 14 | 14 | ||
| 15 | namespace Core { | 15 | namespace Core { |
| 16 | class System; | 16 | class System; |
| @@ -20,18 +20,17 @@ namespace FileSys { | |||
| 20 | enum class ContentRecordType : u8; | 20 | enum class ContentRecordType : u8; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | namespace Service::AM::Applets { | 23 | namespace Service::AM::Frontend { |
| 24 | 24 | ||
| 25 | class WebBrowser final : public Applet { | 25 | class WebBrowser final : public FrontendApplet { |
| 26 | public: | 26 | public: |
| 27 | WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, | 27 | WebBrowser(Core::System& system_, std::shared_ptr<Applet> applet_, |
| 28 | const Core::Frontend::WebBrowserApplet& frontend_); | 28 | LibraryAppletMode applet_mode_, const Core::Frontend::WebBrowserApplet& frontend_); |
| 29 | 29 | ||
| 30 | ~WebBrowser() override; | 30 | ~WebBrowser() override; |
| 31 | 31 | ||
| 32 | void Initialize() override; | 32 | void Initialize() override; |
| 33 | 33 | ||
| 34 | bool TransactionComplete() const override; | ||
| 35 | Result GetStatus() const override; | 34 | Result GetStatus() const override; |
| 36 | void ExecuteInteractive() override; | 35 | void ExecuteInteractive() override; |
| 37 | void Execute() override; | 36 | void Execute() override; |
| @@ -80,8 +79,6 @@ private: | |||
| 80 | FileSys::VirtualFile offline_romfs; | 79 | FileSys::VirtualFile offline_romfs; |
| 81 | 80 | ||
| 82 | std::string external_url; | 81 | std::string external_url; |
| 83 | |||
| 84 | Core::System& system; | ||
| 85 | }; | 82 | }; |
| 86 | 83 | ||
| 87 | } // namespace Service::AM::Applets | 84 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/applets/applet_web_browser_types.h b/src/core/hle/service/am/frontend/applet_web_browser_types.h index c522c5c1a..2f7c05c24 100644 --- a/src/core/hle/service/am/applets/applet_web_browser_types.h +++ b/src/core/hle/service/am/frontend/applet_web_browser_types.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 13 | 13 | ||
| 14 | namespace Service::AM::Applets { | 14 | namespace Service::AM::Frontend { |
| 15 | 15 | ||
| 16 | enum class WebAppletVersion : u32_le { | 16 | enum class WebAppletVersion : u32_le { |
| 17 | Version0 = 0x0, // Only used by WifiWebAuthApplet | 17 | Version0 = 0x0, // Only used by WifiWebAuthApplet |
| @@ -174,4 +174,4 @@ static_assert(sizeof(WebCommonReturnValue) == 0x1010, "WebCommonReturnValue has | |||
| 174 | 174 | ||
| 175 | using WebArgInputTLVMap = std::unordered_map<WebArgInputTLVType, std::vector<u8>>; | 175 | using WebArgInputTLVMap = std::unordered_map<WebArgInputTLVType, std::vector<u8>>; |
| 176 | 176 | ||
| 177 | } // namespace Service::AM::Applets | 177 | } // namespace Service::AM::Frontend |
diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp new file mode 100644 index 000000000..db2b04575 --- /dev/null +++ b/src/core/hle/service/am/frontend/applets.cpp | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | |||
| 6 | #include "common/assert.h" | ||
| 7 | #include "core/core.h" | ||
| 8 | #include "core/frontend/applets/cabinet.h" | ||
| 9 | #include "core/frontend/applets/controller.h" | ||
| 10 | #include "core/frontend/applets/error.h" | ||
| 11 | #include "core/frontend/applets/general.h" | ||
| 12 | #include "core/frontend/applets/mii_edit.h" | ||
| 13 | #include "core/frontend/applets/profile_select.h" | ||
| 14 | #include "core/frontend/applets/software_keyboard.h" | ||
| 15 | #include "core/frontend/applets/web_browser.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | ||
| 17 | #include "core/hle/service/am/am.h" | ||
| 18 | #include "core/hle/service/am/applet_ae.h" | ||
| 19 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 20 | #include "core/hle/service/am/applet_manager.h" | ||
| 21 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 22 | #include "core/hle/service/am/applet_oe.h" | ||
| 23 | #include "core/hle/service/am/frontend/applet_cabinet.h" | ||
| 24 | #include "core/hle/service/am/frontend/applet_controller.h" | ||
| 25 | #include "core/hle/service/am/frontend/applet_error.h" | ||
| 26 | #include "core/hle/service/am/frontend/applet_general.h" | ||
| 27 | #include "core/hle/service/am/frontend/applet_mii_edit.h" | ||
| 28 | #include "core/hle/service/am/frontend/applet_profile_select.h" | ||
| 29 | #include "core/hle/service/am/frontend/applet_software_keyboard.h" | ||
| 30 | #include "core/hle/service/am/frontend/applet_web_browser.h" | ||
| 31 | #include "core/hle/service/am/frontend/applets.h" | ||
| 32 | #include "core/hle/service/am/storage.h" | ||
| 33 | #include "core/hle/service/sm/sm.h" | ||
| 34 | |||
| 35 | namespace Service::AM::Frontend { | ||
| 36 | |||
| 37 | FrontendApplet::FrontendApplet(Core::System& system_, std::shared_ptr<Applet> applet_, | ||
| 38 | LibraryAppletMode applet_mode_) | ||
| 39 | : system{system_}, applet{std::move(applet_)}, applet_mode{applet_mode_} {} | ||
| 40 | |||
| 41 | FrontendApplet::~FrontendApplet() = default; | ||
| 42 | |||
| 43 | void FrontendApplet::Initialize() { | ||
| 44 | std::shared_ptr<IStorage> common = PopInData(); | ||
| 45 | ASSERT(common != nullptr); | ||
| 46 | const auto common_data = common->GetData(); | ||
| 47 | |||
| 48 | ASSERT(common_data.size() >= sizeof(CommonArguments)); | ||
| 49 | std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments)); | ||
| 50 | |||
| 51 | initialized = true; | ||
| 52 | } | ||
| 53 | |||
| 54 | std::shared_ptr<IStorage> FrontendApplet::PopInData() { | ||
| 55 | std::shared_ptr<IStorage> ret; | ||
| 56 | applet.lock()->caller_applet_broker->GetInData().Pop(&ret); | ||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | |||
| 60 | std::shared_ptr<IStorage> FrontendApplet::PopInteractiveInData() { | ||
| 61 | std::shared_ptr<IStorage> ret; | ||
| 62 | applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(&ret); | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | void FrontendApplet::PushOutData(std::shared_ptr<IStorage> storage) { | ||
| 67 | applet.lock()->caller_applet_broker->GetOutData().Push(storage); | ||
| 68 | } | ||
| 69 | |||
| 70 | void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) { | ||
| 71 | applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(storage); | ||
| 72 | } | ||
| 73 | |||
| 74 | void FrontendApplet::Exit() { | ||
| 75 | applet.lock()->caller_applet_broker->SignalCompletion(); | ||
| 76 | } | ||
| 77 | |||
| 78 | FrontendAppletSet::FrontendAppletSet() = default; | ||
| 79 | |||
| 80 | FrontendAppletSet::FrontendAppletSet(CabinetApplet cabinet_applet, | ||
| 81 | ControllerApplet controller_applet, ErrorApplet error_applet, | ||
| 82 | MiiEdit mii_edit_, | ||
| 83 | ParentalControlsApplet parental_controls_applet, | ||
| 84 | PhotoViewer photo_viewer_, ProfileSelect profile_select_, | ||
| 85 | SoftwareKeyboard software_keyboard_, WebBrowser web_browser_) | ||
| 86 | : cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)}, | ||
| 87 | error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)}, | ||
| 88 | parental_controls{std::move(parental_controls_applet)}, | ||
| 89 | photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)}, | ||
| 90 | software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {} | ||
| 91 | |||
| 92 | FrontendAppletSet::~FrontendAppletSet() = default; | ||
| 93 | |||
| 94 | FrontendAppletSet::FrontendAppletSet(FrontendAppletSet&&) noexcept = default; | ||
| 95 | |||
| 96 | FrontendAppletSet& FrontendAppletSet::operator=(FrontendAppletSet&&) noexcept = default; | ||
| 97 | |||
| 98 | FrontendAppletHolder::FrontendAppletHolder(Core::System& system_) : system{system_} {} | ||
| 99 | |||
| 100 | FrontendAppletHolder::~FrontendAppletHolder() = default; | ||
| 101 | |||
| 102 | const FrontendAppletSet& FrontendAppletHolder::GetFrontendAppletSet() const { | ||
| 103 | return frontend; | ||
| 104 | } | ||
| 105 | |||
| 106 | NFP::CabinetMode FrontendAppletHolder::GetCabinetMode() const { | ||
| 107 | return cabinet_mode; | ||
| 108 | } | ||
| 109 | |||
| 110 | AppletId FrontendAppletHolder::GetCurrentAppletId() const { | ||
| 111 | return current_applet_id; | ||
| 112 | } | ||
| 113 | |||
| 114 | void FrontendAppletHolder::SetFrontendAppletSet(FrontendAppletSet set) { | ||
| 115 | if (set.cabinet != nullptr) { | ||
| 116 | frontend.cabinet = std::move(set.cabinet); | ||
| 117 | } | ||
| 118 | |||
| 119 | if (set.controller != nullptr) { | ||
| 120 | frontend.controller = std::move(set.controller); | ||
| 121 | } | ||
| 122 | |||
| 123 | if (set.error != nullptr) { | ||
| 124 | frontend.error = std::move(set.error); | ||
| 125 | } | ||
| 126 | |||
| 127 | if (set.mii_edit != nullptr) { | ||
| 128 | frontend.mii_edit = std::move(set.mii_edit); | ||
| 129 | } | ||
| 130 | |||
| 131 | if (set.parental_controls != nullptr) { | ||
| 132 | frontend.parental_controls = std::move(set.parental_controls); | ||
| 133 | } | ||
| 134 | |||
| 135 | if (set.photo_viewer != nullptr) { | ||
| 136 | frontend.photo_viewer = std::move(set.photo_viewer); | ||
| 137 | } | ||
| 138 | |||
| 139 | if (set.profile_select != nullptr) { | ||
| 140 | frontend.profile_select = std::move(set.profile_select); | ||
| 141 | } | ||
| 142 | |||
| 143 | if (set.software_keyboard != nullptr) { | ||
| 144 | frontend.software_keyboard = std::move(set.software_keyboard); | ||
| 145 | } | ||
| 146 | |||
| 147 | if (set.web_browser != nullptr) { | ||
| 148 | frontend.web_browser = std::move(set.web_browser); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | void FrontendAppletHolder::SetCabinetMode(NFP::CabinetMode mode) { | ||
| 153 | cabinet_mode = mode; | ||
| 154 | } | ||
| 155 | |||
| 156 | void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) { | ||
| 157 | current_applet_id = applet_id; | ||
| 158 | } | ||
| 159 | |||
| 160 | void FrontendAppletHolder::SetDefaultAppletsIfMissing() { | ||
| 161 | if (frontend.cabinet == nullptr) { | ||
| 162 | frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>(); | ||
| 163 | } | ||
| 164 | |||
| 165 | if (frontend.controller == nullptr) { | ||
| 166 | frontend.controller = | ||
| 167 | std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore()); | ||
| 168 | } | ||
| 169 | |||
| 170 | if (frontend.error == nullptr) { | ||
| 171 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); | ||
| 172 | } | ||
| 173 | |||
| 174 | if (frontend.mii_edit == nullptr) { | ||
| 175 | frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>(); | ||
| 176 | } | ||
| 177 | |||
| 178 | if (frontend.parental_controls == nullptr) { | ||
| 179 | frontend.parental_controls = | ||
| 180 | std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); | ||
| 181 | } | ||
| 182 | |||
| 183 | if (frontend.photo_viewer == nullptr) { | ||
| 184 | frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); | ||
| 185 | } | ||
| 186 | |||
| 187 | if (frontend.profile_select == nullptr) { | ||
| 188 | frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>(); | ||
| 189 | } | ||
| 190 | |||
| 191 | if (frontend.software_keyboard == nullptr) { | ||
| 192 | frontend.software_keyboard = | ||
| 193 | std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>(); | ||
| 194 | } | ||
| 195 | |||
| 196 | if (frontend.web_browser == nullptr) { | ||
| 197 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | void FrontendAppletHolder::ClearAll() { | ||
| 202 | frontend = {}; | ||
| 203 | } | ||
| 204 | |||
| 205 | std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(std::shared_ptr<Applet> applet, | ||
| 206 | AppletId id, | ||
| 207 | LibraryAppletMode mode) const { | ||
| 208 | switch (id) { | ||
| 209 | case AppletId::Auth: | ||
| 210 | return std::make_shared<Auth>(system, applet, mode, *frontend.parental_controls); | ||
| 211 | case AppletId::Cabinet: | ||
| 212 | return std::make_shared<Cabinet>(system, applet, mode, *frontend.cabinet); | ||
| 213 | case AppletId::Controller: | ||
| 214 | return std::make_shared<Controller>(system, applet, mode, *frontend.controller); | ||
| 215 | case AppletId::Error: | ||
| 216 | return std::make_shared<Error>(system, applet, mode, *frontend.error); | ||
| 217 | case AppletId::ProfileSelect: | ||
| 218 | return std::make_shared<ProfileSelect>(system, applet, mode, *frontend.profile_select); | ||
| 219 | case AppletId::SoftwareKeyboard: | ||
| 220 | return std::make_shared<SoftwareKeyboard>(system, applet, mode, | ||
| 221 | *frontend.software_keyboard); | ||
| 222 | case AppletId::MiiEdit: | ||
| 223 | return std::make_shared<MiiEdit>(system, applet, mode, *frontend.mii_edit); | ||
| 224 | case AppletId::Web: | ||
| 225 | case AppletId::Shop: | ||
| 226 | case AppletId::OfflineWeb: | ||
| 227 | case AppletId::LoginShare: | ||
| 228 | case AppletId::WebAuth: | ||
| 229 | return std::make_shared<WebBrowser>(system, applet, mode, *frontend.web_browser); | ||
| 230 | case AppletId::PhotoViewer: | ||
| 231 | return std::make_shared<PhotoViewer>(system, applet, mode, *frontend.photo_viewer); | ||
| 232 | default: | ||
| 233 | UNIMPLEMENTED_MSG( | ||
| 234 | "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", | ||
| 235 | static_cast<u8>(id)); | ||
| 236 | return std::make_shared<StubApplet>(system, applet, id, mode); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | } // namespace Service::AM::Frontend | ||
diff --git a/src/core/hle/service/am/frontend/applets.h b/src/core/hle/service/am/frontend/applets.h new file mode 100644 index 000000000..1e1fd28b8 --- /dev/null +++ b/src/core/hle/service/am/frontend/applets.h | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <queue> | ||
| 8 | |||
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/hle/service/am/applet.h" | ||
| 11 | |||
| 12 | union Result; | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Core::Frontend { | ||
| 19 | class CabinetApplet; | ||
| 20 | class ControllerApplet; | ||
| 21 | class ECommerceApplet; | ||
| 22 | class ErrorApplet; | ||
| 23 | class MiiEditApplet; | ||
| 24 | class ParentalControlsApplet; | ||
| 25 | class PhotoViewerApplet; | ||
| 26 | class ProfileSelectApplet; | ||
| 27 | class SoftwareKeyboardApplet; | ||
| 28 | class WebBrowserApplet; | ||
| 29 | } // namespace Core::Frontend | ||
| 30 | |||
| 31 | namespace Kernel { | ||
| 32 | class KernelCore; | ||
| 33 | class KEvent; | ||
| 34 | class KReadableEvent; | ||
| 35 | } // namespace Kernel | ||
| 36 | |||
| 37 | namespace Service::NFP { | ||
| 38 | enum class CabinetMode : u8; | ||
| 39 | } // namespace Service::NFP | ||
| 40 | |||
| 41 | namespace Service::AM { | ||
| 42 | |||
| 43 | class IStorage; | ||
| 44 | |||
| 45 | namespace Frontend { | ||
| 46 | |||
| 47 | class FrontendApplet { | ||
| 48 | public: | ||
| 49 | explicit FrontendApplet(Core::System& system_, std::shared_ptr<Applet> applet_, | ||
| 50 | LibraryAppletMode applet_mode_); | ||
| 51 | virtual ~FrontendApplet(); | ||
| 52 | |||
| 53 | virtual void Initialize(); | ||
| 54 | |||
| 55 | virtual Result GetStatus() const = 0; | ||
| 56 | virtual void ExecuteInteractive() = 0; | ||
| 57 | virtual void Execute() = 0; | ||
| 58 | virtual Result RequestExit() = 0; | ||
| 59 | |||
| 60 | LibraryAppletMode GetLibraryAppletMode() const { | ||
| 61 | return applet_mode; | ||
| 62 | } | ||
| 63 | |||
| 64 | bool IsInitialized() const { | ||
| 65 | return initialized; | ||
| 66 | } | ||
| 67 | |||
| 68 | protected: | ||
| 69 | std::shared_ptr<IStorage> PopInData(); | ||
| 70 | std::shared_ptr<IStorage> PopInteractiveInData(); | ||
| 71 | void PushOutData(std::shared_ptr<IStorage> storage); | ||
| 72 | void PushInteractiveOutData(std::shared_ptr<IStorage> storage); | ||
| 73 | void Exit(); | ||
| 74 | |||
| 75 | protected: | ||
| 76 | Core::System& system; | ||
| 77 | CommonArguments common_args{}; | ||
| 78 | std::weak_ptr<Applet> applet{}; | ||
| 79 | LibraryAppletMode applet_mode{}; | ||
| 80 | bool initialized{false}; | ||
| 81 | }; | ||
| 82 | |||
| 83 | struct FrontendAppletSet { | ||
| 84 | using CabinetApplet = std::unique_ptr<Core::Frontend::CabinetApplet>; | ||
| 85 | using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>; | ||
| 86 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; | ||
| 87 | using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>; | ||
| 88 | using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; | ||
| 89 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; | ||
| 90 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; | ||
| 91 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; | ||
| 92 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; | ||
| 93 | |||
| 94 | FrontendAppletSet(); | ||
| 95 | FrontendAppletSet(CabinetApplet cabinet_applet, ControllerApplet controller_applet, | ||
| 96 | ErrorApplet error_applet, MiiEdit mii_edit_, | ||
| 97 | ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_, | ||
| 98 | ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_, | ||
| 99 | WebBrowser web_browser_); | ||
| 100 | ~FrontendAppletSet(); | ||
| 101 | |||
| 102 | FrontendAppletSet(const FrontendAppletSet&) = delete; | ||
| 103 | FrontendAppletSet& operator=(const FrontendAppletSet&) = delete; | ||
| 104 | |||
| 105 | FrontendAppletSet(FrontendAppletSet&&) noexcept; | ||
| 106 | FrontendAppletSet& operator=(FrontendAppletSet&&) noexcept; | ||
| 107 | |||
| 108 | CabinetApplet cabinet; | ||
| 109 | ControllerApplet controller; | ||
| 110 | ErrorApplet error; | ||
| 111 | MiiEdit mii_edit; | ||
| 112 | ParentalControlsApplet parental_controls; | ||
| 113 | PhotoViewer photo_viewer; | ||
| 114 | ProfileSelect profile_select; | ||
| 115 | SoftwareKeyboard software_keyboard; | ||
| 116 | WebBrowser web_browser; | ||
| 117 | }; | ||
| 118 | |||
| 119 | class FrontendAppletHolder { | ||
| 120 | public: | ||
| 121 | explicit FrontendAppletHolder(Core::System& system_); | ||
| 122 | ~FrontendAppletHolder(); | ||
| 123 | |||
| 124 | const FrontendAppletSet& GetFrontendAppletSet() const; | ||
| 125 | NFP::CabinetMode GetCabinetMode() const; | ||
| 126 | AppletId GetCurrentAppletId() const; | ||
| 127 | |||
| 128 | void SetFrontendAppletSet(FrontendAppletSet set); | ||
| 129 | void SetCabinetMode(NFP::CabinetMode mode); | ||
| 130 | void SetCurrentAppletId(AppletId applet_id); | ||
| 131 | void SetDefaultAppletsIfMissing(); | ||
| 132 | void ClearAll(); | ||
| 133 | |||
| 134 | std::shared_ptr<FrontendApplet> GetApplet(std::shared_ptr<Applet> applet, AppletId id, | ||
| 135 | LibraryAppletMode mode) const; | ||
| 136 | |||
| 137 | private: | ||
| 138 | AppletId current_applet_id{}; | ||
| 139 | NFP::CabinetMode cabinet_mode{}; | ||
| 140 | |||
| 141 | FrontendAppletSet frontend; | ||
| 142 | Core::System& system; | ||
| 143 | }; | ||
| 144 | |||
| 145 | } // namespace Frontend | ||
| 146 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp new file mode 100644 index 000000000..ed0eb7108 --- /dev/null +++ b/src/core/hle/service/am/global_state_controller.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/global_state_controller.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IGlobalStateController::IGlobalStateController(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IGlobalStateController"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, nullptr, "RequestToEnterSleep"}, | ||
| 14 | {1, nullptr, "EnterSleep"}, | ||
| 15 | {2, nullptr, "StartSleepSequence"}, | ||
| 16 | {3, nullptr, "StartShutdownSequence"}, | ||
| 17 | {4, nullptr, "StartRebootSequence"}, | ||
| 18 | {9, nullptr, "IsAutoPowerDownRequested"}, | ||
| 19 | {10, nullptr, "LoadAndApplyIdlePolicySettings"}, | ||
| 20 | {11, nullptr, "NotifyCecSettingsChanged"}, | ||
| 21 | {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, | ||
| 22 | {13, nullptr, "UpdateDefaultDisplayResolution"}, | ||
| 23 | {14, nullptr, "ShouldSleepOnBoot"}, | ||
| 24 | {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, | ||
| 25 | {30, nullptr, "OpenCradleFirmwareUpdater"}, | ||
| 26 | }; | ||
| 27 | // clang-format on | ||
| 28 | |||
| 29 | RegisterHandlers(functions); | ||
| 30 | } | ||
| 31 | |||
| 32 | IGlobalStateController::~IGlobalStateController() = default; | ||
| 33 | |||
| 34 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h new file mode 100644 index 000000000..7125464a1 --- /dev/null +++ b/src/core/hle/service/am/global_state_controller.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { | ||
| 11 | public: | ||
| 12 | explicit IGlobalStateController(Core::System& system_); | ||
| 13 | ~IGlobalStateController() override; | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/hid_registration.cpp b/src/core/hle/service/am/hid_registration.cpp new file mode 100644 index 000000000..8ed49bac1 --- /dev/null +++ b/src/core/hle/service/am/hid_registration.cpp | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/service/am/hid_registration.h" | ||
| 6 | #include "core/hle/service/am/process.h" | ||
| 7 | #include "core/hle/service/hid/hid_server.h" | ||
| 8 | #include "core/hle/service/sm/sm.h" | ||
| 9 | #include "hid_core/resource_manager.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) { | ||
| 14 | m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid"); | ||
| 15 | |||
| 16 | if (m_process.IsInitialized()) { | ||
| 17 | m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(), | ||
| 18 | true); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | HidRegistration::~HidRegistration() { | ||
| 23 | if (m_process.IsInitialized()) { | ||
| 24 | m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId( | ||
| 25 | m_process.GetProcessId()); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | void HidRegistration::EnableAppletToGetInput(bool enable) { | ||
| 30 | if (m_process.IsInitialized()) { | ||
| 31 | m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/hid_registration.h b/src/core/hle/service/am/hid_registration.h new file mode 100644 index 000000000..67cd84961 --- /dev/null +++ b/src/core/hle/service/am/hid_registration.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | namespace Core { | ||
| 9 | class System; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | class IHidServer; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::AM { | ||
| 17 | |||
| 18 | class Process; | ||
| 19 | |||
| 20 | class HidRegistration { | ||
| 21 | public: | ||
| 22 | explicit HidRegistration(Core::System& system, Process& process); | ||
| 23 | ~HidRegistration(); | ||
| 24 | |||
| 25 | void EnableAppletToGetInput(bool enable); | ||
| 26 | |||
| 27 | private: | ||
| 28 | Process& m_process; | ||
| 29 | std::shared_ptr<Service::HID::IHidServer> m_hid_server; | ||
| 30 | }; | ||
| 31 | |||
| 32 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp new file mode 100644 index 000000000..640e9fbb7 --- /dev/null +++ b/src/core/hle/service/am/home_menu_functions.cpp | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system, | ||
| 11 | "IHomeMenuFunctions"} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, | ||
| 15 | {11, nullptr, "LockForeground"}, | ||
| 16 | {12, nullptr, "UnlockForeground"}, | ||
| 17 | {20, nullptr, "PopFromGeneralChannel"}, | ||
| 18 | {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, | ||
| 19 | {30, nullptr, "GetHomeButtonWriterLockAccessor"}, | ||
| 20 | {31, nullptr, "GetWriterLockAccessorEx"}, | ||
| 21 | {40, nullptr, "IsSleepEnabled"}, | ||
| 22 | {41, nullptr, "IsRebootEnabled"}, | ||
| 23 | {50, nullptr, "LaunchSystemApplet"}, | ||
| 24 | {51, nullptr, "LaunchStarter"}, | ||
| 25 | {100, nullptr, "PopRequestLaunchApplicationForDebug"}, | ||
| 26 | {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, | ||
| 27 | {200, nullptr, "LaunchDevMenu"}, | ||
| 28 | {1000, nullptr, "SetLastApplicationExitReason"}, | ||
| 29 | }; | ||
| 30 | // clang-format on | ||
| 31 | |||
| 32 | RegisterHandlers(functions); | ||
| 33 | |||
| 34 | pop_from_general_channel_event = | ||
| 35 | service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent"); | ||
| 36 | } | ||
| 37 | |||
| 38 | IHomeMenuFunctions::~IHomeMenuFunctions() { | ||
| 39 | service_context.CloseEvent(pop_from_general_channel_event); | ||
| 40 | } | ||
| 41 | |||
| 42 | void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { | ||
| 43 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(ResultSuccess); | ||
| 47 | } | ||
| 48 | |||
| 49 | void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { | ||
| 50 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); | ||
| 55 | } | ||
| 56 | |||
| 57 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h new file mode 100644 index 000000000..e082d5d73 --- /dev/null +++ b/src/core/hle/service/am/home_menu_functions.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | ||
| 12 | public: | ||
| 13 | explicit IHomeMenuFunctions(Core::System& system_); | ||
| 14 | ~IHomeMenuFunctions() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void RequestToGetForeground(HLERequestContext& ctx); | ||
| 18 | void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); | ||
| 19 | |||
| 20 | KernelHelpers::ServiceContext service_context; | ||
| 21 | |||
| 22 | Kernel::KEvent* pop_from_general_channel_event; | ||
| 23 | }; | ||
| 24 | |||
| 25 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp new file mode 100644 index 000000000..6b20814f8 --- /dev/null +++ b/src/core/hle/service/am/library_applet_accessor.cpp | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/scope_exit.h" | ||
| 5 | #include "core/hle/service/am/am_results.h" | ||
| 6 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 7 | #include "core/hle/service/am/frontend/applets.h" | ||
| 8 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 9 | #include "core/hle/service/am/storage.h" | ||
| 10 | #include "core/hle/service/ipc_helpers.h" | ||
| 11 | |||
| 12 | namespace Service::AM { | ||
| 13 | |||
| 14 | ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, | ||
| 15 | std::shared_ptr<AppletDataBroker> broker_, | ||
| 16 | std::shared_ptr<Applet> applet_) | ||
| 17 | : ServiceFramework{system_, "ILibraryAppletAccessor"}, broker{std::move(broker_)}, | ||
| 18 | applet{std::move(applet_)} { | ||
| 19 | // clang-format off | ||
| 20 | static const FunctionInfo functions[] = { | ||
| 21 | {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, | ||
| 22 | {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, | ||
| 23 | {10, &ILibraryAppletAccessor::Start, "Start"}, | ||
| 24 | {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, | ||
| 25 | {25, nullptr, "Terminate"}, | ||
| 26 | {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, | ||
| 27 | {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, | ||
| 28 | {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"}, | ||
| 29 | {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, | ||
| 30 | {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, | ||
| 31 | {102, nullptr, "PushExtraStorage"}, | ||
| 32 | {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, | ||
| 33 | {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, | ||
| 34 | {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, | ||
| 35 | {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, | ||
| 36 | {110, nullptr, "NeedsToExitProcess"}, | ||
| 37 | {120, nullptr, "GetLibraryAppletInfo"}, | ||
| 38 | {150, nullptr, "RequestForAppletToGetForeground"}, | ||
| 39 | {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"}, | ||
| 40 | }; | ||
| 41 | // clang-format on | ||
| 42 | |||
| 43 | RegisterHandlers(functions); | ||
| 44 | } | ||
| 45 | |||
| 46 | ILibraryAppletAccessor::~ILibraryAppletAccessor() = default; | ||
| 47 | |||
| 48 | void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) { | ||
| 49 | LOG_DEBUG(Service_AM, "called"); | ||
| 50 | |||
| 51 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 52 | rb.Push(ResultSuccess); | ||
| 53 | rb.PushCopyObjects(broker->GetStateChangedEvent().GetHandle()); | ||
| 54 | } | ||
| 55 | |||
| 56 | void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) { | ||
| 57 | LOG_DEBUG(Service_AM, "called"); | ||
| 58 | |||
| 59 | std::scoped_lock lk{applet->lock}; | ||
| 60 | |||
| 61 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 62 | rb.Push(ResultSuccess); | ||
| 63 | rb.Push<u32>(broker->IsCompleted()); | ||
| 64 | } | ||
| 65 | |||
| 66 | void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) { | ||
| 67 | LOG_DEBUG(Service_AM, "called"); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 70 | rb.Push(applet->terminate_result); | ||
| 71 | } | ||
| 72 | |||
| 73 | void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { | ||
| 74 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 75 | |||
| 76 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 77 | rb.Push(ResultSuccess); | ||
| 78 | } | ||
| 79 | |||
| 80 | void ILibraryAppletAccessor::Start(HLERequestContext& ctx) { | ||
| 81 | LOG_DEBUG(Service_AM, "called"); | ||
| 82 | |||
| 83 | applet->process->Run(); | ||
| 84 | FrontendExecute(); | ||
| 85 | |||
| 86 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 87 | rb.Push(ResultSuccess); | ||
| 88 | } | ||
| 89 | |||
| 90 | void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) { | ||
| 91 | LOG_DEBUG(Service_AM, "called"); | ||
| 92 | |||
| 93 | ASSERT(applet != nullptr); | ||
| 94 | applet->message_queue.RequestExit(); | ||
| 95 | FrontendRequestExit(); | ||
| 96 | |||
| 97 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 98 | rb.Push(ResultSuccess); | ||
| 99 | } | ||
| 100 | |||
| 101 | void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { | ||
| 102 | LOG_DEBUG(Service_AM, "called"); | ||
| 103 | |||
| 104 | IPC::RequestParser rp{ctx}; | ||
| 105 | broker->GetInData().Push(rp.PopIpcInterface<IStorage>().lock()); | ||
| 106 | |||
| 107 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 108 | rb.Push(ResultSuccess); | ||
| 109 | } | ||
| 110 | |||
| 111 | void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) { | ||
| 112 | LOG_DEBUG(Service_AM, "called"); | ||
| 113 | |||
| 114 | std::shared_ptr<IStorage> data; | ||
| 115 | const auto res = broker->GetOutData().Pop(&data); | ||
| 116 | |||
| 117 | if (res.IsSuccess()) { | ||
| 118 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 119 | rb.Push(res); | ||
| 120 | rb.PushIpcInterface(std::move(data)); | ||
| 121 | } else { | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(res); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { | ||
| 128 | LOG_DEBUG(Service_AM, "called"); | ||
| 129 | |||
| 130 | IPC::RequestParser rp{ctx}; | ||
| 131 | broker->GetInteractiveInData().Push(rp.PopIpcInterface<IStorage>().lock()); | ||
| 132 | FrontendExecuteInteractive(); | ||
| 133 | |||
| 134 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 135 | rb.Push(ResultSuccess); | ||
| 136 | } | ||
| 137 | |||
| 138 | void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) { | ||
| 139 | LOG_DEBUG(Service_AM, "called"); | ||
| 140 | |||
| 141 | std::shared_ptr<IStorage> data; | ||
| 142 | const auto res = broker->GetInteractiveOutData().Pop(&data); | ||
| 143 | |||
| 144 | if (res.IsSuccess()) { | ||
| 145 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 146 | rb.Push(res); | ||
| 147 | rb.PushIpcInterface(std::move(data)); | ||
| 148 | } else { | ||
| 149 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 150 | rb.Push(res); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { | ||
| 155 | LOG_DEBUG(Service_AM, "called"); | ||
| 156 | |||
| 157 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 158 | rb.Push(ResultSuccess); | ||
| 159 | rb.PushCopyObjects(broker->GetOutData().GetEvent()); | ||
| 160 | } | ||
| 161 | |||
| 162 | void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { | ||
| 163 | LOG_DEBUG(Service_AM, "called"); | ||
| 164 | |||
| 165 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 166 | rb.Push(ResultSuccess); | ||
| 167 | rb.PushCopyObjects(broker->GetInteractiveOutData().GetEvent()); | ||
| 168 | } | ||
| 169 | |||
| 170 | void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { | ||
| 171 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 172 | |||
| 173 | // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is | ||
| 174 | // actually used anywhere | ||
| 175 | constexpr u64 handle = 0xdeadbeef; | ||
| 176 | |||
| 177 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 178 | rb.Push(ResultSuccess); | ||
| 179 | rb.Push(handle); | ||
| 180 | } | ||
| 181 | |||
| 182 | void ILibraryAppletAccessor::FrontendExecute() { | ||
| 183 | if (applet->frontend) { | ||
| 184 | applet->frontend->Initialize(); | ||
| 185 | applet->frontend->Execute(); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | void ILibraryAppletAccessor::FrontendExecuteInteractive() { | ||
| 190 | if (applet->frontend) { | ||
| 191 | applet->frontend->ExecuteInteractive(); | ||
| 192 | applet->frontend->Execute(); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | void ILibraryAppletAccessor::FrontendRequestExit() { | ||
| 197 | if (applet->frontend) { | ||
| 198 | applet->frontend->RequestExit(); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h new file mode 100644 index 000000000..8be29e003 --- /dev/null +++ b/src/core/hle/service/am/library_applet_accessor.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class AppletDataBroker; | ||
| 11 | struct Applet; | ||
| 12 | |||
| 13 | class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { | ||
| 14 | public: | ||
| 15 | explicit ILibraryAppletAccessor(Core::System& system_, | ||
| 16 | std::shared_ptr<AppletDataBroker> broker_, | ||
| 17 | std::shared_ptr<Applet> applet_); | ||
| 18 | ~ILibraryAppletAccessor(); | ||
| 19 | |||
| 20 | protected: | ||
| 21 | void GetAppletStateChangedEvent(HLERequestContext& ctx); | ||
| 22 | void IsCompleted(HLERequestContext& ctx); | ||
| 23 | void GetResult(HLERequestContext& ctx); | ||
| 24 | void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx); | ||
| 25 | void Start(HLERequestContext& ctx); | ||
| 26 | void RequestExit(HLERequestContext& ctx); | ||
| 27 | void PushInData(HLERequestContext& ctx); | ||
| 28 | void PopOutData(HLERequestContext& ctx); | ||
| 29 | void PushInteractiveInData(HLERequestContext& ctx); | ||
| 30 | void PopInteractiveOutData(HLERequestContext& ctx); | ||
| 31 | void GetPopOutDataEvent(HLERequestContext& ctx); | ||
| 32 | void GetPopInteractiveOutDataEvent(HLERequestContext& ctx); | ||
| 33 | void GetIndirectLayerConsumerHandle(HLERequestContext& ctx); | ||
| 34 | |||
| 35 | void FrontendExecute(); | ||
| 36 | void FrontendExecuteInteractive(); | ||
| 37 | void FrontendRequestExit(); | ||
| 38 | |||
| 39 | const std::shared_ptr<AppletDataBroker> broker; | ||
| 40 | const std::shared_ptr<Applet> applet; | ||
| 41 | }; | ||
| 42 | |||
| 43 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp new file mode 100644 index 000000000..47bab7528 --- /dev/null +++ b/src/core/hle/service/am/library_applet_creator.cpp | |||
| @@ -0,0 +1,271 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 5 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 6 | #include "core/hle/service/am/applet_manager.h" | ||
| 7 | #include "core/hle/service/am/frontend/applets.h" | ||
| 8 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 9 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 10 | #include "core/hle/service/am/library_applet_storage.h" | ||
| 11 | #include "core/hle/service/am/storage.h" | ||
| 12 | #include "core/hle/service/ipc_helpers.h" | ||
| 13 | #include "core/hle/service/sm/sm.h" | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | namespace { | ||
| 18 | |||
| 19 | AppletProgramId AppletIdToProgramId(AppletId applet_id) { | ||
| 20 | switch (applet_id) { | ||
| 21 | case AppletId::OverlayDisplay: | ||
| 22 | return AppletProgramId::OverlayDisplay; | ||
| 23 | case AppletId::QLaunch: | ||
| 24 | return AppletProgramId::QLaunch; | ||
| 25 | case AppletId::Starter: | ||
| 26 | return AppletProgramId::Starter; | ||
| 27 | case AppletId::Auth: | ||
| 28 | return AppletProgramId::Auth; | ||
| 29 | case AppletId::Cabinet: | ||
| 30 | return AppletProgramId::Cabinet; | ||
| 31 | case AppletId::Controller: | ||
| 32 | return AppletProgramId::Controller; | ||
| 33 | case AppletId::DataErase: | ||
| 34 | return AppletProgramId::DataErase; | ||
| 35 | case AppletId::Error: | ||
| 36 | return AppletProgramId::Error; | ||
| 37 | case AppletId::NetConnect: | ||
| 38 | return AppletProgramId::NetConnect; | ||
| 39 | case AppletId::ProfileSelect: | ||
| 40 | return AppletProgramId::ProfileSelect; | ||
| 41 | case AppletId::SoftwareKeyboard: | ||
| 42 | return AppletProgramId::SoftwareKeyboard; | ||
| 43 | case AppletId::MiiEdit: | ||
| 44 | return AppletProgramId::MiiEdit; | ||
| 45 | case AppletId::Web: | ||
| 46 | return AppletProgramId::Web; | ||
| 47 | case AppletId::Shop: | ||
| 48 | return AppletProgramId::Shop; | ||
| 49 | case AppletId::PhotoViewer: | ||
| 50 | return AppletProgramId::PhotoViewer; | ||
| 51 | case AppletId::Settings: | ||
| 52 | return AppletProgramId::Settings; | ||
| 53 | case AppletId::OfflineWeb: | ||
| 54 | return AppletProgramId::OfflineWeb; | ||
| 55 | case AppletId::LoginShare: | ||
| 56 | return AppletProgramId::LoginShare; | ||
| 57 | case AppletId::WebAuth: | ||
| 58 | return AppletProgramId::WebAuth; | ||
| 59 | case AppletId::MyPage: | ||
| 60 | return AppletProgramId::MyPage; | ||
| 61 | default: | ||
| 62 | return static_cast<AppletProgramId>(0); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | [[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet( | ||
| 67 | Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id, | ||
| 68 | LibraryAppletMode mode) { | ||
| 69 | const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); | ||
| 70 | if (program_id == 0) { | ||
| 71 | // Unknown applet | ||
| 72 | return {}; | ||
| 73 | } | ||
| 74 | |||
| 75 | auto process = std::make_unique<Process>(system); | ||
| 76 | if (!process->Initialize(program_id)) { | ||
| 77 | // Couldn't initialize the guest process | ||
| 78 | return {}; | ||
| 79 | } | ||
| 80 | |||
| 81 | const auto applet = std::make_shared<Applet>(system, std::move(process)); | ||
| 82 | applet->program_id = program_id; | ||
| 83 | applet->applet_id = applet_id; | ||
| 84 | applet->type = AppletType::LibraryApplet; | ||
| 85 | applet->library_applet_mode = mode; | ||
| 86 | |||
| 87 | // Set focus state | ||
| 88 | switch (mode) { | ||
| 89 | case LibraryAppletMode::AllForeground: | ||
| 90 | case LibraryAppletMode::NoUI: | ||
| 91 | applet->focus_state = FocusState::InFocus; | ||
| 92 | applet->hid_registration.EnableAppletToGetInput(true); | ||
| 93 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 94 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 95 | break; | ||
| 96 | case LibraryAppletMode::AllForegroundInitiallyHidden: | ||
| 97 | applet->system_buffer_manager.SetWindowVisibility(false); | ||
| 98 | applet->focus_state = FocusState::NotInFocus; | ||
| 99 | applet->hid_registration.EnableAppletToGetInput(false); | ||
| 100 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 101 | break; | ||
| 102 | case LibraryAppletMode::Background: | ||
| 103 | case LibraryAppletMode::BackgroundIndirectDisplay: | ||
| 104 | default: | ||
| 105 | applet->focus_state = FocusState::Background; | ||
| 106 | applet->hid_registration.EnableAppletToGetInput(true); | ||
| 107 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | |||
| 111 | auto broker = std::make_shared<AppletDataBroker>(system); | ||
| 112 | applet->caller_applet = caller_applet; | ||
| 113 | applet->caller_applet_broker = broker; | ||
| 114 | |||
| 115 | system.GetAppletManager().InsertApplet(applet); | ||
| 116 | |||
| 117 | return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); | ||
| 118 | } | ||
| 119 | |||
| 120 | [[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet( | ||
| 121 | Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id, | ||
| 122 | LibraryAppletMode mode) { | ||
| 123 | const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); | ||
| 124 | |||
| 125 | auto process = std::make_unique<Process>(system); | ||
| 126 | auto applet = std::make_shared<Applet>(system, std::move(process)); | ||
| 127 | applet->program_id = program_id; | ||
| 128 | applet->applet_id = applet_id; | ||
| 129 | applet->type = AppletType::LibraryApplet; | ||
| 130 | applet->library_applet_mode = mode; | ||
| 131 | |||
| 132 | auto storage = std::make_shared<AppletDataBroker>(system); | ||
| 133 | applet->caller_applet = caller_applet; | ||
| 134 | applet->caller_applet_broker = storage; | ||
| 135 | applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode); | ||
| 136 | |||
| 137 | return std::make_shared<ILibraryAppletAccessor>(system, storage, applet); | ||
| 138 | } | ||
| 139 | |||
| 140 | } // namespace | ||
| 141 | |||
| 142 | ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_) | ||
| 143 | : ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} { | ||
| 144 | static const FunctionInfo functions[] = { | ||
| 145 | {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, | ||
| 146 | {1, nullptr, "TerminateAllLibraryApplets"}, | ||
| 147 | {2, nullptr, "AreAnyLibraryAppletsLeft"}, | ||
| 148 | {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, | ||
| 149 | {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, | ||
| 150 | {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, | ||
| 151 | }; | ||
| 152 | RegisterHandlers(functions); | ||
| 153 | } | ||
| 154 | |||
| 155 | ILibraryAppletCreator::~ILibraryAppletCreator() = default; | ||
| 156 | |||
| 157 | void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { | ||
| 158 | IPC::RequestParser rp{ctx}; | ||
| 159 | |||
| 160 | const auto applet_id = rp.PopRaw<AppletId>(); | ||
| 161 | const auto applet_mode = rp.PopRaw<LibraryAppletMode>(); | ||
| 162 | |||
| 163 | LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, | ||
| 164 | applet_mode); | ||
| 165 | |||
| 166 | auto library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode); | ||
| 167 | if (!library_applet) { | ||
| 168 | LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||
| 169 | |||
| 170 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 171 | rb.Push(ResultUnknown); | ||
| 172 | return; | ||
| 173 | } | ||
| 174 | |||
| 175 | // Applet is created, can now be launched. | ||
| 176 | applet->library_applet_launchable_event.Signal(); | ||
| 177 | |||
| 178 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 179 | rb.Push(ResultSuccess); | ||
| 180 | rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet); | ||
| 181 | } | ||
| 182 | |||
| 183 | void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { | ||
| 184 | IPC::RequestParser rp{ctx}; | ||
| 185 | |||
| 186 | const s64 size{rp.Pop<s64>()}; | ||
| 187 | |||
| 188 | LOG_DEBUG(Service_AM, "called, size={}", size); | ||
| 189 | |||
| 190 | if (size <= 0) { | ||
| 191 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 192 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 193 | rb.Push(ResultUnknown); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | |||
| 197 | std::vector<u8> data(size); | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 200 | rb.Push(ResultSuccess); | ||
| 201 | rb.PushIpcInterface<IStorage>(system, AM::CreateStorage(std::move(data))); | ||
| 202 | } | ||
| 203 | |||
| 204 | void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { | ||
| 205 | IPC::RequestParser rp{ctx}; | ||
| 206 | |||
| 207 | struct Parameters { | ||
| 208 | bool is_writable; | ||
| 209 | s64 size; | ||
| 210 | }; | ||
| 211 | |||
| 212 | const auto params{rp.PopRaw<Parameters>()}; | ||
| 213 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 214 | |||
| 215 | LOG_DEBUG(Service_AM, "called, is_writable={}, size={}, handle={:08X}", params.is_writable, | ||
| 216 | params.size, handle); | ||
| 217 | |||
| 218 | if (params.size <= 0) { | ||
| 219 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 220 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 221 | rb.Push(ResultUnknown); | ||
| 222 | return; | ||
| 223 | } | ||
| 224 | |||
| 225 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 226 | |||
| 227 | if (transfer_mem.IsNull()) { | ||
| 228 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 229 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 230 | rb.Push(ResultUnknown); | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 235 | rb.Push(ResultSuccess); | ||
| 236 | rb.PushIpcInterface<IStorage>( | ||
| 237 | system, AM::CreateTransferMemoryStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), | ||
| 238 | params.is_writable, params.size)); | ||
| 239 | } | ||
| 240 | |||
| 241 | void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | ||
| 242 | IPC::RequestParser rp{ctx}; | ||
| 243 | |||
| 244 | const s64 size{rp.Pop<s64>()}; | ||
| 245 | const auto handle{ctx.GetCopyHandle(0)}; | ||
| 246 | |||
| 247 | LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); | ||
| 248 | |||
| 249 | if (size <= 0) { | ||
| 250 | LOG_ERROR(Service_AM, "size is less than or equal to 0"); | ||
| 251 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 252 | rb.Push(ResultUnknown); | ||
| 253 | return; | ||
| 254 | } | ||
| 255 | |||
| 256 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); | ||
| 257 | |||
| 258 | if (transfer_mem.IsNull()) { | ||
| 259 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | ||
| 260 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 261 | rb.Push(ResultUnknown); | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | |||
| 265 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 266 | rb.Push(ResultSuccess); | ||
| 267 | rb.PushIpcInterface<IStorage>( | ||
| 268 | system, AM::CreateHandleStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), size)); | ||
| 269 | } | ||
| 270 | |||
| 271 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h new file mode 100644 index 000000000..551f287bd --- /dev/null +++ b/src/core/hle/service/am/library_applet_creator.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | ||
| 13 | public: | ||
| 14 | explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 15 | ~ILibraryAppletCreator() override; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void CreateLibraryApplet(HLERequestContext& ctx); | ||
| 19 | void CreateStorage(HLERequestContext& ctx); | ||
| 20 | void CreateTransferMemoryStorage(HLERequestContext& ctx); | ||
| 21 | void CreateHandleStorage(HLERequestContext& ctx); | ||
| 22 | |||
| 23 | const std::shared_ptr<Applet> applet; | ||
| 24 | }; | ||
| 25 | |||
| 26 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp new file mode 100644 index 000000000..d6108fba3 --- /dev/null +++ b/src/core/hle/service/am/library_applet_proxy.cpp | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/audio_controller.h" | ||
| 6 | #include "core/hle/service/am/common_state_getter.h" | ||
| 7 | #include "core/hle/service/am/debug_functions.h" | ||
| 8 | #include "core/hle/service/am/display_controller.h" | ||
| 9 | #include "core/hle/service/am/global_state_controller.h" | ||
| 10 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 11 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 12 | #include "core/hle/service/am/library_applet_proxy.h" | ||
| 13 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 14 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 15 | #include "core/hle/service/am/self_controller.h" | ||
| 16 | #include "core/hle/service/am/window_controller.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | ||
| 18 | |||
| 19 | namespace Service::AM { | ||
| 20 | |||
| 21 | ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 22 | std::shared_ptr<Applet> applet_, Core::System& system_) | ||
| 23 | : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( | ||
| 24 | applet_)} { | ||
| 25 | // clang-format off | ||
| 26 | static const FunctionInfo functions[] = { | ||
| 27 | {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 28 | {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 29 | {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 30 | {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 31 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 32 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, | ||
| 33 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 34 | {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, | ||
| 35 | {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 36 | {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 37 | {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 38 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 39 | }; | ||
| 40 | // clang-format on | ||
| 41 | |||
| 42 | RegisterHandlers(functions); | ||
| 43 | } | ||
| 44 | |||
| 45 | ILibraryAppletProxy::~ILibraryAppletProxy() = default; | ||
| 46 | |||
| 47 | void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 48 | LOG_DEBUG(Service_AM, "called"); | ||
| 49 | |||
| 50 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 51 | rb.Push(ResultSuccess); | ||
| 52 | rb.PushIpcInterface<ICommonStateGetter>(system, applet); | ||
| 53 | } | ||
| 54 | |||
| 55 | void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 56 | LOG_DEBUG(Service_AM, "called"); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 59 | rb.Push(ResultSuccess); | ||
| 60 | rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); | ||
| 61 | } | ||
| 62 | |||
| 63 | void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 64 | LOG_DEBUG(Service_AM, "called"); | ||
| 65 | |||
| 66 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 67 | rb.Push(ResultSuccess); | ||
| 68 | rb.PushIpcInterface<IWindowController>(system, applet); | ||
| 69 | } | ||
| 70 | |||
| 71 | void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 72 | LOG_DEBUG(Service_AM, "called"); | ||
| 73 | |||
| 74 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 75 | rb.Push(ResultSuccess); | ||
| 76 | rb.PushIpcInterface<IAudioController>(system); | ||
| 77 | } | ||
| 78 | |||
| 79 | void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 80 | LOG_DEBUG(Service_AM, "called"); | ||
| 81 | |||
| 82 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 83 | rb.Push(ResultSuccess); | ||
| 84 | rb.PushIpcInterface<IDisplayController>(system, applet); | ||
| 85 | } | ||
| 86 | |||
| 87 | void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) { | ||
| 88 | LOG_DEBUG(Service_AM, "called"); | ||
| 89 | |||
| 90 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 91 | rb.Push(ResultSuccess); | ||
| 92 | rb.PushIpcInterface<IProcessWindingController>(system, applet); | ||
| 93 | } | ||
| 94 | |||
| 95 | void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 96 | LOG_DEBUG(Service_AM, "called"); | ||
| 97 | |||
| 98 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 99 | rb.Push(ResultSuccess); | ||
| 100 | rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); | ||
| 101 | } | ||
| 102 | |||
| 103 | void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { | ||
| 104 | LOG_DEBUG(Service_AM, "called"); | ||
| 105 | |||
| 106 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 107 | rb.Push(ResultSuccess); | ||
| 108 | rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet); | ||
| 109 | } | ||
| 110 | |||
| 111 | void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 112 | LOG_DEBUG(Service_AM, "called"); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | rb.PushIpcInterface<IAppletCommonFunctions>(system, applet); | ||
| 117 | } | ||
| 118 | |||
| 119 | void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 120 | LOG_DEBUG(Service_AM, "called"); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 125 | } | ||
| 126 | |||
| 127 | void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { | ||
| 128 | LOG_DEBUG(Service_AM, "called"); | ||
| 129 | |||
| 130 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 131 | rb.Push(ResultSuccess); | ||
| 132 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 133 | } | ||
| 134 | |||
| 135 | void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 136 | LOG_DEBUG(Service_AM, "called"); | ||
| 137 | |||
| 138 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 139 | rb.Push(ResultSuccess); | ||
| 140 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 141 | } | ||
| 142 | |||
| 143 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h new file mode 100644 index 000000000..8f7a25897 --- /dev/null +++ b/src/core/hle/service/am/library_applet_proxy.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | ||
| 13 | public: | ||
| 14 | explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 15 | std::shared_ptr<Applet> applet_, Core::System& system_); | ||
| 16 | ~ILibraryAppletProxy(); | ||
| 17 | |||
| 18 | private: | ||
| 19 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 20 | void GetSelfController(HLERequestContext& ctx); | ||
| 21 | void GetWindowController(HLERequestContext& ctx); | ||
| 22 | void GetAudioController(HLERequestContext& ctx); | ||
| 23 | void GetDisplayController(HLERequestContext& ctx); | ||
| 24 | void GetProcessWindingController(HLERequestContext& ctx); | ||
| 25 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 26 | void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx); | ||
| 27 | void GetAppletCommonFunctions(HLERequestContext& ctx); | ||
| 28 | void GetHomeMenuFunctions(HLERequestContext& ctx); | ||
| 29 | void GetGlobalStateController(HLERequestContext& ctx); | ||
| 30 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 31 | |||
| 32 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 33 | std::shared_ptr<Applet> applet; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp new file mode 100644 index 000000000..b560f580b --- /dev/null +++ b/src/core/hle/service/am/library_applet_self_accessor.cpp | |||
| @@ -0,0 +1,338 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/scope_exit.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | ||
| 7 | #include "core/file_sys/patch_manager.h" | ||
| 8 | #include "core/file_sys/registered_cache.h" | ||
| 9 | #include "core/hle/service/acc/profile_manager.h" | ||
| 10 | #include "core/hle/service/am/am_results.h" | ||
| 11 | #include "core/hle/service/am/applet_data_broker.h" | ||
| 12 | #include "core/hle/service/am/applet_manager.h" | ||
| 13 | #include "core/hle/service/am/frontend/applet_cabinet.h" | ||
| 14 | #include "core/hle/service/am/frontend/applet_controller.h" | ||
| 15 | #include "core/hle/service/am/frontend/applet_mii_edit_types.h" | ||
| 16 | #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" | ||
| 17 | #include "core/hle/service/am/frontend/applets.h" | ||
| 18 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 19 | #include "core/hle/service/am/storage.h" | ||
| 20 | #include "core/hle/service/ipc_helpers.h" | ||
| 21 | #include "core/hle/service/ns/ns.h" | ||
| 22 | #include "core/hle/service/sm/sm.h" | ||
| 23 | #include "hid_core/hid_types.h" | ||
| 24 | |||
| 25 | namespace Service::AM { | ||
| 26 | |||
| 27 | namespace { | ||
| 28 | |||
| 29 | AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) { | ||
| 30 | if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) { | ||
| 31 | // TODO: is this actually the application ID? | ||
| 32 | return { | ||
| 33 | .applet_id = caller_applet->applet_id, | ||
| 34 | .application_id = caller_applet->program_id, | ||
| 35 | }; | ||
| 36 | } else { | ||
| 37 | return { | ||
| 38 | .applet_id = AppletId::QLaunch, | ||
| 39 | .application_id = 0x0100000000001000ull, | ||
| 40 | }; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | } // namespace | ||
| 45 | |||
| 46 | ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, | ||
| 47 | std::shared_ptr<Applet> applet_) | ||
| 48 | : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)}, | ||
| 49 | broker{applet->caller_applet_broker} { | ||
| 50 | // clang-format off | ||
| 51 | static const FunctionInfo functions[] = { | ||
| 52 | {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, | ||
| 53 | {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, | ||
| 54 | {2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"}, | ||
| 55 | {3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"}, | ||
| 56 | {5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"}, | ||
| 57 | {6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"}, | ||
| 58 | {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, | ||
| 59 | {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, | ||
| 60 | {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, | ||
| 61 | {13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "CanUseApplicationCore"}, | ||
| 62 | {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, | ||
| 63 | {15, nullptr, "GetMainAppletApplicationControlProperty"}, | ||
| 64 | {16, nullptr, "GetMainAppletStorageId"}, | ||
| 65 | {17, nullptr, "GetCallerAppletIdentityInfoStack"}, | ||
| 66 | {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, | ||
| 67 | {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"}, | ||
| 68 | {20, nullptr, "PopExtraStorage"}, | ||
| 69 | {25, nullptr, "GetPopExtraStorageEvent"}, | ||
| 70 | {30, nullptr, "UnpopInData"}, | ||
| 71 | {31, nullptr, "UnpopExtraStorage"}, | ||
| 72 | {40, nullptr, "GetIndirectLayerProducerHandle"}, | ||
| 73 | {50, nullptr, "ReportVisibleError"}, | ||
| 74 | {51, nullptr, "ReportVisibleErrorWithErrorContext"}, | ||
| 75 | {60, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"}, | ||
| 76 | {70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "GetCurrentApplicationId"}, | ||
| 77 | {80, nullptr, "RequestExitToSelf"}, | ||
| 78 | {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, | ||
| 79 | {100, nullptr, "CreateGameMovieTrimmer"}, | ||
| 80 | {101, nullptr, "ReserveResourceForMovieOperation"}, | ||
| 81 | {102, nullptr, "UnreserveResourceForMovieOperation"}, | ||
| 82 | {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"}, | ||
| 83 | {120, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 84 | {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, | ||
| 85 | {140, nullptr, "SetApplicationMemoryReservation"}, | ||
| 86 | {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, | ||
| 87 | {160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"}, | ||
| 88 | }; | ||
| 89 | // clang-format on | ||
| 90 | RegisterHandlers(functions); | ||
| 91 | } | ||
| 92 | |||
| 93 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | ||
| 94 | |||
| 95 | void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { | ||
| 96 | LOG_INFO(Service_AM, "called"); | ||
| 97 | |||
| 98 | std::shared_ptr<IStorage> data; | ||
| 99 | const auto res = broker->GetInData().Pop(&data); | ||
| 100 | |||
| 101 | if (res.IsSuccess()) { | ||
| 102 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 103 | rb.Push(res); | ||
| 104 | rb.PushIpcInterface(std::move(data)); | ||
| 105 | } else { | ||
| 106 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 107 | rb.Push(res); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { | ||
| 112 | LOG_INFO(Service_AM, "called"); | ||
| 113 | |||
| 114 | IPC::RequestParser rp{ctx}; | ||
| 115 | broker->GetOutData().Push(rp.PopIpcInterface<IStorage>().lock()); | ||
| 116 | |||
| 117 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 118 | rb.Push(ResultSuccess); | ||
| 119 | } | ||
| 120 | |||
| 121 | void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) { | ||
| 122 | LOG_INFO(Service_AM, "called"); | ||
| 123 | |||
| 124 | std::shared_ptr<IStorage> data; | ||
| 125 | const auto res = broker->GetInteractiveInData().Pop(&data); | ||
| 126 | |||
| 127 | if (res.IsSuccess()) { | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 129 | rb.Push(res); | ||
| 130 | rb.PushIpcInterface(std::move(data)); | ||
| 131 | } else { | ||
| 132 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 133 | rb.Push(res); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) { | ||
| 138 | LOG_INFO(Service_AM, "called"); | ||
| 139 | |||
| 140 | IPC::RequestParser rp{ctx}; | ||
| 141 | broker->GetInteractiveOutData().Push(rp.PopIpcInterface<IStorage>().lock()); | ||
| 142 | |||
| 143 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 144 | rb.Push(ResultSuccess); | ||
| 145 | } | ||
| 146 | |||
| 147 | void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) { | ||
| 148 | LOG_INFO(Service_AM, "called"); | ||
| 149 | |||
| 150 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 151 | rb.Push(ResultSuccess); | ||
| 152 | rb.PushCopyObjects(broker->GetInData().GetEvent()); | ||
| 153 | } | ||
| 154 | |||
| 155 | void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) { | ||
| 156 | LOG_INFO(Service_AM, "called"); | ||
| 157 | |||
| 158 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 159 | rb.Push(ResultSuccess); | ||
| 160 | rb.PushCopyObjects(broker->GetInteractiveInData().GetEvent()); | ||
| 161 | } | ||
| 162 | |||
| 163 | void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { | ||
| 164 | LOG_INFO(Service_AM, "called"); | ||
| 165 | |||
| 166 | system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid); | ||
| 167 | broker->SignalCompletion(); | ||
| 168 | |||
| 169 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 170 | rb.Push(ResultSuccess); | ||
| 171 | } | ||
| 172 | |||
| 173 | void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { | ||
| 174 | struct LibraryAppletInfo { | ||
| 175 | AppletId applet_id; | ||
| 176 | LibraryAppletMode library_applet_mode; | ||
| 177 | }; | ||
| 178 | |||
| 179 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 180 | |||
| 181 | const LibraryAppletInfo applet_info{ | ||
| 182 | .applet_id = applet->applet_id, | ||
| 183 | .library_applet_mode = applet->library_applet_mode, | ||
| 184 | }; | ||
| 185 | |||
| 186 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 187 | rb.Push(ResultSuccess); | ||
| 188 | rb.PushRaw(applet_info); | ||
| 189 | } | ||
| 190 | |||
| 191 | void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 192 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 193 | |||
| 194 | const AppletIdentityInfo applet_info{ | ||
| 195 | .applet_id = AppletId::QLaunch, | ||
| 196 | .application_id = 0x0100000000001000ull, | ||
| 197 | }; | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 200 | rb.Push(ResultSuccess); | ||
| 201 | rb.PushRaw(applet_info); | ||
| 202 | } | ||
| 203 | |||
| 204 | void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) { | ||
| 205 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 206 | |||
| 207 | // TODO: This appears to read the NPDM from state and check the core mask of the applet. | ||
| 208 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 209 | rb.Push(ResultSuccess); | ||
| 210 | rb.Push<u8>(0); | ||
| 211 | } | ||
| 212 | |||
| 213 | void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 214 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 215 | |||
| 216 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 217 | rb.Push(ResultSuccess); | ||
| 218 | rb.PushRaw(GetCallerIdentity(applet)); | ||
| 219 | } | ||
| 220 | |||
| 221 | void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { | ||
| 222 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 223 | |||
| 224 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 225 | rb.Push(ResultSuccess); | ||
| 226 | rb.Push<u32>(0); | ||
| 227 | } | ||
| 228 | |||
| 229 | void ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) { | ||
| 230 | // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage | ||
| 231 | auto identity = GetCallerIdentity(applet); | ||
| 232 | |||
| 233 | // TODO(bunnei): This should be configurable | ||
| 234 | LOG_DEBUG(Service_AM, "called"); | ||
| 235 | |||
| 236 | // Get supported languages from NACP, if possible | ||
| 237 | // Default to 0 (all languages supported) | ||
| 238 | u32 supported_languages = 0; | ||
| 239 | |||
| 240 | const auto res = [this, identity] { | ||
| 241 | const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(), | ||
| 242 | system.GetContentProvider()}; | ||
| 243 | auto metadata = pm.GetControlMetadata(); | ||
| 244 | if (metadata.first != nullptr) { | ||
| 245 | return metadata; | ||
| 246 | } | ||
| 247 | |||
| 248 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id), | ||
| 249 | system.GetFileSystemController(), | ||
| 250 | system.GetContentProvider()}; | ||
| 251 | return pm_update.GetControlMetadata(); | ||
| 252 | }(); | ||
| 253 | |||
| 254 | if (res.first != nullptr) { | ||
| 255 | supported_languages = res.first->GetSupportedLanguages(); | ||
| 256 | } | ||
| 257 | |||
| 258 | // Call IApplicationManagerInterface implementation. | ||
| 259 | auto& service_manager = system.ServiceManager(); | ||
| 260 | auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); | ||
| 261 | auto app_man = ns_am2->GetApplicationManagerInterface(); | ||
| 262 | |||
| 263 | // Get desired application language | ||
| 264 | u8 desired_language{}; | ||
| 265 | const auto res_lang = | ||
| 266 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 267 | if (res_lang != ResultSuccess) { | ||
| 268 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 269 | rb.Push(res_lang); | ||
| 270 | return; | ||
| 271 | } | ||
| 272 | |||
| 273 | // Convert to settings language code. | ||
| 274 | u64 language_code{}; | ||
| 275 | const auto res_code = | ||
| 276 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 277 | if (res_code != ResultSuccess) { | ||
| 278 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 279 | rb.Push(res_code); | ||
| 280 | return; | ||
| 281 | } | ||
| 282 | |||
| 283 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); | ||
| 284 | |||
| 285 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 286 | rb.Push(ResultSuccess); | ||
| 287 | rb.Push(language_code); | ||
| 288 | } | ||
| 289 | |||
| 290 | void ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) { | ||
| 291 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 292 | |||
| 293 | u64 application_id = 0; | ||
| 294 | if (auto caller_applet = applet->caller_applet.lock(); caller_applet) { | ||
| 295 | application_id = caller_applet->program_id; | ||
| 296 | } | ||
| 297 | |||
| 298 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 299 | rb.Push(ResultSuccess); | ||
| 300 | rb.Push(application_id); | ||
| 301 | } | ||
| 302 | |||
| 303 | void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { | ||
| 304 | const Service::Account::ProfileManager manager{}; | ||
| 305 | bool is_empty{true}; | ||
| 306 | s32 user_count{-1}; | ||
| 307 | |||
| 308 | LOG_INFO(Service_AM, "called"); | ||
| 309 | |||
| 310 | if (manager.GetUserCount() > 0) { | ||
| 311 | is_empty = false; | ||
| 312 | user_count = static_cast<s32>(manager.GetUserCount()); | ||
| 313 | ctx.WriteBuffer(manager.GetAllUsers()); | ||
| 314 | } | ||
| 315 | |||
| 316 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 317 | rb.Push(ResultSuccess); | ||
| 318 | rb.Push<u8>(is_empty); | ||
| 319 | rb.Push(user_count); | ||
| 320 | } | ||
| 321 | |||
| 322 | void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) { | ||
| 323 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 324 | |||
| 325 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 326 | rb.Push(ResultSuccess); | ||
| 327 | rb.Push<u8>(0); | ||
| 328 | } | ||
| 329 | |||
| 330 | void ILibraryAppletSelfAccessor::Cmd160(HLERequestContext& ctx) { | ||
| 331 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 332 | |||
| 333 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 334 | rb.Push(ResultSuccess); | ||
| 335 | rb.Push<u64>(0); | ||
| 336 | } | ||
| 337 | |||
| 338 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h new file mode 100644 index 000000000..8717a989a --- /dev/null +++ b/src/core/hle/service/am/library_applet_self_accessor.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <deque> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Service::AM { | ||
| 12 | |||
| 13 | class AppletDataBroker; | ||
| 14 | struct Applet; | ||
| 15 | |||
| 16 | class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { | ||
| 17 | public: | ||
| 18 | explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 19 | ~ILibraryAppletSelfAccessor() override; | ||
| 20 | |||
| 21 | private: | ||
| 22 | void PopInData(HLERequestContext& ctx); | ||
| 23 | void PushOutData(HLERequestContext& ctx); | ||
| 24 | void PopInteractiveInData(HLERequestContext& ctx); | ||
| 25 | void PushInteractiveOutData(HLERequestContext& ctx); | ||
| 26 | void GetPopInDataEvent(HLERequestContext& ctx); | ||
| 27 | void GetPopInteractiveInDataEvent(HLERequestContext& ctx); | ||
| 28 | void GetLibraryAppletInfo(HLERequestContext& ctx); | ||
| 29 | void GetMainAppletIdentityInfo(HLERequestContext& ctx); | ||
| 30 | void CanUseApplicationCore(HLERequestContext& ctx); | ||
| 31 | void ExitProcessAndReturn(HLERequestContext& ctx); | ||
| 32 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); | ||
| 33 | void GetDesirableKeyboardLayout(HLERequestContext& ctx); | ||
| 34 | void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx); | ||
| 35 | void GetCurrentApplicationId(HLERequestContext& ctx); | ||
| 36 | void GetMainAppletAvailableUsers(HLERequestContext& ctx); | ||
| 37 | void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); | ||
| 38 | void Cmd160(HLERequestContext& ctx); | ||
| 39 | |||
| 40 | const std::shared_ptr<Applet> applet; | ||
| 41 | const std::shared_ptr<AppletDataBroker> broker; | ||
| 42 | }; | ||
| 43 | |||
| 44 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp new file mode 100644 index 000000000..46e6c0111 --- /dev/null +++ b/src/core/hle/service/am/library_applet_storage.cpp | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 5 | #include "core/hle/service/am/am_results.h" | ||
| 6 | #include "core/hle/service/am/library_applet_storage.h" | ||
| 7 | #include "core/memory.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | |||
| 13 | Result ValidateOffset(s64 offset, size_t size, size_t data_size) { | ||
| 14 | R_UNLESS(offset >= 0, AM::ResultInvalidOffset); | ||
| 15 | |||
| 16 | const size_t begin = offset; | ||
| 17 | const size_t end = begin + size; | ||
| 18 | |||
| 19 | R_UNLESS(begin <= end && end <= data_size, AM::ResultInvalidOffset); | ||
| 20 | R_SUCCEED(); | ||
| 21 | } | ||
| 22 | |||
| 23 | class BufferLibraryAppletStorage final : public LibraryAppletStorage { | ||
| 24 | public: | ||
| 25 | explicit BufferLibraryAppletStorage(std::vector<u8>&& data) : m_data(std::move(data)) {} | ||
| 26 | ~BufferLibraryAppletStorage() = default; | ||
| 27 | |||
| 28 | Result Read(s64 offset, void* buffer, size_t size) override { | ||
| 29 | R_TRY(ValidateOffset(offset, size, m_data.size())); | ||
| 30 | |||
| 31 | std::memcpy(buffer, m_data.data() + offset, size); | ||
| 32 | |||
| 33 | R_SUCCEED(); | ||
| 34 | } | ||
| 35 | |||
| 36 | Result Write(s64 offset, const void* buffer, size_t size) override { | ||
| 37 | R_TRY(ValidateOffset(offset, size, m_data.size())); | ||
| 38 | |||
| 39 | std::memcpy(m_data.data() + offset, buffer, size); | ||
| 40 | |||
| 41 | R_SUCCEED(); | ||
| 42 | } | ||
| 43 | |||
| 44 | s64 GetSize() override { | ||
| 45 | return m_data.size(); | ||
| 46 | } | ||
| 47 | |||
| 48 | Kernel::KTransferMemory* GetHandle() override { | ||
| 49 | return nullptr; | ||
| 50 | } | ||
| 51 | |||
| 52 | private: | ||
| 53 | std::vector<u8> m_data; | ||
| 54 | }; | ||
| 55 | |||
| 56 | class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage { | ||
| 57 | public: | ||
| 58 | explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory, | ||
| 59 | Kernel::KTransferMemory* trmem, bool is_writable, | ||
| 60 | s64 size) | ||
| 61 | : m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) { | ||
| 62 | m_trmem->Open(); | ||
| 63 | } | ||
| 64 | |||
| 65 | ~TransferMemoryLibraryAppletStorage() { | ||
| 66 | m_trmem->Close(); | ||
| 67 | m_trmem = nullptr; | ||
| 68 | } | ||
| 69 | |||
| 70 | Result Read(s64 offset, void* buffer, size_t size) override { | ||
| 71 | R_TRY(ValidateOffset(offset, size, m_size)); | ||
| 72 | |||
| 73 | m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size); | ||
| 74 | |||
| 75 | R_SUCCEED(); | ||
| 76 | } | ||
| 77 | |||
| 78 | Result Write(s64 offset, const void* buffer, size_t size) override { | ||
| 79 | R_UNLESS(m_is_writable, ResultUnknown); | ||
| 80 | R_TRY(ValidateOffset(offset, size, m_size)); | ||
| 81 | |||
| 82 | m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size); | ||
| 83 | |||
| 84 | R_SUCCEED(); | ||
| 85 | } | ||
| 86 | |||
| 87 | s64 GetSize() override { | ||
| 88 | return m_size; | ||
| 89 | } | ||
| 90 | |||
| 91 | Kernel::KTransferMemory* GetHandle() override { | ||
| 92 | return nullptr; | ||
| 93 | } | ||
| 94 | |||
| 95 | protected: | ||
| 96 | Core::Memory::Memory& m_memory; | ||
| 97 | Kernel::KTransferMemory* m_trmem; | ||
| 98 | bool m_is_writable; | ||
| 99 | s64 m_size; | ||
| 100 | }; | ||
| 101 | |||
| 102 | class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage { | ||
| 103 | public: | ||
| 104 | explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory, | ||
| 105 | Kernel::KTransferMemory* trmem, s64 size) | ||
| 106 | : TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {} | ||
| 107 | ~HandleLibraryAppletStorage() = default; | ||
| 108 | |||
| 109 | Kernel::KTransferMemory* GetHandle() override { | ||
| 110 | return m_trmem; | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | |||
| 114 | } // namespace | ||
| 115 | |||
| 116 | LibraryAppletStorage::~LibraryAppletStorage() = default; | ||
| 117 | |||
| 118 | std::vector<u8> LibraryAppletStorage::GetData() { | ||
| 119 | std::vector<u8> data(this->GetSize()); | ||
| 120 | this->Read(0, data.data(), data.size()); | ||
| 121 | return data; | ||
| 122 | } | ||
| 123 | |||
| 124 | std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data) { | ||
| 125 | return std::make_shared<BufferLibraryAppletStorage>(std::move(data)); | ||
| 126 | } | ||
| 127 | |||
| 128 | std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory, | ||
| 129 | Kernel::KTransferMemory* trmem, | ||
| 130 | bool is_writable, s64 size) { | ||
| 131 | return std::make_shared<TransferMemoryLibraryAppletStorage>(memory, trmem, is_writable, size); | ||
| 132 | } | ||
| 133 | |||
| 134 | std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory, | ||
| 135 | Kernel::KTransferMemory* trmem, | ||
| 136 | s64 size) { | ||
| 137 | return std::make_shared<HandleLibraryAppletStorage>(memory, trmem, size); | ||
| 138 | } | ||
| 139 | |||
| 140 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/library_applet_storage.h b/src/core/hle/service/am/library_applet_storage.h new file mode 100644 index 000000000..7f53f3a9c --- /dev/null +++ b/src/core/hle/service/am/library_applet_storage.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Core::Memory { | ||
| 9 | class Memory; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KTransferMemory; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::AM { | ||
| 17 | |||
| 18 | class LibraryAppletStorage { | ||
| 19 | public: | ||
| 20 | virtual ~LibraryAppletStorage(); | ||
| 21 | virtual Result Read(s64 offset, void* buffer, size_t size) = 0; | ||
| 22 | virtual Result Write(s64 offset, const void* buffer, size_t size) = 0; | ||
| 23 | virtual s64 GetSize() = 0; | ||
| 24 | virtual Kernel::KTransferMemory* GetHandle() = 0; | ||
| 25 | |||
| 26 | std::vector<u8> GetData(); | ||
| 27 | }; | ||
| 28 | |||
| 29 | std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data); | ||
| 30 | std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory, | ||
| 31 | Kernel::KTransferMemory* trmem, | ||
| 32 | bool is_writable, s64 size); | ||
| 33 | std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory, | ||
| 34 | Kernel::KTransferMemory* trmem, s64 size); | ||
| 35 | |||
| 36 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp new file mode 100644 index 000000000..d0bd8d95e --- /dev/null +++ b/src/core/hle/service/am/lock_accessor.cpp | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/lock_accessor.h" | ||
| 5 | #include "core/hle/service/ipc_helpers.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | ILockAccessor::ILockAccessor(Core::System& system_) | ||
| 10 | : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} { | ||
| 11 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {1, &ILockAccessor::TryLock, "TryLock"}, | ||
| 14 | {2, &ILockAccessor::Unlock, "Unlock"}, | ||
| 15 | {3, &ILockAccessor::GetEvent, "GetEvent"}, | ||
| 16 | {4,&ILockAccessor::IsLocked, "IsLocked"}, | ||
| 17 | }; | ||
| 18 | // clang-format on | ||
| 19 | |||
| 20 | RegisterHandlers(functions); | ||
| 21 | |||
| 22 | lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); | ||
| 23 | } | ||
| 24 | |||
| 25 | ILockAccessor::~ILockAccessor() { | ||
| 26 | service_context.CloseEvent(lock_event); | ||
| 27 | }; | ||
| 28 | |||
| 29 | void ILockAccessor::TryLock(HLERequestContext& ctx) { | ||
| 30 | IPC::RequestParser rp{ctx}; | ||
| 31 | const auto return_handle = rp.Pop<bool>(); | ||
| 32 | |||
| 33 | LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle); | ||
| 34 | |||
| 35 | // TODO: When return_handle is true this function should return the lock handle | ||
| 36 | |||
| 37 | is_locked = true; | ||
| 38 | |||
| 39 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 40 | rb.Push(ResultSuccess); | ||
| 41 | rb.Push<u8>(is_locked); | ||
| 42 | } | ||
| 43 | |||
| 44 | void ILockAccessor::Unlock(HLERequestContext& ctx) { | ||
| 45 | LOG_INFO(Service_AM, "called"); | ||
| 46 | |||
| 47 | is_locked = false; | ||
| 48 | |||
| 49 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 50 | rb.Push(ResultSuccess); | ||
| 51 | } | ||
| 52 | |||
| 53 | void ILockAccessor::GetEvent(HLERequestContext& ctx) { | ||
| 54 | LOG_INFO(Service_AM, "called"); | ||
| 55 | |||
| 56 | lock_event->Signal(); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 59 | rb.Push(ResultSuccess); | ||
| 60 | rb.PushCopyObjects(lock_event->GetReadableEvent()); | ||
| 61 | } | ||
| 62 | |||
| 63 | void ILockAccessor::IsLocked(HLERequestContext& ctx) { | ||
| 64 | LOG_INFO(Service_AM, "called"); | ||
| 65 | |||
| 66 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 67 | rb.Push(ResultSuccess); | ||
| 68 | rb.Push<u8>(is_locked); | ||
| 69 | } | ||
| 70 | |||
| 71 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h new file mode 100644 index 000000000..626f60e07 --- /dev/null +++ b/src/core/hle/service/am/lock_accessor.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class ILockAccessor final : public ServiceFramework<ILockAccessor> { | ||
| 12 | public: | ||
| 13 | explicit ILockAccessor(Core::System& system_); | ||
| 14 | ~ILockAccessor() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void TryLock(HLERequestContext& ctx); | ||
| 18 | void Unlock(HLERequestContext& ctx); | ||
| 19 | void GetEvent(HLERequestContext& ctx); | ||
| 20 | void IsLocked(HLERequestContext& ctx); | ||
| 21 | |||
| 22 | bool is_locked{}; | ||
| 23 | |||
| 24 | Kernel::KEvent* lock_event; | ||
| 25 | KernelHelpers::ServiceContext service_context; | ||
| 26 | }; | ||
| 27 | |||
| 28 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp new file mode 100644 index 000000000..61eb8641a --- /dev/null +++ b/src/core/hle/service/am/managed_layer_holder.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/managed_layer_holder.h" | ||
| 5 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | ManagedLayerHolder::ManagedLayerHolder() = default; | ||
| 10 | ManagedLayerHolder::~ManagedLayerHolder() { | ||
| 11 | if (!m_nvnflinger) { | ||
| 12 | return; | ||
| 13 | } | ||
| 14 | |||
| 15 | for (const auto& layer : m_managed_display_layers) { | ||
| 16 | m_nvnflinger->DestroyLayer(layer); | ||
| 17 | } | ||
| 18 | |||
| 19 | for (const auto& layer : m_managed_display_recording_layers) { | ||
| 20 | m_nvnflinger->DestroyLayer(layer); | ||
| 21 | } | ||
| 22 | |||
| 23 | m_nvnflinger = nullptr; | ||
| 24 | } | ||
| 25 | |||
| 26 | void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) { | ||
| 27 | m_nvnflinger = nvnflinger; | ||
| 28 | } | ||
| 29 | |||
| 30 | void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) { | ||
| 31 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 32 | // create the layer in the Default display. | ||
| 33 | const auto display_id = m_nvnflinger->OpenDisplay("Default"); | ||
| 34 | const auto layer_id = m_nvnflinger->CreateLayer(*display_id); | ||
| 35 | |||
| 36 | m_managed_display_layers.emplace(*layer_id); | ||
| 37 | |||
| 38 | *out_layer = *layer_id; | ||
| 39 | } | ||
| 40 | |||
| 41 | void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer, | ||
| 42 | u64* out_recording_layer) { | ||
| 43 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 44 | // create the layer in the Default display. | ||
| 45 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 46 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 47 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 48 | // side effects. | ||
| 49 | // TODO: Support multiple layers | ||
| 50 | const auto display_id = m_nvnflinger->OpenDisplay("Default"); | ||
| 51 | const auto layer_id = m_nvnflinger->CreateLayer(*display_id); | ||
| 52 | |||
| 53 | m_managed_display_layers.emplace(*layer_id); | ||
| 54 | |||
| 55 | *out_layer = *layer_id; | ||
| 56 | *out_recording_layer = 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h new file mode 100644 index 000000000..f7fe03f24 --- /dev/null +++ b/src/core/hle/service/am/managed_layer_holder.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <set> | ||
| 7 | |||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Service::Nvnflinger { | ||
| 12 | class Nvnflinger; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | class ManagedLayerHolder { | ||
| 18 | public: | ||
| 19 | ManagedLayerHolder(); | ||
| 20 | ~ManagedLayerHolder(); | ||
| 21 | |||
| 22 | void Initialize(Nvnflinger::Nvnflinger* nvnflinger); | ||
| 23 | void CreateManagedDisplayLayer(u64* out_layer); | ||
| 24 | void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer); | ||
| 25 | |||
| 26 | private: | ||
| 27 | Nvnflinger::Nvnflinger* m_nvnflinger{}; | ||
| 28 | std::set<u64> m_managed_display_layers{}; | ||
| 29 | std::set<u64> m_managed_display_recording_layers{}; | ||
| 30 | }; | ||
| 31 | |||
| 32 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp new file mode 100644 index 000000000..16b685f86 --- /dev/null +++ b/src/core/hle/service/am/process.cpp | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/scope_exit.h" | ||
| 5 | |||
| 6 | #include "core/file_sys/nca_metadata.h" | ||
| 7 | #include "core/file_sys/registered_cache.h" | ||
| 8 | #include "core/hle/kernel/k_process.h" | ||
| 9 | #include "core/hle/service/am/process.h" | ||
| 10 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 11 | #include "core/loader/loader.h" | ||
| 12 | |||
| 13 | namespace Service::AM { | ||
| 14 | |||
| 15 | Process::Process(Core::System& system) | ||
| 16 | : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(), | ||
| 17 | m_program_id(), m_process_started() {} | ||
| 18 | |||
| 19 | Process::~Process() { | ||
| 20 | this->Finalize(); | ||
| 21 | } | ||
| 22 | |||
| 23 | bool Process::Initialize(u64 program_id) { | ||
| 24 | // First, ensure we are not holding another process. | ||
| 25 | this->Finalize(); | ||
| 26 | |||
| 27 | // Get the filesystem controller. | ||
| 28 | auto& fsc = m_system.GetFileSystemController(); | ||
| 29 | |||
| 30 | // Attempt to load program NCA. | ||
| 31 | const FileSys::RegisteredCache* bis_system{}; | ||
| 32 | FileSys::VirtualFile nca{}; | ||
| 33 | |||
| 34 | // Get the program NCA from built-in storage. | ||
| 35 | bis_system = fsc.GetSystemNANDContents(); | ||
| 36 | if (bis_system) { | ||
| 37 | nca = bis_system->GetEntryRaw(program_id, FileSys::ContentRecordType::Program); | ||
| 38 | } | ||
| 39 | |||
| 40 | // Ensure we retrieved a program NCA. | ||
| 41 | if (!nca) { | ||
| 42 | return false; | ||
| 43 | } | ||
| 44 | |||
| 45 | // Get the appropriate loader to parse this NCA. | ||
| 46 | auto app_loader = Loader::GetLoader(m_system, nca, program_id, 0); | ||
| 47 | |||
| 48 | // Ensure we have a loader which can parse the NCA. | ||
| 49 | if (!app_loader) { | ||
| 50 | return false; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Create the process. | ||
| 54 | auto* const process = Kernel::KProcess::Create(m_system.Kernel()); | ||
| 55 | Kernel::KProcess::Register(m_system.Kernel(), process); | ||
| 56 | |||
| 57 | // On exit, ensure we free the additional reference to the process. | ||
| 58 | SCOPE_EXIT({ process->Close(); }); | ||
| 59 | |||
| 60 | // Insert process modules into memory. | ||
| 61 | const auto [load_result, load_parameters] = app_loader->Load(*process, m_system); | ||
| 62 | |||
| 63 | // Ensure loading was successful. | ||
| 64 | if (load_result != Loader::ResultStatus::Success) { | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | |||
| 68 | // TODO: remove this, kernel already tracks this | ||
| 69 | m_system.Kernel().AppendNewProcess(process); | ||
| 70 | |||
| 71 | // Note the load parameters from NPDM. | ||
| 72 | m_main_thread_priority = load_parameters->main_thread_priority; | ||
| 73 | m_main_thread_stack_size = load_parameters->main_thread_stack_size; | ||
| 74 | |||
| 75 | // This process has not started yet. | ||
| 76 | m_process_started = false; | ||
| 77 | |||
| 78 | // Take ownership of the process object. | ||
| 79 | m_process = process; | ||
| 80 | m_process->Open(); | ||
| 81 | |||
| 82 | // We succeeded. | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | void Process::Finalize() { | ||
| 87 | // Terminate, if we are currently holding a process. | ||
| 88 | this->Terminate(); | ||
| 89 | |||
| 90 | // Close the process. | ||
| 91 | if (m_process) { | ||
| 92 | m_process->Close(); | ||
| 93 | |||
| 94 | // TODO: remove this, kernel already tracks this | ||
| 95 | m_system.Kernel().RemoveProcess(m_process); | ||
| 96 | } | ||
| 97 | |||
| 98 | // Clean up. | ||
| 99 | m_process = nullptr; | ||
| 100 | m_main_thread_priority = 0; | ||
| 101 | m_main_thread_stack_size = 0; | ||
| 102 | m_program_id = 0; | ||
| 103 | m_process_started = false; | ||
| 104 | } | ||
| 105 | |||
| 106 | bool Process::Run() { | ||
| 107 | // If we already started the process, don't start again. | ||
| 108 | if (m_process_started) { | ||
| 109 | return false; | ||
| 110 | } | ||
| 111 | |||
| 112 | // Start. | ||
| 113 | if (m_process) { | ||
| 114 | m_process->Run(m_main_thread_priority, m_main_thread_stack_size); | ||
| 115 | } | ||
| 116 | |||
| 117 | // Mark as started. | ||
| 118 | m_process_started = true; | ||
| 119 | |||
| 120 | // We succeeded. | ||
| 121 | return true; | ||
| 122 | } | ||
| 123 | |||
| 124 | void Process::Terminate() { | ||
| 125 | if (m_process) { | ||
| 126 | m_process->Terminate(); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | u64 Process::GetProcessId() const { | ||
| 131 | if (m_process) { | ||
| 132 | return m_process->GetProcessId(); | ||
| 133 | } | ||
| 134 | |||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process.h b/src/core/hle/service/am/process.h new file mode 100644 index 000000000..4b908ade4 --- /dev/null +++ b/src/core/hle/service/am/process.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class KProcess; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core { | ||
| 14 | class System; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Service::AM { | ||
| 18 | |||
| 19 | class Process { | ||
| 20 | public: | ||
| 21 | explicit Process(Core::System& system); | ||
| 22 | ~Process(); | ||
| 23 | |||
| 24 | bool Initialize(u64 program_id); | ||
| 25 | void Finalize(); | ||
| 26 | |||
| 27 | bool Run(); | ||
| 28 | void Terminate(); | ||
| 29 | |||
| 30 | bool IsInitialized() const { | ||
| 31 | return m_process != nullptr; | ||
| 32 | } | ||
| 33 | u64 GetProcessId() const; | ||
| 34 | u64 GetProgramId() const { | ||
| 35 | return m_program_id; | ||
| 36 | } | ||
| 37 | Kernel::KProcess* GetProcess() const { | ||
| 38 | return m_process; | ||
| 39 | } | ||
| 40 | |||
| 41 | private: | ||
| 42 | Core::System& m_system; | ||
| 43 | Kernel::KProcess* m_process{}; | ||
| 44 | s32 m_main_thread_priority{}; | ||
| 45 | u64 m_main_thread_stack_size{}; | ||
| 46 | u64 m_program_id{}; | ||
| 47 | bool m_process_started{}; | ||
| 48 | }; | ||
| 49 | |||
| 50 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp new file mode 100644 index 000000000..b48b52797 --- /dev/null +++ b/src/core/hle/service/am/process_winding_controller.cpp | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/frontend/applets.h" | ||
| 5 | #include "core/hle/service/am/library_applet_accessor.h" | ||
| 6 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | IProcessWindingController::IProcessWindingController(Core::System& system_, | ||
| 12 | std::shared_ptr<Applet> applet_) | ||
| 13 | : ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} { | ||
| 14 | // clang-format off | ||
| 15 | static const FunctionInfo functions[] = { | ||
| 16 | {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, | ||
| 17 | {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"}, | ||
| 18 | {21, nullptr, "PushContext"}, | ||
| 19 | {22, nullptr, "PopContext"}, | ||
| 20 | {23, nullptr, "CancelWindingReservation"}, | ||
| 21 | {30, nullptr, "WindAndDoReserved"}, | ||
| 22 | {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, | ||
| 23 | {41, nullptr, "ReserveToStartAndWait"}, | ||
| 24 | }; | ||
| 25 | // clang-format on | ||
| 26 | |||
| 27 | RegisterHandlers(functions); | ||
| 28 | } | ||
| 29 | |||
| 30 | IProcessWindingController::~IProcessWindingController() = default; | ||
| 31 | |||
| 32 | void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { | ||
| 33 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 34 | |||
| 35 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 36 | rb.Push(ResultSuccess); | ||
| 37 | rb.PushRaw(applet->launch_reason); | ||
| 38 | } | ||
| 39 | |||
| 40 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { | ||
| 41 | const auto caller_applet = applet->caller_applet.lock(); | ||
| 42 | if (caller_applet == nullptr) { | ||
| 43 | LOG_ERROR(Service_AM, "No calling applet available"); | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(ResultUnknown); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 51 | rb.Push(ResultSuccess); | ||
| 52 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_broker, | ||
| 53 | caller_applet); | ||
| 54 | } | ||
| 55 | |||
| 56 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h new file mode 100644 index 000000000..71ae4c4f5 --- /dev/null +++ b/src/core/hle/service/am/process_winding_controller.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { | ||
| 13 | public: | ||
| 14 | explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 15 | ~IProcessWindingController() override; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetLaunchReason(HLERequestContext& ctx); | ||
| 19 | void OpenCallingLibraryApplet(HLERequestContext& ctx); | ||
| 20 | |||
| 21 | const std::shared_ptr<Applet> applet; | ||
| 22 | }; | ||
| 23 | |||
| 24 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp new file mode 100644 index 000000000..0289f5cf1 --- /dev/null +++ b/src/core/hle/service/am/self_controller.cpp | |||
| @@ -0,0 +1,456 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/am_results.h" | ||
| 5 | #include "core/hle/service/am/frontend/applets.h" | ||
| 6 | #include "core/hle/service/am/self_controller.h" | ||
| 7 | #include "core/hle/service/caps/caps_su.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | ||
| 9 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 10 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 11 | #include "core/hle/service/sm/sm.h" | ||
| 12 | #include "core/hle/service/vi/vi_results.h" | ||
| 13 | |||
| 14 | namespace Service::AM { | ||
| 15 | |||
| 16 | ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_, | ||
| 17 | Nvnflinger::Nvnflinger& nvnflinger_) | ||
| 18 | : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move( | ||
| 19 | applet_)} { | ||
| 20 | // clang-format off | ||
| 21 | static const FunctionInfo functions[] = { | ||
| 22 | {0, &ISelfController::Exit, "Exit"}, | ||
| 23 | {1, &ISelfController::LockExit, "LockExit"}, | ||
| 24 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | ||
| 25 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, | ||
| 26 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, | ||
| 27 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | ||
| 28 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | ||
| 29 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | ||
| 30 | {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, | ||
| 31 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | ||
| 32 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 33 | {15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"}, | ||
| 34 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | ||
| 35 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | ||
| 36 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | ||
| 37 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, | ||
| 38 | {20, nullptr, "SetDesirableKeyboardLayout"}, | ||
| 39 | {21, nullptr, "GetScreenShotProgramId"}, | ||
| 40 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | ||
| 41 | {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, | ||
| 42 | {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, | ||
| 43 | {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, | ||
| 44 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, | ||
| 45 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, | ||
| 46 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, | ||
| 47 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, | ||
| 48 | {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, | ||
| 49 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, | ||
| 50 | {61, nullptr, "SetMediaPlaybackState"}, | ||
| 51 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, | ||
| 52 | {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, | ||
| 53 | {64, nullptr, "SetInputDetectionSourceSet"}, | ||
| 54 | {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, | ||
| 55 | {66, nullptr, "GetCurrentIlluminance"}, | ||
| 56 | {67, nullptr, "IsIlluminanceAvailable"}, | ||
| 57 | {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, | ||
| 58 | {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, | ||
| 59 | {70, nullptr, "ReportMultimediaError"}, | ||
| 60 | {71, nullptr, "GetCurrentIlluminanceEx"}, | ||
| 61 | {72, nullptr, "SetInputDetectionPolicy"}, | ||
| 62 | {80, nullptr, "SetWirelessPriorityMode"}, | ||
| 63 | {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, | ||
| 64 | {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, | ||
| 65 | {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, | ||
| 66 | {110, nullptr, "SetApplicationAlbumUserData"}, | ||
| 67 | {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, | ||
| 68 | {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, | ||
| 69 | {1000, nullptr, "GetDebugStorageChannel"}, | ||
| 70 | }; | ||
| 71 | // clang-format on | ||
| 72 | |||
| 73 | RegisterHandlers(functions); | ||
| 74 | } | ||
| 75 | |||
| 76 | ISelfController::~ISelfController() = default; | ||
| 77 | |||
| 78 | void ISelfController::Exit(HLERequestContext& ctx) { | ||
| 79 | LOG_DEBUG(Service_AM, "called"); | ||
| 80 | |||
| 81 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 82 | rb.Push(ResultSuccess); | ||
| 83 | |||
| 84 | // TODO | ||
| 85 | system.Exit(); | ||
| 86 | } | ||
| 87 | |||
| 88 | void ISelfController::LockExit(HLERequestContext& ctx) { | ||
| 89 | LOG_DEBUG(Service_AM, "called"); | ||
| 90 | |||
| 91 | system.SetExitLocked(true); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 94 | rb.Push(ResultSuccess); | ||
| 95 | } | ||
| 96 | |||
| 97 | void ISelfController::UnlockExit(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_AM, "called"); | ||
| 99 | |||
| 100 | system.SetExitLocked(false); | ||
| 101 | |||
| 102 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 103 | rb.Push(ResultSuccess); | ||
| 104 | |||
| 105 | if (system.GetExitRequested()) { | ||
| 106 | system.Exit(); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | void ISelfController::EnterFatalSection(HLERequestContext& ctx) { | ||
| 111 | |||
| 112 | std::scoped_lock lk{applet->lock}; | ||
| 113 | applet->fatal_section_count++; | ||
| 114 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count); | ||
| 115 | |||
| 116 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 117 | rb.Push(ResultSuccess); | ||
| 118 | } | ||
| 119 | |||
| 120 | void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { | ||
| 121 | LOG_DEBUG(Service_AM, "called."); | ||
| 122 | |||
| 123 | // Entry and exit of fatal sections must be balanced. | ||
| 124 | std::scoped_lock lk{applet->lock}; | ||
| 125 | if (applet->fatal_section_count == 0) { | ||
| 126 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(AM::ResultFatalSectionCountImbalance); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | applet->fatal_section_count--; | ||
| 132 | |||
| 133 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 134 | rb.Push(ResultSuccess); | ||
| 135 | } | ||
| 136 | |||
| 137 | void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { | ||
| 138 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 139 | |||
| 140 | applet->library_applet_launchable_event.Signal(); | ||
| 141 | |||
| 142 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 143 | rb.Push(ResultSuccess); | ||
| 144 | rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle()); | ||
| 145 | } | ||
| 146 | |||
| 147 | void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { | ||
| 148 | IPC::RequestParser rp{ctx}; | ||
| 149 | const auto permission = rp.PopEnum<ScreenshotPermission>(); | ||
| 150 | LOG_DEBUG(Service_AM, "called, permission={}", permission); | ||
| 151 | |||
| 152 | std::scoped_lock lk{applet->lock}; | ||
| 153 | applet->screenshot_permission = permission; | ||
| 154 | |||
| 155 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 156 | rb.Push(ResultSuccess); | ||
| 157 | } | ||
| 158 | |||
| 159 | void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { | ||
| 160 | IPC::RequestParser rp{ctx}; | ||
| 161 | |||
| 162 | const bool notification_enabled = rp.Pop<bool>(); | ||
| 163 | LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); | ||
| 164 | |||
| 165 | std::scoped_lock lk{applet->lock}; | ||
| 166 | applet->operation_mode_changed_notification_enabled = notification_enabled; | ||
| 167 | |||
| 168 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 169 | rb.Push(ResultSuccess); | ||
| 170 | } | ||
| 171 | |||
| 172 | void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { | ||
| 173 | IPC::RequestParser rp{ctx}; | ||
| 174 | |||
| 175 | const bool notification_enabled = rp.Pop<bool>(); | ||
| 176 | LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); | ||
| 177 | |||
| 178 | std::scoped_lock lk{applet->lock}; | ||
| 179 | applet->performance_mode_changed_notification_enabled = notification_enabled; | ||
| 180 | |||
| 181 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 182 | rb.Push(ResultSuccess); | ||
| 183 | } | ||
| 184 | |||
| 185 | void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { | ||
| 186 | IPC::RequestParser rp{ctx}; | ||
| 187 | |||
| 188 | const auto flags = rp.PopRaw<FocusHandlingMode>(); | ||
| 189 | |||
| 190 | LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", | ||
| 191 | flags.unknown0, flags.unknown1, flags.unknown2); | ||
| 192 | |||
| 193 | std::scoped_lock lk{applet->lock}; | ||
| 194 | applet->focus_handling_mode = flags; | ||
| 195 | |||
| 196 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 197 | rb.Push(ResultSuccess); | ||
| 198 | } | ||
| 199 | |||
| 200 | void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { | ||
| 201 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 202 | |||
| 203 | std::scoped_lock lk{applet->lock}; | ||
| 204 | applet->restart_message_enabled = true; | ||
| 205 | |||
| 206 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 207 | rb.Push(ResultSuccess); | ||
| 208 | } | ||
| 209 | |||
| 210 | void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) { | ||
| 211 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 212 | |||
| 213 | IPC::RequestParser rp{ctx}; | ||
| 214 | std::scoped_lock lk{applet->lock}; | ||
| 215 | applet->screen_shot_identity = rp.PopRaw<AppletIdentityInfo>(); | ||
| 216 | |||
| 217 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 218 | rb.Push(ResultSuccess); | ||
| 219 | } | ||
| 220 | |||
| 221 | void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { | ||
| 222 | IPC::RequestParser rp{ctx}; | ||
| 223 | |||
| 224 | const bool enabled = rp.Pop<bool>(); | ||
| 225 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 226 | |||
| 227 | std::scoped_lock lk{applet->lock}; | ||
| 228 | ASSERT(applet->type == AppletType::Application); | ||
| 229 | applet->out_of_focus_suspension_enabled = enabled; | ||
| 230 | |||
| 231 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 232 | rb.Push(ResultSuccess); | ||
| 233 | } | ||
| 234 | |||
| 235 | void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { | ||
| 236 | IPC::RequestParser rp{ctx}; | ||
| 237 | |||
| 238 | const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>(); | ||
| 239 | LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation)); | ||
| 240 | |||
| 241 | std::scoped_lock lk{applet->lock}; | ||
| 242 | applet->album_image_orientation = orientation; | ||
| 243 | |||
| 244 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 245 | rb.Push(ResultSuccess); | ||
| 246 | } | ||
| 247 | |||
| 248 | void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { | ||
| 249 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 250 | |||
| 251 | u64 layer_id{}; | ||
| 252 | applet->managed_layer_holder.Initialize(&nvnflinger); | ||
| 253 | applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id); | ||
| 254 | |||
| 255 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 256 | rb.Push(ResultSuccess); | ||
| 257 | rb.Push(layer_id); | ||
| 258 | } | ||
| 259 | |||
| 260 | void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { | ||
| 261 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 262 | |||
| 263 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 264 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 265 | } | ||
| 266 | |||
| 267 | void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { | ||
| 268 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 269 | |||
| 270 | u64 buffer_id, layer_id; | ||
| 271 | applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); | ||
| 272 | |||
| 273 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 274 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 275 | rb.Push<s64>(buffer_id); | ||
| 276 | rb.Push<s64>(layer_id); | ||
| 277 | } | ||
| 278 | |||
| 279 | void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { | ||
| 280 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 281 | |||
| 282 | u64 buffer_id, layer_id; | ||
| 283 | applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); | ||
| 284 | |||
| 285 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 286 | rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); | ||
| 287 | rb.Push<s64>(buffer_id); | ||
| 288 | } | ||
| 289 | |||
| 290 | Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { | ||
| 291 | if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) { | ||
| 292 | return ResultSuccess; | ||
| 293 | } | ||
| 294 | |||
| 295 | return VI::ResultOperationFailed; | ||
| 296 | } | ||
| 297 | |||
| 298 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { | ||
| 299 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 300 | |||
| 301 | u64 layer_id{}; | ||
| 302 | u64 recording_layer_id{}; | ||
| 303 | applet->managed_layer_holder.Initialize(&nvnflinger); | ||
| 304 | applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id); | ||
| 305 | |||
| 306 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 307 | rb.Push(ResultSuccess); | ||
| 308 | rb.Push(layer_id); | ||
| 309 | rb.Push(recording_layer_id); | ||
| 310 | } | ||
| 311 | |||
| 312 | void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { | ||
| 313 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 314 | |||
| 315 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 316 | rb.Push(ResultSuccess); | ||
| 317 | } | ||
| 318 | |||
| 319 | void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { | ||
| 320 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 321 | |||
| 322 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 323 | rb.Push(ResultSuccess); | ||
| 324 | } | ||
| 325 | |||
| 326 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 327 | IPC::RequestParser rp{ctx}; | ||
| 328 | |||
| 329 | const auto extension = rp.PopRaw<IdleTimeDetectionExtension>(); | ||
| 330 | LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension); | ||
| 331 | |||
| 332 | std::scoped_lock lk{applet->lock}; | ||
| 333 | applet->idle_time_detection_extension = extension; | ||
| 334 | |||
| 335 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 336 | rb.Push(ResultSuccess); | ||
| 337 | } | ||
| 338 | |||
| 339 | void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { | ||
| 340 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 341 | |||
| 342 | std::scoped_lock lk{applet->lock}; | ||
| 343 | |||
| 344 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 345 | rb.Push(ResultSuccess); | ||
| 346 | rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension); | ||
| 347 | } | ||
| 348 | |||
| 349 | void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { | ||
| 350 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 351 | |||
| 352 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 353 | rb.Push(ResultSuccess); | ||
| 354 | } | ||
| 355 | |||
| 356 | void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 357 | IPC::RequestParser rp{ctx}; | ||
| 358 | |||
| 359 | std::scoped_lock lk{applet->lock}; | ||
| 360 | applet->auto_sleep_disabled = rp.Pop<bool>(); | ||
| 361 | |||
| 362 | // On the system itself, if the previous state of is_auto_sleep_disabled | ||
| 363 | // differed from the current value passed in, it'd signify the internal | ||
| 364 | // window manager to update (and also increment some statistics like update counts) | ||
| 365 | // | ||
| 366 | // It'd also indicate this change to an idle handling context. | ||
| 367 | // | ||
| 368 | // However, given we're emulating this behavior, most of this can be ignored | ||
| 369 | // and it's sufficient to simply set the member variable for querying via | ||
| 370 | // IsAutoSleepDisabled(). | ||
| 371 | |||
| 372 | LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled); | ||
| 373 | |||
| 374 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 375 | rb.Push(ResultSuccess); | ||
| 376 | } | ||
| 377 | |||
| 378 | void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { | ||
| 379 | LOG_DEBUG(Service_AM, "called."); | ||
| 380 | |||
| 381 | std::scoped_lock lk{applet->lock}; | ||
| 382 | |||
| 383 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 384 | rb.Push(ResultSuccess); | ||
| 385 | rb.Push(applet->auto_sleep_disabled); | ||
| 386 | } | ||
| 387 | |||
| 388 | void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { | ||
| 389 | LOG_DEBUG(Service_AM, "called."); | ||
| 390 | |||
| 391 | std::scoped_lock lk{applet->lock}; | ||
| 392 | // This command returns the total number of system ticks since ISelfController creation | ||
| 393 | // where the game was suspended. Since Yuzu doesn't implement game suspension, this command | ||
| 394 | // can just always return 0 ticks. | ||
| 395 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 396 | rb.Push(ResultSuccess); | ||
| 397 | rb.Push<u64>(applet->suspended_ticks); | ||
| 398 | } | ||
| 399 | |||
| 400 | void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { | ||
| 401 | LOG_DEBUG(Service_AM, "called."); | ||
| 402 | |||
| 403 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 404 | rb.Push(ResultSuccess); | ||
| 405 | rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle()); | ||
| 406 | } | ||
| 407 | |||
| 408 | void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { | ||
| 409 | IPC::RequestParser rp{ctx}; | ||
| 410 | |||
| 411 | // This service call sets an internal flag whether a notification is shown when an image is | ||
| 412 | // captured. Currently we do not support capturing images via the capture button, so this can be | ||
| 413 | // stubbed for now. | ||
| 414 | const bool enabled = rp.Pop<bool>(); | ||
| 415 | LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); | ||
| 416 | |||
| 417 | std::scoped_lock lk{applet->lock}; | ||
| 418 | applet->album_image_taken_notification_enabled = enabled; | ||
| 419 | |||
| 420 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 421 | rb.Push(ResultSuccess); | ||
| 422 | } | ||
| 423 | |||
| 424 | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | ||
| 425 | IPC::RequestParser rp{ctx}; | ||
| 426 | |||
| 427 | const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); | ||
| 428 | |||
| 429 | LOG_INFO(Service_AM, "called, report_option={}", report_option); | ||
| 430 | |||
| 431 | const auto screenshot_service = | ||
| 432 | system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( | ||
| 433 | "caps:su"); | ||
| 434 | |||
| 435 | if (screenshot_service) { | ||
| 436 | screenshot_service->CaptureAndSaveScreenshot(report_option); | ||
| 437 | } | ||
| 438 | |||
| 439 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 440 | rb.Push(ResultSuccess); | ||
| 441 | } | ||
| 442 | |||
| 443 | void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { | ||
| 444 | IPC::RequestParser rp{ctx}; | ||
| 445 | |||
| 446 | const auto enabled = rp.Pop<bool>(); | ||
| 447 | LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); | ||
| 448 | |||
| 449 | std::scoped_lock lk{applet->lock}; | ||
| 450 | applet->record_volume_muted = enabled; | ||
| 451 | |||
| 452 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 453 | rb.Push(ResultSuccess); | ||
| 454 | } | ||
| 455 | |||
| 456 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h new file mode 100644 index 000000000..a63bc2e74 --- /dev/null +++ b/src/core/hle/service/am/self_controller.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | struct Applet; | ||
| 12 | |||
| 13 | class ISelfController final : public ServiceFramework<ISelfController> { | ||
| 14 | public: | ||
| 15 | explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_, | ||
| 16 | Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 17 | ~ISelfController() override; | ||
| 18 | |||
| 19 | private: | ||
| 20 | void Exit(HLERequestContext& ctx); | ||
| 21 | void LockExit(HLERequestContext& ctx); | ||
| 22 | void UnlockExit(HLERequestContext& ctx); | ||
| 23 | void EnterFatalSection(HLERequestContext& ctx); | ||
| 24 | void LeaveFatalSection(HLERequestContext& ctx); | ||
| 25 | void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); | ||
| 26 | void SetScreenShotPermission(HLERequestContext& ctx); | ||
| 27 | void SetOperationModeChangedNotification(HLERequestContext& ctx); | ||
| 28 | void SetPerformanceModeChangedNotification(HLERequestContext& ctx); | ||
| 29 | void SetFocusHandlingMode(HLERequestContext& ctx); | ||
| 30 | void SetRestartMessageEnabled(HLERequestContext& ctx); | ||
| 31 | void SetScreenShotAppletIdentityInfo(HLERequestContext& ctx); | ||
| 32 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); | ||
| 33 | void SetAlbumImageOrientation(HLERequestContext& ctx); | ||
| 34 | void IsSystemBufferSharingEnabled(HLERequestContext& ctx); | ||
| 35 | void GetSystemSharedBufferHandle(HLERequestContext& ctx); | ||
| 36 | void GetSystemSharedLayerHandle(HLERequestContext& ctx); | ||
| 37 | void CreateManagedDisplayLayer(HLERequestContext& ctx); | ||
| 38 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); | ||
| 39 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); | ||
| 40 | void ApproveToDisplay(HLERequestContext& ctx); | ||
| 41 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 42 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); | ||
| 43 | void ReportUserIsActive(HLERequestContext& ctx); | ||
| 44 | void SetAutoSleepDisabled(HLERequestContext& ctx); | ||
| 45 | void IsAutoSleepDisabled(HLERequestContext& ctx); | ||
| 46 | void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); | ||
| 47 | void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); | ||
| 48 | void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); | ||
| 49 | void SaveCurrentScreenshot(HLERequestContext& ctx); | ||
| 50 | void SetRecordVolumeMuted(HLERequestContext& ctx); | ||
| 51 | |||
| 52 | Result EnsureBufferSharingEnabled(Kernel::KProcess* process); | ||
| 53 | |||
| 54 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 55 | const std::shared_ptr<Applet> applet; | ||
| 56 | }; | ||
| 57 | |||
| 58 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp new file mode 100644 index 000000000..4e82afd1c --- /dev/null +++ b/src/core/hle/service/am/storage.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/am_results.h" | ||
| 5 | #include "core/hle/service/am/library_applet_storage.h" | ||
| 6 | #include "core/hle/service/am/storage.h" | ||
| 7 | #include "core/hle/service/am/storage_accessor.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | ||
| 9 | |||
| 10 | namespace Service::AM { | ||
| 11 | |||
| 12 | IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_) | ||
| 13 | : ServiceFramework{system_, "IStorage"}, impl{std::move(impl_)} { | ||
| 14 | static const FunctionInfo functions[] = { | ||
| 15 | {0, &IStorage::Open, "Open"}, | ||
| 16 | {1, &IStorage::OpenTransferStorage, "OpenTransferStorage"}, | ||
| 17 | }; | ||
| 18 | |||
| 19 | RegisterHandlers(functions); | ||
| 20 | } | ||
| 21 | |||
| 22 | IStorage::IStorage(Core::System& system_, std::vector<u8>&& data) | ||
| 23 | : IStorage(system_, CreateStorage(std::move(data))) {} | ||
| 24 | |||
| 25 | IStorage::~IStorage() = default; | ||
| 26 | |||
| 27 | void IStorage::Open(HLERequestContext& ctx) { | ||
| 28 | LOG_DEBUG(Service_AM, "called"); | ||
| 29 | |||
| 30 | if (impl->GetHandle() != nullptr) { | ||
| 31 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 32 | rb.Push(AM::ResultInvalidStorageType); | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | |||
| 36 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 37 | rb.Push(ResultSuccess); | ||
| 38 | rb.PushIpcInterface<IStorageAccessor>(system, impl); | ||
| 39 | } | ||
| 40 | |||
| 41 | void IStorage::OpenTransferStorage(HLERequestContext& ctx) { | ||
| 42 | LOG_DEBUG(Service_AM, "called"); | ||
| 43 | |||
| 44 | if (impl->GetHandle() == nullptr) { | ||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(AM::ResultInvalidStorageType); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 51 | rb.Push(ResultSuccess); | ||
| 52 | rb.PushIpcInterface<ITransferStorageAccessor>(system, impl); | ||
| 53 | } | ||
| 54 | |||
| 55 | std::vector<u8> IStorage::GetData() const { | ||
| 56 | return impl->GetData(); | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h new file mode 100644 index 000000000..10d00b141 --- /dev/null +++ b/src/core/hle/service/am/storage.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | class LibraryAppletStorage; | ||
| 11 | |||
| 12 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 13 | public: | ||
| 14 | explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_); | ||
| 15 | explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); | ||
| 16 | ~IStorage() override; | ||
| 17 | |||
| 18 | std::shared_ptr<LibraryAppletStorage> GetImpl() const { | ||
| 19 | return impl; | ||
| 20 | } | ||
| 21 | |||
| 22 | std::vector<u8> GetData() const; | ||
| 23 | |||
| 24 | private: | ||
| 25 | void Open(HLERequestContext& ctx); | ||
| 26 | void OpenTransferStorage(HLERequestContext& ctx); | ||
| 27 | |||
| 28 | const std::shared_ptr<LibraryAppletStorage> impl; | ||
| 29 | }; | ||
| 30 | |||
| 31 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp new file mode 100644 index 000000000..a1184b065 --- /dev/null +++ b/src/core/hle/service/am/storage_accessor.cpp | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 5 | #include "core/hle/service/am/am_results.h" | ||
| 6 | #include "core/hle/service/am/library_applet_storage.h" | ||
| 7 | #include "core/hle/service/am/storage_accessor.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | ||
| 9 | |||
| 10 | namespace Service::AM { | ||
| 11 | |||
| 12 | IStorageAccessor::IStorageAccessor(Core::System& system_, | ||
| 13 | std::shared_ptr<LibraryAppletStorage> impl_) | ||
| 14 | : ServiceFramework{system_, "IStorageAccessor"}, impl{std::move(impl_)} { | ||
| 15 | static const FunctionInfo functions[] = { | ||
| 16 | {0, &IStorageAccessor::GetSize, "GetSize"}, | ||
| 17 | {10, &IStorageAccessor::Write, "Write"}, | ||
| 18 | {11, &IStorageAccessor::Read, "Read"}, | ||
| 19 | }; | ||
| 20 | |||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | IStorageAccessor::~IStorageAccessor() = default; | ||
| 25 | |||
| 26 | void IStorageAccessor::GetSize(HLERequestContext& ctx) { | ||
| 27 | LOG_DEBUG(Service_AM, "called"); | ||
| 28 | |||
| 29 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 30 | |||
| 31 | rb.Push(ResultSuccess); | ||
| 32 | rb.Push(impl->GetSize()); | ||
| 33 | } | ||
| 34 | |||
| 35 | void IStorageAccessor::Write(HLERequestContext& ctx) { | ||
| 36 | IPC::RequestParser rp{ctx}; | ||
| 37 | |||
| 38 | const s64 offset{rp.Pop<s64>()}; | ||
| 39 | const auto data{ctx.ReadBuffer()}; | ||
| 40 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); | ||
| 41 | |||
| 42 | const auto res{impl->Write(offset, data.data(), data.size())}; | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 45 | rb.Push(res); | ||
| 46 | } | ||
| 47 | |||
| 48 | void IStorageAccessor::Read(HLERequestContext& ctx) { | ||
| 49 | IPC::RequestParser rp{ctx}; | ||
| 50 | |||
| 51 | const s64 offset{rp.Pop<s64>()}; | ||
| 52 | std::vector<u8> data(ctx.GetWriteBufferSize()); | ||
| 53 | |||
| 54 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); | ||
| 55 | |||
| 56 | const auto res{impl->Read(offset, data.data(), data.size())}; | ||
| 57 | |||
| 58 | ctx.WriteBuffer(data); | ||
| 59 | |||
| 60 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 61 | rb.Push(res); | ||
| 62 | } | ||
| 63 | |||
| 64 | ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_, | ||
| 65 | std::shared_ptr<LibraryAppletStorage> impl_) | ||
| 66 | : ServiceFramework{system_, "ITransferStorageAccessor"}, impl{std::move(impl_)} { | ||
| 67 | static const FunctionInfo functions[] = { | ||
| 68 | {0, &ITransferStorageAccessor::GetSize, "GetSize"}, | ||
| 69 | {1, &ITransferStorageAccessor::GetHandle, "GetHandle"}, | ||
| 70 | }; | ||
| 71 | |||
| 72 | RegisterHandlers(functions); | ||
| 73 | } | ||
| 74 | |||
| 75 | ITransferStorageAccessor::~ITransferStorageAccessor() = default; | ||
| 76 | |||
| 77 | void ITransferStorageAccessor::GetSize(HLERequestContext& ctx) { | ||
| 78 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 79 | rb.Push(ResultSuccess); | ||
| 80 | rb.Push(impl->GetSize()); | ||
| 81 | } | ||
| 82 | |||
| 83 | void ITransferStorageAccessor::GetHandle(HLERequestContext& ctx) { | ||
| 84 | IPC::ResponseBuilder rb{ctx, 4, 1}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | rb.Push(impl->GetSize()); | ||
| 87 | rb.PushCopyObjects(impl->GetHandle()); | ||
| 88 | } | ||
| 89 | |||
| 90 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h new file mode 100644 index 000000000..b9aa85a66 --- /dev/null +++ b/src/core/hle/service/am/storage_accessor.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/storage.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | ||
| 12 | public: | ||
| 13 | explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_); | ||
| 14 | ~IStorageAccessor() override; | ||
| 15 | |||
| 16 | private: | ||
| 17 | void GetSize(HLERequestContext& ctx); | ||
| 18 | void Write(HLERequestContext& ctx); | ||
| 19 | void Read(HLERequestContext& ctx); | ||
| 20 | |||
| 21 | const std::shared_ptr<LibraryAppletStorage> impl; | ||
| 22 | }; | ||
| 23 | |||
| 24 | class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> { | ||
| 25 | public: | ||
| 26 | explicit ITransferStorageAccessor(Core::System& system_, | ||
| 27 | std::shared_ptr<LibraryAppletStorage> impl_); | ||
| 28 | ~ITransferStorageAccessor() override; | ||
| 29 | |||
| 30 | private: | ||
| 31 | void GetSize(HLERequestContext& ctx); | ||
| 32 | void GetHandle(HLERequestContext& ctx); | ||
| 33 | |||
| 34 | const std::shared_ptr<LibraryAppletStorage> impl; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp new file mode 100644 index 000000000..38643408e --- /dev/null +++ b/src/core/hle/service/am/system_applet_proxy.cpp | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet_common_functions.h" | ||
| 5 | #include "core/hle/service/am/application_creator.h" | ||
| 6 | #include "core/hle/service/am/audio_controller.h" | ||
| 7 | #include "core/hle/service/am/common_state_getter.h" | ||
| 8 | #include "core/hle/service/am/debug_functions.h" | ||
| 9 | #include "core/hle/service/am/display_controller.h" | ||
| 10 | #include "core/hle/service/am/global_state_controller.h" | ||
| 11 | #include "core/hle/service/am/home_menu_functions.h" | ||
| 12 | #include "core/hle/service/am/library_applet_creator.h" | ||
| 13 | #include "core/hle/service/am/library_applet_self_accessor.h" | ||
| 14 | #include "core/hle/service/am/process_winding_controller.h" | ||
| 15 | #include "core/hle/service/am/self_controller.h" | ||
| 16 | #include "core/hle/service/am/system_applet_proxy.h" | ||
| 17 | #include "core/hle/service/am/window_controller.h" | ||
| 18 | #include "core/hle/service/ipc_helpers.h" | ||
| 19 | |||
| 20 | namespace Service::AM { | ||
| 21 | |||
| 22 | ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 23 | std::shared_ptr<Applet> applet_, Core::System& system_) | ||
| 24 | : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( | ||
| 25 | applet_)} { | ||
| 26 | // clang-format off | ||
| 27 | static const FunctionInfo functions[] = { | ||
| 28 | {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, | ||
| 29 | {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, | ||
| 30 | {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"}, | ||
| 31 | {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"}, | ||
| 32 | {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"}, | ||
| 33 | {10, nullptr, "GetProcessWindingController"}, | ||
| 34 | {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | ||
| 35 | {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, | ||
| 36 | {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, | ||
| 37 | {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, | ||
| 38 | {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, | ||
| 39 | {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | ||
| 40 | }; | ||
| 41 | // clang-format on | ||
| 42 | |||
| 43 | RegisterHandlers(functions); | ||
| 44 | } | ||
| 45 | |||
| 46 | ISystemAppletProxy::~ISystemAppletProxy() = default; | ||
| 47 | |||
| 48 | void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { | ||
| 49 | LOG_DEBUG(Service_AM, "called"); | ||
| 50 | |||
| 51 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 52 | rb.Push(ResultSuccess); | ||
| 53 | rb.PushIpcInterface<ICommonStateGetter>(system, applet); | ||
| 54 | } | ||
| 55 | |||
| 56 | void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { | ||
| 57 | LOG_DEBUG(Service_AM, "called"); | ||
| 58 | |||
| 59 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 60 | rb.Push(ResultSuccess); | ||
| 61 | rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); | ||
| 62 | } | ||
| 63 | |||
| 64 | void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { | ||
| 65 | LOG_DEBUG(Service_AM, "called"); | ||
| 66 | |||
| 67 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 68 | rb.Push(ResultSuccess); | ||
| 69 | rb.PushIpcInterface<IWindowController>(system, applet); | ||
| 70 | } | ||
| 71 | |||
| 72 | void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) { | ||
| 73 | LOG_DEBUG(Service_AM, "called"); | ||
| 74 | |||
| 75 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 76 | rb.Push(ResultSuccess); | ||
| 77 | rb.PushIpcInterface<IAudioController>(system); | ||
| 78 | } | ||
| 79 | |||
| 80 | void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) { | ||
| 81 | LOG_DEBUG(Service_AM, "called"); | ||
| 82 | |||
| 83 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 84 | rb.Push(ResultSuccess); | ||
| 85 | rb.PushIpcInterface<IDisplayController>(system, applet); | ||
| 86 | } | ||
| 87 | |||
| 88 | void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { | ||
| 89 | LOG_DEBUG(Service_AM, "called"); | ||
| 90 | |||
| 91 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 92 | rb.Push(ResultSuccess); | ||
| 93 | rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); | ||
| 94 | } | ||
| 95 | |||
| 96 | void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { | ||
| 97 | LOG_DEBUG(Service_AM, "called"); | ||
| 98 | |||
| 99 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 100 | rb.Push(ResultSuccess); | ||
| 101 | rb.PushIpcInterface<IHomeMenuFunctions>(system); | ||
| 102 | } | ||
| 103 | |||
| 104 | void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { | ||
| 105 | LOG_DEBUG(Service_AM, "called"); | ||
| 106 | |||
| 107 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 108 | rb.Push(ResultSuccess); | ||
| 109 | rb.PushIpcInterface<IGlobalStateController>(system); | ||
| 110 | } | ||
| 111 | |||
| 112 | void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) { | ||
| 113 | LOG_DEBUG(Service_AM, "called"); | ||
| 114 | |||
| 115 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 116 | rb.Push(ResultSuccess); | ||
| 117 | rb.PushIpcInterface<IApplicationCreator>(system); | ||
| 118 | } | ||
| 119 | |||
| 120 | void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { | ||
| 121 | LOG_DEBUG(Service_AM, "called"); | ||
| 122 | |||
| 123 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 124 | rb.Push(ResultSuccess); | ||
| 125 | rb.PushIpcInterface<IAppletCommonFunctions>(system, applet); | ||
| 126 | } | ||
| 127 | |||
| 128 | void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { | ||
| 129 | LOG_DEBUG(Service_AM, "called"); | ||
| 130 | |||
| 131 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 132 | rb.Push(ResultSuccess); | ||
| 133 | rb.PushIpcInterface<IDebugFunctions>(system); | ||
| 134 | } | ||
| 135 | |||
| 136 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h new file mode 100644 index 000000000..0390cd1e5 --- /dev/null +++ b/src/core/hle/service/am/system_applet_proxy.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | struct Applet; | ||
| 12 | |||
| 13 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | ||
| 14 | public: | ||
| 15 | explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 16 | std::shared_ptr<Applet> applet_, Core::System& system_); | ||
| 17 | ~ISystemAppletProxy(); | ||
| 18 | |||
| 19 | private: | ||
| 20 | void GetCommonStateGetter(HLERequestContext& ctx); | ||
| 21 | void GetSelfController(HLERequestContext& ctx); | ||
| 22 | void GetWindowController(HLERequestContext& ctx); | ||
| 23 | void GetAudioController(HLERequestContext& ctx); | ||
| 24 | void GetDisplayController(HLERequestContext& ctx); | ||
| 25 | void GetLibraryAppletCreator(HLERequestContext& ctx); | ||
| 26 | void GetHomeMenuFunctions(HLERequestContext& ctx); | ||
| 27 | void GetGlobalStateController(HLERequestContext& ctx); | ||
| 28 | void GetApplicationCreator(HLERequestContext& ctx); | ||
| 29 | void GetAppletCommonFunctions(HLERequestContext& ctx); | ||
| 30 | void GetDebugFunctions(HLERequestContext& ctx); | ||
| 31 | |||
| 32 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 33 | std::shared_ptr<Applet> applet; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp new file mode 100644 index 000000000..60a9afc9d --- /dev/null +++ b/src/core/hle/service/am/system_buffer_manager.cpp | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/system_buffer_manager.h" | ||
| 5 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 6 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 7 | #include "core/hle/service/vi/vi_results.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | SystemBufferManager::SystemBufferManager() = default; | ||
| 12 | |||
| 13 | SystemBufferManager::~SystemBufferManager() { | ||
| 14 | if (!m_nvnflinger) { | ||
| 15 | return; | ||
| 16 | } | ||
| 17 | |||
| 18 | // Clean up shared layers. | ||
| 19 | if (m_buffer_sharing_enabled) { | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, | ||
| 24 | AppletId applet_id) { | ||
| 25 | if (m_nvnflinger) { | ||
| 26 | return m_buffer_sharing_enabled; | ||
| 27 | } | ||
| 28 | |||
| 29 | m_process = process; | ||
| 30 | m_nvnflinger = nvnflinger; | ||
| 31 | m_buffer_sharing_enabled = false; | ||
| 32 | m_system_shared_buffer_id = 0; | ||
| 33 | m_system_shared_layer_id = 0; | ||
| 34 | |||
| 35 | if (applet_id <= AppletId::Application) { | ||
| 36 | return false; | ||
| 37 | } | ||
| 38 | |||
| 39 | const auto display_id = m_nvnflinger->OpenDisplay("Default").value(); | ||
| 40 | const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( | ||
| 41 | &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id); | ||
| 42 | |||
| 43 | if (res.IsSuccess()) { | ||
| 44 | m_buffer_sharing_enabled = true; | ||
| 45 | m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); | ||
| 46 | } | ||
| 47 | |||
| 48 | return m_buffer_sharing_enabled; | ||
| 49 | } | ||
| 50 | |||
| 51 | void SystemBufferManager::SetWindowVisibility(bool visible) { | ||
| 52 | if (m_visible == visible) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | m_visible = visible; | ||
| 57 | |||
| 58 | if (m_nvnflinger) { | ||
| 59 | m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, | ||
| 64 | s32* out_fbshare_layer_index) { | ||
| 65 | // TODO | ||
| 66 | R_SUCCEED(); | ||
| 67 | } | ||
| 68 | |||
| 69 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h new file mode 100644 index 000000000..98c3cf055 --- /dev/null +++ b/src/core/hle/service/am/system_buffer_manager.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <set> | ||
| 7 | |||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | #include "core/hle/service/am/am_types.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | class KProcess; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Service::Nvnflinger { | ||
| 18 | class Nvnflinger; | ||
| 19 | } | ||
| 20 | |||
| 21 | union Result; | ||
| 22 | |||
| 23 | namespace Service::AM { | ||
| 24 | |||
| 25 | class SystemBufferManager { | ||
| 26 | public: | ||
| 27 | SystemBufferManager(); | ||
| 28 | ~SystemBufferManager(); | ||
| 29 | |||
| 30 | bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id); | ||
| 31 | |||
| 32 | void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, | ||
| 33 | u64* out_system_shared_layer_id) { | ||
| 34 | *out_system_shared_buffer_id = m_system_shared_buffer_id; | ||
| 35 | *out_system_shared_layer_id = m_system_shared_layer_id; | ||
| 36 | } | ||
| 37 | |||
| 38 | void SetWindowVisibility(bool visible); | ||
| 39 | |||
| 40 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); | ||
| 41 | |||
| 42 | private: | ||
| 43 | Kernel::KProcess* m_process{}; | ||
| 44 | Nvnflinger::Nvnflinger* m_nvnflinger{}; | ||
| 45 | bool m_buffer_sharing_enabled{}; | ||
| 46 | bool m_visible{true}; | ||
| 47 | u64 m_system_shared_buffer_id{}; | ||
| 48 | u64 m_system_shared_layer_id{}; | ||
| 49 | }; | ||
| 50 | |||
| 51 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp new file mode 100644 index 000000000..f00957f83 --- /dev/null +++ b/src/core/hle/service/am/window_controller.cpp | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/applet.h" | ||
| 5 | #include "core/hle/service/am/window_controller.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_) | ||
| 11 | : ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {0, nullptr, "CreateWindow"}, | ||
| 15 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | ||
| 16 | {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 17 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | ||
| 18 | {11, nullptr, "ReleaseForegroundRights"}, | ||
| 19 | {12, nullptr, "RejectToChangeIntoBackground"}, | ||
| 20 | {20, &IWindowController::SetAppletWindowVisibility, "SetAppletWindowVisibility"}, | ||
| 21 | {21, &IWindowController::SetAppletGpuTimeSlice, "SetAppletGpuTimeSlice"}, | ||
| 22 | }; | ||
| 23 | // clang-format on | ||
| 24 | |||
| 25 | RegisterHandlers(functions); | ||
| 26 | } | ||
| 27 | |||
| 28 | IWindowController::~IWindowController() = default; | ||
| 29 | |||
| 30 | void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { | ||
| 31 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 32 | rb.Push(ResultSuccess); | ||
| 33 | rb.Push<u64>(applet->aruid); | ||
| 34 | } | ||
| 35 | |||
| 36 | void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { | ||
| 37 | u64 aruid = 0; | ||
| 38 | if (auto caller = applet->caller_applet.lock(); caller) { | ||
| 39 | aruid = caller->aruid; | ||
| 40 | } | ||
| 41 | |||
| 42 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.Push<u64>(aruid); | ||
| 47 | } | ||
| 48 | |||
| 49 | void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { | ||
| 50 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 51 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 52 | rb.Push(ResultSuccess); | ||
| 53 | } | ||
| 54 | |||
| 55 | void IWindowController::SetAppletWindowVisibility(HLERequestContext& ctx) { | ||
| 56 | LOG_INFO(Service_AM, "called"); | ||
| 57 | |||
| 58 | IPC::RequestParser rp{ctx}; | ||
| 59 | const bool visible = rp.Pop<bool>(); | ||
| 60 | |||
| 61 | applet->system_buffer_manager.SetWindowVisibility(visible); | ||
| 62 | applet->hid_registration.EnableAppletToGetInput(visible); | ||
| 63 | |||
| 64 | if (visible) { | ||
| 65 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | ||
| 66 | applet->focus_state = FocusState::InFocus; | ||
| 67 | } else { | ||
| 68 | applet->focus_state = FocusState::NotInFocus; | ||
| 69 | } | ||
| 70 | applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | ||
| 71 | |||
| 72 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 73 | rb.Push(ResultSuccess); | ||
| 74 | } | ||
| 75 | |||
| 76 | void IWindowController::SetAppletGpuTimeSlice(HLERequestContext& ctx) { | ||
| 77 | IPC::RequestParser rp{ctx}; | ||
| 78 | const auto time_slice = rp.Pop<s64>(); | ||
| 79 | |||
| 80 | LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice); | ||
| 81 | |||
| 82 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 83 | rb.Push(ResultSuccess); | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h new file mode 100644 index 000000000..a28219abe --- /dev/null +++ b/src/core/hle/service/am/window_controller.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/service.h" | ||
| 7 | |||
| 8 | namespace Service::AM { | ||
| 9 | |||
| 10 | struct Applet; | ||
| 11 | |||
| 12 | class IWindowController final : public ServiceFramework<IWindowController> { | ||
| 13 | public: | ||
| 14 | explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_); | ||
| 15 | ~IWindowController() override; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void GetAppletResourceUserId(HLERequestContext& ctx); | ||
| 19 | void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); | ||
| 20 | void AcquireForegroundRights(HLERequestContext& ctx); | ||
| 21 | void SetAppletWindowVisibility(HLERequestContext& ctx); | ||
| 22 | void SetAppletGpuTimeSlice(HLERequestContext& ctx); | ||
| 23 | |||
| 24 | const std::shared_ptr<Applet> applet; | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 7075ab800..486719cc0 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) { | |||
| 202 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, | 202 | LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, |
| 203 | process_id); | 203 | process_id); |
| 204 | 204 | ||
| 205 | const auto current = system.GetApplicationProcessProgramID(); | 205 | const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); |
| 206 | 206 | ||
| 207 | std::vector<u32> out; | 207 | std::vector<u32> out; |
| 208 | const auto& disabled = Settings::values.disabled_addons[current]; | 208 | const auto& disabled = Settings::values.disabled_addons[current]; |
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp index e3b8ecf3e..3a22b135f 100644 --- a/src/core/hle/service/caps/caps_manager.cpp +++ b/src/core/hle/service/caps/caps_manager.cpp | |||
| @@ -246,10 +246,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | |||
| 246 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 246 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 247 | 247 | ||
| 248 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; | 248 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; |
| 249 | static_service->GetStandardUserSystemClock(user_clock); | 249 | static_service->GetStandardUserSystemClock(&user_clock); |
| 250 | 250 | ||
| 251 | s64 posix_time{}; | 251 | s64 posix_time{}; |
| 252 | auto result = user_clock->GetCurrentTime(posix_time); | 252 | auto result = user_clock->GetCurrentTime(&posix_time); |
| 253 | 253 | ||
| 254 | if (result.IsError()) { | 254 | if (result.IsError()) { |
| 255 | return result; | 255 | return result; |
| @@ -268,10 +268,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, | |||
| 268 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 268 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 269 | 269 | ||
| 270 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; | 270 | std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; |
| 271 | static_service->GetStandardUserSystemClock(user_clock); | 271 | static_service->GetStandardUserSystemClock(&user_clock); |
| 272 | 272 | ||
| 273 | s64 posix_time{}; | 273 | s64 posix_time{}; |
| 274 | auto result = user_clock->GetCurrentTime(posix_time); | 274 | auto result = user_clock->GetCurrentTime(&posix_time); |
| 275 | 275 | ||
| 276 | if (result.IsError()) { | 276 | if (result.IsError()) { |
| 277 | return result; | 277 | return result; |
| @@ -470,11 +470,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const { | |||
| 470 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 470 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 471 | 471 | ||
| 472 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; | 472 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; |
| 473 | static_service->GetTimeZoneService(timezone_service); | 473 | static_service->GetTimeZoneService(&timezone_service); |
| 474 | 474 | ||
| 475 | Service::PSC::Time::CalendarTime calendar_time{}; | 475 | Service::PSC::Time::CalendarTime calendar_time{}; |
| 476 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; | 476 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; |
| 477 | timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time); | 477 | timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time); |
| 478 | 478 | ||
| 479 | return { | 479 | return { |
| 480 | .year = calendar_time.year, | 480 | .year = calendar_time.year, |
diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h index 9eb10e816..315475e71 100644 --- a/src/core/hle/service/cmif_serialization.h +++ b/src/core/hle/service/cmif_serialization.h | |||
| @@ -12,6 +12,109 @@ | |||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | 13 | ||
| 14 | // clang-format off | 14 | // clang-format off |
| 15 | template <typename T> | ||
| 16 | struct UnwrapArg { | ||
| 17 | using Type = std::remove_cvref_t<T>; | ||
| 18 | }; | ||
| 19 | |||
| 20 | template <typename T, int A> | ||
| 21 | struct UnwrapArg<InLargeData<T, A>> { | ||
| 22 | using Type = std::remove_cv_t<typename InLargeData<T, A>::Type>; | ||
| 23 | }; | ||
| 24 | |||
| 25 | template <typename T> | ||
| 26 | struct UnwrapArg<Out<T>> { | ||
| 27 | using Type = AutoOut<typename Out<T>::Type>; | ||
| 28 | }; | ||
| 29 | |||
| 30 | template <typename T> | ||
| 31 | struct UnwrapArg<OutCopyHandle<T>> { | ||
| 32 | using Type = AutoOut<typename OutCopyHandle<T>::Type>; | ||
| 33 | }; | ||
| 34 | |||
| 35 | template <typename T> | ||
| 36 | struct UnwrapArg<OutMoveHandle<T>> { | ||
| 37 | using Type = AutoOut<typename OutMoveHandle<T>::Type>; | ||
| 38 | }; | ||
| 39 | |||
| 40 | template <typename T, int A> | ||
| 41 | struct UnwrapArg<OutLargeData<T, A>> { | ||
| 42 | using Type = AutoOut<typename OutLargeData<T, A>::Type>; | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum class ArgumentType { | ||
| 46 | InProcessId, | ||
| 47 | InData, | ||
| 48 | InInterface, | ||
| 49 | InCopyHandle, | ||
| 50 | OutData, | ||
| 51 | OutInterface, | ||
| 52 | OutCopyHandle, | ||
| 53 | OutMoveHandle, | ||
| 54 | InBuffer, | ||
| 55 | InLargeData, | ||
| 56 | OutBuffer, | ||
| 57 | OutLargeData, | ||
| 58 | }; | ||
| 59 | |||
| 60 | template <typename T> | ||
| 61 | struct ArgumentTraits; | ||
| 62 | |||
| 63 | template <> | ||
| 64 | struct ArgumentTraits<ClientProcessId> { | ||
| 65 | static constexpr ArgumentType Type = ArgumentType::InProcessId; | ||
| 66 | }; | ||
| 67 | |||
| 68 | template <typename T> | ||
| 69 | struct ArgumentTraits<SharedPointer<T>> { | ||
| 70 | static constexpr ArgumentType Type = ArgumentType::InInterface; | ||
| 71 | }; | ||
| 72 | |||
| 73 | template <typename T> | ||
| 74 | struct ArgumentTraits<InCopyHandle<T>> { | ||
| 75 | static constexpr ArgumentType Type = ArgumentType::InCopyHandle; | ||
| 76 | }; | ||
| 77 | |||
| 78 | template <typename T> | ||
| 79 | struct ArgumentTraits<Out<SharedPointer<T>>> { | ||
| 80 | static constexpr ArgumentType Type = ArgumentType::OutInterface; | ||
| 81 | }; | ||
| 82 | |||
| 83 | template <typename T> | ||
| 84 | struct ArgumentTraits<Out<T>> { | ||
| 85 | static constexpr ArgumentType Type = ArgumentType::OutData; | ||
| 86 | }; | ||
| 87 | |||
| 88 | template <typename T> | ||
| 89 | struct ArgumentTraits<OutCopyHandle<T>> { | ||
| 90 | static constexpr ArgumentType Type = ArgumentType::OutCopyHandle; | ||
| 91 | }; | ||
| 92 | |||
| 93 | template <typename T> | ||
| 94 | struct ArgumentTraits<OutMoveHandle<T>> { | ||
| 95 | static constexpr ArgumentType Type = ArgumentType::OutMoveHandle; | ||
| 96 | }; | ||
| 97 | |||
| 98 | template <typename T, int A> | ||
| 99 | struct ArgumentTraits<Buffer<T, A>> { | ||
| 100 | static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer; | ||
| 101 | }; | ||
| 102 | |||
| 103 | template <typename T, int A> | ||
| 104 | struct ArgumentTraits<InLargeData<T, A>> { | ||
| 105 | static constexpr ArgumentType Type = ArgumentType::InLargeData; | ||
| 106 | }; | ||
| 107 | |||
| 108 | template <typename T, int A> | ||
| 109 | struct ArgumentTraits<OutLargeData<T, A>> { | ||
| 110 | static constexpr ArgumentType Type = ArgumentType::OutLargeData; | ||
| 111 | }; | ||
| 112 | |||
| 113 | template <typename T> | ||
| 114 | struct ArgumentTraits { | ||
| 115 | static constexpr ArgumentType Type = ArgumentType::InData; | ||
| 116 | }; | ||
| 117 | |||
| 15 | struct RequestLayout { | 118 | struct RequestLayout { |
| 16 | u32 copy_handle_count; | 119 | u32 copy_handle_count; |
| 17 | u32 move_handle_count; | 120 | u32 move_handle_count; |
| @@ -19,14 +122,14 @@ struct RequestLayout { | |||
| 19 | u32 domain_interface_count; | 122 | u32 domain_interface_count; |
| 20 | }; | 123 | }; |
| 21 | 124 | ||
| 22 | template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> | 125 | template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> |
| 23 | constexpr u32 GetArgumentRawDataSize() { | 126 | constexpr u32 GetInRawDataSize() { |
| 24 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { | 127 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { |
| 25 | return static_cast<u32>(DataOffset); | 128 | return static_cast<u32>(DataOffset); |
| 26 | } else { | 129 | } else { |
| 27 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | 130 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; |
| 28 | 131 | ||
| 29 | if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) { | 132 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) { |
| 30 | constexpr size_t ArgAlign = alignof(ArgType); | 133 | constexpr size_t ArgAlign = alignof(ArgType); |
| 31 | constexpr size_t ArgSize = sizeof(ArgType); | 134 | constexpr size_t ArgSize = sizeof(ArgType); |
| 32 | 135 | ||
| @@ -35,9 +138,33 @@ constexpr u32 GetArgumentRawDataSize() { | |||
| 35 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | 138 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); |
| 36 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | 139 | constexpr size_t ArgEnd = ArgOffset + ArgSize; |
| 37 | 140 | ||
| 38 | return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); | 141 | return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); |
| 39 | } else { | 142 | } else { |
| 40 | return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); | 143 | return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); |
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0> | ||
| 149 | constexpr u32 GetOutRawDataSize() { | ||
| 150 | if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) { | ||
| 151 | return static_cast<u32>(DataOffset); | ||
| 152 | } else { | ||
| 153 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | ||
| 154 | |||
| 155 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { | ||
| 156 | using RawArgType = typename ArgType::Type; | ||
| 157 | constexpr size_t ArgAlign = alignof(RawArgType); | ||
| 158 | constexpr size_t ArgSize = sizeof(RawArgType); | ||
| 159 | |||
| 160 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); | ||
| 161 | |||
| 162 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | ||
| 163 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | ||
| 164 | |||
| 165 | return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>(); | ||
| 166 | } else { | ||
| 167 | return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>(); | ||
| 41 | } | 168 | } |
| 42 | } | 169 | } |
| 43 | } | 170 | } |
| @@ -62,7 +189,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() { | |||
| 62 | return RequestLayout{ | 189 | return RequestLayout{ |
| 63 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), | 190 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), |
| 64 | .move_handle_count = 0, | 191 | .move_handle_count = 0, |
| 65 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(), | 192 | .cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), |
| 66 | .domain_interface_count = 0, | 193 | .domain_interface_count = 0, |
| 67 | }; | 194 | }; |
| 68 | } | 195 | } |
| @@ -72,7 +199,7 @@ constexpr RequestLayout GetDomainReplyInLayout() { | |||
| 72 | return RequestLayout{ | 199 | return RequestLayout{ |
| 73 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), | 200 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(), |
| 74 | .move_handle_count = 0, | 201 | .move_handle_count = 0, |
| 75 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(), | 202 | .cmif_raw_data_size = GetInRawDataSize<MethodArguments>(), |
| 76 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(), | 203 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(), |
| 77 | }; | 204 | }; |
| 78 | } | 205 | } |
| @@ -82,7 +209,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() { | |||
| 82 | return RequestLayout{ | 209 | return RequestLayout{ |
| 83 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), | 210 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), |
| 84 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), | 211 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), |
| 85 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(), | 212 | .cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), |
| 86 | .domain_interface_count = 0, | 213 | .domain_interface_count = 0, |
| 87 | }; | 214 | }; |
| 88 | } | 215 | } |
| @@ -92,7 +219,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() { | |||
| 92 | return RequestLayout{ | 219 | return RequestLayout{ |
| 93 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), | 220 | .copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(), |
| 94 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(), | 221 | .move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(), |
| 95 | .cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(), | 222 | .cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(), |
| 96 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), | 223 | .domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(), |
| 97 | }; | 224 | }; |
| 98 | } | 225 | } |
| @@ -122,6 +249,8 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | |||
| 122 | 249 | ||
| 123 | static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment"); | 250 | static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment"); |
| 124 | static_assert(!RawDataFinished, "All input interface arguments must appear after raw data"); | 251 | static_assert(!RawDataFinished, "All input interface arguments must appear after raw data"); |
| 252 | static_assert(!std::is_pointer_v<ArgType>, "Input raw data must not be a pointer"); | ||
| 253 | static_assert(std::is_trivially_copyable_v<ArgType>, "Input raw data must be trivially copyable"); | ||
| 125 | 254 | ||
| 126 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | 255 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); |
| 127 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | 256 | constexpr size_t ArgEnd = ArgOffset + ArgSize; |
| @@ -154,7 +283,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | |||
| 154 | 283 | ||
| 155 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 284 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 156 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) { | 285 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) { |
| 157 | constexpr size_t BufferSize = sizeof(ArgType); | 286 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 158 | 287 | ||
| 159 | // Clear the existing data. | 288 | // Clear the existing data. |
| 160 | std::memset(&std::get<ArgIndex>(args), 0, BufferSize); | 289 | std::memset(&std::get<ArgIndex>(args), 0, BufferSize); |
| @@ -195,10 +324,10 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | |||
| 195 | 324 | ||
| 196 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 325 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 197 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { | 326 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { |
| 198 | constexpr size_t BufferSize = sizeof(ArgType); | 327 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 199 | 328 | ||
| 200 | // Clear the existing data. | 329 | // Clear the existing data. |
| 201 | std::memset(&std::get<ArgIndex>(args), 0, BufferSize); | 330 | std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize); |
| 202 | 331 | ||
| 203 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 332 | return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 204 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) { | 333 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) { |
| @@ -232,36 +361,40 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ | |||
| 232 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; | 361 | using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>; |
| 233 | 362 | ||
| 234 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { | 363 | if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) { |
| 235 | constexpr size_t ArgAlign = alignof(ArgType); | 364 | using RawArgType = decltype(std::get<ArgIndex>(args).raw); |
| 236 | constexpr size_t ArgSize = sizeof(ArgType); | 365 | constexpr size_t ArgAlign = alignof(RawArgType); |
| 366 | constexpr size_t ArgSize = sizeof(RawArgType); | ||
| 237 | 367 | ||
| 238 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); | 368 | static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); |
| 239 | static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); | 369 | static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); |
| 370 | static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer"); | ||
| 371 | static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer"); | ||
| 372 | static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable"); | ||
| 240 | 373 | ||
| 241 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); | 374 | constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); |
| 242 | constexpr size_t ArgEnd = ArgOffset + ArgSize; | 375 | constexpr size_t ArgEnd = ArgOffset + ArgSize; |
| 243 | 376 | ||
| 244 | std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize); | 377 | std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize); |
| 245 | 378 | ||
| 246 | return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 379 | return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 247 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) { | 380 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) { |
| 248 | if (is_domain) { | 381 | if (is_domain) { |
| 249 | ctx.AddDomainObject(std::get<ArgIndex>(args)); | 382 | ctx.AddDomainObject(std::get<ArgIndex>(args).raw); |
| 250 | } else { | 383 | } else { |
| 251 | ctx.AddMoveInterface(std::get<ArgIndex>(args)); | 384 | ctx.AddMoveInterface(std::get<ArgIndex>(args).raw); |
| 252 | } | 385 | } |
| 253 | 386 | ||
| 254 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 387 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 255 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) { | 388 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) { |
| 256 | ctx.AddCopyObject(std::get<ArgIndex>(args)); | 389 | ctx.AddCopyObject(std::get<ArgIndex>(args).raw); |
| 257 | 390 | ||
| 258 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 391 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 259 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) { | 392 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) { |
| 260 | ctx.AddMoveObject(std::get<ArgIndex>(args)); | 393 | ctx.AddMoveObject(std::get<ArgIndex>(args).raw); |
| 261 | 394 | ||
| 262 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); | 395 | return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); |
| 263 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { | 396 | } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { |
| 264 | constexpr size_t BufferSize = sizeof(ArgType); | 397 | constexpr size_t BufferSize = sizeof(typename ArgType::Type); |
| 265 | 398 | ||
| 266 | ASSERT(ctx.CanWriteBuffer(OutBufferIndex)); | 399 | ASSERT(ctx.CanWriteBuffer(OutBufferIndex)); |
| 267 | if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { | 400 | if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { |
| @@ -302,10 +435,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) { | |||
| 302 | } | 435 | } |
| 303 | const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false; | 436 | const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false; |
| 304 | 437 | ||
| 305 | using MethodArguments = std::tuple<std::remove_reference_t<A>...>; | 438 | using MethodArguments = std::tuple<std::remove_cvref_t<A>...>; |
| 306 | 439 | ||
| 307 | OutTemporaryBuffers buffers{}; | 440 | OutTemporaryBuffers buffers{}; |
| 308 | auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>(); | 441 | auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>(); |
| 309 | 442 | ||
| 310 | // Read inputs. | 443 | // Read inputs. |
| 311 | const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2; | 444 | const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2; |
diff --git a/src/core/hle/service/cmif_types.h b/src/core/hle/service/cmif_types.h index 2610c49f3..dc06169f4 100644 --- a/src/core/hle/service/cmif_types.h +++ b/src/core/hle/service/cmif_types.h | |||
| @@ -13,21 +13,30 @@ namespace Service { | |||
| 13 | 13 | ||
| 14 | // clang-format off | 14 | // clang-format off |
| 15 | template <typename T> | 15 | template <typename T> |
| 16 | struct AutoOut { | ||
| 17 | T raw; | ||
| 18 | }; | ||
| 19 | |||
| 20 | template <typename T> | ||
| 16 | class Out { | 21 | class Out { |
| 17 | public: | 22 | public: |
| 18 | using Type = T; | 23 | using Type = T; |
| 19 | 24 | ||
| 20 | /* implicit */ Out(Type& t) : raw(&t) {} | 25 | /* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {} |
| 21 | ~Out() = default; | 26 | /* implicit */ Out(Type* t) : raw(t) {} |
| 22 | 27 | ||
| 23 | Type* Get() const { | 28 | Type* Get() const { |
| 24 | return raw; | 29 | return raw; |
| 25 | } | 30 | } |
| 26 | 31 | ||
| 27 | Type& operator*() { | 32 | Type& operator*() const { |
| 28 | return *raw; | 33 | return *raw; |
| 29 | } | 34 | } |
| 30 | 35 | ||
| 36 | Type* operator->() const { | ||
| 37 | return raw; | ||
| 38 | } | ||
| 39 | |||
| 31 | private: | 40 | private: |
| 32 | Type* raw; | 41 | Type* raw; |
| 33 | }; | 42 | }; |
| @@ -35,6 +44,9 @@ private: | |||
| 35 | template <typename T> | 44 | template <typename T> |
| 36 | using SharedPointer = std::shared_ptr<T>; | 45 | using SharedPointer = std::shared_ptr<T>; |
| 37 | 46 | ||
| 47 | template <typename T> | ||
| 48 | using OutInterface = Out<SharedPointer<T>>; | ||
| 49 | |||
| 38 | struct ClientProcessId { | 50 | struct ClientProcessId { |
| 39 | explicit operator bool() const { | 51 | explicit operator bool() const { |
| 40 | return pid != 0; | 52 | return pid != 0; |
| @@ -101,17 +113,21 @@ class OutCopyHandle { | |||
| 101 | public: | 113 | public: |
| 102 | using Type = T*; | 114 | using Type = T*; |
| 103 | 115 | ||
| 104 | /* implicit */ OutCopyHandle(Type& t) : raw(&t) {} | 116 | /* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {} |
| 105 | ~OutCopyHandle() = default; | 117 | /* implicit */ OutCopyHandle(Type* t) : raw(t) {} |
| 106 | 118 | ||
| 107 | Type* Get() const { | 119 | Type* Get() const { |
| 108 | return raw; | 120 | return raw; |
| 109 | } | 121 | } |
| 110 | 122 | ||
| 111 | Type& operator*() { | 123 | Type& operator*() const { |
| 112 | return *raw; | 124 | return *raw; |
| 113 | } | 125 | } |
| 114 | 126 | ||
| 127 | Type* operator->() const { | ||
| 128 | return raw; | ||
| 129 | } | ||
| 130 | |||
| 115 | private: | 131 | private: |
| 116 | Type* raw; | 132 | Type* raw; |
| 117 | }; | 133 | }; |
| @@ -121,30 +137,34 @@ class OutMoveHandle { | |||
| 121 | public: | 137 | public: |
| 122 | using Type = T*; | 138 | using Type = T*; |
| 123 | 139 | ||
| 124 | /* implicit */ OutMoveHandle(Type& t) : raw(&t) {} | 140 | /* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {} |
| 125 | ~OutMoveHandle() = default; | 141 | /* implicit */ OutMoveHandle(Type* t) : raw(t) {} |
| 126 | 142 | ||
| 127 | Type* Get() const { | 143 | Type* Get() const { |
| 128 | return raw; | 144 | return raw; |
| 129 | } | 145 | } |
| 130 | 146 | ||
| 131 | Type& operator*() { | 147 | Type& operator*() const { |
| 132 | return *raw; | 148 | return *raw; |
| 133 | } | 149 | } |
| 134 | 150 | ||
| 151 | Type* operator->() const { | ||
| 152 | return raw; | ||
| 153 | } | ||
| 154 | |||
| 135 | private: | 155 | private: |
| 136 | Type* raw; | 156 | Type* raw; |
| 137 | }; | 157 | }; |
| 138 | 158 | ||
| 139 | enum BufferAttr : int { | 159 | enum BufferAttr : int { |
| 140 | BufferAttr_In = (1U << 0), | 160 | /* 0x01 */ BufferAttr_In = (1U << 0), |
| 141 | BufferAttr_Out = (1U << 1), | 161 | /* 0x02 */ BufferAttr_Out = (1U << 1), |
| 142 | BufferAttr_HipcMapAlias = (1U << 2), | 162 | /* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2), |
| 143 | BufferAttr_HipcPointer = (1U << 3), | 163 | /* 0x08 */ BufferAttr_HipcPointer = (1U << 3), |
| 144 | BufferAttr_FixedSize = (1U << 4), | 164 | /* 0x10 */ BufferAttr_FixedSize = (1U << 4), |
| 145 | BufferAttr_HipcAutoSelect = (1U << 5), | 165 | /* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5), |
| 146 | BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), | 166 | /* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), |
| 147 | BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), | 167 | /* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), |
| 148 | }; | 168 | }; |
| 149 | 169 | ||
| 150 | template <typename T, int A> | 170 | template <typename T, int A> |
| @@ -172,123 +192,80 @@ struct Buffer : public std::span<T> { | |||
| 172 | } | 192 | } |
| 173 | }; | 193 | }; |
| 174 | 194 | ||
| 175 | template <BufferAttr A> | 195 | template <int A> |
| 176 | using InBuffer = Buffer<const u8, BufferAttr_In | A>; | 196 | using InBuffer = Buffer<const u8, BufferAttr_In | A>; |
| 177 | 197 | ||
| 178 | template <typename T, BufferAttr A> | 198 | template <typename T, int A> |
| 179 | using InArray = Buffer<T, BufferAttr_In | A>; | 199 | using InArray = Buffer<T, BufferAttr_In | A>; |
| 180 | 200 | ||
| 181 | template <BufferAttr A> | 201 | template <int A> |
| 182 | using OutBuffer = Buffer<u8, BufferAttr_Out | A>; | 202 | using OutBuffer = Buffer<u8, BufferAttr_Out | A>; |
| 183 | 203 | ||
| 184 | template <typename T, BufferAttr A> | 204 | template <typename T, int A> |
| 185 | using OutArray = Buffer<T, BufferAttr_Out | A>; | 205 | using OutArray = Buffer<T, BufferAttr_Out | A>; |
| 186 | 206 | ||
| 187 | template <typename T, int A> | 207 | template <typename T, int A> |
| 188 | struct LargeData : public T { | 208 | class InLargeData { |
| 209 | public: | ||
| 189 | static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); | 210 | static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); |
| 190 | static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize"); | 211 | static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out"); |
| 191 | static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out"); | 212 | static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize); |
| 192 | static constexpr BufferAttr Attr = static_cast<BufferAttr>(A); | 213 | using Type = const T; |
| 193 | using Type = T; | ||
| 194 | |||
| 195 | /* implicit */ LargeData(const T& rhs) : T(rhs) {} | ||
| 196 | /* implicit */ LargeData() = default; | ||
| 197 | }; | ||
| 198 | |||
| 199 | template <typename T, BufferAttr A> | ||
| 200 | using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>; | ||
| 201 | |||
| 202 | template <typename T, BufferAttr A> | ||
| 203 | using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>; | ||
| 204 | 214 | ||
| 205 | template <typename T> | 215 | /* implicit */ InLargeData(Type& t) : raw(&t) {} |
| 206 | struct RemoveOut { | 216 | ~InLargeData() = default; |
| 207 | using Type = std::remove_reference_t<T>; | ||
| 208 | }; | ||
| 209 | |||
| 210 | template <typename T> | ||
| 211 | struct RemoveOut<Out<T>> { | ||
| 212 | using Type = typename Out<T>::Type; | ||
| 213 | }; | ||
| 214 | 217 | ||
| 215 | template <typename T> | 218 | InLargeData& operator=(Type* rhs) { |
| 216 | struct RemoveOut<OutCopyHandle<T>> { | 219 | raw = rhs; |
| 217 | using Type = typename OutCopyHandle<T>::Type; | 220 | return *this; |
| 218 | }; | 221 | } |
| 219 | |||
| 220 | template <typename T> | ||
| 221 | struct RemoveOut<OutMoveHandle<T>> { | ||
| 222 | using Type = typename OutMoveHandle<T>::Type; | ||
| 223 | }; | ||
| 224 | |||
| 225 | enum class ArgumentType { | ||
| 226 | InProcessId, | ||
| 227 | InData, | ||
| 228 | InInterface, | ||
| 229 | InCopyHandle, | ||
| 230 | OutData, | ||
| 231 | OutInterface, | ||
| 232 | OutCopyHandle, | ||
| 233 | OutMoveHandle, | ||
| 234 | InBuffer, | ||
| 235 | InLargeData, | ||
| 236 | OutBuffer, | ||
| 237 | OutLargeData, | ||
| 238 | }; | ||
| 239 | 222 | ||
| 240 | template <typename T> | 223 | Type* Get() const { |
| 241 | struct ArgumentTraits; | 224 | return raw; |
| 225 | } | ||
| 242 | 226 | ||
| 243 | template <> | 227 | Type& operator*() const { |
| 244 | struct ArgumentTraits<ClientProcessId> { | 228 | return *raw; |
| 245 | static constexpr ArgumentType Type = ArgumentType::InProcessId; | 229 | } |
| 246 | }; | ||
| 247 | 230 | ||
| 248 | template <typename T> | 231 | Type* operator->() const { |
| 249 | struct ArgumentTraits<SharedPointer<T>> { | 232 | return raw; |
| 250 | static constexpr ArgumentType Type = ArgumentType::InInterface; | 233 | } |
| 251 | }; | ||
| 252 | 234 | ||
| 253 | template <typename T> | 235 | explicit operator bool() const { |
| 254 | struct ArgumentTraits<InCopyHandle<T>> { | 236 | return raw != nullptr; |
| 255 | static constexpr ArgumentType Type = ArgumentType::InCopyHandle; | 237 | } |
| 256 | }; | ||
| 257 | 238 | ||
| 258 | template <typename T> | 239 | private: |
| 259 | struct ArgumentTraits<Out<SharedPointer<T>>> { | 240 | Type* raw; |
| 260 | static constexpr ArgumentType Type = ArgumentType::OutInterface; | ||
| 261 | }; | 241 | }; |
| 262 | 242 | ||
| 263 | template <typename T> | 243 | template <typename T, int A> |
| 264 | struct ArgumentTraits<Out<T>> { | 244 | class OutLargeData { |
| 265 | static constexpr ArgumentType Type = ArgumentType::OutData; | 245 | public: |
| 266 | }; | 246 | static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); |
| 247 | static_assert((A & BufferAttr_In) == 0, "OutLargeData attr must not be In"); | ||
| 248 | static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize); | ||
| 249 | using Type = T; | ||
| 267 | 250 | ||
| 268 | template <typename T> | 251 | /* implicit */ OutLargeData(Type* t) : raw(t) {} |
| 269 | struct ArgumentTraits<OutCopyHandle<T>> { | 252 | /* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {} |
| 270 | static constexpr ArgumentType Type = ArgumentType::OutCopyHandle; | ||
| 271 | }; | ||
| 272 | 253 | ||
| 273 | template <typename T> | 254 | Type* Get() const { |
| 274 | struct ArgumentTraits<OutMoveHandle<T>> { | 255 | return raw; |
| 275 | static constexpr ArgumentType Type = ArgumentType::OutMoveHandle; | 256 | } |
| 276 | }; | ||
| 277 | 257 | ||
| 278 | template <typename T, int A> | 258 | Type& operator*() const { |
| 279 | struct ArgumentTraits<Buffer<T, A>> { | 259 | return *raw; |
| 280 | static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer; | 260 | } |
| 281 | }; | ||
| 282 | 261 | ||
| 283 | template <typename T, int A> | 262 | Type* operator->() const { |
| 284 | struct ArgumentTraits<LargeData<T, A>> { | 263 | return raw; |
| 285 | static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData; | 264 | } |
| 286 | }; | ||
| 287 | 265 | ||
| 288 | template <typename T> | 266 | private: |
| 289 | struct ArgumentTraits { | 267 | Type* raw; |
| 290 | static constexpr ArgumentType Type = ArgumentType::InData; | ||
| 291 | }; | 268 | }; |
| 292 | // clang-format on | 269 | // clang-format on |
| 293 | 270 | ||
| 294 | } // namespace Service | 271 | } // namespace Service \ No newline at end of file |
diff --git a/src/core/hle/service/event.cpp b/src/core/hle/service/event.cpp new file mode 100644 index 000000000..375660d72 --- /dev/null +++ b/src/core/hle/service/event.cpp | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_event.h" | ||
| 5 | #include "core/hle/service/event.h" | ||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | |||
| 8 | namespace Service { | ||
| 9 | |||
| 10 | Event::Event(KernelHelpers::ServiceContext& ctx) { | ||
| 11 | m_event = ctx.CreateEvent("Event"); | ||
| 12 | } | ||
| 13 | |||
| 14 | Event::~Event() { | ||
| 15 | m_event->GetReadableEvent().Close(); | ||
| 16 | m_event->Close(); | ||
| 17 | } | ||
| 18 | |||
| 19 | void Event::Signal() { | ||
| 20 | m_event->Signal(); | ||
| 21 | } | ||
| 22 | |||
| 23 | void Event::Clear() { | ||
| 24 | m_event->Clear(); | ||
| 25 | } | ||
| 26 | |||
| 27 | Kernel::KReadableEvent* Event::GetHandle() { | ||
| 28 | return &m_event->GetReadableEvent(); | ||
| 29 | } | ||
| 30 | |||
| 31 | } // namespace Service | ||
diff --git a/src/core/hle/service/event.h b/src/core/hle/service/event.h new file mode 100644 index 000000000..cdbc4635a --- /dev/null +++ b/src/core/hle/service/event.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | namespace Kernel { | ||
| 7 | class KEvent; | ||
| 8 | class KReadableEvent; | ||
| 9 | } // namespace Kernel | ||
| 10 | |||
| 11 | namespace Service { | ||
| 12 | |||
| 13 | namespace KernelHelpers { | ||
| 14 | class ServiceContext; | ||
| 15 | } | ||
| 16 | |||
| 17 | class Event { | ||
| 18 | public: | ||
| 19 | explicit Event(KernelHelpers::ServiceContext& ctx); | ||
| 20 | ~Event(); | ||
| 21 | |||
| 22 | void Signal(); | ||
| 23 | void Clear(); | ||
| 24 | |||
| 25 | Kernel::KReadableEvent* GetHandle(); | ||
| 26 | |||
| 27 | private: | ||
| 28 | Kernel::KEvent* m_event; | ||
| 29 | }; | ||
| 30 | |||
| 31 | } // namespace Service | ||
diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index 2be72b021..5fe534c73 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp | |||
| @@ -15,11 +15,13 @@ | |||
| 15 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 16 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/file_sys/content_archive.h" | ||
| 18 | #include "core/file_sys/errors.h" | 19 | #include "core/file_sys/errors.h" |
| 19 | #include "core/file_sys/fs_directory.h" | 20 | #include "core/file_sys/fs_directory.h" |
| 20 | #include "core/file_sys/fs_filesystem.h" | 21 | #include "core/file_sys/fs_filesystem.h" |
| 21 | #include "core/file_sys/nca_metadata.h" | 22 | #include "core/file_sys/nca_metadata.h" |
| 22 | #include "core/file_sys/patch_manager.h" | 23 | #include "core/file_sys/patch_manager.h" |
| 24 | #include "core/file_sys/romfs.h" | ||
| 23 | #include "core/file_sys/romfs_factory.h" | 25 | #include "core/file_sys/romfs_factory.h" |
| 24 | #include "core/file_sys/savedata_factory.h" | 26 | #include "core/file_sys/savedata_factory.h" |
| 25 | #include "core/file_sys/system_archive/system_archive.h" | 27 | #include "core/file_sys/system_archive/system_archive.h" |
| @@ -33,18 +35,20 @@ | |||
| 33 | #include "core/hle/service/filesystem/save_data_controller.h" | 35 | #include "core/hle/service/filesystem/save_data_controller.h" |
| 34 | #include "core/hle/service/hle_ipc.h" | 36 | #include "core/hle/service/hle_ipc.h" |
| 35 | #include "core/hle/service/ipc_helpers.h" | 37 | #include "core/hle/service/ipc_helpers.h" |
| 38 | #include "core/loader/loader.h" | ||
| 36 | #include "core/reporter.h" | 39 | #include "core/reporter.h" |
| 37 | 40 | ||
| 38 | namespace Service::FileSystem { | 41 | namespace Service::FileSystem { |
| 39 | enum class FileSystemType : u8 { | 42 | enum class FileSystemProxyType : u8 { |
| 40 | Invalid0 = 0, | 43 | Code = 0, |
| 41 | Invalid1 = 1, | 44 | Rom = 1, |
| 42 | Logo = 2, | 45 | Logo = 2, |
| 43 | ContentControl = 3, | 46 | Control = 3, |
| 44 | ContentManual = 4, | 47 | Manual = 4, |
| 45 | ContentMeta = 5, | 48 | Meta = 5, |
| 46 | ContentData = 6, | 49 | Data = 6, |
| 47 | ApplicationPackage = 7, | 50 | Package = 7, |
| 51 | RegisteredUpdate = 8, | ||
| 48 | }; | 52 | }; |
| 49 | 53 | ||
| 50 | class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { | 54 | class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { |
| @@ -357,12 +361,30 @@ void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) { | |||
| 357 | void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { | 361 | void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { |
| 358 | IPC::RequestParser rp{ctx}; | 362 | IPC::RequestParser rp{ctx}; |
| 359 | 363 | ||
| 360 | const auto type = rp.PopRaw<FileSystemType>(); | 364 | struct InputParameters { |
| 361 | const auto title_id = rp.PopRaw<u64>(); | 365 | FileSystemProxyType type; |
| 362 | LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}", type, title_id); | 366 | u64 program_id; |
| 367 | }; | ||
| 368 | static_assert(sizeof(InputParameters) == 0x10, "InputParameters has wrong size"); | ||
| 369 | |||
| 370 | const auto params = rp.PopRaw<InputParameters>(); | ||
| 371 | LOG_ERROR(Service_FS, "(STUBBED) called with type={}, program_id={:016X}", params.type, | ||
| 372 | params.program_id); | ||
| 373 | |||
| 374 | // FIXME: many issues with this | ||
| 375 | ASSERT(params.type == FileSystemProxyType::Manual); | ||
| 376 | const auto manual_romfs = romfs_controller->OpenPatchedRomFS( | ||
| 377 | params.program_id, FileSys::ContentRecordType::HtmlDocument); | ||
| 363 | 378 | ||
| 364 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | 379 | ASSERT(manual_romfs != nullptr); |
| 365 | rb.Push(ResultUnknown); | 380 | |
| 381 | const auto extracted_romfs = FileSys::ExtractRomFS(manual_romfs); | ||
| 382 | ASSERT(extracted_romfs != nullptr); | ||
| 383 | |||
| 384 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 385 | rb.Push(ResultSuccess); | ||
| 386 | rb.PushIpcInterface<IFileSystem>(system, extracted_romfs, | ||
| 387 | SizeGetter::FromStorageId(fsc, FileSys::StorageId::NandUser)); | ||
| 366 | } | 388 | } |
| 367 | 389 | ||
| 368 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { | 390 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp index f549ed00a..3ff071f4a 100644 --- a/src/core/hle/service/glue/time/alarm_worker.cpp +++ b/src/core/hle/service/glue/time/alarm_worker.cpp | |||
| @@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i | |||
| 41 | Service::PSC::Time::AlarmInfo alarm_info{}; | 41 | Service::PSC::Time::AlarmInfo alarm_info{}; |
| 42 | s64 closest_time{}; | 42 | s64 closest_time{}; |
| 43 | 43 | ||
| 44 | auto res = m_time_m->GetClosestAlarmInfo(is_valid, alarm_info, closest_time); | 44 | auto res = m_time_m->GetClosestAlarmInfo(&is_valid, &alarm_info, &closest_time); |
| 45 | ASSERT(res == ResultSuccess); | 45 | ASSERT(res == ResultSuccess); |
| 46 | 46 | ||
| 47 | if (is_valid) { | 47 | if (is_valid) { |
| @@ -76,6 +76,7 @@ void AlarmWorker::OnPowerStateChanged() { | |||
| 76 | 76 | ||
| 77 | Result AlarmWorker::AttachToClosestAlarmEvent() { | 77 | Result AlarmWorker::AttachToClosestAlarmEvent() { |
| 78 | m_time_m->GetClosestAlarmUpdatedEvent(&m_event); | 78 | m_time_m->GetClosestAlarmUpdatedEvent(&m_event); |
| 79 | |||
| 79 | R_SUCCEED(); | 80 | R_SUCCEED(); |
| 80 | } | 81 | } |
| 81 | 82 | ||
diff --git a/src/core/hle/service/glue/time/alarm_worker.h b/src/core/hle/service/glue/time/alarm_worker.h index f269cffdb..131d012a6 100644 --- a/src/core/hle/service/glue/time/alarm_worker.h +++ b/src/core/hle/service/glue/time/alarm_worker.h | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | 26 | ||
| 27 | void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m); | 27 | void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m); |
| 28 | 28 | ||
| 29 | Kernel::KEvent& GetEvent() { | 29 | Kernel::KReadableEvent& GetEvent() { |
| 30 | return *m_event; | 30 | return *m_event; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| @@ -44,7 +44,7 @@ private: | |||
| 44 | KernelHelpers::ServiceContext m_ctx; | 44 | KernelHelpers::ServiceContext m_ctx; |
| 45 | std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m; | 45 | std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m; |
| 46 | 46 | ||
| 47 | Kernel::KEvent* m_event{}; | 47 | Kernel::KReadableEvent* m_event{}; |
| 48 | Kernel::KEvent* m_timer_event{}; | 48 | Kernel::KEvent* m_timer_event{}; |
| 49 | std::shared_ptr<Core::Timing::EventType> m_timer_timing_event; | 49 | std::shared_ptr<Core::Timing::EventType> m_timer_timing_event; |
| 50 | StandardSteadyClockResource& m_steady_clock_resource; | 50 | StandardSteadyClockResource& m_steady_clock_resource; |
diff --git a/src/core/hle/service/glue/time/file_timestamp_worker.cpp b/src/core/hle/service/glue/time/file_timestamp_worker.cpp index 5a6309549..048ff174c 100644 --- a/src/core/hle/service/glue/time/file_timestamp_worker.cpp +++ b/src/core/hle/service/glue/time/file_timestamp_worker.cpp | |||
| @@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() { | |||
| 13 | Service::PSC::Time::CalendarTime calendar_time{}; | 13 | Service::PSC::Time::CalendarTime calendar_time{}; |
| 14 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; | 14 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; |
| 15 | 15 | ||
| 16 | if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess && | 16 | if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess && |
| 17 | m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) == | 17 | m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) == |
| 18 | ResultSuccess) { | 18 | ResultSuccess) { |
| 19 | // TODO IFileSystemProxy::SetCurrentPosixTime | 19 | // TODO IFileSystemProxy::SetCurrentPosixTime |
| 20 | } | 20 | } |
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index b56762941..0c27e8029 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp | |||
| @@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN | |||
| 79 | auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); | 79 | auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); |
| 80 | 80 | ||
| 81 | Service::PSC::Time::LocationName configured_name{}; | 81 | Service::PSC::Time::LocationName configured_name{}; |
| 82 | std::memcpy(configured_name.name.data(), configured_zone.data(), | 82 | std::memcpy(configured_name.data(), configured_zone.data(), |
| 83 | std::min(configured_name.name.size(), configured_zone.size())); | 83 | std::min(configured_name.size(), configured_zone.size())); |
| 84 | 84 | ||
| 85 | if (!IsTimeZoneBinaryValid(configured_name)) { | 85 | if (!IsTimeZoneBinaryValid(configured_name)) { |
| 86 | configured_zone = Common::TimeZone::FindSystemTimeZone(); | 86 | configured_zone = Common::TimeZone::FindSystemTimeZone(); |
| 87 | configured_name = {}; | 87 | configured_name = {}; |
| 88 | std::memcpy(configured_name.name.data(), configured_zone.data(), | 88 | std::memcpy(configured_name.data(), configured_zone.data(), |
| 89 | std::min(configured_name.name.size(), configured_zone.size())); | 89 | std::min(configured_name.size(), configured_zone.size())); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", | 92 | ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", |
| 93 | configured_name.name.data()); | 93 | configured_name.data()); |
| 94 | 94 | ||
| 95 | return configured_name; | 95 | return configured_name; |
| 96 | } | 96 | } |
| @@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system) | |||
| 103 | m_time_m = | 103 | m_time_m = |
| 104 | system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true); | 104 | system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true); |
| 105 | 105 | ||
| 106 | auto res = m_time_m->GetStaticServiceAsServiceManager(m_time_sm); | 106 | auto res = m_time_m->GetStaticServiceAsServiceManager(&m_time_sm); |
| 107 | ASSERT(res == ResultSuccess); | 107 | ASSERT(res == ResultSuccess); |
| 108 | 108 | ||
| 109 | m_set_sys = | 109 | m_set_sys = |
| @@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system) | |||
| 114 | 114 | ||
| 115 | m_worker.Initialize(m_time_sm, m_set_sys); | 115 | m_worker.Initialize(m_time_sm, m_set_sys); |
| 116 | 116 | ||
| 117 | res = m_time_sm->GetStandardUserSystemClock(m_file_timestamp_worker.m_system_clock); | 117 | res = m_time_sm->GetStandardUserSystemClock(&m_file_timestamp_worker.m_system_clock); |
| 118 | ASSERT(res == ResultSuccess); | 118 | ASSERT(res == ResultSuccess); |
| 119 | 119 | ||
| 120 | res = m_time_sm->GetTimeZoneService(m_file_timestamp_worker.m_time_zone); | 120 | res = m_time_sm->GetTimeZoneService(&m_file_timestamp_worker.m_time_zone); |
| 121 | ASSERT(res == ResultSuccess); | 121 | ASSERT(res == ResultSuccess); |
| 122 | 122 | ||
| 123 | res = SetupStandardSteadyClockCore(); | 123 | res = SetupStandardSteadyClockCore(); |
| @@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system) | |||
| 161 | automatic_correction_time_point); | 161 | automatic_correction_time_point); |
| 162 | ASSERT(res == ResultSuccess); | 162 | ASSERT(res == ResultSuccess); |
| 163 | 163 | ||
| 164 | res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point, | 164 | res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled, |
| 165 | is_automatic_correction_enabled); | 165 | automatic_correction_time_point); |
| 166 | ASSERT(res == ResultSuccess); | 166 | ASSERT(res == ResultSuccess); |
| 167 | 167 | ||
| 168 | res = m_time_m->SetupEphemeralNetworkSystemClockCore(); | 168 | res = m_time_m->SetupEphemeralNetworkSystemClockCore(); |
| @@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system) | |||
| 184 | m_file_timestamp_worker.m_initialized = true; | 184 | m_file_timestamp_worker.m_initialized = true; |
| 185 | 185 | ||
| 186 | s64 system_clock_time{}; | 186 | s64 system_clock_time{}; |
| 187 | if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(system_clock_time) == | 187 | if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(&system_clock_time) == |
| 188 | ResultSuccess) { | 188 | ResultSuccess) { |
| 189 | Service::PSC::Time::CalendarTime calendar_time{}; | 189 | Service::PSC::Time::CalendarTime calendar_time{}; |
| 190 | Service::PSC::Time::CalendarAdditionalInfo calendar_additional{}; | 190 | Service::PSC::Time::CalendarAdditionalInfo calendar_additional{}; |
| 191 | if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule( | 191 | if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule( |
| 192 | calendar_time, calendar_additional, system_clock_time) == ResultSuccess) { | 192 | &calendar_time, &calendar_additional, system_clock_time) == ResultSuccess) { |
| 193 | // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time, | 193 | // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time, |
| 194 | // calendar_additional.ut_offset) | 194 | // calendar_additional.ut_offset) |
| 195 | } | 195 | } |
| @@ -228,10 +228,9 @@ Result TimeManager::SetupStandardSteadyClockCore() { | |||
| 228 | m_set_sys->SetExternalSteadyClockSourceId(clock_source_id); | 228 | m_set_sys->SetExternalSteadyClockSourceId(clock_source_id); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(), | 231 | res = m_time_m->SetupStandardSteadyClockCore( |
| 232 | external_steady_clock_internal_offset_ns, | 232 | reset_detected, clock_source_id, m_steady_clock_resource.GetTime(), |
| 233 | standard_steady_clock_test_offset_ns, | 233 | external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns); |
| 234 | reset_detected); | ||
| 235 | ASSERT(res == ResultSuccess); | 234 | ASSERT(res == ResultSuccess); |
| 236 | R_SUCCEED(); | 235 | R_SUCCEED(); |
| 237 | } | 236 | } |
| @@ -243,14 +242,15 @@ Result TimeManager::SetupTimeZoneServiceCore() { | |||
| 243 | 242 | ||
| 244 | auto configured_zone = GetTimeZoneString(name); | 243 | auto configured_zone = GetTimeZoneString(name); |
| 245 | 244 | ||
| 246 | if (configured_zone.name != name.name) { | 245 | if (configured_zone != name) { |
| 247 | m_set_sys->SetDeviceTimeZoneLocationName(configured_zone); | 246 | m_set_sys->SetDeviceTimeZoneLocationName(configured_zone); |
| 248 | name = configured_zone; | 247 | name = configured_zone; |
| 249 | 248 | ||
| 250 | std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; | 249 | std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; |
| 251 | m_time_sm->GetStandardLocalSystemClock(local_clock); | 250 | m_time_sm->GetStandardLocalSystemClock(&local_clock); |
| 251 | |||
| 252 | Service::PSC::Time::SystemClockContext context{}; | 252 | Service::PSC::Time::SystemClockContext context{}; |
| 253 | local_clock->GetSystemClockContext(context); | 253 | local_clock->GetSystemClockContext(&context); |
| 254 | m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point); | 254 | m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| @@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() { | |||
| 267 | res = GetTimeZoneRule(rule_buffer, rule_size, name); | 267 | res = GetTimeZoneRule(rule_buffer, rule_size, name); |
| 268 | ASSERT(res == ResultSuccess); | 268 | ASSERT(res == ResultSuccess); |
| 269 | 269 | ||
| 270 | res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count, | 270 | res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point, |
| 271 | rule_buffer); | 271 | rule_buffer); |
| 272 | ASSERT(res == ResultSuccess); | 272 | ASSERT(res == ResultSuccess); |
| 273 | 273 | ||
diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp index 63b7d91da..f56db76e1 100644 --- a/src/core/hle/service/glue/time/static.cpp +++ b/src/core/hle/service/glue/time/static.cpp | |||
| @@ -3,9 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | #include <chrono> | 4 | #include <chrono> |
| 5 | 5 | ||
| 6 | #include "common/scope_exit.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_shared_memory.h" | 8 | #include "core/hle/kernel/k_shared_memory.h" |
| 8 | #include "core/hle/kernel/svc.h" | 9 | #include "core/hle/kernel/svc.h" |
| 10 | #include "core/hle/service/cmif_serialization.h" | ||
| 9 | #include "core/hle/service/glue/time/file_timestamp_worker.h" | 11 | #include "core/hle/service/glue/time/file_timestamp_worker.h" |
| 10 | #include "core/hle/service/glue/time/static.h" | 12 | #include "core/hle/service/glue/time/static.h" |
| 11 | #include "core/hle/service/psc/time/errors.h" | 13 | #include "core/hle/service/psc/time/errors.h" |
| @@ -41,25 +43,25 @@ StaticService::StaticService(Core::System& system_, | |||
| 41 | time->m_steady_clock_resource} { | 43 | time->m_steady_clock_resource} { |
| 42 | // clang-format off | 44 | // clang-format off |
| 43 | static const FunctionInfo functions[] = { | 45 | static const FunctionInfo functions[] = { |
| 44 | {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | 46 | {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, |
| 45 | {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, | 47 | {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, |
| 46 | {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, | 48 | {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, |
| 47 | {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, | 49 | {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, |
| 48 | {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, | 50 | {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, |
| 49 | {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, | 51 | {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, |
| 50 | {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, | 52 | {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, |
| 51 | {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, | 53 | {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, |
| 52 | {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, | 54 | {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, |
| 53 | {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, | 55 | {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 54 | {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, | 56 | {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 55 | {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, | 57 | {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, |
| 56 | {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, | 58 | {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, |
| 57 | {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, | 59 | {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, |
| 58 | {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, | 60 | {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, |
| 59 | {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, | 61 | {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, |
| 60 | {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, | 62 | {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, |
| 61 | {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, | 63 | {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, |
| 62 | {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, | 64 | {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, |
| 63 | }; | 65 | }; |
| 64 | // clang-format on | 66 | // clang-format on |
| 65 | 67 | ||
| @@ -71,314 +73,80 @@ StaticService::StaticService(Core::System& system_, | |||
| 71 | if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock && | 73 | if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock && |
| 72 | !m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location && | 74 | !m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location && |
| 73 | !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { | 75 | !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { |
| 74 | m_time_m->GetStaticServiceAsAdmin(m_wrapped_service); | 76 | m_time_m->GetStaticServiceAsAdmin(&m_wrapped_service); |
| 75 | } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && | 77 | } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && |
| 76 | !m_setup_info.can_write_network_clock && | 78 | !m_setup_info.can_write_network_clock && |
| 77 | !m_setup_info.can_write_timezone_device_location && | 79 | !m_setup_info.can_write_timezone_device_location && |
| 78 | !m_setup_info.can_write_steady_clock && | 80 | !m_setup_info.can_write_steady_clock && |
| 79 | !m_setup_info.can_write_uninitialized_clock) { | 81 | !m_setup_info.can_write_uninitialized_clock) { |
| 80 | m_time_m->GetStaticServiceAsUser(m_wrapped_service); | 82 | m_time_m->GetStaticServiceAsUser(&m_wrapped_service); |
| 81 | } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && | 83 | } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && |
| 82 | !m_setup_info.can_write_network_clock && | 84 | !m_setup_info.can_write_network_clock && |
| 83 | !m_setup_info.can_write_timezone_device_location && | 85 | !m_setup_info.can_write_timezone_device_location && |
| 84 | m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { | 86 | m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { |
| 85 | m_time_m->GetStaticServiceAsRepair(m_wrapped_service); | 87 | m_time_m->GetStaticServiceAsRepair(&m_wrapped_service); |
| 86 | } else { | 88 | } else { |
| 87 | UNREACHABLE(); | 89 | UNREACHABLE(); |
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | auto res = m_wrapped_service->GetTimeZoneService(m_time_zone); | 92 | auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone); |
| 91 | ASSERT(res == ResultSuccess); | 93 | ASSERT(res == ResultSuccess); |
| 92 | } | 94 | } |
| 93 | 95 | ||
| 94 | void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) { | 96 | Result StaticService::GetStandardUserSystemClock( |
| 95 | LOG_DEBUG(Service_Time, "called."); | 97 | OutInterface<Service::PSC::Time::SystemClock> out_service) { |
| 96 | |||
| 97 | std::shared_ptr<Service::PSC::Time::SystemClock> service{}; | ||
| 98 | auto res = GetStandardUserSystemClock(service); | ||
| 99 | |||
| 100 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 101 | rb.Push(res); | ||
| 102 | rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); | ||
| 103 | } | ||
| 104 | |||
| 105 | void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) { | ||
| 106 | LOG_DEBUG(Service_Time, "called."); | ||
| 107 | |||
| 108 | std::shared_ptr<Service::PSC::Time::SystemClock> service{}; | ||
| 109 | auto res = GetStandardNetworkSystemClock(service); | ||
| 110 | |||
| 111 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 112 | rb.Push(res); | ||
| 113 | rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); | ||
| 114 | } | ||
| 115 | |||
| 116 | void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) { | ||
| 117 | LOG_DEBUG(Service_Time, "called."); | ||
| 118 | |||
| 119 | std::shared_ptr<Service::PSC::Time::SteadyClock> service{}; | ||
| 120 | auto res = GetStandardSteadyClock(service); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 123 | rb.Push(res); | ||
| 124 | rb.PushIpcInterface(std::move(service)); | ||
| 125 | } | ||
| 126 | |||
| 127 | void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) { | ||
| 128 | LOG_DEBUG(Service_Time, "called."); | ||
| 129 | |||
| 130 | std::shared_ptr<TimeZoneService> service{}; | ||
| 131 | auto res = GetTimeZoneService(service); | ||
| 132 | |||
| 133 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 134 | rb.Push(res); | ||
| 135 | rb.PushIpcInterface(std::move(service)); | ||
| 136 | } | ||
| 137 | |||
| 138 | void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) { | ||
| 139 | LOG_DEBUG(Service_Time, "called."); | ||
| 140 | |||
| 141 | std::shared_ptr<Service::PSC::Time::SystemClock> service{}; | ||
| 142 | auto res = GetStandardLocalSystemClock(service); | ||
| 143 | |||
| 144 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 145 | rb.Push(res); | ||
| 146 | rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); | ||
| 147 | } | ||
| 148 | |||
| 149 | void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) { | ||
| 150 | LOG_DEBUG(Service_Time, "called."); | ||
| 151 | |||
| 152 | std::shared_ptr<Service::PSC::Time::SystemClock> service{}; | ||
| 153 | auto res = GetEphemeralNetworkSystemClock(service); | ||
| 154 | |||
| 155 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 156 | rb.Push(res); | ||
| 157 | rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service)); | ||
| 158 | } | ||
| 159 | |||
| 160 | void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) { | ||
| 161 | LOG_DEBUG(Service_Time, "called."); | ||
| 162 | |||
| 163 | Kernel::KSharedMemory* shared_memory{}; | ||
| 164 | auto res = GetSharedMemoryNativeHandle(&shared_memory); | ||
| 165 | |||
| 166 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 167 | rb.Push(res); | ||
| 168 | rb.PushCopyObjects(shared_memory); | ||
| 169 | } | ||
| 170 | |||
| 171 | void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) { | ||
| 172 | LOG_DEBUG(Service_Time, "called."); | ||
| 173 | |||
| 174 | IPC::RequestParser rp{ctx}; | ||
| 175 | auto offset_ns{rp.Pop<s64>()}; | ||
| 176 | |||
| 177 | auto res = SetStandardSteadyClockInternalOffset(offset_ns); | ||
| 178 | |||
| 179 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 180 | rb.Push(res); | ||
| 181 | } | ||
| 182 | |||
| 183 | void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) { | ||
| 184 | LOG_DEBUG(Service_Time, "called."); | ||
| 185 | |||
| 186 | s64 rtc_value{}; | ||
| 187 | auto res = GetStandardSteadyClockRtcValue(rtc_value); | ||
| 188 | |||
| 189 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 190 | rb.Push(res); | ||
| 191 | rb.Push(rtc_value); | ||
| 192 | } | ||
| 193 | |||
| 194 | void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 195 | HLERequestContext& ctx) { | ||
| 196 | LOG_DEBUG(Service_Time, "called."); | ||
| 197 | |||
| 198 | bool is_enabled{}; | ||
| 199 | auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled); | ||
| 200 | |||
| 201 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 202 | rb.Push(res); | ||
| 203 | rb.Push<bool>(is_enabled); | ||
| 204 | } | ||
| 205 | |||
| 206 | void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 207 | HLERequestContext& ctx) { | ||
| 208 | LOG_DEBUG(Service_Time, "called."); | ||
| 209 | |||
| 210 | IPC::RequestParser rp{ctx}; | ||
| 211 | auto automatic_correction{rp.Pop<bool>()}; | ||
| 212 | |||
| 213 | auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction); | ||
| 214 | |||
| 215 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 216 | rb.Push(res); | ||
| 217 | } | ||
| 218 | |||
| 219 | void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) { | ||
| 220 | LOG_DEBUG(Service_Time, "called."); | ||
| 221 | |||
| 222 | s32 initial_year{}; | ||
| 223 | auto res = GetStandardUserSystemClockInitialYear(initial_year); | ||
| 224 | |||
| 225 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 226 | rb.Push(res); | ||
| 227 | rb.Push(initial_year); | ||
| 228 | } | ||
| 229 | |||
| 230 | void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) { | ||
| 231 | LOG_DEBUG(Service_Time, "called."); | 98 | LOG_DEBUG(Service_Time, "called."); |
| 232 | 99 | ||
| 233 | bool is_sufficient{}; | 100 | R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service)); |
| 234 | auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient); | ||
| 235 | |||
| 236 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 237 | rb.Push(res); | ||
| 238 | rb.Push<bool>(is_sufficient); | ||
| 239 | } | 101 | } |
| 240 | 102 | ||
| 241 | void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 103 | Result StaticService::GetStandardNetworkSystemClock( |
| 242 | HLERequestContext& ctx) { | 104 | OutInterface<Service::PSC::Time::SystemClock> out_service) { |
| 243 | LOG_DEBUG(Service_Time, "called."); | 105 | LOG_DEBUG(Service_Time, "called."); |
| 244 | 106 | ||
| 245 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 107 | R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service)); |
| 246 | auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); | ||
| 247 | |||
| 248 | IPC::ResponseBuilder rb{ctx, | ||
| 249 | 2 + sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32)}; | ||
| 250 | rb.Push(res); | ||
| 251 | rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); | ||
| 252 | } | 108 | } |
| 253 | 109 | ||
| 254 | void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { | 110 | Result StaticService::GetStandardSteadyClock( |
| 111 | OutInterface<Service::PSC::Time::SteadyClock> out_service) { | ||
| 255 | LOG_DEBUG(Service_Time, "called."); | 112 | LOG_DEBUG(Service_Time, "called."); |
| 256 | 113 | ||
| 257 | IPC::RequestParser rp{ctx}; | 114 | R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service)); |
| 258 | auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; | ||
| 259 | |||
| 260 | s64 time{}; | ||
| 261 | auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context); | ||
| 262 | |||
| 263 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 264 | rb.Push(res); | ||
| 265 | rb.Push<s64>(time); | ||
| 266 | } | 115 | } |
| 267 | 116 | ||
| 268 | void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { | 117 | Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { |
| 269 | LOG_DEBUG(Service_Time, "called."); | 118 | LOG_DEBUG(Service_Time, "called."); |
| 270 | 119 | ||
| 271 | IPC::RequestParser rp{ctx}; | 120 | *out_service = std::make_shared<TimeZoneService>( |
| 272 | auto type{rp.PopEnum<Service::PSC::Time::TimeType>()}; | 121 | m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location, |
| 273 | 122 | m_time_zone); | |
| 274 | Service::PSC::Time::ClockSnapshot snapshot{}; | 123 | R_SUCCEED(); |
| 275 | auto res = GetClockSnapshot(snapshot, type); | ||
| 276 | |||
| 277 | ctx.WriteBuffer(snapshot); | ||
| 278 | |||
| 279 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 280 | rb.Push(res); | ||
| 281 | } | 124 | } |
| 282 | 125 | ||
| 283 | void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { | 126 | Result StaticService::GetStandardLocalSystemClock( |
| 127 | OutInterface<Service::PSC::Time::SystemClock> out_service) { | ||
| 284 | LOG_DEBUG(Service_Time, "called."); | 128 | LOG_DEBUG(Service_Time, "called."); |
| 285 | 129 | ||
| 286 | IPC::RequestParser rp{ctx}; | 130 | R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service)); |
| 287 | auto clock_type{rp.PopEnum<Service::PSC::Time::TimeType>()}; | ||
| 288 | [[maybe_unused]] auto alignment{rp.Pop<u32>()}; | ||
| 289 | auto user_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; | ||
| 290 | auto network_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; | ||
| 291 | |||
| 292 | Service::PSC::Time::ClockSnapshot snapshot{}; | ||
| 293 | auto res = | ||
| 294 | GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type); | ||
| 295 | |||
| 296 | ctx.WriteBuffer(snapshot); | ||
| 297 | |||
| 298 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 299 | rb.Push(res); | ||
| 300 | } | 131 | } |
| 301 | 132 | ||
| 302 | void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( | 133 | Result StaticService::GetEphemeralNetworkSystemClock( |
| 303 | HLERequestContext& ctx) { | 134 | OutInterface<Service::PSC::Time::SystemClock> out_service) { |
| 304 | LOG_DEBUG(Service_Time, "called."); | 135 | LOG_DEBUG(Service_Time, "called."); |
| 305 | 136 | ||
| 306 | Service::PSC::Time::ClockSnapshot a{}; | 137 | R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service)); |
| 307 | Service::PSC::Time::ClockSnapshot b{}; | ||
| 308 | |||
| 309 | auto a_buffer{ctx.ReadBuffer(0)}; | ||
| 310 | auto b_buffer{ctx.ReadBuffer(1)}; | ||
| 311 | |||
| 312 | std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); | ||
| 313 | std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); | ||
| 314 | |||
| 315 | s64 difference{}; | ||
| 316 | auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b); | ||
| 317 | |||
| 318 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 319 | rb.Push(res); | ||
| 320 | rb.Push(difference); | ||
| 321 | } | 138 | } |
| 322 | 139 | ||
| 323 | void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { | 140 | Result StaticService::GetSharedMemoryNativeHandle( |
| 141 | OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { | ||
| 324 | LOG_DEBUG(Service_Time, "called."); | 142 | LOG_DEBUG(Service_Time, "called."); |
| 325 | 143 | ||
| 326 | Service::PSC::Time::ClockSnapshot a{}; | ||
| 327 | Service::PSC::Time::ClockSnapshot b{}; | ||
| 328 | |||
| 329 | auto a_buffer{ctx.ReadBuffer(0)}; | ||
| 330 | auto b_buffer{ctx.ReadBuffer(1)}; | ||
| 331 | |||
| 332 | std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); | ||
| 333 | std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot)); | ||
| 334 | |||
| 335 | s64 time{}; | ||
| 336 | auto res = CalculateSpanBetween(time, a, b); | ||
| 337 | |||
| 338 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 339 | rb.Push(res); | ||
| 340 | rb.Push(time); | ||
| 341 | } | ||
| 342 | |||
| 343 | // =============================== Implementations =========================== | ||
| 344 | |||
| 345 | Result StaticService::GetStandardUserSystemClock( | ||
| 346 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { | ||
| 347 | R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service)); | ||
| 348 | } | ||
| 349 | |||
| 350 | Result StaticService::GetStandardNetworkSystemClock( | ||
| 351 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { | ||
| 352 | R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service)); | ||
| 353 | } | ||
| 354 | |||
| 355 | Result StaticService::GetStandardSteadyClock( | ||
| 356 | std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) { | ||
| 357 | R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service)); | ||
| 358 | } | ||
| 359 | |||
| 360 | Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) { | ||
| 361 | out_service = std::make_shared<TimeZoneService>(m_system, m_file_timestamp_worker, | ||
| 362 | m_setup_info.can_write_timezone_device_location, | ||
| 363 | m_time_zone); | ||
| 364 | R_SUCCEED(); | ||
| 365 | } | ||
| 366 | |||
| 367 | Result StaticService::GetStandardLocalSystemClock( | ||
| 368 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { | ||
| 369 | R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service)); | ||
| 370 | } | ||
| 371 | |||
| 372 | Result StaticService::GetEphemeralNetworkSystemClock( | ||
| 373 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) { | ||
| 374 | R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service)); | ||
| 375 | } | ||
| 376 | |||
| 377 | Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) { | ||
| 378 | R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory)); | 144 | R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory)); |
| 379 | } | 145 | } |
| 380 | 146 | ||
| 381 | Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { | 147 | Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { |
| 148 | LOG_DEBUG(Service_Time, "called. offset_ns={}", offset_ns); | ||
| 149 | |||
| 382 | R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied); | 150 | R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied); |
| 383 | 151 | ||
| 384 | R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset( | 152 | R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset( |
| @@ -386,62 +154,92 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { | |||
| 386 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count())); | 154 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count())); |
| 387 | } | 155 | } |
| 388 | 156 | ||
| 389 | Result StaticService::GetStandardSteadyClockRtcValue(s64& out_rtc_value) { | 157 | Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { |
| 390 | R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(out_rtc_value)); | 158 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); |
| 159 | |||
| 160 | R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value)); | ||
| 391 | } | 161 | } |
| 392 | 162 | ||
| 393 | Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( | 163 | Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( |
| 394 | bool& out_automatic_correction) { | 164 | Out<bool> out_automatic_correction) { |
| 165 | SCOPE_EXIT({ | ||
| 166 | LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction); | ||
| 167 | }); | ||
| 168 | |||
| 395 | R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( | 169 | R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( |
| 396 | out_automatic_correction)); | 170 | out_automatic_correction)); |
| 397 | } | 171 | } |
| 398 | 172 | ||
| 399 | Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( | 173 | Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( |
| 400 | bool automatic_correction) { | 174 | bool automatic_correction) { |
| 175 | LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction); | ||
| 176 | |||
| 401 | R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled( | 177 | R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled( |
| 402 | automatic_correction)); | 178 | automatic_correction)); |
| 403 | } | 179 | } |
| 404 | 180 | ||
| 405 | Result StaticService::GetStandardUserSystemClockInitialYear(s32& out_year) { | 181 | Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { |
| 406 | out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); | 182 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); }); |
| 183 | |||
| 184 | *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); | ||
| 407 | R_SUCCEED(); | 185 | R_SUCCEED(); |
| 408 | } | 186 | } |
| 409 | 187 | ||
| 410 | Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { | 188 | Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { |
| 189 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); | ||
| 190 | |||
| 411 | R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient)); | 191 | R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient)); |
| 412 | } | 192 | } |
| 413 | 193 | ||
| 414 | Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 194 | Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( |
| 415 | Service::PSC::Time::SteadyClockTimePoint& out_time_point) { | 195 | Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { |
| 196 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); | ||
| 197 | |||
| 416 | R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 198 | R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( |
| 417 | out_time_point)); | 199 | out_time_point)); |
| 418 | } | 200 | } |
| 419 | 201 | ||
| 420 | Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( | 202 | Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( |
| 421 | s64& out_time, Service::PSC::Time::SystemClockContext& context) { | 203 | Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) { |
| 204 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); | ||
| 205 | |||
| 422 | R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); | 206 | R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); |
| 423 | } | 207 | } |
| 424 | 208 | ||
| 425 | Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, | 209 | Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, |
| 426 | Service::PSC::Time::TimeType type) { | 210 | Service::PSC::Time::TimeType type) { |
| 211 | SCOPE_EXIT( | ||
| 212 | { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); | ||
| 213 | |||
| 427 | R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type)); | 214 | R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type)); |
| 428 | } | 215 | } |
| 429 | 216 | ||
| 430 | Result StaticService::GetClockSnapshotFromSystemClockContext( | 217 | Result StaticService::GetClockSnapshotFromSystemClockContext( |
| 431 | Service::PSC::Time::ClockSnapshot& out_snapshot, | 218 | Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, |
| 432 | Service::PSC::Time::SystemClockContext& user_context, | 219 | Service::PSC::Time::SystemClockContext& user_context, |
| 433 | Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) { | 220 | Service::PSC::Time::SystemClockContext& network_context) { |
| 434 | R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context, | 221 | SCOPE_EXIT({ |
| 435 | network_context, type)); | 222 | LOG_DEBUG(Service_Time, |
| 223 | "called. type={} out_snapshot={} user_context={} network_context={}", type, | ||
| 224 | *out_snapshot, user_context, network_context); | ||
| 225 | }); | ||
| 226 | |||
| 227 | R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext( | ||
| 228 | type, out_snapshot, user_context, network_context)); | ||
| 436 | } | 229 | } |
| 437 | 230 | ||
| 438 | Result StaticService::CalculateStandardUserSystemClockDifferenceByUser( | 231 | Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time, |
| 439 | s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) { | 232 | InClockSnapshot a, |
| 233 | InClockSnapshot b) { | ||
| 234 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); | ||
| 235 | |||
| 440 | R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b)); | 236 | R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b)); |
| 441 | } | 237 | } |
| 442 | 238 | ||
| 443 | Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a, | 239 | Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, |
| 444 | Service::PSC::Time::ClockSnapshot& b) { | 240 | InClockSnapshot b) { |
| 241 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); | ||
| 242 | |||
| 445 | R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b)); | 243 | R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b)); |
| 446 | } | 244 | } |
| 447 | 245 | ||
diff --git a/src/core/hle/service/glue/time/static.h b/src/core/hle/service/glue/time/static.h index 75fe4e2cd..d3cc0fdd6 100644 --- a/src/core/hle/service/glue/time/static.h +++ b/src/core/hle/service/glue/time/static.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "core/hle/service/cmif_types.h" | ||
| 7 | #include "core/hle/service/glue/time/manager.h" | 8 | #include "core/hle/service/glue/time/manager.h" |
| 8 | #include "core/hle/service/glue/time/time_zone.h" | 9 | #include "core/hle/service/glue/time/time_zone.h" |
| 9 | #include "core/hle/service/psc/time/common.h" | 10 | #include "core/hle/service/psc/time/common.h" |
| @@ -29,6 +30,10 @@ class FileTimestampWorker; | |||
| 29 | class StandardSteadyClockResource; | 30 | class StandardSteadyClockResource; |
| 30 | 31 | ||
| 31 | class StaticService final : public ServiceFramework<StaticService> { | 32 | class StaticService final : public ServiceFramework<StaticService> { |
| 33 | using InClockSnapshot = InLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>; | ||
| 34 | using OutClockSnapshot = | ||
| 35 | OutLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>; | ||
| 36 | |||
| 32 | public: | 37 | public: |
| 33 | explicit StaticService(Core::System& system, | 38 | explicit StaticService(Core::System& system, |
| 34 | Service::PSC::Time::StaticServiceSetupInfo setup_info, | 39 | Service::PSC::Time::StaticServiceSetupInfo setup_info, |
| @@ -36,65 +41,34 @@ public: | |||
| 36 | 41 | ||
| 37 | ~StaticService() override = default; | 42 | ~StaticService() override = default; |
| 38 | 43 | ||
| 39 | Result GetStandardUserSystemClock( | 44 | Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); |
| 40 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); | 45 | Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); |
| 41 | Result GetStandardNetworkSystemClock( | 46 | Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service); |
| 42 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); | 47 | Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); |
| 43 | Result GetStandardSteadyClock(std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service); | 48 | Result GetStandardLocalSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service); |
| 44 | Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service); | ||
| 45 | Result GetStandardLocalSystemClock( | ||
| 46 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); | ||
| 47 | Result GetEphemeralNetworkSystemClock( | 49 | Result GetEphemeralNetworkSystemClock( |
| 48 | std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); | 50 | OutInterface<Service::PSC::Time::SystemClock> out_service); |
| 49 | Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); | 51 | Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); |
| 50 | Result SetStandardSteadyClockInternalOffset(s64 offset); | 52 | Result SetStandardSteadyClockInternalOffset(s64 offset_ns); |
| 51 | Result GetStandardSteadyClockRtcValue(s64& out_rtc_value); | 53 | Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value); |
| 52 | Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction); | 54 | Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled); |
| 53 | Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); | 55 | Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); |
| 54 | Result GetStandardUserSystemClockInitialYear(s32& out_year); | 56 | Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); |
| 55 | Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); | 57 | Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient); |
| 56 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 58 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( |
| 57 | Service::PSC::Time::SteadyClockTimePoint& out_time_point); | 59 | Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); |
| 58 | Result CalculateMonotonicSystemClockBaseTimePoint( | 60 | Result CalculateMonotonicSystemClockBaseTimePoint( |
| 59 | s64& out_time, Service::PSC::Time::SystemClockContext& context); | 61 | Out<s64> out_time, Service::PSC::Time::SystemClockContext& context); |
| 60 | Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, | 62 | Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type); |
| 61 | Service::PSC::Time::TimeType type); | ||
| 62 | Result GetClockSnapshotFromSystemClockContext( | 63 | Result GetClockSnapshotFromSystemClockContext( |
| 63 | Service::PSC::Time::ClockSnapshot& out_snapshot, | 64 | Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, |
| 64 | Service::PSC::Time::SystemClockContext& user_context, | 65 | Service::PSC::Time::SystemClockContext& user_context, |
| 65 | Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type); | 66 | Service::PSC::Time::SystemClockContext& network_context); |
| 66 | Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, | 67 | Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, |
| 67 | Service::PSC::Time::ClockSnapshot& a, | 68 | InClockSnapshot a, InClockSnapshot b); |
| 68 | Service::PSC::Time::ClockSnapshot& b); | 69 | Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); |
| 69 | Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a, | ||
| 70 | Service::PSC::Time::ClockSnapshot& b); | ||
| 71 | 70 | ||
| 72 | private: | 71 | private: |
| 73 | Result GetClockSnapshotImpl(Service::PSC::Time::ClockSnapshot& out_snapshot, | ||
| 74 | Service::PSC::Time::SystemClockContext& user_context, | ||
| 75 | Service::PSC::Time::SystemClockContext& network_context, | ||
| 76 | Service::PSC::Time::TimeType type); | ||
| 77 | |||
| 78 | void Handle_GetStandardUserSystemClock(HLERequestContext& ctx); | ||
| 79 | void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx); | ||
| 80 | void Handle_GetStandardSteadyClock(HLERequestContext& ctx); | ||
| 81 | void Handle_GetTimeZoneService(HLERequestContext& ctx); | ||
| 82 | void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx); | ||
| 83 | void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx); | ||
| 84 | void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx); | ||
| 85 | void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx); | ||
| 86 | void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx); | ||
| 87 | void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||
| 88 | void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||
| 89 | void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx); | ||
| 90 | void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx); | ||
| 91 | void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); | ||
| 92 | void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx); | ||
| 93 | void Handle_GetClockSnapshot(HLERequestContext& ctx); | ||
| 94 | void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx); | ||
| 95 | void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx); | ||
| 96 | void Handle_CalculateSpanBetween(HLERequestContext& ctx); | ||
| 97 | |||
| 98 | Core::System& m_system; | 72 | Core::System& m_system; |
| 99 | 73 | ||
| 100 | std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; | 74 | std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; |
diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 503c327dd..98d928697 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp | |||
| @@ -3,8 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | #include <chrono> | 4 | #include <chrono> |
| 5 | 5 | ||
| 6 | #include "common/scope_exit.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/svc.h" | 8 | #include "core/hle/kernel/svc.h" |
| 9 | #include "core/hle/service/cmif_serialization.h" | ||
| 8 | #include "core/hle/service/glue/time/file_timestamp_worker.h" | 10 | #include "core/hle/service/glue/time/file_timestamp_worker.h" |
| 9 | #include "core/hle/service/glue/time/time_zone.h" | 11 | #include "core/hle/service/glue/time/time_zone.h" |
| 10 | #include "core/hle/service/glue/time/time_zone_binary.h" | 12 | #include "core/hle/service/glue/time/time_zone_binary.h" |
| @@ -28,20 +30,20 @@ TimeZoneService::TimeZoneService( | |||
| 28 | m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} { | 30 | m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} { |
| 29 | // clang-format off | 31 | // clang-format off |
| 30 | static const FunctionInfo functions[] = { | 32 | static const FunctionInfo functions[] = { |
| 31 | {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, | 33 | {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, |
| 32 | {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, | 34 | {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, |
| 33 | {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, | 35 | {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, |
| 34 | {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, | 36 | {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, |
| 35 | {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, | 37 | {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, |
| 36 | {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, | 38 | {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, |
| 37 | {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, | 39 | {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, |
| 38 | {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, | 40 | {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, |
| 39 | {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, | 41 | {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, |
| 40 | {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, | 42 | {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, |
| 41 | {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, | 43 | {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, |
| 42 | {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, | 44 | {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, |
| 43 | {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, | 45 | {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, |
| 44 | {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, | 46 | {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, |
| 45 | }; | 47 | }; |
| 46 | // clang-format on | 48 | // clang-format on |
| 47 | RegisterHandlers(functions); | 49 | RegisterHandlers(functions); |
| @@ -53,220 +55,16 @@ TimeZoneService::TimeZoneService( | |||
| 53 | 55 | ||
| 54 | TimeZoneService::~TimeZoneService() = default; | 56 | TimeZoneService::~TimeZoneService() = default; |
| 55 | 57 | ||
| 56 | void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { | 58 | Result TimeZoneService::GetDeviceLocationName( |
| 57 | LOG_DEBUG(Service_Time, "called."); | 59 | Out<Service::PSC::Time::LocationName> out_location_name) { |
| 58 | 60 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); | |
| 59 | Service::PSC::Time::LocationName name{}; | ||
| 60 | auto res = GetDeviceLocationName(name); | ||
| 61 | |||
| 62 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)}; | ||
| 63 | rb.Push(res); | ||
| 64 | rb.PushRaw<Service::PSC::Time::LocationName>(name); | ||
| 65 | } | ||
| 66 | |||
| 67 | void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) { | ||
| 68 | LOG_DEBUG(Service_Time, "called."); | ||
| 69 | |||
| 70 | IPC::RequestParser rp{ctx}; | ||
| 71 | auto name{rp.PopRaw<Service::PSC::Time::LocationName>()}; | ||
| 72 | |||
| 73 | auto res = SetDeviceLocation(name); | ||
| 74 | |||
| 75 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 76 | rb.Push(res); | ||
| 77 | } | ||
| 78 | |||
| 79 | void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) { | ||
| 80 | LOG_DEBUG(Service_Time, "called."); | ||
| 81 | |||
| 82 | u32 count{}; | ||
| 83 | auto res = GetTotalLocationNameCount(count); | ||
| 84 | |||
| 85 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 86 | rb.Push(res); | ||
| 87 | rb.Push(count); | ||
| 88 | } | ||
| 89 | |||
| 90 | void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) { | ||
| 91 | LOG_DEBUG(Service_Time, "called."); | ||
| 92 | |||
| 93 | IPC::RequestParser rp{ctx}; | ||
| 94 | auto index{rp.Pop<u32>()}; | ||
| 95 | |||
| 96 | auto max_names{ctx.GetWriteBufferSize() / sizeof(Service::PSC::Time::LocationName)}; | ||
| 97 | |||
| 98 | std::vector<Service::PSC::Time::LocationName> names{}; | ||
| 99 | u32 count{}; | ||
| 100 | auto res = LoadLocationNameList(count, names, max_names, index); | ||
| 101 | |||
| 102 | ctx.WriteBuffer(names); | ||
| 103 | |||
| 104 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 105 | rb.Push(res); | ||
| 106 | rb.Push(count); | ||
| 107 | } | ||
| 108 | |||
| 109 | void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) { | ||
| 110 | LOG_DEBUG(Service_Time, "called."); | ||
| 111 | |||
| 112 | IPC::RequestParser rp{ctx}; | ||
| 113 | auto name{rp.PopRaw<Service::PSC::Time::LocationName>()}; | ||
| 114 | |||
| 115 | Tz::Rule rule{}; | ||
| 116 | auto res = LoadTimeZoneRule(rule, name); | ||
| 117 | |||
| 118 | ctx.WriteBuffer(rule); | ||
| 119 | |||
| 120 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 121 | rb.Push(res); | ||
| 122 | } | ||
| 123 | |||
| 124 | void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) { | ||
| 125 | LOG_DEBUG(Service_Time, "called."); | ||
| 126 | |||
| 127 | Service::PSC::Time::RuleVersion rule_version{}; | ||
| 128 | auto res = GetTimeZoneRuleVersion(rule_version); | ||
| 129 | |||
| 130 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::RuleVersion) / sizeof(u32)}; | ||
| 131 | rb.Push(res); | ||
| 132 | rb.PushRaw<Service::PSC::Time::RuleVersion>(rule_version); | ||
| 133 | } | ||
| 134 | |||
| 135 | void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) { | ||
| 136 | LOG_DEBUG(Service_Time, "called."); | ||
| 137 | |||
| 138 | Service::PSC::Time::LocationName name{}; | ||
| 139 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | ||
| 140 | auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name); | ||
| 141 | |||
| 142 | IPC::ResponseBuilder rb{ctx, | ||
| 143 | 2 + (sizeof(Service::PSC::Time::LocationName) / sizeof(u32)) + | ||
| 144 | (sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32))}; | ||
| 145 | rb.Push(res); | ||
| 146 | rb.PushRaw<Service::PSC::Time::LocationName>(name); | ||
| 147 | rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); | ||
| 148 | } | ||
| 149 | |||
| 150 | void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) { | ||
| 151 | LOG_DEBUG(Service_Time, "called."); | ||
| 152 | |||
| 153 | auto res = SetDeviceLocationNameWithTimeZoneRule(); | ||
| 154 | |||
| 155 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 156 | rb.Push(res); | ||
| 157 | } | ||
| 158 | |||
| 159 | void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) { | ||
| 160 | LOG_DEBUG(Service_Time, "called."); | ||
| 161 | |||
| 162 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 163 | rb.Push(Service::PSC::Time::ResultNotImplemented); | ||
| 164 | } | ||
| 165 | |||
| 166 | void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle( | ||
| 167 | HLERequestContext& ctx) { | ||
| 168 | LOG_DEBUG(Service_Time, "called."); | ||
| 169 | 61 | ||
| 170 | Kernel::KEvent* event{}; | ||
| 171 | auto res = GetDeviceLocationNameOperationEventReadableHandle(&event); | ||
| 172 | |||
| 173 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 174 | rb.Push(res); | ||
| 175 | rb.PushCopyObjects(event->GetReadableEvent()); | ||
| 176 | } | ||
| 177 | |||
| 178 | void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) { | ||
| 179 | LOG_DEBUG(Service_Time, "called."); | ||
| 180 | |||
| 181 | IPC::RequestParser rp{ctx}; | ||
| 182 | auto time{rp.Pop<s64>()}; | ||
| 183 | |||
| 184 | auto rule_buffer{ctx.ReadBuffer()}; | ||
| 185 | Tz::Rule rule{}; | ||
| 186 | std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule)); | ||
| 187 | |||
| 188 | Service::PSC::Time::CalendarTime calendar_time{}; | ||
| 189 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; | ||
| 190 | auto res = ToCalendarTime(calendar_time, additional_info, time, rule); | ||
| 191 | |||
| 192 | IPC::ResponseBuilder rb{ctx, | ||
| 193 | 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) + | ||
| 194 | (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))}; | ||
| 195 | rb.Push(res); | ||
| 196 | rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time); | ||
| 197 | rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info); | ||
| 198 | } | ||
| 199 | |||
| 200 | void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) { | ||
| 201 | IPC::RequestParser rp{ctx}; | ||
| 202 | auto time{rp.Pop<s64>()}; | ||
| 203 | |||
| 204 | LOG_DEBUG(Service_Time, "called. time={}", time); | ||
| 205 | |||
| 206 | Service::PSC::Time::CalendarTime calendar_time{}; | ||
| 207 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; | ||
| 208 | auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time); | ||
| 209 | |||
| 210 | IPC::ResponseBuilder rb{ctx, | ||
| 211 | 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) + | ||
| 212 | (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))}; | ||
| 213 | rb.Push(res); | ||
| 214 | rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time); | ||
| 215 | rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info); | ||
| 216 | } | ||
| 217 | |||
| 218 | void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) { | ||
| 219 | IPC::RequestParser rp{ctx}; | ||
| 220 | auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()}; | ||
| 221 | |||
| 222 | LOG_DEBUG(Service_Time, "called. calendar year {} month {} day {} hour {} minute {} second {}", | ||
| 223 | calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute, | ||
| 224 | calendar.second); | ||
| 225 | |||
| 226 | auto binary{ctx.ReadBuffer()}; | ||
| 227 | |||
| 228 | Tz::Rule rule{}; | ||
| 229 | std::memcpy(&rule, binary.data(), sizeof(Tz::Rule)); | ||
| 230 | |||
| 231 | u32 count{}; | ||
| 232 | std::array<s64, 2> times{}; | ||
| 233 | u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; | ||
| 234 | |||
| 235 | auto res = ToPosixTime(count, times, times_count, calendar, rule); | ||
| 236 | |||
| 237 | ctx.WriteBuffer(times); | ||
| 238 | |||
| 239 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 240 | rb.Push(res); | ||
| 241 | rb.Push(count); | ||
| 242 | } | ||
| 243 | |||
| 244 | void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) { | ||
| 245 | LOG_DEBUG(Service_Time, "called."); | ||
| 246 | |||
| 247 | IPC::RequestParser rp{ctx}; | ||
| 248 | auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()}; | ||
| 249 | |||
| 250 | u32 count{}; | ||
| 251 | std::array<s64, 2> times{}; | ||
| 252 | u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; | ||
| 253 | |||
| 254 | auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar); | ||
| 255 | |||
| 256 | ctx.WriteBuffer(times); | ||
| 257 | |||
| 258 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 259 | rb.Push(res); | ||
| 260 | rb.Push(count); | ||
| 261 | } | ||
| 262 | |||
| 263 | // =============================== Implementations =========================== | ||
| 264 | |||
| 265 | Result TimeZoneService::GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name) { | ||
| 266 | R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); | 62 | R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); |
| 267 | } | 63 | } |
| 268 | 64 | ||
| 269 | Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& location_name) { | 65 | Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) { |
| 66 | LOG_DEBUG(Service_Time, "called. location_name={}", location_name); | ||
| 67 | |||
| 270 | R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); | 68 | R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); |
| 271 | R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound); | 69 | R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound); |
| 272 | 70 | ||
| @@ -282,7 +80,7 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca | |||
| 282 | 80 | ||
| 283 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 81 | Service::PSC::Time::SteadyClockTimePoint time_point{}; |
| 284 | Service::PSC::Time::LocationName name{}; | 82 | Service::PSC::Time::LocationName name{}; |
| 285 | R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name)); | 83 | R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point)); |
| 286 | 84 | ||
| 287 | m_set_sys->SetDeviceTimeZoneLocationName(name); | 85 | m_set_sys->SetDeviceTimeZoneLocationName(name); |
| 288 | m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point); | 86 | m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point); |
| @@ -294,19 +92,27 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca | |||
| 294 | R_SUCCEED(); | 92 | R_SUCCEED(); |
| 295 | } | 93 | } |
| 296 | 94 | ||
| 297 | Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { | 95 | Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { |
| 96 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); | ||
| 97 | |||
| 298 | R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); | 98 | R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); |
| 299 | } | 99 | } |
| 300 | 100 | ||
| 301 | Result TimeZoneService::LoadLocationNameList( | 101 | Result TimeZoneService::LoadLocationNameList( |
| 302 | u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names, | 102 | Out<u32> out_count, |
| 303 | u32 index) { | 103 | OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { |
| 104 | SCOPE_EXIT({ | ||
| 105 | LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}", | ||
| 106 | index, *out_count, out_names[0], out_names[1]); | ||
| 107 | }); | ||
| 108 | |||
| 304 | std::scoped_lock l{m_mutex}; | 109 | std::scoped_lock l{m_mutex}; |
| 305 | R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index)); | 110 | R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); |
| 306 | } | 111 | } |
| 307 | 112 | ||
| 308 | Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule, | 113 | Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) { |
| 309 | Service::PSC::Time::LocationName& name) { | 114 | LOG_DEBUG(Service_Time, "called. name={}", name); |
| 115 | |||
| 310 | std::scoped_lock l{m_mutex}; | 116 | std::scoped_lock l{m_mutex}; |
| 311 | std::span<const u8> binary{}; | 117 | std::span<const u8> binary{}; |
| 312 | size_t binary_size{}; | 118 | size_t binary_size{}; |
| @@ -314,23 +120,43 @@ Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule, | |||
| 314 | R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary)); | 120 | R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary)); |
| 315 | } | 121 | } |
| 316 | 122 | ||
| 317 | Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) { | 123 | Result TimeZoneService::GetTimeZoneRuleVersion( |
| 124 | Out<Service::PSC::Time::RuleVersion> out_rule_version) { | ||
| 125 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); | ||
| 126 | |||
| 318 | R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version)); | 127 | R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version)); |
| 319 | } | 128 | } |
| 320 | 129 | ||
| 321 | Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( | 130 | Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( |
| 322 | Service::PSC::Time::SteadyClockTimePoint& out_time_point, | 131 | Out<Service::PSC::Time::LocationName> location_name, |
| 323 | Service::PSC::Time::LocationName& location_name) { | 132 | Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { |
| 324 | R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name)); | 133 | SCOPE_EXIT({ |
| 134 | LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name, | ||
| 135 | *out_time_point); | ||
| 136 | }); | ||
| 137 | |||
| 138 | R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point)); | ||
| 325 | } | 139 | } |
| 326 | 140 | ||
| 327 | Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule() { | 141 | Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( |
| 142 | Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { | ||
| 143 | LOG_DEBUG(Service_Time, "called. location_name={}", location_name); | ||
| 144 | |||
| 328 | R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); | 145 | R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); |
| 329 | R_RETURN(Service::PSC::Time::ResultNotImplemented); | 146 | R_RETURN(Service::PSC::Time::ResultNotImplemented); |
| 330 | } | 147 | } |
| 331 | 148 | ||
| 149 | Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule, | ||
| 150 | InBuffer<BufferAttr_HipcAutoSelect> binary) { | ||
| 151 | LOG_DEBUG(Service_Time, "called."); | ||
| 152 | |||
| 153 | R_RETURN(Service::PSC::Time::ResultNotImplemented); | ||
| 154 | } | ||
| 155 | |||
| 332 | Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( | 156 | Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( |
| 333 | Kernel::KEvent** out_event) { | 157 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 158 | LOG_DEBUG(Service_Time, "called."); | ||
| 159 | |||
| 334 | if (!operation_event_initialized) { | 160 | if (!operation_event_initialized) { |
| 335 | operation_event_initialized = false; | 161 | operation_event_initialized = false; |
| 336 | 162 | ||
| @@ -342,36 +168,56 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( | |||
| 342 | g_list_nodes.push_back(m_operation_event); | 168 | g_list_nodes.push_back(m_operation_event); |
| 343 | } | 169 | } |
| 344 | 170 | ||
| 345 | *out_event = m_operation_event.m_event; | 171 | *out_event = &m_operation_event.m_event->GetReadableEvent(); |
| 346 | R_SUCCEED(); | 172 | R_SUCCEED(); |
| 347 | } | 173 | } |
| 348 | 174 | ||
| 349 | Result TimeZoneService::ToCalendarTime( | 175 | Result TimeZoneService::ToCalendarTime( |
| 350 | Service::PSC::Time::CalendarTime& out_calendar_time, | 176 | Out<Service::PSC::Time::CalendarTime> out_calendar_time, |
| 351 | Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule) { | 177 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { |
| 178 | SCOPE_EXIT({ | ||
| 179 | LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, | ||
| 180 | *out_calendar_time, *out_additional_info); | ||
| 181 | }); | ||
| 182 | |||
| 352 | R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); | 183 | R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); |
| 353 | } | 184 | } |
| 354 | 185 | ||
| 355 | Result TimeZoneService::ToCalendarTimeWithMyRule( | 186 | Result TimeZoneService::ToCalendarTimeWithMyRule( |
| 356 | Service::PSC::Time::CalendarTime& out_calendar_time, | 187 | Out<Service::PSC::Time::CalendarTime> out_calendar_time, |
| 357 | Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time) { | 188 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) { |
| 189 | SCOPE_EXIT({ | ||
| 190 | LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, | ||
| 191 | *out_calendar_time, *out_additional_info); | ||
| 192 | }); | ||
| 193 | |||
| 358 | R_RETURN( | 194 | R_RETURN( |
| 359 | m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); | 195 | m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); |
| 360 | } | 196 | } |
| 361 | 197 | ||
| 362 | Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, | 198 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, |
| 363 | u32 out_times_count, | 199 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 364 | Service::PSC::Time::CalendarTime& calendar_time, | 200 | const Service::PSC::Time::CalendarTime& calendar_time, |
| 365 | Tz::Rule& rule) { | 201 | InRule rule) { |
| 366 | R_RETURN( | 202 | SCOPE_EXIT({ |
| 367 | m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); | 203 | LOG_DEBUG(Service_Time, |
| 204 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", | ||
| 205 | calendar_time, *out_count, out_times[0], out_times[1]); | ||
| 206 | }); | ||
| 207 | |||
| 208 | R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule)); | ||
| 368 | } | 209 | } |
| 369 | 210 | ||
| 370 | Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, | 211 | Result TimeZoneService::ToPosixTimeWithMyRule( |
| 371 | u32 out_times_count, | 212 | Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 372 | Service::PSC::Time::CalendarTime& calendar_time) { | 213 | const Service::PSC::Time::CalendarTime& calendar_time) { |
| 373 | R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count, | 214 | SCOPE_EXIT({ |
| 374 | calendar_time)); | 215 | LOG_DEBUG(Service_Time, |
| 216 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", | ||
| 217 | calendar_time, *out_count, out_times[0], out_times[1]); | ||
| 218 | }); | ||
| 219 | |||
| 220 | R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time)); | ||
| 375 | } | 221 | } |
| 376 | 222 | ||
| 377 | } // namespace Service::Glue::Time | 223 | } // namespace Service::Glue::Time |
diff --git a/src/core/hle/service/glue/time/time_zone.h b/src/core/hle/service/glue/time/time_zone.h index 3c8ae4bf8..9c1530966 100644 --- a/src/core/hle/service/glue/time/time_zone.h +++ b/src/core/hle/service/glue/time/time_zone.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <span> | 8 | #include <span> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "core/hle/service/cmif_types.h" | ||
| 11 | #include "core/hle/service/ipc_helpers.h" | 12 | #include "core/hle/service/ipc_helpers.h" |
| 12 | #include "core/hle/service/psc/time/common.h" | 13 | #include "core/hle/service/psc/time/common.h" |
| 13 | #include "core/hle/service/server_manager.h" | 14 | #include "core/hle/service/server_manager.h" |
| @@ -33,6 +34,9 @@ namespace Service::Glue::Time { | |||
| 33 | class FileTimestampWorker; | 34 | class FileTimestampWorker; |
| 34 | 35 | ||
| 35 | class TimeZoneService final : public ServiceFramework<TimeZoneService> { | 36 | class TimeZoneService final : public ServiceFramework<TimeZoneService> { |
| 37 | using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; | ||
| 38 | using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; | ||
| 39 | |||
| 36 | public: | 40 | public: |
| 37 | explicit TimeZoneService( | 41 | explicit TimeZoneService( |
| 38 | Core::System& system, FileTimestampWorker& file_timestamp_worker, | 42 | Core::System& system, FileTimestampWorker& file_timestamp_worker, |
| @@ -41,46 +45,35 @@ public: | |||
| 41 | 45 | ||
| 42 | ~TimeZoneService() override; | 46 | ~TimeZoneService() override; |
| 43 | 47 | ||
| 44 | Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name); | 48 | Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name); |
| 45 | Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name); | 49 | Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name); |
| 46 | Result GetTotalLocationNameCount(u32& out_count); | 50 | Result GetTotalLocationNameCount(Out<u32> out_count); |
| 47 | Result LoadLocationNameList(u32& out_count, | 51 | Result LoadLocationNameList( |
| 48 | std::vector<Service::PSC::Time::LocationName>& out_names, | 52 | Out<u32> out_count, |
| 49 | size_t max_names, u32 index); | 53 | OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index); |
| 50 | Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name); | 54 | Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name); |
| 51 | Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version); | 55 | Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version); |
| 52 | Result GetDeviceLocationNameAndUpdatedTime( | 56 | Result GetDeviceLocationNameAndUpdatedTime( |
| 53 | Service::PSC::Time::SteadyClockTimePoint& out_time_point, | 57 | Out<Service::PSC::Time::LocationName> location_name, |
| 54 | Service::PSC::Time::LocationName& location_name); | 58 | Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); |
| 55 | Result SetDeviceLocationNameWithTimeZoneRule(); | 59 | Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name, |
| 56 | Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event); | 60 | InBuffer<BufferAttr_HipcAutoSelect> binary); |
| 57 | Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time, | 61 | Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); |
| 58 | Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, | 62 | Result GetDeviceLocationNameOperationEventReadableHandle( |
| 59 | Tz::Rule& rule); | 63 | OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 60 | Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time, | 64 | Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time, |
| 61 | Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, | 65 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, |
| 62 | s64 time); | 66 | s64 time, InRule rule); |
| 63 | Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 67 | Result ToCalendarTimeWithMyRule( |
| 64 | Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule); | 68 | Out<Service::PSC::Time::CalendarTime> out_calendar_time, |
| 65 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 69 | Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time); |
| 66 | Service::PSC::Time::CalendarTime& calendar_time); | 70 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 71 | const Service::PSC::Time::CalendarTime& calendar_time, InRule rule); | ||
| 72 | Result ToPosixTimeWithMyRule(Out<u32> out_count, | ||
| 73 | OutArray<s64, BufferAttr_HipcPointer> out_times, | ||
| 74 | const Service::PSC::Time::CalendarTime& calendar_time); | ||
| 67 | 75 | ||
| 68 | private: | 76 | private: |
| 69 | void Handle_GetDeviceLocationName(HLERequestContext& ctx); | ||
| 70 | void Handle_SetDeviceLocationName(HLERequestContext& ctx); | ||
| 71 | void Handle_GetTotalLocationNameCount(HLERequestContext& ctx); | ||
| 72 | void Handle_LoadLocationNameList(HLERequestContext& ctx); | ||
| 73 | void Handle_LoadTimeZoneRule(HLERequestContext& ctx); | ||
| 74 | void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx); | ||
| 75 | void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx); | ||
| 76 | void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx); | ||
| 77 | void Handle_ParseTimeZoneBinary(HLERequestContext& ctx); | ||
| 78 | void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx); | ||
| 79 | void Handle_ToCalendarTime(HLERequestContext& ctx); | ||
| 80 | void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx); | ||
| 81 | void Handle_ToPosixTime(HLERequestContext& ctx); | ||
| 82 | void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx); | ||
| 83 | |||
| 84 | Core::System& m_system; | 77 | Core::System& m_system; |
| 85 | std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; | 78 | std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; |
| 86 | 79 | ||
diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp index d33f784c0..cc50b6b7b 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.cpp +++ b/src/core/hle/service/glue/time/time_zone_binary.cpp | |||
| @@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName | |||
| 103 | return; | 103 | return; |
| 104 | } | 104 | } |
| 105 | // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name); | 105 | // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name); |
| 106 | out_path = fmt::format("/zoneinfo/{}", name.name.data()); | 106 | out_path = fmt::format("/zoneinfo/{}", name.data()); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { | 109 | bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { |
| @@ -169,7 +169,7 @@ Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | Result GetTimeZoneLocationList(u32& out_count, | 171 | Result GetTimeZoneLocationList(u32& out_count, |
| 172 | std::vector<Service::PSC::Time::LocationName>& out_names, | 172 | std::span<Service::PSC::Time::LocationName> out_names, |
| 173 | size_t max_names, u32 index) { | 173 | size_t max_names, u32 index) { |
| 174 | std::string path{}; | 174 | std::string path{}; |
| 175 | GetTimeZoneBinaryListPath(path); | 175 | GetTimeZoneBinaryListPath(path); |
| @@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count, | |||
| 193 | 193 | ||
| 194 | if (chr == '\n') { | 194 | if (chr == '\n') { |
| 195 | if (name_count >= index) { | 195 | if (name_count >= index) { |
| 196 | out_names.push_back(current_name); | 196 | out_names[out_count] = current_name; |
| 197 | out_count++; | 197 | out_count++; |
| 198 | if (out_count >= max_names) { | 198 | if (out_count >= max_names) { |
| 199 | break; | 199 | break; |
| @@ -209,10 +209,9 @@ Result GetTimeZoneLocationList(u32& out_count, | |||
| 209 | break; | 209 | break; |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | R_UNLESS(current_name_len <= current_name.name.size() - 2, | 212 | R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed); |
| 213 | Service::PSC::Time::ResultFailed); | ||
| 214 | 213 | ||
| 215 | current_name.name[current_name_len++] = chr; | 214 | current_name[current_name_len++] = chr; |
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | R_SUCCEED(); | 217 | R_SUCCEED(); |
diff --git a/src/core/hle/service/glue/time/time_zone_binary.h b/src/core/hle/service/glue/time/time_zone_binary.h index 2cad6b458..461f4577e 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.h +++ b/src/core/hle/service/glue/time/time_zone_binary.h | |||
| @@ -26,7 +26,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version); | |||
| 26 | Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, | 26 | Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, |
| 27 | Service::PSC::Time::LocationName& name); | 27 | Service::PSC::Time::LocationName& name); |
| 28 | Result GetTimeZoneLocationList(u32& out_count, | 28 | Result GetTimeZoneLocationList(u32& out_count, |
| 29 | std::vector<Service::PSC::Time::LocationName>& out_names, | 29 | std::span<Service::PSC::Time::LocationName> out_names, |
| 30 | size_t max_names, u32 index); | 30 | size_t max_names, u32 index); |
| 31 | 31 | ||
| 32 | } // namespace Service::Glue::Time | 32 | } // namespace Service::Glue::Time |
diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index ea0e49b90..f44f3077e 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp | |||
| @@ -38,11 +38,12 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set | |||
| 38 | 38 | ||
| 39 | TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, | 39 | TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, |
| 40 | FileTimestampWorker& file_timestamp_worker) | 40 | FileTimestampWorker& file_timestamp_worker) |
| 41 | : m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")}, | 41 | : m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent( |
| 42 | "Glue:TimeWorker:Event")}, | ||
| 42 | m_steady_clock_resource{steady_clock_resource}, | 43 | m_steady_clock_resource{steady_clock_resource}, |
| 43 | m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( | 44 | m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( |
| 44 | "Glue:58:SteadyClockTimerEvent")}, | 45 | "Glue:TimeWorker:SteadyClockTimerEvent")}, |
| 45 | m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")}, | 46 | m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}, |
| 46 | m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { | 47 | m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { |
| 47 | g_ig_report_network_clock_context_set = false; | 48 | g_ig_report_network_clock_context_set = false; |
| 48 | g_report_network_clock_context = {}; | 49 | g_report_network_clock_context = {}; |
| @@ -113,17 +114,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t | |||
| 113 | std::chrono::nanoseconds(fs_notify_time_ns), | 114 | std::chrono::nanoseconds(fs_notify_time_ns), |
| 114 | m_timer_file_system_timing_event); | 115 | m_timer_file_system_timing_event); |
| 115 | 116 | ||
| 116 | auto res = m_time_sm->GetStandardLocalSystemClock(m_local_clock); | 117 | auto res = m_time_sm->GetStandardLocalSystemClock(&m_local_clock); |
| 117 | ASSERT(res == ResultSuccess); | 118 | ASSERT(res == ResultSuccess); |
| 118 | res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event); | 119 | res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event); |
| 119 | ASSERT(res == ResultSuccess); | 120 | ASSERT(res == ResultSuccess); |
| 120 | 121 | ||
| 121 | res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock); | 122 | res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock); |
| 122 | ASSERT(res == ResultSuccess); | 123 | ASSERT(res == ResultSuccess); |
| 123 | res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event); | 124 | res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event); |
| 124 | ASSERT(res == ResultSuccess); | 125 | ASSERT(res == ResultSuccess); |
| 125 | 126 | ||
| 126 | res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock); | 127 | res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock); |
| 127 | ASSERT(res == ResultSuccess); | 128 | ASSERT(res == ResultSuccess); |
| 128 | res = | 129 | res = |
| 129 | m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event); | 130 | m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event); |
| @@ -183,22 +184,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { | |||
| 183 | AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); | 184 | AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); |
| 184 | // TODO | 185 | // TODO |
| 185 | // AddWaiter(gIPmModuleService::GetEvent(), 1); | 186 | // AddWaiter(gIPmModuleService::GetEvent(), 1); |
| 186 | AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); | 187 | AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); |
| 187 | } else { | 188 | } else { |
| 188 | AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); | 189 | AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); |
| 189 | // TODO | 190 | // TODO |
| 190 | // AddWaiter(gIPmModuleService::GetEvent(), 1); | 191 | // AddWaiter(gIPmModuleService::GetEvent(), 1); |
| 191 | AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); | 192 | AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange); |
| 192 | AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms); | 193 | AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms); |
| 193 | AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock); | 194 | AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock); |
| 194 | AddWaiter(&m_network_clock_event->GetReadableEvent(), | 195 | AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock); |
| 195 | EventType::UpdateNetworkSystemClock); | 196 | AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock); |
| 196 | AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(), | ||
| 197 | EventType::UpdateEphemeralSystemClock); | ||
| 198 | AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock); | 197 | AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock); |
| 199 | AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp); | 198 | AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp); |
| 200 | AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(), | 199 | AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect); |
| 201 | EventType::AutoCorrect); | ||
| 202 | } | 200 | } |
| 203 | 201 | ||
| 204 | s32 out_index{-1}; | 202 | s32 out_index{-1}; |
| @@ -237,7 +235,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { | |||
| 237 | m_local_clock_event->Clear(); | 235 | m_local_clock_event->Clear(); |
| 238 | 236 | ||
| 239 | Service::PSC::Time::SystemClockContext context{}; | 237 | Service::PSC::Time::SystemClockContext context{}; |
| 240 | auto res = m_local_clock->GetSystemClockContext(context); | 238 | auto res = m_local_clock->GetSystemClockContext(&context); |
| 241 | ASSERT(res == ResultSuccess); | 239 | ASSERT(res == ResultSuccess); |
| 242 | 240 | ||
| 243 | m_set_sys->SetUserSystemClockContext(context); | 241 | m_set_sys->SetUserSystemClockContext(context); |
| @@ -248,12 +246,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { | |||
| 248 | case EventType::UpdateNetworkSystemClock: { | 246 | case EventType::UpdateNetworkSystemClock: { |
| 249 | m_network_clock_event->Clear(); | 247 | m_network_clock_event->Clear(); |
| 250 | Service::PSC::Time::SystemClockContext context{}; | 248 | Service::PSC::Time::SystemClockContext context{}; |
| 251 | auto res = m_network_clock->GetSystemClockContext(context); | 249 | auto res = m_network_clock->GetSystemClockContext(&context); |
| 252 | ASSERT(res == ResultSuccess); | 250 | ASSERT(res == ResultSuccess); |
| 253 | m_set_sys->SetNetworkSystemClockContext(context); | 251 | m_set_sys->SetNetworkSystemClockContext(context); |
| 254 | 252 | ||
| 255 | s64 time{}; | 253 | s64 time{}; |
| 256 | if (m_network_clock->GetCurrentTime(time) != ResultSuccess) { | 254 | if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) { |
| 257 | break; | 255 | break; |
| 258 | } | 256 | } |
| 259 | 257 | ||
| @@ -275,13 +273,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { | |||
| 275 | m_ephemeral_clock_event->Clear(); | 273 | m_ephemeral_clock_event->Clear(); |
| 276 | 274 | ||
| 277 | Service::PSC::Time::SystemClockContext context{}; | 275 | Service::PSC::Time::SystemClockContext context{}; |
| 278 | auto res = m_ephemeral_clock->GetSystemClockContext(context); | 276 | auto res = m_ephemeral_clock->GetSystemClockContext(&context); |
| 279 | if (res != ResultSuccess) { | 277 | if (res != ResultSuccess) { |
| 280 | break; | 278 | break; |
| 281 | } | 279 | } |
| 282 | 280 | ||
| 283 | s64 time{}; | 281 | s64 time{}; |
| 284 | res = m_ephemeral_clock->GetCurrentTime(time); | 282 | res = m_ephemeral_clock->GetCurrentTime(&time); |
| 285 | if (res != ResultSuccess) { | 283 | if (res != ResultSuccess) { |
| 286 | break; | 284 | break; |
| 287 | } | 285 | } |
| @@ -317,11 +315,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { | |||
| 317 | 315 | ||
| 318 | bool automatic_correction{}; | 316 | bool automatic_correction{}; |
| 319 | auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( | 317 | auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( |
| 320 | automatic_correction); | 318 | &automatic_correction); |
| 321 | ASSERT(res == ResultSuccess); | 319 | ASSERT(res == ResultSuccess); |
| 322 | 320 | ||
| 323 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 321 | Service::PSC::Time::SteadyClockTimePoint time_point{}; |
| 324 | res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); | 322 | res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point); |
| 325 | ASSERT(res == ResultSuccess); | 323 | ASSERT(res == ResultSuccess); |
| 326 | 324 | ||
| 327 | m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction); | 325 | m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction); |
diff --git a/src/core/hle/service/glue/time/worker.h b/src/core/hle/service/glue/time/worker.h index adbbe6b6d..75e5c4d0f 100644 --- a/src/core/hle/service/glue/time/worker.h +++ b/src/core/hle/service/glue/time/worker.h | |||
| @@ -49,10 +49,10 @@ private: | |||
| 49 | std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock; | 49 | std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock; |
| 50 | StandardSteadyClockResource& m_steady_clock_resource; | 50 | StandardSteadyClockResource& m_steady_clock_resource; |
| 51 | FileTimestampWorker& m_file_timestamp_worker; | 51 | FileTimestampWorker& m_file_timestamp_worker; |
| 52 | Kernel::KEvent* m_local_clock_event{}; | 52 | Kernel::KReadableEvent* m_local_clock_event{}; |
| 53 | Kernel::KEvent* m_network_clock_event{}; | 53 | Kernel::KReadableEvent* m_network_clock_event{}; |
| 54 | Kernel::KEvent* m_ephemeral_clock_event{}; | 54 | Kernel::KReadableEvent* m_ephemeral_clock_event{}; |
| 55 | Kernel::KEvent* m_standard_user_auto_correct_clock_event{}; | 55 | Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{}; |
| 56 | Kernel::KEvent* m_timer_steady_clock{}; | 56 | Kernel::KEvent* m_timer_steady_clock{}; |
| 57 | std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event; | 57 | std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event; |
| 58 | Kernel::KEvent* m_timer_file_system{}; | 58 | Kernel::KEvent* m_timer_file_system{}; |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 9ffe027ff..3603d8ccf 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/kernel/k_shared_memory.h" | 8 | #include "core/hle/kernel/k_shared_memory.h" |
| 9 | #include "core/hle/kernel/k_transfer_memory.h" | 9 | #include "core/hle/kernel/k_transfer_memory.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/service/cmif_serialization.h" | ||
| 11 | #include "core/hle/service/hid/hid_server.h" | 12 | #include "core/hle/service/hid/hid_server.h" |
| 12 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 13 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| @@ -153,7 +154,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r | |||
| 153 | {104, &IHidServer::DeactivateNpad, "DeactivateNpad"}, | 154 | {104, &IHidServer::DeactivateNpad, "DeactivateNpad"}, |
| 154 | {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, | 155 | {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, |
| 155 | {107, &IHidServer::DisconnectNpad, "DisconnectNpad"}, | 156 | {107, &IHidServer::DisconnectNpad, "DisconnectNpad"}, |
| 156 | {108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"}, | 157 | {108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"}, |
| 157 | {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, | 158 | {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, |
| 158 | {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, | 159 | {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, |
| 159 | {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, | 160 | {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, |
| @@ -1135,19 +1136,39 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) { | |||
| 1135 | rb.Push(ResultSuccess); | 1136 | rb.Push(ResultSuccess); |
| 1136 | } | 1137 | } |
| 1137 | 1138 | ||
| 1138 | void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { | 1139 | Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, |
| 1139 | IPC::RequestParser rp{ctx}; | 1140 | Core::HID::NpadIdType npad_id) { |
| 1140 | const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()}; | ||
| 1141 | |||
| 1142 | Core::HID::LedPattern pattern{0, 0, 0, 0}; | ||
| 1143 | auto controller = GetResourceManager()->GetNpad(); | ||
| 1144 | const auto result = controller->GetLedPattern(npad_id, pattern); | ||
| 1145 | |||
| 1146 | LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); | 1141 | LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); |
| 1147 | 1142 | ||
| 1148 | IPC::ResponseBuilder rb{ctx, 4}; | 1143 | switch (npad_id) { |
| 1149 | rb.Push(result); | 1144 | case Core::HID::NpadIdType::Player1: |
| 1150 | rb.Push(pattern.raw); | 1145 | *out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0}; |
| 1146 | R_SUCCEED(); | ||
| 1147 | case Core::HID::NpadIdType::Player2: | ||
| 1148 | *out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0}; | ||
| 1149 | R_SUCCEED(); | ||
| 1150 | case Core::HID::NpadIdType::Player3: | ||
| 1151 | *out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0}; | ||
| 1152 | R_SUCCEED(); | ||
| 1153 | case Core::HID::NpadIdType::Player4: | ||
| 1154 | *out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1}; | ||
| 1155 | R_SUCCEED(); | ||
| 1156 | case Core::HID::NpadIdType::Player5: | ||
| 1157 | *out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1}; | ||
| 1158 | R_SUCCEED(); | ||
| 1159 | case Core::HID::NpadIdType::Player6: | ||
| 1160 | *out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0}; | ||
| 1161 | R_SUCCEED(); | ||
| 1162 | case Core::HID::NpadIdType::Player7: | ||
| 1163 | *out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1}; | ||
| 1164 | R_SUCCEED(); | ||
| 1165 | case Core::HID::NpadIdType::Player8: | ||
| 1166 | *out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0}; | ||
| 1167 | R_SUCCEED(); | ||
| 1168 | default: | ||
| 1169 | *out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0}; | ||
| 1170 | R_SUCCEED(); | ||
| 1171 | } | ||
| 1151 | } | 1172 | } |
| 1152 | 1173 | ||
| 1153 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { | 1174 | void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index 3a2e0a230..faf775689 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h | |||
| @@ -3,7 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "hid_core/hid_types.h" | ||
| 7 | 9 | ||
| 8 | namespace Core { | 10 | namespace Core { |
| 9 | class System; | 11 | class System; |
| @@ -66,7 +68,8 @@ private: | |||
| 66 | void DeactivateNpad(HLERequestContext& ctx); | 68 | void DeactivateNpad(HLERequestContext& ctx); |
| 67 | void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); | 69 | void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx); |
| 68 | void DisconnectNpad(HLERequestContext& ctx); | 70 | void DisconnectNpad(HLERequestContext& ctx); |
| 69 | void GetPlayerLedPattern(HLERequestContext& ctx); | 71 | Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern, |
| 72 | Core::HID::NpadIdType npad_id); | ||
| 70 | void ActivateNpadWithRevision(HLERequestContext& ctx); | 73 | void ActivateNpadWithRevision(HLERequestContext& ctx); |
| 71 | void SetNpadJoyHoldType(HLERequestContext& ctx); | 74 | void SetNpadJoyHoldType(HLERequestContext& ctx); |
| 72 | void GetNpadJoyHoldType(HLERequestContext& ctx); | 75 | void GetNpadJoyHoldType(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index b4d16fed5..efb7f6e32 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -111,7 +111,8 @@ private: | |||
| 111 | R_RETURN(result); | 111 | R_RETURN(result); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) { | 114 | Result UpdateLatest(Out<CharInfo> out_char_info, const CharInfo& char_info, |
| 115 | SourceFlag source_flag) { | ||
| 115 | LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); | 116 | LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); |
| 116 | 117 | ||
| 117 | R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag)); | 118 | R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag)); |
| @@ -159,7 +160,7 @@ private: | |||
| 159 | R_RETURN(result); | 160 | R_RETURN(result); |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data, | 163 | Result UpdateLatest1(Out<StoreData> out_store_data, const StoreData& store_data, |
| 163 | SourceFlag source_flag) { | 164 | SourceFlag source_flag) { |
| 164 | LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); | 165 | LOG_INFO(Service_Mii, "called with source_flag={}", source_flag); |
| 165 | R_UNLESS(is_system, ResultPermissionDenied); | 166 | R_UNLESS(is_system, ResultPermissionDenied); |
| @@ -243,7 +244,7 @@ private: | |||
| 243 | R_SUCCEED(); | 244 | R_SUCCEED(); |
| 244 | } | 245 | } |
| 245 | 246 | ||
| 246 | Result GetIndex(Out<s32> out_index, CharInfo& char_info) { | 247 | Result GetIndex(Out<s32> out_index, const CharInfo& char_info) { |
| 247 | LOG_DEBUG(Service_Mii, "called"); | 248 | LOG_DEBUG(Service_Mii, "called"); |
| 248 | 249 | ||
| 249 | R_RETURN(manager->GetIndex(metadata, char_info, *out_index)); | 250 | R_RETURN(manager->GetIndex(metadata, char_info, *out_index)); |
| @@ -257,25 +258,25 @@ private: | |||
| 257 | R_SUCCEED(); | 258 | R_SUCCEED(); |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) { | 261 | Result Convert(Out<CharInfo> out_char_info, const Ver3StoreData& mii_v3) { |
| 261 | LOG_INFO(Service_Mii, "called"); | 262 | LOG_INFO(Service_Mii, "called"); |
| 262 | 263 | ||
| 263 | R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3)); | 264 | R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3)); |
| 264 | } | 265 | } |
| 265 | 266 | ||
| 266 | Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) { | 267 | Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, const CoreData& core_data) { |
| 267 | LOG_INFO(Service_Mii, "called"); | 268 | LOG_INFO(Service_Mii, "called"); |
| 268 | 269 | ||
| 269 | R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data)); | 270 | R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data)); |
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) { | 273 | Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, const CharInfo& char_info) { |
| 273 | LOG_INFO(Service_Mii, "called"); | 274 | LOG_INFO(Service_Mii, "called"); |
| 274 | 275 | ||
| 275 | R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info)); | 276 | R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info)); |
| 276 | } | 277 | } |
| 277 | 278 | ||
| 278 | Result Append(CharInfo& char_info) { | 279 | Result Append(const CharInfo& char_info) { |
| 279 | LOG_INFO(Service_Mii, "called"); | 280 | LOG_INFO(Service_Mii, "called"); |
| 280 | 281 | ||
| 281 | R_RETURN(manager->Append(metadata, char_info)); | 282 | R_RETURN(manager->Append(metadata, char_info)); |
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 1e2d2d212..28e3000bd 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { | |||
| 1405 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 1405 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 1406 | 1406 | ||
| 1407 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; | 1407 | std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; |
| 1408 | static_service->GetTimeZoneService(timezone_service); | 1408 | static_service->GetTimeZoneService(&timezone_service); |
| 1409 | 1409 | ||
| 1410 | Service::PSC::Time::CalendarTime calendar_time{}; | 1410 | Service::PSC::Time::CalendarTime calendar_time{}; |
| 1411 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; | 1411 | Service::PSC::Time::CalendarAdditionalInfo additional_info{}; |
| @@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const { | |||
| 1416 | amiibo_date.SetMonth(1); | 1416 | amiibo_date.SetMonth(1); |
| 1417 | amiibo_date.SetDay(1); | 1417 | amiibo_date.SetDay(1); |
| 1418 | 1418 | ||
| 1419 | if (timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time) == | 1419 | if (timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time) == |
| 1420 | ResultSuccess) { | 1420 | ResultSuccess) { |
| 1421 | amiibo_date.SetYear(calendar_time.year); | 1421 | amiibo_date.SetYear(calendar_time.year); |
| 1422 | amiibo_date.SetMonth(calendar_time.month); | 1422 | amiibo_date.SetMonth(calendar_time.month); |
| @@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const { | |||
| 1431 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 1431 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 1432 | 1432 | ||
| 1433 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; | 1433 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; |
| 1434 | static_service->GetStandardSteadyClock(steady_clock); | 1434 | static_service->GetStandardSteadyClock(&steady_clock); |
| 1435 | 1435 | ||
| 1436 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 1436 | Service::PSC::Time::SteadyClockTimePoint time_point{}; |
| 1437 | R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); | 1437 | R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); |
| 1438 | return time_point.time_point; | 1438 | return time_point.time_point; |
| 1439 | } | 1439 | } |
| 1440 | 1440 | ||
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index b60699c45..94a8243b5 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp | |||
| @@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max | |||
| 91 | true); | 91 | true); |
| 92 | 92 | ||
| 93 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; | 93 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; |
| 94 | static_service->GetStandardSteadyClock(steady_clock); | 94 | static_service->GetStandardSteadyClock(&steady_clock); |
| 95 | 95 | ||
| 96 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 96 | Service::PSC::Time::SteadyClockTimePoint time_point{}; |
| 97 | R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); | 97 | R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); |
| 98 | 98 | ||
| 99 | const s64 elapsed_time = time_point.time_point - time_since_last_error; | 99 | const s64 elapsed_time = time_point.time_point - time_since_last_error; |
| 100 | if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { | 100 | if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { |
| @@ -754,10 +754,10 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, | |||
| 754 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); | 754 | system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); |
| 755 | 755 | ||
| 756 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; | 756 | std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; |
| 757 | static_service->GetStandardSteadyClock(steady_clock); | 757 | static_service->GetStandardSteadyClock(&steady_clock); |
| 758 | 758 | ||
| 759 | Service::PSC::Time::SteadyClockTimePoint time_point{}; | 759 | Service::PSC::Time::SteadyClockTimePoint time_point{}; |
| 760 | R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); | 760 | R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point)); |
| 761 | 761 | ||
| 762 | time_since_last_error = time_point.time_point; | 762 | time_since_last_error = time_point.time_point; |
| 763 | } | 763 | } |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 22dc55a6d..8e3224f73 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -185,7 +185,7 @@ public: | |||
| 185 | {3, &IRequest::Cancel, "Cancel"}, | 185 | {3, &IRequest::Cancel, "Cancel"}, |
| 186 | {4, &IRequest::Submit, "Submit"}, | 186 | {4, &IRequest::Submit, "Submit"}, |
| 187 | {5, nullptr, "SetRequirement"}, | 187 | {5, nullptr, "SetRequirement"}, |
| 188 | {6, nullptr, "SetRequirementPreset"}, | 188 | {6, &IRequest::SetRequirementPreset, "SetRequirementPreset"}, |
| 189 | {8, nullptr, "SetPriority"}, | 189 | {8, nullptr, "SetPriority"}, |
| 190 | {9, nullptr, "SetNetworkProfileId"}, | 190 | {9, nullptr, "SetNetworkProfileId"}, |
| 191 | {10, nullptr, "SetRejectable"}, | 191 | {10, nullptr, "SetRejectable"}, |
| @@ -237,6 +237,16 @@ private: | |||
| 237 | rb.PushEnum(state); | 237 | rb.PushEnum(state); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | void SetRequirementPreset(HLERequestContext& ctx) { | ||
| 241 | IPC::RequestParser rp{ctx}; | ||
| 242 | const auto param_1 = rp.Pop<u32>(); | ||
| 243 | |||
| 244 | LOG_WARNING(Service_NIFM, "(STUBBED) called, param_1={}", param_1); | ||
| 245 | |||
| 246 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 247 | rb.Push(ResultSuccess); | ||
| 248 | } | ||
| 249 | |||
| 240 | void GetResult(HLERequestContext& ctx) { | 250 | void GetResult(HLERequestContext& ctx) { |
| 241 | LOG_DEBUG(Service_NIFM, "(STUBBED) called"); | 251 | LOG_DEBUG(Service_NIFM, "(STUBBED) called"); |
| 242 | 252 | ||
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 2258ee609..19c3ff01b 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "core/arm/debug.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/file_sys/control_metadata.h" | 8 | #include "core/file_sys/control_metadata.h" |
| 8 | #include "core/file_sys/patch_manager.h" | 9 | #include "core/file_sys/patch_manager.h" |
| @@ -544,8 +545,8 @@ IDocumentInterface::IDocumentInterface(Core::System& system_) | |||
| 544 | // clang-format off | 545 | // clang-format off |
| 545 | static const FunctionInfo functions[] = { | 546 | static const FunctionInfo functions[] = { |
| 546 | {21, nullptr, "GetApplicationContentPath"}, | 547 | {21, nullptr, "GetApplicationContentPath"}, |
| 547 | {23, nullptr, "ResolveApplicationContentPath"}, | 548 | {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"}, |
| 548 | {93, nullptr, "GetRunningApplicationProgramId"}, | 549 | {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"}, |
| 549 | }; | 550 | }; |
| 550 | // clang-format on | 551 | // clang-format on |
| 551 | 552 | ||
| @@ -554,6 +555,32 @@ IDocumentInterface::IDocumentInterface(Core::System& system_) | |||
| 554 | 555 | ||
| 555 | IDocumentInterface::~IDocumentInterface() = default; | 556 | IDocumentInterface::~IDocumentInterface() = default; |
| 556 | 557 | ||
| 558 | void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) { | ||
| 559 | struct ContentPath { | ||
| 560 | u8 file_system_proxy_type; | ||
| 561 | u64 program_id; | ||
| 562 | }; | ||
| 563 | static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size"); | ||
| 564 | |||
| 565 | IPC::RequestParser rp{ctx}; | ||
| 566 | auto content_path = rp.PopRaw<ContentPath>(); | ||
| 567 | LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", | ||
| 568 | content_path.file_system_proxy_type, content_path.program_id); | ||
| 569 | |||
| 570 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 571 | rb.Push(ResultSuccess); | ||
| 572 | } | ||
| 573 | |||
| 574 | void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) { | ||
| 575 | IPC::RequestParser rp{ctx}; | ||
| 576 | const auto caller_program_id = rp.PopRaw<u64>(); | ||
| 577 | LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); | ||
| 578 | |||
| 579 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 580 | rb.Push(ResultSuccess); | ||
| 581 | rb.Push<u64>(system.GetApplicationProcessProgramID()); | ||
| 582 | } | ||
| 583 | |||
| 557 | IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) | 584 | IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) |
| 558 | : ServiceFramework{system_, "IDownloadTaskInterface"} { | 585 | : ServiceFramework{system_, "IDownloadTaskInterface"} { |
| 559 | // clang-format off | 586 | // clang-format off |
| @@ -613,6 +640,40 @@ IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) | |||
| 613 | 640 | ||
| 614 | IFactoryResetInterface::~IFactoryResetInterface() = default; | 641 | IFactoryResetInterface::~IFactoryResetInterface() = default; |
| 615 | 642 | ||
| 643 | IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) | ||
| 644 | : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { | ||
| 645 | static const FunctionInfo functions[] = { | ||
| 646 | {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"}, | ||
| 647 | {1, nullptr, "NotifyApplicationFailure"}, | ||
| 648 | {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"}, | ||
| 649 | }; | ||
| 650 | // clang-format on | ||
| 651 | |||
| 652 | RegisterHandlers(functions); | ||
| 653 | } | ||
| 654 | |||
| 655 | IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; | ||
| 656 | |||
| 657 | void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) { | ||
| 658 | IPC::RequestParser rp{ctx}; | ||
| 659 | const u64 program_id = rp.PopRaw<u64>(); | ||
| 660 | LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id); | ||
| 661 | |||
| 662 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 663 | rb.Push(ResultSuccess); | ||
| 664 | rb.Push<u8>(1); | ||
| 665 | } | ||
| 666 | |||
| 667 | void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) { | ||
| 668 | IPC::RequestParser rp{ctx}; | ||
| 669 | const auto result = rp.PopRaw<Result>(); | ||
| 670 | LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); | ||
| 671 | |||
| 672 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 673 | rb.Push(ResultSuccess); | ||
| 674 | rb.Push<u8>(0); | ||
| 675 | } | ||
| 676 | |||
| 616 | IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( | 677 | IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( |
| 617 | Core::System& system_) | 678 | Core::System& system_) |
| 618 | : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { | 679 | : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { |
| @@ -663,7 +724,7 @@ NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name | |||
| 663 | static const FunctionInfo functions[] = { | 724 | static const FunctionInfo functions[] = { |
| 664 | {7988, nullptr, "GetDynamicRightsInterface"}, | 725 | {7988, nullptr, "GetDynamicRightsInterface"}, |
| 665 | {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, | 726 | {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, |
| 666 | {7991, nullptr, "GetReadOnlyApplicationRecordInterface"}, | 727 | {7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"}, |
| 667 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, | 728 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, |
| 668 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, | 729 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, |
| 669 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, | 730 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, |
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 34d2a45dc..9ee306ef9 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h | |||
| @@ -58,6 +58,10 @@ class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { | |||
| 58 | public: | 58 | public: |
| 59 | explicit IDocumentInterface(Core::System& system_); | 59 | explicit IDocumentInterface(Core::System& system_); |
| 60 | ~IDocumentInterface() override; | 60 | ~IDocumentInterface() override; |
| 61 | |||
| 62 | private: | ||
| 63 | void ResolveApplicationContentPath(HLERequestContext& ctx); | ||
| 64 | void GetRunningApplicationProgramId(HLERequestContext& ctx); | ||
| 61 | }; | 65 | }; |
| 62 | 66 | ||
| 63 | class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { | 67 | class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { |
| @@ -78,6 +82,17 @@ public: | |||
| 78 | ~IFactoryResetInterface() override; | 82 | ~IFactoryResetInterface() override; |
| 79 | }; | 83 | }; |
| 80 | 84 | ||
| 85 | class IReadOnlyApplicationRecordInterface final | ||
| 86 | : public ServiceFramework<IReadOnlyApplicationRecordInterface> { | ||
| 87 | public: | ||
| 88 | explicit IReadOnlyApplicationRecordInterface(Core::System& system_); | ||
| 89 | ~IReadOnlyApplicationRecordInterface() override; | ||
| 90 | |||
| 91 | private: | ||
| 92 | void HasApplicationRecord(HLERequestContext& ctx); | ||
| 93 | void IsDataCorruptedResult(HLERequestContext& ctx); | ||
| 94 | }; | ||
| 95 | |||
| 81 | class IReadOnlyApplicationControlDataInterface final | 96 | class IReadOnlyApplicationControlDataInterface final |
| 82 | : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { | 97 | : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { |
| 83 | public: | 98 | public: |
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp index dc1b4d5be..e89cca6f2 100644 --- a/src/core/hle/service/nvdrv/core/container.cpp +++ b/src/core/hle/service/nvdrv/core/container.cpp | |||
| @@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) { | |||
| 83 | 83 | ||
| 84 | // Check if this memory block is heap. | 84 | // Check if this memory block is heap. |
| 85 | if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { | 85 | if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { |
| 86 | if (svc_mem_info.size > region_size) { | 86 | if (region_start + region_size == svc_mem_info.base_address) { |
| 87 | region_size += svc_mem_info.size; | ||
| 88 | } else if (svc_mem_info.size > region_size) { | ||
| 87 | region_size = svc_mem_info.size; | 89 | region_size = svc_mem_info.size; |
| 88 | region_start = svc_mem_info.base_address; | 90 | region_start = svc_mem_info.base_address; |
| 89 | } | 91 | } |
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 86e272b41..e71652cdf 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | |||
| @@ -128,7 +128,7 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::D | |||
| 128 | 128 | ||
| 129 | // Ensure we maintain a clean state on failure. | 129 | // Ensure we maintain a clean state on failure. |
| 130 | ON_RESULT_FAILURE { | 130 | ON_RESULT_FAILURE { |
| 131 | ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd))); | 131 | R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd)); |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | // Assign the allocated memory to the handle. | 134 | // Assign the allocated memory to the handle. |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 71d6fdb0c..51133853c 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -198,6 +198,16 @@ bool Nvnflinger::CloseLayer(u64 layer_id) { | |||
| 198 | return false; | 198 | return false; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) { | ||
| 202 | const auto lock_guard = Lock(); | ||
| 203 | |||
| 204 | for (auto& display : displays) { | ||
| 205 | if (auto* layer = display.FindLayer(layer_id); layer) { | ||
| 206 | layer->SetVisibility(visible); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 201 | void Nvnflinger::DestroyLayer(u64 layer_id) { | 211 | void Nvnflinger::DestroyLayer(u64 layer_id) { |
| 202 | const auto lock_guard = Lock(); | 212 | const auto lock_guard = Lock(); |
| 203 | 213 | ||
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index a60e0ae6b..369439142 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -79,6 +79,9 @@ public: | |||
| 79 | /// Closes a layer on all displays for the given layer ID. | 79 | /// Closes a layer on all displays for the given layer ID. |
| 80 | bool CloseLayer(u64 layer_id); | 80 | bool CloseLayer(u64 layer_id); |
| 81 | 81 | ||
| 82 | /// Makes a layer visible on all displays for the given layer ID. | ||
| 83 | void SetLayerVisibility(u64 layer_id, bool visible); | ||
| 84 | |||
| 82 | /// Destroys the given layer ID. | 85 | /// Destroys the given layer ID. |
| 83 | void DestroyLayer(u64 layer_id); | 86 | void DestroyLayer(u64 layer_id); |
| 84 | 87 | ||
diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h index d17b31143..3e13144a0 100644 --- a/src/core/hle/service/psc/time/common.h +++ b/src/core/hle/service/psc/time/common.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <chrono> | 7 | #include <chrono> |
| 8 | #include <fmt/format.h> | ||
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "common/intrusive_list.h" | 11 | #include "common/intrusive_list.h" |
| @@ -21,8 +22,14 @@ class System; | |||
| 21 | namespace Service::PSC::Time { | 22 | namespace Service::PSC::Time { |
| 22 | using ClockSourceId = Common::UUID; | 23 | using ClockSourceId = Common::UUID; |
| 23 | 24 | ||
| 25 | enum class TimeType : u8 { | ||
| 26 | UserSystemClock = 0, | ||
| 27 | NetworkSystemClock = 1, | ||
| 28 | LocalSystemClock = 2, | ||
| 29 | }; | ||
| 30 | |||
| 24 | struct SteadyClockTimePoint { | 31 | struct SteadyClockTimePoint { |
| 25 | constexpr bool IdMatches(SteadyClockTimePoint& other) { | 32 | constexpr bool IdMatches(const SteadyClockTimePoint& other) const { |
| 26 | return clock_source_id == other.clock_source_id; | 33 | return clock_source_id == other.clock_source_id; |
| 27 | } | 34 | } |
| 28 | bool operator==(const SteadyClockTimePoint& other) const = default; | 35 | bool operator==(const SteadyClockTimePoint& other) const = default; |
| @@ -42,12 +49,6 @@ struct SystemClockContext { | |||
| 42 | static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!"); | 49 | static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!"); |
| 43 | static_assert(std::is_trivial_v<SystemClockContext>); | 50 | static_assert(std::is_trivial_v<SystemClockContext>); |
| 44 | 51 | ||
| 45 | enum class TimeType : u8 { | ||
| 46 | UserSystemClock, | ||
| 47 | NetworkSystemClock, | ||
| 48 | LocalSystemClock, | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct CalendarTime { | 52 | struct CalendarTime { |
| 52 | s16 year; | 53 | s16 year; |
| 53 | s8 month; | 54 | s8 month; |
| @@ -67,14 +68,10 @@ struct CalendarAdditionalInfo { | |||
| 67 | }; | 68 | }; |
| 68 | static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!"); | 69 | static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!"); |
| 69 | 70 | ||
| 70 | struct LocationName { | 71 | using LocationName = std::array<char, 0x24>; |
| 71 | std::array<char, 36> name; | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!"); | 72 | static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!"); |
| 74 | 73 | ||
| 75 | struct RuleVersion { | 74 | using RuleVersion = std::array<char, 0x10>; |
| 76 | std::array<char, 16> version; | ||
| 77 | }; | ||
| 78 | static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!"); | 75 | static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!"); |
| 79 | 76 | ||
| 80 | struct ClockSnapshot { | 77 | struct ClockSnapshot { |
| @@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { | |||
| 152 | return std::chrono::nanoseconds(a + b); | 149 | return std::chrono::nanoseconds(a + b); |
| 153 | } | 150 | } |
| 154 | 151 | ||
| 155 | constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a, | 152 | constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a, |
| 156 | SteadyClockTimePoint& b) { | 153 | const SteadyClockTimePoint& b) { |
| 157 | R_UNLESS(out_seconds, ResultInvalidArgument); | 154 | R_UNLESS(out_seconds, ResultInvalidArgument); |
| 158 | R_UNLESS(a.IdMatches(b), ResultInvalidArgument); | 155 | R_UNLESS(a.IdMatches(b), ResultInvalidArgument); |
| 159 | R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(), | 156 | R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(), |
| @@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi | |||
| 166 | } | 163 | } |
| 167 | 164 | ||
| 168 | } // namespace Service::PSC::Time | 165 | } // namespace Service::PSC::Time |
| 166 | |||
| 167 | template <> | ||
| 168 | struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> { | ||
| 169 | template <typename FormatContext> | ||
| 170 | auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) { | ||
| 171 | const string_view name = [type] { | ||
| 172 | using Service::PSC::Time::TimeType; | ||
| 173 | switch (type) { | ||
| 174 | case TimeType::UserSystemClock: | ||
| 175 | return "UserSystemClock"; | ||
| 176 | case TimeType::NetworkSystemClock: | ||
| 177 | return "NetworkSystemClock"; | ||
| 178 | case TimeType::LocalSystemClock: | ||
| 179 | return "LocalSystemClock"; | ||
| 180 | } | ||
| 181 | return "Invalid"; | ||
| 182 | }(); | ||
| 183 | return formatter<string_view>::format(name, ctx); | ||
| 184 | } | ||
| 185 | }; | ||
| 186 | |||
| 187 | template <> | ||
| 188 | struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> { | ||
| 189 | template <typename FormatContext> | ||
| 190 | auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point, | ||
| 191 | FormatContext& ctx) const { | ||
| 192 | return fmt::format_to(ctx.out(), "[time_point={}]", time_point.time_point); | ||
| 193 | } | ||
| 194 | }; | ||
| 195 | |||
| 196 | template <> | ||
| 197 | struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> { | ||
| 198 | template <typename FormatContext> | ||
| 199 | auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const { | ||
| 200 | return fmt::format_to(ctx.out(), "[offset={} steady_time_point={}]", context.offset, | ||
| 201 | context.steady_time_point.time_point); | ||
| 202 | } | ||
| 203 | }; | ||
| 204 | |||
| 205 | template <> | ||
| 206 | struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> { | ||
| 207 | template <typename FormatContext> | ||
| 208 | auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const { | ||
| 209 | return fmt::format_to(ctx.out(), "[{:02}/{:02}/{:04} {:02}:{:02}:{:02}]", calendar.day, | ||
| 210 | calendar.month, calendar.year, calendar.hour, calendar.minute, | ||
| 211 | calendar.second); | ||
| 212 | } | ||
| 213 | }; | ||
| 214 | |||
| 215 | template <> | ||
| 216 | struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo> | ||
| 217 | : fmt::formatter<fmt::string_view> { | ||
| 218 | template <typename FormatContext> | ||
| 219 | auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional, | ||
| 220 | FormatContext& ctx) const { | ||
| 221 | return fmt::format_to(ctx.out(), "[weekday={} yearday={} name={} is_dst={} ut_offset={}]", | ||
| 222 | additional.day_of_week, additional.day_of_year, | ||
| 223 | additional.name.data(), additional.is_dst, additional.ut_offset); | ||
| 224 | } | ||
| 225 | }; | ||
| 226 | |||
| 227 | template <> | ||
| 228 | struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> { | ||
| 229 | template <typename FormatContext> | ||
| 230 | auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const { | ||
| 231 | return formatter<string_view>::format(name.data(), ctx); | ||
| 232 | } | ||
| 233 | }; | ||
| 234 | |||
| 235 | template <> | ||
| 236 | struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> { | ||
| 237 | template <typename FormatContext> | ||
| 238 | auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const { | ||
| 239 | return formatter<string_view>::format(version.data(), ctx); | ||
| 240 | } | ||
| 241 | }; | ||
| 242 | |||
| 243 | template <> | ||
| 244 | struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> { | ||
| 245 | template <typename FormatContext> | ||
| 246 | auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const { | ||
| 247 | return fmt::format_to( | ||
| 248 | ctx.out(), | ||
| 249 | "[user_context={} network_context={} user_time={} network_time={} " | ||
| 250 | "user_calendar_time={} " | ||
| 251 | "network_calendar_time={} user_calendar_additional_time={} " | ||
| 252 | "network_calendar_additional_time={} steady_clock_time_point={} location={} " | ||
| 253 | "is_automatic_correction_enabled={} type={}]", | ||
| 254 | snapshot.user_context, snapshot.network_context, snapshot.user_time, | ||
| 255 | snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time, | ||
| 256 | snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time, | ||
| 257 | snapshot.steady_clock_time_point, snapshot.location_name, | ||
| 258 | snapshot.is_automatic_correction_enabled, snapshot.type); | ||
| 259 | } | ||
| 260 | }; | ||
| 261 | |||
| 262 | template <> | ||
| 263 | struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint> | ||
| 264 | : fmt::formatter<fmt::string_view> { | ||
| 265 | template <typename FormatContext> | ||
| 266 | auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point, | ||
| 267 | FormatContext& ctx) const { | ||
| 268 | return fmt::format_to(ctx.out(), | ||
| 269 | "[rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}]", | ||
| 270 | time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount, | ||
| 271 | time_point.lower, time_point.upper); | ||
| 272 | } | ||
| 273 | }; \ No newline at end of file | ||
diff --git a/src/core/hle/service/psc/time/power_state_service.cpp b/src/core/hle/service/psc/time/power_state_service.cpp index b0ae71bf9..ab1d32c70 100644 --- a/src/core/hle/service/psc/time/power_state_service.cpp +++ b/src/core/hle/service/psc/time/power_state_service.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_serialization.h" | ||
| 4 | #include "core/hle/service/psc/time/power_state_service.h" | 5 | #include "core/hle/service/psc/time/power_state_service.h" |
| 5 | 6 | ||
| 6 | namespace Service::PSC::Time { | 7 | namespace Service::PSC::Time { |
| @@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler( | |||
| 11 | power_state_request_manager} { | 12 | power_state_request_manager} { |
| 12 | // clang-format off | 13 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
| 14 | {0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"}, | 15 | {0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"}, |
| 15 | {1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"}, | 16 | {1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"}, |
| 16 | }; | 17 | }; |
| 17 | // clang-format on | 18 | // clang-format on |
| 18 | 19 | ||
| 19 | RegisterHandlers(functions); | 20 | RegisterHandlers(functions); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) { | 23 | Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle( |
| 24 | OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||
| 23 | LOG_DEBUG(Service_Time, "called."); | 25 | LOG_DEBUG(Service_Time, "called."); |
| 24 | 26 | ||
| 25 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 27 | *out_event = &m_power_state_request_manager.GetReadableEvent(); |
| 26 | rb.Push(ResultSuccess); | 28 | R_SUCCEED(); |
| 27 | rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent()); | ||
| 28 | } | 29 | } |
| 29 | 30 | ||
| 30 | void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) { | 31 | Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared, |
| 32 | Out<u32> out_priority) { | ||
| 31 | LOG_DEBUG(Service_Time, "called."); | 33 | LOG_DEBUG(Service_Time, "called."); |
| 32 | 34 | ||
| 33 | u32 priority{}; | 35 | u32 priority{}; |
| 34 | auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority); | 36 | auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority); |
| 37 | *out_cleared = cleared; | ||
| 35 | 38 | ||
| 36 | if (cleared) { | 39 | if (cleared) { |
| 37 | IPC::ResponseBuilder rb{ctx, 4}; | 40 | *out_priority = priority; |
| 38 | rb.Push(ResultSuccess); | ||
| 39 | rb.Push(priority); | ||
| 40 | rb.Push(cleared); | ||
| 41 | return; | ||
| 42 | } | 41 | } |
| 43 | 42 | R_SUCCEED(); | |
| 44 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.Push(cleared); | ||
| 47 | } | 43 | } |
| 48 | 44 | ||
| 49 | } // namespace Service::PSC::Time | 45 | } // namespace Service::PSC::Time |
diff --git a/src/core/hle/service/psc/time/power_state_service.h b/src/core/hle/service/psc/time/power_state_service.h index 3ebfddb79..56e2c4b87 100644 --- a/src/core/hle/service/psc/time/power_state_service.h +++ b/src/core/hle/service/psc/time/power_state_service.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 7 | #include "core/hle/service/psc/time/power_state_request_manager.h" | 8 | #include "core/hle/service/psc/time/power_state_request_manager.h" |
| 8 | #include "core/hle/service/server_manager.h" | 9 | #include "core/hle/service/server_manager.h" |
| @@ -21,10 +22,10 @@ public: | |||
| 21 | 22 | ||
| 22 | ~IPowerStateRequestHandler() override = default; | 23 | ~IPowerStateRequestHandler() override = default; |
| 23 | 24 | ||
| 24 | private: | 25 | Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 25 | void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx); | 26 | Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority); |
| 26 | void GetAndClearPowerStateRequest(HLERequestContext& ctx); | ||
| 27 | 27 | ||
| 28 | private: | ||
| 28 | Core::System& m_system; | 29 | Core::System& m_system; |
| 29 | PowerStateRequestManager& m_power_state_request_manager; | 30 | PowerStateRequestManager& m_power_state_request_manager; |
| 30 | }; | 31 | }; |
diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index 60820aa9b..4e1643fcb 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include "core/core.h" | 4 | #include "core/core.h" |
| 5 | #include "core/core_timing.h" | 5 | #include "core/core_timing.h" |
| 6 | #include "core/hle/service/cmif_serialization.h" | ||
| 6 | #include "core/hle/service/psc/time/power_state_service.h" | 7 | #include "core/hle/service/psc/time/power_state_service.h" |
| 7 | #include "core/hle/service/psc/time/service_manager.h" | 8 | #include "core/hle/service/psc/time/service_manager.h" |
| 8 | #include "core/hle/service/psc/time/static.h" | 9 | #include "core/hle/service/psc/time/static.h" |
| @@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage | |||
| 25 | m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} { | 26 | m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} { |
| 26 | // clang-format off | 27 | // clang-format off |
| 27 | static const FunctionInfo functions[] = { | 28 | static const FunctionInfo functions[] = { |
| 28 | {0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"}, | 29 | {0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"}, |
| 29 | {5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"}, | 30 | {5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"}, |
| 30 | {6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"}, | 31 | {6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"}, |
| 31 | {9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"}, | 32 | {9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"}, |
| 32 | {10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"}, | 33 | {10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"}, |
| 33 | {11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"}, | 34 | {11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"}, |
| 34 | {12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"}, | 35 | {12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"}, |
| 35 | {13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"}, | 36 | {13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"}, |
| 36 | {14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"}, | 37 | {14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"}, |
| 37 | {15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"}, | 38 | {15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"}, |
| 38 | {50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"}, | 39 | {50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"}, |
| 39 | {51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"}, | 40 | {51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"}, |
| 40 | {52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"}, | 41 | {52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"}, |
| 41 | {60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, | 42 | {60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, |
| 42 | {100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"}, | 43 | {100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"}, |
| 43 | {200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"}, | 44 | {200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"}, |
| 44 | {201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"}, | 45 | {201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"}, |
| 45 | {202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "}, | 46 | {202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "}, |
| 46 | }; | 47 | }; |
| 47 | // clang-format on | 48 | // clang-format on |
| 48 | RegisterHandlers(functions); | 49 | RegisterHandlers(functions); |
| @@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage | |||
| 52 | m_ephemeral_system_context_writer.Link(m_ephemeral_operation); | 53 | m_ephemeral_system_context_writer.Link(m_ephemeral_operation); |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | void ServiceManager::SetupSAndP() { | 56 | Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) { |
| 56 | if (!m_is_s_and_p_setup) { | ||
| 57 | m_is_s_and_p_setup = true; | ||
| 58 | m_server_manager.RegisterNamedService( | ||
| 59 | "time:s", std::make_shared<StaticService>( | ||
| 60 | m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s")); | ||
| 61 | m_server_manager.RegisterNamedService("time:p", | ||
| 62 | std::make_shared<IPowerStateRequestHandler>( | ||
| 63 | m_system, m_time->m_power_state_request_manager)); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | void ServiceManager::CheckAndSetupServicesSAndP() { | ||
| 68 | if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() && | ||
| 69 | m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() && | ||
| 70 | m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) { | ||
| 71 | SetupSAndP(); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) { | ||
| 76 | LOG_DEBUG(Service_Time, "called."); | 57 | LOG_DEBUG(Service_Time, "called."); |
| 77 | 58 | ||
| 78 | std::shared_ptr<StaticService> service{}; | 59 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u")); |
| 79 | auto res = GetStaticServiceAsUser(service); | ||
| 80 | |||
| 81 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 82 | rb.Push(res); | ||
| 83 | rb.PushIpcInterface<StaticService>(std::move(service)); | ||
| 84 | } | ||
| 85 | |||
| 86 | void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) { | ||
| 87 | LOG_DEBUG(Service_Time, "called."); | ||
| 88 | |||
| 89 | std::shared_ptr<StaticService> service{}; | ||
| 90 | auto res = GetStaticServiceAsAdmin(service); | ||
| 91 | |||
| 92 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 93 | rb.Push(res); | ||
| 94 | rb.PushIpcInterface<StaticService>(std::move(service)); | ||
| 95 | } | ||
| 96 | |||
| 97 | void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_Time, "called."); | ||
| 99 | |||
| 100 | std::shared_ptr<StaticService> service{}; | ||
| 101 | auto res = GetStaticServiceAsRepair(service); | ||
| 102 | |||
| 103 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 104 | rb.Push(res); | ||
| 105 | rb.PushIpcInterface<StaticService>(std::move(service)); | ||
| 106 | } | ||
| 107 | |||
| 108 | void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) { | ||
| 109 | LOG_DEBUG(Service_Time, "called."); | ||
| 110 | |||
| 111 | std::shared_ptr<StaticService> service{}; | ||
| 112 | auto res = GetStaticServiceAsServiceManager(service); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 115 | rb.Push(res); | ||
| 116 | rb.PushIpcInterface<StaticService>(std::move(service)); | ||
| 117 | } | ||
| 118 | |||
| 119 | void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) { | ||
| 120 | LOG_DEBUG(Service_Time, "called."); | ||
| 121 | |||
| 122 | struct Parameters { | ||
| 123 | bool reset_detected; | ||
| 124 | Common::UUID clock_source_id; | ||
| 125 | s64 rtc_offset; | ||
| 126 | s64 internal_offset; | ||
| 127 | s64 test_offset; | ||
| 128 | }; | ||
| 129 | static_assert(sizeof(Parameters) == 0x30); | ||
| 130 | |||
| 131 | IPC::RequestParser rp{ctx}; | ||
| 132 | auto params{rp.PopRaw<Parameters>()}; | ||
| 133 | |||
| 134 | auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset, | ||
| 135 | params.internal_offset, params.test_offset, | ||
| 136 | params.reset_detected); | ||
| 137 | |||
| 138 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 139 | rb.Push(res); | ||
| 140 | } | ||
| 141 | |||
| 142 | void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) { | ||
| 143 | LOG_DEBUG(Service_Time, "called."); | ||
| 144 | |||
| 145 | IPC::RequestParser rp{ctx}; | ||
| 146 | auto context{rp.PopRaw<SystemClockContext>()}; | ||
| 147 | auto time{rp.Pop<s64>()}; | ||
| 148 | |||
| 149 | auto res = SetupStandardLocalSystemClockCore(context, time); | ||
| 150 | |||
| 151 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 152 | rb.Push(res); | ||
| 153 | } | ||
| 154 | |||
| 155 | void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) { | ||
| 156 | LOG_DEBUG(Service_Time, "called."); | ||
| 157 | |||
| 158 | IPC::RequestParser rp{ctx}; | ||
| 159 | auto context{rp.PopRaw<SystemClockContext>()}; | ||
| 160 | auto accuracy{rp.Pop<s64>()}; | ||
| 161 | |||
| 162 | auto res = SetupStandardNetworkSystemClockCore(context, accuracy); | ||
| 163 | |||
| 164 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 165 | rb.Push(res); | ||
| 166 | } | ||
| 167 | |||
| 168 | void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) { | ||
| 169 | LOG_DEBUG(Service_Time, "called."); | ||
| 170 | |||
| 171 | struct Parameters { | ||
| 172 | bool automatic_correction; | ||
| 173 | SteadyClockTimePoint time_point; | ||
| 174 | }; | ||
| 175 | static_assert(sizeof(Parameters) == 0x20); | ||
| 176 | |||
| 177 | IPC::RequestParser rp{ctx}; | ||
| 178 | auto params{rp.PopRaw<Parameters>()}; | ||
| 179 | |||
| 180 | auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction); | ||
| 181 | |||
| 182 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 183 | rb.Push(res); | ||
| 184 | } | ||
| 185 | |||
| 186 | void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) { | ||
| 187 | LOG_DEBUG(Service_Time, "called."); | ||
| 188 | |||
| 189 | struct Parameters { | ||
| 190 | u32 location_count; | ||
| 191 | LocationName name; | ||
| 192 | SteadyClockTimePoint time_point; | ||
| 193 | RuleVersion rule_version; | ||
| 194 | }; | ||
| 195 | static_assert(sizeof(Parameters) == 0x50); | ||
| 196 | |||
| 197 | IPC::RequestParser rp{ctx}; | ||
| 198 | auto params{rp.PopRaw<Parameters>()}; | ||
| 199 | |||
| 200 | auto rule_buffer{ctx.ReadBuffer()}; | ||
| 201 | |||
| 202 | auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version, | ||
| 203 | params.location_count, rule_buffer); | ||
| 204 | |||
| 205 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 206 | rb.Push(res); | ||
| 207 | } | ||
| 208 | |||
| 209 | void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) { | ||
| 210 | LOG_DEBUG(Service_Time, "called."); | ||
| 211 | |||
| 212 | auto res = SetupEphemeralNetworkSystemClockCore(); | ||
| 213 | |||
| 214 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 215 | rb.Push(res); | ||
| 216 | } | ||
| 217 | |||
| 218 | void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) { | ||
| 219 | LOG_DEBUG(Service_Time, "called."); | ||
| 220 | |||
| 221 | Kernel::KEvent* event{}; | ||
| 222 | auto res = GetStandardLocalClockOperationEvent(&event); | ||
| 223 | |||
| 224 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 225 | rb.Push(res); | ||
| 226 | rb.PushCopyObjects(event->GetReadableEvent()); | ||
| 227 | } | ||
| 228 | |||
| 229 | void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager( | ||
| 230 | HLERequestContext& ctx) { | ||
| 231 | LOG_DEBUG(Service_Time, "called."); | ||
| 232 | |||
| 233 | Kernel::KEvent* event{}; | ||
| 234 | auto res = GetStandardNetworkClockOperationEventForServiceManager(&event); | ||
| 235 | |||
| 236 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 237 | rb.Push(res); | ||
| 238 | rb.PushCopyObjects(event); | ||
| 239 | } | ||
| 240 | |||
| 241 | void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager( | ||
| 242 | HLERequestContext& ctx) { | ||
| 243 | LOG_DEBUG(Service_Time, "called."); | ||
| 244 | |||
| 245 | Kernel::KEvent* event{}; | ||
| 246 | auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event); | ||
| 247 | |||
| 248 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 249 | rb.Push(res); | ||
| 250 | rb.PushCopyObjects(event); | ||
| 251 | } | ||
| 252 | |||
| 253 | void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( | ||
| 254 | HLERequestContext& ctx) { | ||
| 255 | LOG_DEBUG(Service_Time, "called."); | ||
| 256 | |||
| 257 | Kernel::KEvent* event{}; | ||
| 258 | auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event); | ||
| 259 | |||
| 260 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 261 | rb.Push(res); | ||
| 262 | rb.PushCopyObjects(event); | ||
| 263 | } | ||
| 264 | |||
| 265 | void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) { | ||
| 266 | LOG_DEBUG(Service_Time, "called."); | ||
| 267 | |||
| 268 | IPC::RequestParser rp{ctx}; | ||
| 269 | auto base_time{rp.Pop<s64>()}; | ||
| 270 | |||
| 271 | auto res = SetStandardSteadyClockBaseTime(base_time); | ||
| 272 | |||
| 273 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 274 | rb.Push(res); | ||
| 275 | } | 60 | } |
| 276 | 61 | ||
| 277 | void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) { | 62 | Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) { |
| 278 | LOG_DEBUG(Service_Time, "called."); | 63 | LOG_DEBUG(Service_Time, "called."); |
| 279 | 64 | ||
| 280 | Kernel::KEvent* event{}; | 65 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a")); |
| 281 | auto res = GetClosestAlarmUpdatedEvent(&event); | ||
| 282 | |||
| 283 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 284 | rb.Push(res); | ||
| 285 | rb.PushCopyObjects(event->GetReadableEvent()); | ||
| 286 | } | 66 | } |
| 287 | 67 | ||
| 288 | void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) { | 68 | Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) { |
| 289 | LOG_DEBUG(Service_Time, "called."); | 69 | LOG_DEBUG(Service_Time, "called."); |
| 290 | 70 | ||
| 291 | auto res = CheckAndSignalAlarms(); | 71 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r")); |
| 292 | |||
| 293 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 294 | rb.Push(res); | ||
| 295 | } | 72 | } |
| 296 | 73 | ||
| 297 | void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) { | 74 | Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) { |
| 298 | LOG_DEBUG(Service_Time, "called."); | 75 | LOG_DEBUG(Service_Time, "called."); |
| 299 | 76 | ||
| 300 | AlarmInfo alarm_info{}; | ||
| 301 | bool is_valid{}; | ||
| 302 | s64 time{}; | ||
| 303 | auto res = GetClosestAlarmInfo(is_valid, alarm_info, time); | ||
| 304 | |||
| 305 | struct OutParameters { | ||
| 306 | bool is_valid; | ||
| 307 | AlarmInfo alarm_info; | ||
| 308 | s64 time; | ||
| 309 | }; | ||
| 310 | static_assert(sizeof(OutParameters) == 0x20); | ||
| 311 | |||
| 312 | OutParameters out_params{ | ||
| 313 | .is_valid = is_valid, | ||
| 314 | .alarm_info = alarm_info, | ||
| 315 | .time = time, | ||
| 316 | }; | ||
| 317 | |||
| 318 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)}; | ||
| 319 | rb.Push(res); | ||
| 320 | rb.PushRaw<OutParameters>(out_params); | ||
| 321 | } | ||
| 322 | |||
| 323 | // =============================== Implementations =========================== | ||
| 324 | |||
| 325 | Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service, | ||
| 326 | StaticServiceSetupInfo setup_info, const char* name) { | ||
| 327 | out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name); | ||
| 328 | R_SUCCEED(); | ||
| 329 | } | ||
| 330 | |||
| 331 | Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) { | ||
| 332 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u")); | ||
| 333 | } | ||
| 334 | |||
| 335 | Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) { | ||
| 336 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a")); | ||
| 337 | } | ||
| 338 | |||
| 339 | Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) { | ||
| 340 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r")); | ||
| 341 | } | ||
| 342 | |||
| 343 | Result ServiceManager::GetStaticServiceAsServiceManager( | ||
| 344 | std::shared_ptr<StaticService>& out_service) { | ||
| 345 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm")); | 77 | R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm")); |
| 346 | } | 78 | } |
| 347 | 79 | ||
| 348 | Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, | 80 | Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected, |
| 349 | s64 internal_offset, s64 test_offset, | 81 | Common::UUID& clock_source_id, s64 rtc_offset, |
| 350 | bool is_rtc_reset_detected) { | 82 | s64 internal_offset, s64 test_offset) { |
| 83 | LOG_DEBUG(Service_Time, | ||
| 84 | "called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} " | ||
| 85 | "internal_offset={} test_offset={}", | ||
| 86 | is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset, | ||
| 87 | test_offset); | ||
| 88 | |||
| 351 | m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset, | 89 | m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset, |
| 352 | is_rtc_reset_detected); | 90 | is_rtc_reset_detected); |
| 353 | auto time = m_steady_clock.GetRawTime(); | 91 | auto time = m_steady_clock.GetRawTime(); |
| @@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i | |||
| 365 | } | 103 | } |
| 366 | 104 | ||
| 367 | Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { | 105 | Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { |
| 106 | LOG_DEBUG(Service_Time, | ||
| 107 | "called. context={} context.steady_time_point.clock_source_id={} time={}", context, | ||
| 108 | context.steady_time_point.clock_source_id.RawString(), time); | ||
| 109 | |||
| 368 | m_local_system_clock.SetContextWriter(m_local_system_context_writer); | 110 | m_local_system_clock.SetContextWriter(m_local_system_context_writer); |
| 369 | m_local_system_clock.Initialize(context, time); | 111 | m_local_system_clock.Initialize(context, time); |
| 370 | 112 | ||
| @@ -374,12 +116,12 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con | |||
| 374 | 116 | ||
| 375 | Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, | 117 | Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, |
| 376 | s64 accuracy) { | 118 | s64 accuracy) { |
| 119 | LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}", | ||
| 120 | context, context.steady_time_point.clock_source_id.RawString(), accuracy); | ||
| 121 | |||
| 377 | // TODO this is a hack! The network clock should be updated independently, from the ntc service | 122 | // TODO this is a hack! The network clock should be updated independently, from the ntc service |
| 378 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot | 123 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock. |
| 379 | // to avoid it being stuck at 0. | 124 | m_local_system_clock.GetContext(context); |
| 380 | if (context == Service::PSC::Time::SystemClockContext{}) { | ||
| 381 | m_local_system_clock.GetContext(context); | ||
| 382 | } | ||
| 383 | 125 | ||
| 384 | m_network_system_clock.SetContextWriter(m_network_system_context_writer); | 126 | m_network_system_clock.SetContextWriter(m_network_system_context_writer); |
| 385 | m_network_system_clock.Initialize(context, accuracy); | 127 | m_network_system_clock.Initialize(context, accuracy); |
| @@ -388,14 +130,10 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c | |||
| 388 | R_SUCCEED(); | 130 | R_SUCCEED(); |
| 389 | } | 131 | } |
| 390 | 132 | ||
| 391 | Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, | 133 | Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction, |
| 392 | bool automatic_correction) { | 134 | SteadyClockTimePoint& time_point) { |
| 393 | // TODO this is a hack! The user clock should be updated independently, from the ntc service | 135 | LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", |
| 394 | // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot | 136 | automatic_correction, time_point, time_point.clock_source_id.RawString()); |
| 395 | // to avoid it being stuck at 0. | ||
| 396 | if (time_point == Service::PSC::Time::SteadyClockTimePoint{}) { | ||
| 397 | m_local_system_clock.GetCurrentTimePoint(time_point); | ||
| 398 | } | ||
| 399 | 137 | ||
| 400 | m_user_system_clock.SetAutomaticCorrection(automatic_correction); | 138 | m_user_system_clock.SetAutomaticCorrection(automatic_correction); |
| 401 | m_user_system_clock.SetTimePointAndSignal(time_point); | 139 | m_user_system_clock.SetTimePointAndSignal(time_point); |
| @@ -406,10 +144,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti | |||
| 406 | R_SUCCEED(); | 144 | R_SUCCEED(); |
| 407 | } | 145 | } |
| 408 | 146 | ||
| 409 | Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, | 147 | Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, |
| 148 | u32 location_count, | ||
| 410 | SteadyClockTimePoint& time_point, | 149 | SteadyClockTimePoint& time_point, |
| 411 | RuleVersion& rule_version, u32 location_count, | 150 | InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) { |
| 412 | std::span<const u8> rule_buffer) { | 151 | LOG_DEBUG(Service_Time, |
| 152 | "called. name={} rule_version={} location_count={} time_point={} " | ||
| 153 | "clock_source_id={}", | ||
| 154 | name, rule_version, location_count, time_point, | ||
| 155 | time_point.clock_source_id.RawString()); | ||
| 156 | |||
| 413 | if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) { | 157 | if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) { |
| 414 | LOG_ERROR(Service_Time, "Failed to parse time zone binary!"); | 158 | LOG_ERROR(Service_Time, "Failed to parse time zone binary!"); |
| 415 | } | 159 | } |
| @@ -424,6 +168,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, | |||
| 424 | } | 168 | } |
| 425 | 169 | ||
| 426 | Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { | 170 | Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { |
| 171 | LOG_DEBUG(Service_Time, "called."); | ||
| 172 | |||
| 427 | m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer); | 173 | m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer); |
| 428 | m_ephemeral_network_clock.SetInitialized(); | 174 | m_ephemeral_network_clock.SetInitialized(); |
| 429 | 175 | ||
| @@ -431,30 +177,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { | |||
| 431 | R_SUCCEED(); | 177 | R_SUCCEED(); |
| 432 | } | 178 | } |
| 433 | 179 | ||
| 434 | Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) { | 180 | Result ServiceManager::GetStandardLocalClockOperationEvent( |
| 435 | *out_event = m_local_operation.m_event; | 181 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 182 | LOG_DEBUG(Service_Time, "called."); | ||
| 183 | |||
| 184 | *out_event = &m_local_operation.m_event->GetReadableEvent(); | ||
| 436 | R_SUCCEED(); | 185 | R_SUCCEED(); |
| 437 | } | 186 | } |
| 438 | 187 | ||
| 439 | Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager( | 188 | Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager( |
| 440 | Kernel::KEvent** out_event) { | 189 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 441 | *out_event = m_network_operation.m_event; | 190 | LOG_DEBUG(Service_Time, "called."); |
| 191 | |||
| 192 | *out_event = &m_network_operation.m_event->GetReadableEvent(); | ||
| 442 | R_SUCCEED(); | 193 | R_SUCCEED(); |
| 443 | } | 194 | } |
| 444 | 195 | ||
| 445 | Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager( | 196 | Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager( |
| 446 | Kernel::KEvent** out_event) { | 197 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 447 | *out_event = m_ephemeral_operation.m_event; | 198 | LOG_DEBUG(Service_Time, "called."); |
| 199 | |||
| 200 | *out_event = &m_ephemeral_operation.m_event->GetReadableEvent(); | ||
| 448 | R_SUCCEED(); | 201 | R_SUCCEED(); |
| 449 | } | 202 | } |
| 450 | 203 | ||
| 451 | Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( | 204 | Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( |
| 452 | Kernel::KEvent** out_event) { | 205 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 453 | *out_event = &m_user_system_clock.GetEvent(); | 206 | LOG_DEBUG(Service_Time, "called."); |
| 207 | |||
| 208 | *out_event = &m_user_system_clock.GetEvent().GetReadableEvent(); | ||
| 454 | R_SUCCEED(); | 209 | R_SUCCEED(); |
| 455 | } | 210 | } |
| 456 | 211 | ||
| 457 | Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { | 212 | Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { |
| 213 | LOG_DEBUG(Service_Time, "called. base_time={}", base_time); | ||
| 214 | |||
| 458 | m_steady_clock.SetRtcOffset(base_time); | 215 | m_steady_clock.SetRtcOffset(base_time); |
| 459 | auto time = m_steady_clock.GetRawTime(); | 216 | auto time = m_steady_clock.GetRawTime(); |
| 460 | auto ticks = m_system.CoreTiming().GetClockTicks(); | 217 | auto ticks = m_system.CoreTiming().GetClockTicks(); |
| @@ -468,26 +225,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { | |||
| 468 | R_SUCCEED(); | 225 | R_SUCCEED(); |
| 469 | } | 226 | } |
| 470 | 227 | ||
| 471 | Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) { | 228 | Result ServiceManager::GetClosestAlarmUpdatedEvent( |
| 472 | *out_event = &m_alarms.GetEvent(); | 229 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 230 | LOG_DEBUG(Service_Time, "called."); | ||
| 231 | |||
| 232 | *out_event = &m_alarms.GetEvent().GetReadableEvent(); | ||
| 473 | R_SUCCEED(); | 233 | R_SUCCEED(); |
| 474 | } | 234 | } |
| 475 | 235 | ||
| 476 | Result ServiceManager::CheckAndSignalAlarms() { | 236 | Result ServiceManager::CheckAndSignalAlarms() { |
| 237 | LOG_DEBUG(Service_Time, "called."); | ||
| 238 | |||
| 477 | m_alarms.CheckAndSignal(); | 239 | m_alarms.CheckAndSignal(); |
| 478 | R_SUCCEED(); | 240 | R_SUCCEED(); |
| 479 | } | 241 | } |
| 480 | 242 | ||
| 481 | Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) { | 243 | Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, |
| 244 | Out<s64> out_time) { | ||
| 482 | Alarm* alarm{nullptr}; | 245 | Alarm* alarm{nullptr}; |
| 483 | out_is_valid = m_alarms.GetClosestAlarm(&alarm); | 246 | *out_is_valid = m_alarms.GetClosestAlarm(&alarm); |
| 484 | if (out_is_valid) { | 247 | if (*out_is_valid) { |
| 485 | out_info = { | 248 | *out_info = { |
| 486 | .alert_time = alarm->GetAlertTime(), | 249 | .alert_time = alarm->GetAlertTime(), |
| 487 | .priority = alarm->GetPriority(), | 250 | .priority = alarm->GetPriority(), |
| 488 | }; | 251 | }; |
| 489 | out_time = m_alarms.GetRawTime(); | 252 | *out_time = m_alarms.GetRawTime(); |
| 253 | } | ||
| 254 | |||
| 255 | LOG_DEBUG(Service_Time, | ||
| 256 | "called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}", | ||
| 257 | *out_is_valid, out_info->alert_time, out_info->priority, *out_time); | ||
| 258 | |||
| 259 | R_SUCCEED(); | ||
| 260 | } | ||
| 261 | |||
| 262 | void ServiceManager::CheckAndSetupServicesSAndP() { | ||
| 263 | if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() && | ||
| 264 | m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() && | ||
| 265 | m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) { | ||
| 266 | SetupSAndP(); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | void ServiceManager::SetupSAndP() { | ||
| 271 | if (!m_is_s_and_p_setup) { | ||
| 272 | m_is_s_and_p_setup = true; | ||
| 273 | m_server_manager.RegisterNamedService( | ||
| 274 | "time:s", std::make_shared<StaticService>( | ||
| 275 | m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s")); | ||
| 276 | m_server_manager.RegisterNamedService("time:p", | ||
| 277 | std::make_shared<IPowerStateRequestHandler>( | ||
| 278 | m_system, m_time->m_power_state_request_manager)); | ||
| 490 | } | 279 | } |
| 280 | } | ||
| 281 | |||
| 282 | Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service, | ||
| 283 | StaticServiceSetupInfo setup_info, const char* name) { | ||
| 284 | *out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name); | ||
| 491 | R_SUCCEED(); | 285 | R_SUCCEED(); |
| 492 | } | 286 | } |
| 493 | 287 | ||
diff --git a/src/core/hle/service/psc/time/service_manager.h b/src/core/hle/service/psc/time/service_manager.h index 1d9952317..25d361d4f 100644 --- a/src/core/hle/service/psc/time/service_manager.h +++ b/src/core/hle/service/psc/time/service_manager.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <list> | 6 | #include <list> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | 8 | ||
| 9 | #include "core/hle/service/cmif_types.h" | ||
| 9 | #include "core/hle/service/ipc_helpers.h" | 10 | #include "core/hle/service/ipc_helpers.h" |
| 10 | #include "core/hle/service/psc/time/common.h" | 11 | #include "core/hle/service/psc/time/common.h" |
| 11 | #include "core/hle/service/psc/time/manager.h" | 12 | #include "core/hle/service/psc/time/manager.h" |
| @@ -29,55 +30,38 @@ public: | |||
| 29 | ServerManager* server_manager); | 30 | ServerManager* server_manager); |
| 30 | ~ServiceManager() override = default; | 31 | ~ServiceManager() override = default; |
| 31 | 32 | ||
| 32 | Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service); | 33 | Result GetStaticServiceAsUser(OutInterface<StaticService> out_service); |
| 33 | Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service); | 34 | Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service); |
| 34 | Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service); | 35 | Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service); |
| 35 | Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service); | 36 | Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service); |
| 36 | Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, | 37 | Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id, |
| 37 | s64 internal_offset, s64 test_offset, | 38 | s64 rtc_offset, s64 internal_offset, s64 test_offset); |
| 38 | bool is_rtc_reset_detected); | ||
| 39 | Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); | 39 | Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); |
| 40 | Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); | 40 | Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); |
| 41 | Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, | 41 | Result SetupStandardUserSystemClockCore(bool automatic_correction, |
| 42 | bool automatic_correction); | 42 | SteadyClockTimePoint& time_point); |
| 43 | Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point, | 43 | Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, |
| 44 | RuleVersion& rule_version, u32 location_count, | 44 | u32 location_count, SteadyClockTimePoint& time_point, |
| 45 | std::span<const u8> rule_buffer); | 45 | InBuffer<BufferAttr_HipcAutoSelect> rule_buffer); |
| 46 | Result SetupEphemeralNetworkSystemClockCore(); | 46 | Result SetupEphemeralNetworkSystemClockCore(); |
| 47 | Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event); | 47 | Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 48 | Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); | 48 | Result GetStandardNetworkClockOperationEventForServiceManager( |
| 49 | Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); | 49 | OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 50 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event); | 50 | Result GetEphemeralNetworkClockOperationEventForServiceManager( |
| 51 | OutCopyHandle<Kernel::KReadableEvent> out_event); | ||
| 52 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( | ||
| 53 | OutCopyHandle<Kernel::KReadableEvent> out_event); | ||
| 51 | Result SetStandardSteadyClockBaseTime(s64 base_time); | 54 | Result SetStandardSteadyClockBaseTime(s64 base_time); |
| 52 | Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event); | 55 | Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 53 | Result CheckAndSignalAlarms(); | 56 | Result CheckAndSignalAlarms(); |
| 54 | Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time); | 57 | Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time); |
| 55 | 58 | ||
| 56 | private: | 59 | private: |
| 57 | void CheckAndSetupServicesSAndP(); | 60 | void CheckAndSetupServicesSAndP(); |
| 58 | void SetupSAndP(); | 61 | void SetupSAndP(); |
| 59 | Result GetStaticService(std::shared_ptr<StaticService>& out_service, | 62 | Result GetStaticService(OutInterface<StaticService> out_service, |
| 60 | StaticServiceSetupInfo setup_info, const char* name); | 63 | StaticServiceSetupInfo setup_info, const char* name); |
| 61 | 64 | ||
| 62 | void Handle_GetStaticServiceAsUser(HLERequestContext& ctx); | ||
| 63 | void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx); | ||
| 64 | void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx); | ||
| 65 | void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx); | ||
| 66 | void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx); | ||
| 67 | void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx); | ||
| 68 | void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx); | ||
| 69 | void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx); | ||
| 70 | void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx); | ||
| 71 | void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx); | ||
| 72 | void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx); | ||
| 73 | void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx); | ||
| 74 | void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx); | ||
| 75 | void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx); | ||
| 76 | void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx); | ||
| 77 | void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx); | ||
| 78 | void Handle_CheckAndSignalAlarms(HLERequestContext& ctx); | ||
| 79 | void Handle_GetClosestAlarmInfo(HLERequestContext& ctx); | ||
| 80 | |||
| 81 | Core::System& m_system; | 65 | Core::System& m_system; |
| 82 | std::shared_ptr<TimeManager> m_time; | 66 | std::shared_ptr<TimeManager> m_time; |
| 83 | ServerManager& m_server_manager; | 67 | ServerManager& m_server_manager; |
diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 6f8cf3f88..3ca3311af 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/scope_exit.h" | ||
| 4 | #include "core/core.h" | 5 | #include "core/core.h" |
| 5 | #include "core/core_timing.h" | 6 | #include "core/core_timing.h" |
| 6 | #include "core/hle/kernel/k_shared_memory.h" | 7 | #include "core/hle/kernel/k_shared_memory.h" |
| 8 | #include "core/hle/service/cmif_serialization.h" | ||
| 7 | #include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h" | 9 | #include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h" |
| 8 | #include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h" | 10 | #include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h" |
| 9 | #include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h" | 11 | #include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h" |
| @@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup | |||
| 39 | m_time->m_shared_memory} { | 41 | m_time->m_shared_memory} { |
| 40 | // clang-format off | 42 | // clang-format off |
| 41 | static const FunctionInfo functions[] = { | 43 | static const FunctionInfo functions[] = { |
| 42 | {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | 44 | {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"}, |
| 43 | {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, | 45 | {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"}, |
| 44 | {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, | 46 | {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"}, |
| 45 | {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, | 47 | {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"}, |
| 46 | {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, | 48 | {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"}, |
| 47 | {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, | 49 | {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"}, |
| 48 | {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, | 50 | {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, |
| 49 | {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, | 51 | {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"}, |
| 50 | {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, | 52 | {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"}, |
| 51 | {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, | 53 | {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 52 | {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, | 54 | {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 53 | {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, | 55 | {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"}, |
| 54 | {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, | 56 | {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"}, |
| 55 | {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, | 57 | {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, |
| 56 | {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, | 58 | {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"}, |
| 57 | {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, | 59 | {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"}, |
| 58 | {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, | 60 | {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"}, |
| 59 | {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, | 61 | {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"}, |
| 60 | {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, | 62 | {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"}, |
| 61 | }; | 63 | }; |
| 62 | // clang-format on | 64 | // clang-format on |
| 63 | 65 | ||
| 64 | RegisterHandlers(functions); | 66 | RegisterHandlers(functions); |
| 65 | } | 67 | } |
| 66 | 68 | ||
| 67 | Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot, | 69 | Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) { |
| 68 | SystemClockContext& user_context, | ||
| 69 | SystemClockContext& network_context, TimeType type) { | ||
| 70 | out_snapshot.user_context = user_context; | ||
| 71 | out_snapshot.network_context = network_context; | ||
| 72 | |||
| 73 | R_TRY( | ||
| 74 | m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point)); | ||
| 75 | |||
| 76 | out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection(); | ||
| 77 | |||
| 78 | R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name)); | ||
| 79 | |||
| 80 | R_TRY(GetTimeFromTimePointAndContext( | ||
| 81 | &out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context)); | ||
| 82 | |||
| 83 | R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time, | ||
| 84 | out_snapshot.user_calendar_additional_time, | ||
| 85 | out_snapshot.user_time)); | ||
| 86 | |||
| 87 | if (GetTimeFromTimePointAndContext(&out_snapshot.network_time, | ||
| 88 | out_snapshot.steady_clock_time_point, | ||
| 89 | out_snapshot.network_context) != ResultSuccess) { | ||
| 90 | out_snapshot.network_time = 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time, | ||
| 94 | out_snapshot.network_calendar_additional_time, | ||
| 95 | out_snapshot.network_time)); | ||
| 96 | out_snapshot.type = type; | ||
| 97 | out_snapshot.unk_CE = 0; | ||
| 98 | R_SUCCEED(); | ||
| 99 | } | ||
| 100 | |||
| 101 | void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) { | ||
| 102 | LOG_DEBUG(Service_Time, "called."); | ||
| 103 | |||
| 104 | std::shared_ptr<SystemClock> service{}; | ||
| 105 | auto res = GetStandardUserSystemClock(service); | ||
| 106 | |||
| 107 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 108 | rb.Push(res); | ||
| 109 | rb.PushIpcInterface<SystemClock>(std::move(service)); | ||
| 110 | } | ||
| 111 | |||
| 112 | void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) { | ||
| 113 | LOG_DEBUG(Service_Time, "called."); | 70 | LOG_DEBUG(Service_Time, "called."); |
| 114 | 71 | ||
| 115 | std::shared_ptr<SystemClock> service{}; | 72 | *out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock, |
| 116 | auto res = GetStandardNetworkSystemClock(service); | 73 | m_setup_info.can_write_user_clock, |
| 117 | 74 | m_setup_info.can_write_uninitialized_clock); | |
| 118 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 75 | R_SUCCEED(); |
| 119 | rb.Push(res); | ||
| 120 | rb.PushIpcInterface<SystemClock>(std::move(service)); | ||
| 121 | } | ||
| 122 | |||
| 123 | void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) { | ||
| 124 | LOG_DEBUG(Service_Time, "called."); | ||
| 125 | |||
| 126 | std::shared_ptr<SteadyClock> service{}; | ||
| 127 | auto res = GetStandardSteadyClock(service); | ||
| 128 | |||
| 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 130 | rb.Push(res); | ||
| 131 | rb.PushIpcInterface(std::move(service)); | ||
| 132 | } | ||
| 133 | |||
| 134 | void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) { | ||
| 135 | LOG_DEBUG(Service_Time, "called."); | ||
| 136 | |||
| 137 | std::shared_ptr<TimeZoneService> service{}; | ||
| 138 | auto res = GetTimeZoneService(service); | ||
| 139 | |||
| 140 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 141 | rb.Push(res); | ||
| 142 | rb.PushIpcInterface(std::move(service)); | ||
| 143 | } | ||
| 144 | |||
| 145 | void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) { | ||
| 146 | LOG_DEBUG(Service_Time, "called."); | ||
| 147 | |||
| 148 | std::shared_ptr<SystemClock> service{}; | ||
| 149 | auto res = GetStandardLocalSystemClock(service); | ||
| 150 | |||
| 151 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 152 | rb.Push(res); | ||
| 153 | rb.PushIpcInterface<SystemClock>(std::move(service)); | ||
| 154 | } | ||
| 155 | |||
| 156 | void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) { | ||
| 157 | LOG_DEBUG(Service_Time, "called."); | ||
| 158 | |||
| 159 | std::shared_ptr<SystemClock> service{}; | ||
| 160 | auto res = GetEphemeralNetworkSystemClock(service); | ||
| 161 | |||
| 162 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 163 | rb.Push(res); | ||
| 164 | rb.PushIpcInterface<SystemClock>(std::move(service)); | ||
| 165 | } | ||
| 166 | |||
| 167 | void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) { | ||
| 168 | LOG_DEBUG(Service_Time, "called."); | ||
| 169 | |||
| 170 | Kernel::KSharedMemory* shared_memory{}; | ||
| 171 | auto res = GetSharedMemoryNativeHandle(&shared_memory); | ||
| 172 | |||
| 173 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 174 | rb.Push(res); | ||
| 175 | rb.PushCopyObjects(shared_memory); | ||
| 176 | } | ||
| 177 | |||
| 178 | void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) { | ||
| 179 | LOG_DEBUG(Service_Time, "called."); | ||
| 180 | |||
| 181 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 182 | rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied); | ||
| 183 | } | ||
| 184 | |||
| 185 | void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) { | ||
| 186 | LOG_DEBUG(Service_Time, "called."); | ||
| 187 | |||
| 188 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 189 | rb.Push(ResultNotImplemented); | ||
| 190 | } | ||
| 191 | |||
| 192 | void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 193 | HLERequestContext& ctx) { | ||
| 194 | LOG_DEBUG(Service_Time, "called."); | ||
| 195 | |||
| 196 | bool is_enabled{}; | ||
| 197 | auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled); | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 200 | rb.Push(res); | ||
| 201 | rb.Push<bool>(is_enabled); | ||
| 202 | } | ||
| 203 | |||
| 204 | void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 205 | HLERequestContext& ctx) { | ||
| 206 | LOG_DEBUG(Service_Time, "called."); | ||
| 207 | |||
| 208 | IPC::RequestParser rp{ctx}; | ||
| 209 | auto automatic_correction{rp.Pop<bool>()}; | ||
| 210 | |||
| 211 | auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction); | ||
| 212 | |||
| 213 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 214 | rb.Push(res); | ||
| 215 | } | ||
| 216 | |||
| 217 | void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) { | ||
| 218 | LOG_DEBUG(Service_Time, "called."); | ||
| 219 | |||
| 220 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 221 | rb.Push(ResultNotImplemented); | ||
| 222 | } | ||
| 223 | |||
| 224 | void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) { | ||
| 225 | LOG_DEBUG(Service_Time, "called."); | ||
| 226 | |||
| 227 | bool is_sufficient{}; | ||
| 228 | auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient); | ||
| 229 | |||
| 230 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 231 | rb.Push(res); | ||
| 232 | rb.Push<bool>(is_sufficient); | ||
| 233 | } | 76 | } |
| 234 | 77 | ||
| 235 | void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 78 | Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) { |
| 236 | HLERequestContext& ctx) { | ||
| 237 | LOG_DEBUG(Service_Time, "called."); | 79 | LOG_DEBUG(Service_Time, "called."); |
| 238 | 80 | ||
| 239 | SteadyClockTimePoint time_point{}; | 81 | *out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, |
| 240 | auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); | 82 | m_setup_info.can_write_network_clock, |
| 241 | 83 | m_setup_info.can_write_uninitialized_clock); | |
| 242 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)}; | 84 | R_SUCCEED(); |
| 243 | rb.Push(res); | ||
| 244 | rb.PushRaw<SteadyClockTimePoint>(time_point); | ||
| 245 | } | 85 | } |
| 246 | 86 | ||
| 247 | void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { | 87 | Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) { |
| 248 | LOG_DEBUG(Service_Time, "called."); | 88 | LOG_DEBUG(Service_Time, "called."); |
| 249 | 89 | ||
| 250 | IPC::RequestParser rp{ctx}; | 90 | *out_service = |
| 251 | auto context{rp.PopRaw<SystemClockContext>()}; | 91 | std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock, |
| 252 | 92 | m_setup_info.can_write_uninitialized_clock); | |
| 253 | s64 time{}; | 93 | R_SUCCEED(); |
| 254 | auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context); | ||
| 255 | |||
| 256 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 257 | rb.Push(res); | ||
| 258 | rb.Push<s64>(time); | ||
| 259 | } | 94 | } |
| 260 | 95 | ||
| 261 | void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { | 96 | Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) { |
| 262 | LOG_DEBUG(Service_Time, "called."); | 97 | LOG_DEBUG(Service_Time, "called."); |
| 263 | 98 | ||
| 264 | IPC::RequestParser rp{ctx}; | 99 | *out_service = |
| 265 | auto type{rp.PopEnum<TimeType>()}; | 100 | std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone, |
| 266 | 101 | m_setup_info.can_write_timezone_device_location); | |
| 267 | ClockSnapshot snapshot{}; | 102 | R_SUCCEED(); |
| 268 | auto res = GetClockSnapshot(snapshot, type); | ||
| 269 | |||
| 270 | ctx.WriteBuffer(snapshot); | ||
| 271 | |||
| 272 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 273 | rb.Push(res); | ||
| 274 | } | 103 | } |
| 275 | 104 | ||
| 276 | void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { | 105 | Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) { |
| 277 | LOG_DEBUG(Service_Time, "called."); | 106 | LOG_DEBUG(Service_Time, "called."); |
| 278 | 107 | ||
| 279 | IPC::RequestParser rp{ctx}; | 108 | *out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, |
| 280 | auto clock_type{rp.PopEnum<TimeType>()}; | 109 | m_setup_info.can_write_local_clock, |
| 281 | [[maybe_unused]] auto alignment{rp.Pop<u32>()}; | 110 | m_setup_info.can_write_uninitialized_clock); |
| 282 | auto user_context{rp.PopRaw<SystemClockContext>()}; | 111 | R_SUCCEED(); |
| 283 | auto network_context{rp.PopRaw<SystemClockContext>()}; | ||
| 284 | |||
| 285 | ClockSnapshot snapshot{}; | ||
| 286 | auto res = | ||
| 287 | GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type); | ||
| 288 | |||
| 289 | ctx.WriteBuffer(snapshot); | ||
| 290 | |||
| 291 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 292 | rb.Push(res); | ||
| 293 | } | 112 | } |
| 294 | 113 | ||
| 295 | void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( | 114 | Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) { |
| 296 | HLERequestContext& ctx) { | ||
| 297 | LOG_DEBUG(Service_Time, "called."); | 115 | LOG_DEBUG(Service_Time, "called."); |
| 298 | 116 | ||
| 299 | ClockSnapshot a{}; | 117 | *out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock, |
| 300 | ClockSnapshot b{}; | 118 | m_setup_info.can_write_network_clock, |
| 301 | 119 | m_setup_info.can_write_uninitialized_clock); | |
| 302 | auto a_buffer{ctx.ReadBuffer(0)}; | 120 | R_SUCCEED(); |
| 303 | auto b_buffer{ctx.ReadBuffer(1)}; | ||
| 304 | |||
| 305 | std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot)); | ||
| 306 | std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot)); | ||
| 307 | |||
| 308 | s64 difference{}; | ||
| 309 | auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b); | ||
| 310 | |||
| 311 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 312 | rb.Push(res); | ||
| 313 | rb.Push(difference); | ||
| 314 | } | 121 | } |
| 315 | 122 | ||
| 316 | void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { | 123 | Result StaticService::GetSharedMemoryNativeHandle( |
| 124 | OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { | ||
| 317 | LOG_DEBUG(Service_Time, "called."); | 125 | LOG_DEBUG(Service_Time, "called."); |
| 318 | 126 | ||
| 319 | ClockSnapshot a{}; | 127 | *out_shared_memory = &m_shared_memory.GetKSharedMemory(); |
| 320 | ClockSnapshot b{}; | ||
| 321 | |||
| 322 | auto a_buffer{ctx.ReadBuffer(0)}; | ||
| 323 | auto b_buffer{ctx.ReadBuffer(1)}; | ||
| 324 | |||
| 325 | std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot)); | ||
| 326 | std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot)); | ||
| 327 | |||
| 328 | s64 time{}; | ||
| 329 | auto res = CalculateSpanBetween(time, a, b); | ||
| 330 | |||
| 331 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 332 | rb.Push(res); | ||
| 333 | rb.Push(time); | ||
| 334 | } | ||
| 335 | |||
| 336 | // =============================== Implementations =========================== | ||
| 337 | |||
| 338 | Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) { | ||
| 339 | out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock, | ||
| 340 | m_setup_info.can_write_user_clock, | ||
| 341 | m_setup_info.can_write_uninitialized_clock); | ||
| 342 | R_SUCCEED(); | 128 | R_SUCCEED(); |
| 343 | } | 129 | } |
| 344 | 130 | ||
| 345 | Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { | 131 | Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { |
| 346 | out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, | 132 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); |
| 347 | m_setup_info.can_write_network_clock, | ||
| 348 | m_setup_info.can_write_uninitialized_clock); | ||
| 349 | R_SUCCEED(); | ||
| 350 | } | ||
| 351 | 133 | ||
| 352 | Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) { | 134 | R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied); |
| 353 | out_service = | ||
| 354 | std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock, | ||
| 355 | m_setup_info.can_write_uninitialized_clock); | ||
| 356 | R_SUCCEED(); | ||
| 357 | } | ||
| 358 | 135 | ||
| 359 | Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) { | 136 | R_RETURN(ResultNotImplemented); |
| 360 | out_service = | ||
| 361 | std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone, | ||
| 362 | m_setup_info.can_write_timezone_device_location); | ||
| 363 | R_SUCCEED(); | ||
| 364 | } | 137 | } |
| 365 | 138 | ||
| 366 | Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) { | 139 | Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { |
| 367 | out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, | 140 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); |
| 368 | m_setup_info.can_write_local_clock, | ||
| 369 | m_setup_info.can_write_uninitialized_clock); | ||
| 370 | R_SUCCEED(); | ||
| 371 | } | ||
| 372 | 141 | ||
| 373 | Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { | 142 | R_RETURN(ResultNotImplemented); |
| 374 | out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock, | ||
| 375 | m_setup_info.can_write_network_clock, | ||
| 376 | m_setup_info.can_write_uninitialized_clock); | ||
| 377 | R_SUCCEED(); | ||
| 378 | } | 143 | } |
| 379 | 144 | ||
| 380 | Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) { | 145 | Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( |
| 381 | *out_shared_memory = &m_shared_memory.GetKSharedMemory(); | 146 | Out<bool> out_is_enabled) { |
| 382 | R_SUCCEED(); | 147 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); }); |
| 383 | } | ||
| 384 | 148 | ||
| 385 | Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) { | ||
| 386 | R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); | 149 | R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); |
| 387 | 150 | ||
| 388 | out_is_enabled = m_user_system_clock.GetAutomaticCorrection(); | 151 | *out_is_enabled = m_user_system_clock.GetAutomaticCorrection(); |
| 152 | |||
| 389 | R_SUCCEED(); | 153 | R_SUCCEED(); |
| 390 | } | 154 | } |
| 391 | 155 | ||
| 392 | Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( | 156 | Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( |
| 393 | bool automatic_correction) { | 157 | bool automatic_correction) { |
| 158 | LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction); | ||
| 159 | |||
| 394 | R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(), | 160 | R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(), |
| 395 | ResultClockUninitialized); | 161 | ResultClockUninitialized); |
| 396 | R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied); | 162 | R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied); |
| @@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( | |||
| 407 | R_SUCCEED(); | 173 | R_SUCCEED(); |
| 408 | } | 174 | } |
| 409 | 175 | ||
| 410 | Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { | 176 | Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { |
| 411 | out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); | 177 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); |
| 178 | |||
| 179 | R_RETURN(ResultNotImplemented); | ||
| 180 | } | ||
| 181 | |||
| 182 | Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { | ||
| 183 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); | ||
| 184 | |||
| 185 | *out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); | ||
| 186 | |||
| 412 | R_SUCCEED(); | 187 | R_SUCCEED(); |
| 413 | } | 188 | } |
| 414 | 189 | ||
| 415 | Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 190 | Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( |
| 416 | SteadyClockTimePoint& out_time_point) { | 191 | Out<SteadyClockTimePoint> out_time_point) { |
| 192 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); | ||
| 193 | |||
| 417 | R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); | 194 | R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); |
| 418 | 195 | ||
| 419 | m_user_system_clock.GetTimePoint(out_time_point); | 196 | m_user_system_clock.GetTimePoint(*out_time_point); |
| 420 | 197 | ||
| 421 | R_SUCCEED(); | 198 | R_SUCCEED(); |
| 422 | } | 199 | } |
| 423 | 200 | ||
| 424 | Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, | 201 | Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, |
| 425 | SystemClockContext& context) { | 202 | SystemClockContext& context) { |
| 203 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); | ||
| 204 | |||
| 426 | R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); | 205 | R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); |
| 427 | 206 | ||
| 428 | SteadyClockTimePoint time_point{}; | 207 | SteadyClockTimePoint time_point{}; |
| @@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, | |||
| 433 | auto one_second_ns{ | 212 | auto one_second_ns{ |
| 434 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; | 213 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; |
| 435 | auto ticks{m_system.CoreTiming().GetClockTicks()}; | 214 | auto ticks{m_system.CoreTiming().GetClockTicks()}; |
| 436 | auto current_time{ConvertToTimeSpan(ticks).count()}; | 215 | auto current_time_ns{ConvertToTimeSpan(ticks).count()}; |
| 437 | out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns)); | 216 | *out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns)); |
| 217 | |||
| 438 | R_SUCCEED(); | 218 | R_SUCCEED(); |
| 439 | } | 219 | } |
| 440 | 220 | ||
| 441 | Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) { | 221 | Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) { |
| 222 | SCOPE_EXIT( | ||
| 223 | { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); | ||
| 224 | |||
| 442 | SystemClockContext user_context{}; | 225 | SystemClockContext user_context{}; |
| 443 | R_TRY(m_user_system_clock.GetContext(user_context)); | 226 | R_TRY(m_user_system_clock.GetContext(user_context)); |
| 444 | 227 | ||
| @@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ | |||
| 448 | R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); | 231 | R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); |
| 449 | } | 232 | } |
| 450 | 233 | ||
| 451 | Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, | 234 | Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type, |
| 235 | OutClockSnapshot out_snapshot, | ||
| 452 | SystemClockContext& user_context, | 236 | SystemClockContext& user_context, |
| 453 | SystemClockContext& network_context, | 237 | SystemClockContext& network_context) { |
| 454 | TimeType type) { | 238 | SCOPE_EXIT({ |
| 239 | LOG_DEBUG(Service_Time, | ||
| 240 | "called. type={} user_context={} network_context={} out_snapshot={}", type, | ||
| 241 | user_context, network_context, *out_snapshot); | ||
| 242 | }); | ||
| 243 | |||
| 455 | R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); | 244 | R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); |
| 456 | } | 245 | } |
| 457 | 246 | ||
| 458 | Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, | 247 | Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, |
| 459 | ClockSnapshot& a, | 248 | InClockSnapshot a, |
| 460 | ClockSnapshot& b) { | 249 | InClockSnapshot b) { |
| 250 | SCOPE_EXIT({ | ||
| 251 | LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference); | ||
| 252 | }); | ||
| 253 | |||
| 461 | auto diff_s = | 254 | auto diff_s = |
| 462 | std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset); | 255 | std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset); |
| 463 | 256 | ||
| 464 | if (a.user_context == b.user_context || | 257 | if (a->user_context == b->user_context || |
| 465 | !a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) { | 258 | !a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) { |
| 466 | out_time = 0; | 259 | *out_difference = 0; |
| 467 | R_SUCCEED(); | 260 | R_SUCCEED(); |
| 468 | } | 261 | } |
| 469 | 262 | ||
| 470 | if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) { | 263 | if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) { |
| 471 | out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); | 264 | *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); |
| 472 | R_SUCCEED(); | 265 | R_SUCCEED(); |
| 473 | } | 266 | } |
| 474 | 267 | ||
| 475 | if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) || | 268 | if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) || |
| 476 | b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) { | 269 | b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) { |
| 477 | out_time = 0; | 270 | *out_difference = 0; |
| 478 | R_SUCCEED(); | 271 | R_SUCCEED(); |
| 479 | } | 272 | } |
| 480 | 273 | ||
| 481 | out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); | 274 | *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); |
| 482 | R_SUCCEED(); | 275 | R_SUCCEED(); |
| 483 | } | 276 | } |
| 484 | 277 | ||
| 485 | Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) { | 278 | Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, |
| 279 | InClockSnapshot b) { | ||
| 280 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); | ||
| 281 | |||
| 486 | s64 time_s{}; | 282 | s64 time_s{}; |
| 487 | auto res = | 283 | auto res = |
| 488 | GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point); | 284 | GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point); |
| 489 | 285 | ||
| 490 | if (res != ResultSuccess) { | 286 | if (res != ResultSuccess) { |
| 491 | R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound); | 287 | R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound); |
| 492 | time_s = b.network_time - a.network_time; | 288 | time_s = b->network_time - a->network_time; |
| 493 | } | 289 | } |
| 494 | 290 | ||
| 495 | out_time = | 291 | *out_time = |
| 496 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count(); | 292 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count(); |
| 497 | R_SUCCEED(); | 293 | R_SUCCEED(); |
| 498 | } | 294 | } |
| 499 | 295 | ||
| 296 | Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot, | ||
| 297 | SystemClockContext& user_context, | ||
| 298 | SystemClockContext& network_context, TimeType type) { | ||
| 299 | out_snapshot->user_context = user_context; | ||
| 300 | out_snapshot->network_context = network_context; | ||
| 301 | |||
| 302 | R_TRY( | ||
| 303 | m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point)); | ||
| 304 | |||
| 305 | out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection(); | ||
| 306 | |||
| 307 | R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name)); | ||
| 308 | |||
| 309 | R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time, | ||
| 310 | out_snapshot->steady_clock_time_point, | ||
| 311 | out_snapshot->user_context)); | ||
| 312 | |||
| 313 | R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time, | ||
| 314 | out_snapshot->user_calendar_additional_time, | ||
| 315 | out_snapshot->user_time)); | ||
| 316 | |||
| 317 | if (GetTimeFromTimePointAndContext(&out_snapshot->network_time, | ||
| 318 | out_snapshot->steady_clock_time_point, | ||
| 319 | out_snapshot->network_context) != ResultSuccess) { | ||
| 320 | out_snapshot->network_time = 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time, | ||
| 324 | out_snapshot->network_calendar_additional_time, | ||
| 325 | out_snapshot->network_time)); | ||
| 326 | out_snapshot->type = type; | ||
| 327 | out_snapshot->unk_CE = 0; | ||
| 328 | R_SUCCEED(); | ||
| 329 | } | ||
| 330 | |||
| 500 | } // namespace Service::PSC::Time | 331 | } // namespace Service::PSC::Time |
diff --git a/src/core/hle/service/psc/time/static.h b/src/core/hle/service/psc/time/static.h index 498cd5ab5..120bab259 100644 --- a/src/core/hle/service/psc/time/static.h +++ b/src/core/hle/service/psc/time/static.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 7 | #include "core/hle/service/psc/time/common.h" | 8 | #include "core/hle/service/psc/time/common.h" |
| 8 | #include "core/hle/service/server_manager.h" | 9 | #include "core/hle/service/server_manager.h" |
| @@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore; | |||
| 29 | class SharedMemory; | 30 | class SharedMemory; |
| 30 | 31 | ||
| 31 | class StaticService final : public ServiceFramework<StaticService> { | 32 | class StaticService final : public ServiceFramework<StaticService> { |
| 33 | using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>; | ||
| 34 | using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>; | ||
| 35 | |||
| 32 | public: | 36 | public: |
| 33 | explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info, | 37 | explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info, |
| 34 | std::shared_ptr<TimeManager> time, const char* name); | 38 | std::shared_ptr<TimeManager> time, const char* name); |
| 35 | 39 | ||
| 36 | ~StaticService() override = default; | 40 | ~StaticService() override = default; |
| 37 | 41 | ||
| 38 | Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service); | 42 | Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service); |
| 39 | Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); | 43 | Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service); |
| 40 | Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service); | 44 | Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service); |
| 41 | Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service); | 45 | Result GetTimeZoneService(OutInterface<TimeZoneService> out_service); |
| 42 | Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service); | 46 | Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service); |
| 43 | Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); | 47 | Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service); |
| 44 | Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); | 48 | Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); |
| 45 | Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled); | 49 | Result SetStandardSteadyClockInternalOffset(s64 offset_ns); |
| 50 | Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value); | ||
| 51 | Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled); | ||
| 46 | Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); | 52 | Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); |
| 47 | Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); | 53 | Result GetStandardUserSystemClockInitialYear(Out<s32> out_year); |
| 54 | Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient); | ||
| 48 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( | 55 | Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( |
| 49 | SteadyClockTimePoint& out_time_point); | 56 | Out<SteadyClockTimePoint> out_time_point); |
| 50 | Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context); | 57 | Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, |
| 51 | Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type); | 58 | SystemClockContext& context); |
| 52 | Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, | 59 | Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type); |
| 60 | Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot, | ||
| 53 | SystemClockContext& user_context, | 61 | SystemClockContext& user_context, |
| 54 | SystemClockContext& network_context, | 62 | SystemClockContext& network_context); |
| 55 | TimeType type); | 63 | Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, |
| 56 | Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a, | 64 | InClockSnapshot a, InClockSnapshot b); |
| 57 | ClockSnapshot& b); | 65 | Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); |
| 58 | Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b); | ||
| 59 | 66 | ||
| 60 | private: | 67 | private: |
| 61 | Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context, | 68 | Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context, |
| 62 | SystemClockContext& network_context, TimeType type); | 69 | SystemClockContext& network_context, TimeType type); |
| 63 | 70 | ||
| 64 | void Handle_GetStandardUserSystemClock(HLERequestContext& ctx); | ||
| 65 | void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx); | ||
| 66 | void Handle_GetStandardSteadyClock(HLERequestContext& ctx); | ||
| 67 | void Handle_GetTimeZoneService(HLERequestContext& ctx); | ||
| 68 | void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx); | ||
| 69 | void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx); | ||
| 70 | void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx); | ||
| 71 | void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx); | ||
| 72 | void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx); | ||
| 73 | void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||
| 74 | void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||
| 75 | void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx); | ||
| 76 | void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx); | ||
| 77 | void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); | ||
| 78 | void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx); | ||
| 79 | void Handle_GetClockSnapshot(HLERequestContext& ctx); | ||
| 80 | void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx); | ||
| 81 | void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx); | ||
| 82 | void Handle_CalculateSpanBetween(HLERequestContext& ctx); | ||
| 83 | |||
| 84 | Core::System& m_system; | 71 | Core::System& m_system; |
| 85 | StaticServiceSetupInfo m_setup_info; | 72 | StaticServiceSetupInfo m_setup_info; |
| 86 | std::shared_ptr<TimeManager> m_time; | 73 | std::shared_ptr<TimeManager> m_time; |
diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp index 1ed5c7679..948610a2b 100644 --- a/src/core/hle/service/psc/time/steady_clock.cpp +++ b/src/core/hle/service/psc/time/steady_clock.cpp | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/scope_exit.h" | ||
| 4 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/service/cmif_serialization.h" | ||
| 5 | #include "core/hle/service/psc/time/steady_clock.h" | 7 | #include "core/hle/service/psc/time/steady_clock.h" |
| 6 | 8 | ||
| 7 | namespace Service::PSC::Time { | 9 | namespace Service::PSC::Time { |
| @@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man | |||
| 14 | can_write_uninitialized_clock} { | 16 | can_write_uninitialized_clock} { |
| 15 | // clang-format off | 17 | // clang-format off |
| 16 | static const FunctionInfo functions[] = { | 18 | static const FunctionInfo functions[] = { |
| 17 | {0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"}, | 19 | {0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"}, |
| 18 | {2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"}, | 20 | {2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"}, |
| 19 | {3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"}, | 21 | {3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"}, |
| 20 | {100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"}, | 22 | {100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"}, |
| 21 | {101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"}, | 23 | {101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"}, |
| 22 | {102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"}, | 24 | {102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"}, |
| 23 | {200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"}, | 25 | {200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"}, |
| 24 | }; | 26 | }; |
| 25 | // clang-format on | 27 | // clang-format on |
| 26 | RegisterHandlers(functions); | 28 | RegisterHandlers(functions); |
| 27 | } | 29 | } |
| 28 | 30 | ||
| 29 | void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) { | 31 | Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) { |
| 30 | LOG_DEBUG(Service_Time, "called."); | 32 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); |
| 31 | 33 | ||
| 32 | SteadyClockTimePoint time_point{}; | ||
| 33 | auto res = GetCurrentTimePoint(time_point); | ||
| 34 | |||
| 35 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)}; | ||
| 36 | rb.Push(res); | ||
| 37 | rb.PushRaw<SteadyClockTimePoint>(time_point); | ||
| 38 | } | ||
| 39 | |||
| 40 | void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) { | ||
| 41 | LOG_DEBUG(Service_Time, "called."); | ||
| 42 | |||
| 43 | s64 test_offset{}; | ||
| 44 | auto res = GetTestOffset(test_offset); | ||
| 45 | |||
| 46 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 47 | rb.Push(res); | ||
| 48 | rb.Push(test_offset); | ||
| 49 | } | ||
| 50 | |||
| 51 | void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) { | ||
| 52 | LOG_DEBUG(Service_Time, "called."); | ||
| 53 | |||
| 54 | IPC::RequestParser rp{ctx}; | ||
| 55 | auto test_offset{rp.Pop<s64>()}; | ||
| 56 | |||
| 57 | auto res = SetTestOffset(test_offset); | ||
| 58 | |||
| 59 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 60 | rb.Push(res); | ||
| 61 | } | ||
| 62 | |||
| 63 | void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) { | ||
| 64 | LOG_DEBUG(Service_Time, "called."); | ||
| 65 | |||
| 66 | s64 rtc_value{}; | ||
| 67 | auto res = GetRtcValue(rtc_value); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 70 | rb.Push(res); | ||
| 71 | rb.Push(rtc_value); | ||
| 72 | } | ||
| 73 | |||
| 74 | void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) { | ||
| 75 | LOG_DEBUG(Service_Time, "called."); | ||
| 76 | |||
| 77 | bool reset_detected{false}; | ||
| 78 | auto res = IsRtcResetDetected(reset_detected); | ||
| 79 | |||
| 80 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 81 | rb.Push(res); | ||
| 82 | rb.Push(reset_detected); | ||
| 83 | } | ||
| 84 | |||
| 85 | void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) { | ||
| 86 | LOG_DEBUG(Service_Time, "called."); | ||
| 87 | |||
| 88 | Result result_value{ResultSuccess}; | ||
| 89 | auto res = GetSetupResultValue(result_value); | ||
| 90 | |||
| 91 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 92 | rb.Push(res); | ||
| 93 | rb.Push(result_value); | ||
| 94 | } | ||
| 95 | |||
| 96 | void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) { | ||
| 97 | LOG_DEBUG(Service_Time, "called."); | ||
| 98 | |||
| 99 | s64 internal_offset{}; | ||
| 100 | auto res = GetInternalOffset(internal_offset); | ||
| 101 | |||
| 102 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 103 | rb.Push(res); | ||
| 104 | rb.Push(internal_offset); | ||
| 105 | } | ||
| 106 | |||
| 107 | // =============================== Implementations =========================== | ||
| 108 | |||
| 109 | Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) { | ||
| 110 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 34 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 111 | ResultClockUninitialized); | 35 | ResultClockUninitialized); |
| 112 | 36 | ||
| 113 | R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point)); | 37 | R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point)); |
| 114 | } | 38 | } |
| 115 | 39 | ||
| 116 | Result SteadyClock::GetTestOffset(s64& out_test_offset) { | 40 | Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) { |
| 41 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); }); | ||
| 42 | |||
| 117 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 43 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 118 | ResultClockUninitialized); | 44 | ResultClockUninitialized); |
| 119 | 45 | ||
| 120 | out_test_offset = m_clock_core.GetTestOffset(); | 46 | *out_test_offset = m_clock_core.GetTestOffset(); |
| 121 | R_SUCCEED(); | 47 | R_SUCCEED(); |
| 122 | } | 48 | } |
| 123 | 49 | ||
| 124 | Result SteadyClock::SetTestOffset(s64 test_offset) { | 50 | Result SteadyClock::SetTestOffset(s64 test_offset) { |
| 51 | LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset); | ||
| 52 | |||
| 125 | R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied); | 53 | R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied); |
| 126 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 54 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 127 | ResultClockUninitialized); | 55 | ResultClockUninitialized); |
| @@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) { | |||
| 130 | R_SUCCEED(); | 58 | R_SUCCEED(); |
| 131 | } | 59 | } |
| 132 | 60 | ||
| 133 | Result SteadyClock::GetRtcValue(s64& out_rtc_value) { | 61 | Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { |
| 62 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); | ||
| 63 | |||
| 134 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 64 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 135 | ResultClockUninitialized); | 65 | ResultClockUninitialized); |
| 136 | 66 | ||
| 137 | R_RETURN(m_clock_core.GetRtcValue(out_rtc_value)); | 67 | R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value)); |
| 138 | } | 68 | } |
| 139 | 69 | ||
| 140 | Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) { | 70 | Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { |
| 71 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); }); | ||
| 72 | |||
| 141 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 73 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 142 | ResultClockUninitialized); | 74 | ResultClockUninitialized); |
| 143 | 75 | ||
| 144 | out_is_detected = m_clock_core.IsResetDetected(); | 76 | *out_is_detected = m_clock_core.IsResetDetected(); |
| 145 | R_SUCCEED(); | 77 | R_SUCCEED(); |
| 146 | } | 78 | } |
| 147 | 79 | ||
| 148 | Result SteadyClock::GetSetupResultValue(Result& out_result) { | 80 | Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { |
| 81 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); }); | ||
| 82 | |||
| 149 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 83 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 150 | ResultClockUninitialized); | 84 | ResultClockUninitialized); |
| 151 | 85 | ||
| 152 | out_result = m_clock_core.GetSetupResultValue(); | 86 | *out_result = m_clock_core.GetSetupResultValue(); |
| 153 | R_SUCCEED(); | 87 | R_SUCCEED(); |
| 154 | } | 88 | } |
| 155 | 89 | ||
| 156 | Result SteadyClock::GetInternalOffset(s64& out_internal_offset) { | 90 | Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) { |
| 91 | SCOPE_EXIT( | ||
| 92 | { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); }); | ||
| 93 | |||
| 157 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 94 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 158 | ResultClockUninitialized); | 95 | ResultClockUninitialized); |
| 159 | 96 | ||
| 160 | out_internal_offset = m_clock_core.GetInternalOffset(); | 97 | *out_internal_offset = m_clock_core.GetInternalOffset(); |
| 161 | R_SUCCEED(); | 98 | R_SUCCEED(); |
| 162 | } | 99 | } |
| 163 | 100 | ||
diff --git a/src/core/hle/service/psc/time/steady_clock.h b/src/core/hle/service/psc/time/steady_clock.h index 115e9b138..025d758a6 100644 --- a/src/core/hle/service/psc/time/steady_clock.h +++ b/src/core/hle/service/psc/time/steady_clock.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 7 | #include "core/hle/service/psc/time/common.h" | 8 | #include "core/hle/service/psc/time/common.h" |
| 8 | #include "core/hle/service/psc/time/manager.h" | 9 | #include "core/hle/service/psc/time/manager.h" |
| @@ -22,23 +23,15 @@ public: | |||
| 22 | 23 | ||
| 23 | ~SteadyClock() override = default; | 24 | ~SteadyClock() override = default; |
| 24 | 25 | ||
| 25 | Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point); | 26 | Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point); |
| 26 | Result GetTestOffset(s64& out_test_offset); | 27 | Result GetTestOffset(Out<s64> out_test_offset); |
| 27 | Result SetTestOffset(s64 test_offset); | 28 | Result SetTestOffset(s64 test_offset); |
| 28 | Result GetRtcValue(s64& out_rtc_value); | 29 | Result GetRtcValue(Out<s64> out_rtc_value); |
| 29 | Result IsRtcResetDetected(bool& out_is_detected); | 30 | Result IsRtcResetDetected(Out<bool> out_is_detected); |
| 30 | Result GetSetupResultValue(Result& out_result); | 31 | Result GetSetupResultValue(Out<Result> out_result); |
| 31 | Result GetInternalOffset(s64& out_internal_offset); | 32 | Result GetInternalOffset(Out<s64> out_internal_offset); |
| 32 | 33 | ||
| 33 | private: | 34 | private: |
| 34 | void Handle_GetCurrentTimePoint(HLERequestContext& ctx); | ||
| 35 | void Handle_GetTestOffset(HLERequestContext& ctx); | ||
| 36 | void Handle_SetTestOffset(HLERequestContext& ctx); | ||
| 37 | void Handle_GetRtcValue(HLERequestContext& ctx); | ||
| 38 | void Handle_IsRtcResetDetected(HLERequestContext& ctx); | ||
| 39 | void Handle_GetSetupResultValue(HLERequestContext& ctx); | ||
| 40 | void Handle_GetInternalOffset(HLERequestContext& ctx); | ||
| 41 | |||
| 42 | Core::System& m_system; | 35 | Core::System& m_system; |
| 43 | 36 | ||
| 44 | StandardSteadyClockCore& m_clock_core; | 37 | StandardSteadyClockCore& m_clock_core; |
diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp index 13d2f1d11..0695502d5 100644 --- a/src/core/hle/service/psc/time/system_clock.cpp +++ b/src/core/hle/service/psc/time/system_clock.cpp | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/scope_exit.h" | ||
| 4 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/service/cmif_serialization.h" | ||
| 5 | #include "core/hle/service/psc/time/system_clock.h" | 7 | #include "core/hle/service/psc/time/system_clock.h" |
| 6 | 8 | ||
| 7 | namespace Service::PSC::Time { | 9 | namespace Service::PSC::Time { |
| @@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo | |||
| 13 | can_write_uninitialized_clock} { | 15 | can_write_uninitialized_clock} { |
| 14 | // clang-format off | 16 | // clang-format off |
| 15 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
| 16 | {0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"}, | 18 | {0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"}, |
| 17 | {1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"}, | 19 | {1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"}, |
| 18 | {2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"}, | 20 | {2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"}, |
| 19 | {3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"}, | 21 | {3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"}, |
| 20 | {4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"}, | 22 | {4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"}, |
| 21 | }; | 23 | }; |
| 22 | // clang-format on | 24 | // clang-format on |
| 23 | RegisterHandlers(functions); | 25 | RegisterHandlers(functions); |
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) { | 28 | Result SystemClock::GetCurrentTime(Out<s64> out_time) { |
| 27 | LOG_DEBUG(Service_Time, "called."); | 29 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); }); |
| 28 | |||
| 29 | s64 time{}; | ||
| 30 | auto res = GetCurrentTime(time); | ||
| 31 | |||
| 32 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 33 | rb.Push(res); | ||
| 34 | rb.Push<s64>(time); | ||
| 35 | } | ||
| 36 | |||
| 37 | void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) { | ||
| 38 | LOG_DEBUG(Service_Time, "called."); | ||
| 39 | |||
| 40 | IPC::RequestParser rp{ctx}; | ||
| 41 | auto time{rp.Pop<s64>()}; | ||
| 42 | |||
| 43 | auto res = SetCurrentTime(time); | ||
| 44 | |||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(res); | ||
| 47 | } | ||
| 48 | |||
| 49 | void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) { | ||
| 50 | LOG_DEBUG(Service_Time, "called."); | ||
| 51 | |||
| 52 | SystemClockContext context{}; | ||
| 53 | auto res = GetSystemClockContext(context); | ||
| 54 | |||
| 55 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)}; | ||
| 56 | rb.Push(res); | ||
| 57 | rb.PushRaw<SystemClockContext>(context); | ||
| 58 | } | ||
| 59 | |||
| 60 | void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) { | ||
| 61 | LOG_DEBUG(Service_Time, "called."); | ||
| 62 | |||
| 63 | IPC::RequestParser rp{ctx}; | ||
| 64 | auto context{rp.PopRaw<SystemClockContext>()}; | ||
| 65 | |||
| 66 | auto res = SetSystemClockContext(context); | ||
| 67 | |||
| 68 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 69 | rb.Push(res); | ||
| 70 | } | ||
| 71 | |||
| 72 | void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) { | ||
| 73 | LOG_DEBUG(Service_Time, "called."); | ||
| 74 | |||
| 75 | Kernel::KEvent* event{}; | ||
| 76 | auto res = GetOperationEventReadableHandle(&event); | ||
| 77 | 30 | ||
| 78 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 79 | rb.Push(res); | ||
| 80 | rb.PushCopyObjects(event->GetReadableEvent()); | ||
| 81 | } | ||
| 82 | |||
| 83 | // =============================== Implementations =========================== | ||
| 84 | |||
| 85 | Result SystemClock::GetCurrentTime(s64& out_time) { | ||
| 86 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 31 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 87 | ResultClockUninitialized); | 32 | ResultClockUninitialized); |
| 88 | 33 | ||
| 89 | R_RETURN(m_clock_core.GetCurrentTime(&out_time)); | 34 | R_RETURN(m_clock_core.GetCurrentTime(out_time.Get())); |
| 90 | } | 35 | } |
| 91 | 36 | ||
| 92 | Result SystemClock::SetCurrentTime(s64 time) { | 37 | Result SystemClock::SetCurrentTime(s64 time) { |
| 38 | LOG_DEBUG(Service_Time, "called. time={}", time); | ||
| 39 | |||
| 93 | R_UNLESS(m_can_write_clock, ResultPermissionDenied); | 40 | R_UNLESS(m_can_write_clock, ResultPermissionDenied); |
| 94 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 41 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 95 | ResultClockUninitialized); | 42 | ResultClockUninitialized); |
| @@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) { | |||
| 97 | R_RETURN(m_clock_core.SetCurrentTime(time)); | 44 | R_RETURN(m_clock_core.SetCurrentTime(time)); |
| 98 | } | 45 | } |
| 99 | 46 | ||
| 100 | Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) { | 47 | Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { |
| 48 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); }); | ||
| 49 | |||
| 101 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 50 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 102 | ResultClockUninitialized); | 51 | ResultClockUninitialized); |
| 103 | 52 | ||
| 104 | R_RETURN(m_clock_core.GetContext(out_context)); | 53 | R_RETURN(m_clock_core.GetContext(*out_context)); |
| 105 | } | 54 | } |
| 106 | 55 | ||
| 107 | Result SystemClock::SetSystemClockContext(SystemClockContext& context) { | 56 | Result SystemClock::SetSystemClockContext(SystemClockContext& context) { |
| 57 | LOG_DEBUG(Service_Time, "called. context={}", context); | ||
| 58 | |||
| 108 | R_UNLESS(m_can_write_clock, ResultPermissionDenied); | 59 | R_UNLESS(m_can_write_clock, ResultPermissionDenied); |
| 109 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), | 60 | R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), |
| 110 | ResultClockUninitialized); | 61 | ResultClockUninitialized); |
| @@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) { | |||
| 112 | R_RETURN(m_clock_core.SetContextAndWrite(context)); | 63 | R_RETURN(m_clock_core.SetContextAndWrite(context)); |
| 113 | } | 64 | } |
| 114 | 65 | ||
| 115 | Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) { | 66 | Result SystemClock::GetOperationEventReadableHandle( |
| 67 | OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||
| 68 | LOG_DEBUG(Service_Time, "called."); | ||
| 69 | |||
| 116 | if (!m_operation_event) { | 70 | if (!m_operation_event) { |
| 117 | m_operation_event = std::make_unique<OperationEvent>(m_system); | 71 | m_operation_event = std::make_unique<OperationEvent>(m_system); |
| 118 | R_UNLESS(m_operation_event != nullptr, ResultFailed); | 72 | R_UNLESS(m_operation_event != nullptr, ResultFailed); |
| @@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) | |||
| 120 | m_clock_core.LinkOperationEvent(*m_operation_event); | 74 | m_clock_core.LinkOperationEvent(*m_operation_event); |
| 121 | } | 75 | } |
| 122 | 76 | ||
| 123 | *out_event = m_operation_event->m_event; | 77 | *out_event = &m_operation_event->m_event->GetReadableEvent(); |
| 124 | R_SUCCEED(); | 78 | R_SUCCEED(); |
| 125 | } | 79 | } |
| 126 | 80 | ||
diff --git a/src/core/hle/service/psc/time/system_clock.h b/src/core/hle/service/psc/time/system_clock.h index f30027e7b..b40d73595 100644 --- a/src/core/hle/service/psc/time/system_clock.h +++ b/src/core/hle/service/psc/time/system_clock.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 7 | #include "core/hle/service/psc/time/common.h" | 8 | #include "core/hle/service/psc/time/common.h" |
| 8 | #include "core/hle/service/psc/time/manager.h" | 9 | #include "core/hle/service/psc/time/manager.h" |
| @@ -22,19 +23,13 @@ public: | |||
| 22 | 23 | ||
| 23 | ~SystemClock() override = default; | 24 | ~SystemClock() override = default; |
| 24 | 25 | ||
| 25 | Result GetCurrentTime(s64& out_time); | 26 | Result GetCurrentTime(Out<s64> out_time); |
| 26 | Result SetCurrentTime(s64 time); | 27 | Result SetCurrentTime(s64 time); |
| 27 | Result GetSystemClockContext(SystemClockContext& out_context); | 28 | Result GetSystemClockContext(Out<SystemClockContext> out_context); |
| 28 | Result SetSystemClockContext(SystemClockContext& context); | 29 | Result SetSystemClockContext(SystemClockContext& context); |
| 29 | Result GetOperationEventReadableHandle(Kernel::KEvent** out_event); | 30 | Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 30 | 31 | ||
| 31 | private: | 32 | private: |
| 32 | void Handle_GetCurrentTime(HLERequestContext& ctx); | ||
| 33 | void Handle_SetCurrentTime(HLERequestContext& ctx); | ||
| 34 | void Handle_GetSystemClockContext(HLERequestContext& ctx); | ||
| 35 | void Handle_SetSystemClockContext(HLERequestContext& ctx); | ||
| 36 | void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx); | ||
| 37 | |||
| 38 | Core::System& m_system; | 33 | Core::System& m_system; |
| 39 | 34 | ||
| 40 | SystemClockCore& m_clock_core; | 35 | SystemClockCore& m_clock_core; |
diff --git a/src/core/hle/service/psc/time/time_zone.cpp b/src/core/hle/service/psc/time/time_zone.cpp index cfee8f866..cc855c763 100644 --- a/src/core/hle/service/psc/time/time_zone.cpp +++ b/src/core/hle/service/psc/time/time_zone.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | namespace Service::PSC::Time { | 6 | namespace Service::PSC::Time { |
| 7 | namespace { | 7 | namespace { |
| 8 | constexpr Result ValidateRule(Tz::Rule& rule) { | 8 | constexpr Result ValidateRule(const Tz::Rule& rule) { |
| 9 | if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) || | 9 | if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) || |
| 10 | rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) || | 10 | rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) || |
| 11 | rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) { | 11 | rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) { |
| @@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) { | |||
| 26 | R_SUCCEED(); | 26 | R_SUCCEED(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index, | 29 | constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index, |
| 30 | s32 index_offset) { | 30 | s32 index_offset) { |
| 31 | s32 found_idx{}; | 31 | s32 found_idx{}; |
| 32 | s32 expected_index{index + index_offset}; | 32 | s32 expected_index{index + index_offset}; |
| @@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) { | |||
| 107 | 107 | ||
| 108 | Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time, | 108 | Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time, |
| 109 | CalendarAdditionalInfo& out_additional_info, s64 time, | 109 | CalendarAdditionalInfo& out_additional_info, s64 time, |
| 110 | Tz::Rule& rule) { | 110 | const Tz::Rule& rule) { |
| 111 | std::scoped_lock l{m_mutex}; | 111 | std::scoped_lock l{m_mutex}; |
| 112 | R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule)); | 112 | R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule)); |
| 113 | } | 113 | } |
| @@ -140,11 +140,11 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary) | |||
| 140 | R_RETURN(ParseBinaryImpl(out_rule, binary)); | 140 | R_RETURN(ParseBinaryImpl(out_rule, binary)); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 143 | Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 144 | CalendarTime& calendar, Tz::Rule& rule) { | 144 | const CalendarTime& calendar, const Tz::Rule& rule) { |
| 145 | std::scoped_lock l{m_mutex}; | 145 | std::scoped_lock l{m_mutex}; |
| 146 | 146 | ||
| 147 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1); | 147 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1); |
| 148 | 148 | ||
| 149 | if (res != ResultSuccess) { | 149 | if (res != ResultSuccess) { |
| 150 | if (res == ResultTimeZoneNotFound) { | 150 | if (res == ResultTimeZoneNotFound) { |
| @@ -157,11 +157,11 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou | |||
| 157 | R_RETURN(res); | 157 | R_RETURN(res); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, | 160 | Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, |
| 161 | u32 out_times_count, CalendarTime& calendar) { | 161 | size_t out_times_max_count, const CalendarTime& calendar) { |
| 162 | std::scoped_lock l{m_mutex}; | 162 | std::scoped_lock l{m_mutex}; |
| 163 | 163 | ||
| 164 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1); | 164 | auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1); |
| 165 | 165 | ||
| 166 | if (res != ResultSuccess) { | 166 | if (res != ResultSuccess) { |
| 167 | if (res == ResultTimeZoneNotFound) { | 167 | if (res == ResultTimeZoneNotFound) { |
| @@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary) | |||
| 183 | 183 | ||
| 184 | Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, | 184 | Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, |
| 185 | CalendarAdditionalInfo& out_additional_info, s64 time, | 185 | CalendarAdditionalInfo& out_additional_info, s64 time, |
| 186 | Tz::Rule& rule) { | 186 | const Tz::Rule& rule) { |
| 187 | R_TRY(ValidateRule(rule)); | 187 | R_TRY(ValidateRule(rule)); |
| 188 | 188 | ||
| 189 | Tz::CalendarTimeInternal calendar_internal{}; | 189 | Tz::CalendarTimeInternal calendar_internal{}; |
| @@ -212,20 +212,23 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, | |||
| 212 | R_SUCCEED(); | 212 | R_SUCCEED(); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 215 | Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, |
| 216 | CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) { | 216 | size_t out_times_max_count, const CalendarTime& calendar, |
| 217 | const Tz::Rule& rule, s32 is_dst) { | ||
| 217 | R_TRY(ValidateRule(rule)); | 218 | R_TRY(ValidateRule(rule)); |
| 218 | 219 | ||
| 219 | calendar.month -= 1; | 220 | CalendarTime local_calendar{calendar}; |
| 220 | calendar.year -= 1900; | 221 | |
| 222 | local_calendar.month -= 1; | ||
| 223 | local_calendar.year -= 1900; | ||
| 221 | 224 | ||
| 222 | Tz::CalendarTimeInternal internal{ | 225 | Tz::CalendarTimeInternal internal{ |
| 223 | .tm_sec = calendar.second, | 226 | .tm_sec = local_calendar.second, |
| 224 | .tm_min = calendar.minute, | 227 | .tm_min = local_calendar.minute, |
| 225 | .tm_hour = calendar.hour, | 228 | .tm_hour = local_calendar.hour, |
| 226 | .tm_mday = calendar.day, | 229 | .tm_mday = local_calendar.day, |
| 227 | .tm_mon = calendar.month, | 230 | .tm_mon = local_calendar.month, |
| 228 | .tm_year = calendar.year, | 231 | .tm_year = local_calendar.year, |
| 229 | .tm_wday = 0, | 232 | .tm_wday = 0, |
| 230 | .tm_yday = 0, | 233 | .tm_yday = 0, |
| 231 | .tm_isdst = is_dst, | 234 | .tm_isdst = is_dst, |
| @@ -243,9 +246,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u3 | |||
| 243 | R_RETURN(ResultTimeZoneNotFound); | 246 | R_RETURN(ResultTimeZoneNotFound); |
| 244 | } | 247 | } |
| 245 | 248 | ||
| 246 | if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute || | 249 | if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute || |
| 247 | internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day || | 250 | internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day || |
| 248 | internal.tm_mon != calendar.month || internal.tm_year != calendar.year) { | 251 | internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) { |
| 249 | R_RETURN(ResultTimeZoneNotFound); | 252 | R_RETURN(ResultTimeZoneNotFound); |
| 250 | } | 253 | } |
| 251 | 254 | ||
| @@ -254,7 +257,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u3 | |||
| 254 | } | 257 | } |
| 255 | 258 | ||
| 256 | out_times[0] = time; | 259 | out_times[0] = time; |
| 257 | if (out_times_count < 2) { | 260 | if (out_times_max_count < 2) { |
| 258 | out_count = 1; | 261 | out_count = 1; |
| 259 | R_SUCCEED(); | 262 | R_SUCCEED(); |
| 260 | } | 263 | } |
diff --git a/src/core/hle/service/psc/time/time_zone.h b/src/core/hle/service/psc/time/time_zone.h index ce2acca17..6248e45f9 100644 --- a/src/core/hle/service/psc/time/time_zone.h +++ b/src/core/hle/service/psc/time/time_zone.h | |||
| @@ -32,23 +32,24 @@ public: | |||
| 32 | Result GetTimePoint(SteadyClockTimePoint& out_time_point); | 32 | Result GetTimePoint(SteadyClockTimePoint& out_time_point); |
| 33 | 33 | ||
| 34 | Result ToCalendarTime(CalendarTime& out_calendar_time, | 34 | Result ToCalendarTime(CalendarTime& out_calendar_time, |
| 35 | CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); | 35 | CalendarAdditionalInfo& out_additional_info, s64 time, |
| 36 | const Tz::Rule& rule); | ||
| 36 | Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, | 37 | Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, |
| 37 | CalendarAdditionalInfo& calendar_additional, s64 time); | 38 | CalendarAdditionalInfo& calendar_additional, s64 time); |
| 38 | Result ParseBinary(LocationName& name, std::span<const u8> binary); | 39 | Result ParseBinary(LocationName& name, std::span<const u8> binary); |
| 39 | Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); | 40 | Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); |
| 40 | Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 41 | Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 41 | CalendarTime& calendar, Tz::Rule& rule); | 42 | const CalendarTime& calendar, const Tz::Rule& rule); |
| 42 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 43 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, |
| 43 | CalendarTime& calendar); | 44 | size_t out_times_max_count, const CalendarTime& calendar); |
| 44 | 45 | ||
| 45 | private: | 46 | private: |
| 46 | Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); | 47 | Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); |
| 47 | Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, | 48 | Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, |
| 48 | CalendarAdditionalInfo& out_additional_info, s64 time, | 49 | CalendarAdditionalInfo& out_additional_info, s64 time, |
| 49 | Tz::Rule& rule); | 50 | const Tz::Rule& rule); |
| 50 | Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 51 | Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, |
| 51 | CalendarTime& calendar, Tz::Rule& rule, s32 is_dst); | 52 | const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst); |
| 52 | 53 | ||
| 53 | bool m_initialized{}; | 54 | bool m_initialized{}; |
| 54 | std::recursive_mutex m_mutex; | 55 | std::recursive_mutex m_mutex; |
diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index e304c8387..eb81f5b03 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp | |||
| @@ -2,7 +2,10 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <tz/tz.h> | 4 | #include <tz/tz.h> |
| 5 | |||
| 6 | #include "common/scope_exit.h" | ||
| 5 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/service/cmif_serialization.h" | ||
| 6 | #include "core/hle/service/psc/time/time_zone_service.h" | 9 | #include "core/hle/service/psc/time/time_zone_service.h" |
| 7 | 10 | ||
| 8 | namespace Service::PSC::Time { | 11 | namespace Service::PSC::Time { |
| @@ -14,276 +17,149 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore& | |||
| 14 | can_write_timezone_device_location} { | 17 | can_write_timezone_device_location} { |
| 15 | // clang-format off | 18 | // clang-format off |
| 16 | static const FunctionInfo functions[] = { | 19 | static const FunctionInfo functions[] = { |
| 17 | {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, | 20 | {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"}, |
| 18 | {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, | 21 | {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"}, |
| 19 | {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, | 22 | {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"}, |
| 20 | {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, | 23 | {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"}, |
| 21 | {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, | 24 | {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"}, |
| 22 | {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, | 25 | {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"}, |
| 23 | {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, | 26 | {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"}, |
| 24 | {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, | 27 | {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"}, |
| 25 | {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, | 28 | {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"}, |
| 26 | {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, | 29 | {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"}, |
| 27 | {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, | 30 | {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"}, |
| 28 | {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, | 31 | {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"}, |
| 29 | {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, | 32 | {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"}, |
| 30 | {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, | 33 | {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"}, |
| 31 | }; | 34 | }; |
| 32 | // clang-format on | 35 | // clang-format on |
| 33 | RegisterHandlers(functions); | 36 | RegisterHandlers(functions); |
| 34 | } | 37 | } |
| 35 | 38 | ||
| 36 | void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { | 39 | Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) { |
| 37 | LOG_DEBUG(Service_Time, "called."); | 40 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); |
| 38 | |||
| 39 | LocationName name{}; | ||
| 40 | auto res = GetDeviceLocationName(name); | ||
| 41 | |||
| 42 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)}; | ||
| 43 | rb.Push(res); | ||
| 44 | rb.PushRaw<LocationName>(name); | ||
| 45 | } | ||
| 46 | |||
| 47 | void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) { | ||
| 48 | LOG_DEBUG(Service_Time, "called."); | ||
| 49 | |||
| 50 | IPC::RequestParser rp{ctx}; | ||
| 51 | [[maybe_unused]] auto name{rp.PopRaw<LocationName>()}; | ||
| 52 | |||
| 53 | if (!m_can_write_timezone_device_location) { | ||
| 54 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 55 | rb.Push(ResultPermissionDenied); | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 60 | rb.Push(ResultNotImplemented); | ||
| 61 | } | ||
| 62 | |||
| 63 | void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) { | ||
| 64 | LOG_DEBUG(Service_Time, "called."); | ||
| 65 | |||
| 66 | u32 count{}; | ||
| 67 | auto res = GetTotalLocationNameCount(count); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 70 | rb.Push(res); | ||
| 71 | rb.Push(count); | ||
| 72 | } | ||
| 73 | |||
| 74 | void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) { | ||
| 75 | LOG_DEBUG(Service_Time, "called."); | ||
| 76 | 41 | ||
| 77 | IPC::ResponseBuilder rb{ctx, 2}; | 42 | R_RETURN(m_time_zone.GetLocationName(*out_location_name)); |
| 78 | rb.Push(ResultNotImplemented); | ||
| 79 | } | 43 | } |
| 80 | 44 | ||
| 81 | void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) { | 45 | Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) { |
| 82 | LOG_DEBUG(Service_Time, "called."); | 46 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); |
| 83 | 47 | ||
| 84 | IPC::ResponseBuilder rb{ctx, 2}; | 48 | R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); |
| 85 | rb.Push(ResultNotImplemented); | 49 | R_RETURN(ResultNotImplemented); |
| 86 | } | 50 | } |
| 87 | 51 | ||
| 88 | void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) { | 52 | Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { |
| 89 | LOG_DEBUG(Service_Time, "called."); | 53 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); |
| 90 | |||
| 91 | RuleVersion rule_version{}; | ||
| 92 | auto res = GetTimeZoneRuleVersion(rule_version); | ||
| 93 | 54 | ||
| 94 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)}; | 55 | R_RETURN(m_time_zone.GetTotalLocationCount(*out_count)); |
| 95 | rb.Push(res); | ||
| 96 | rb.PushRaw<RuleVersion>(rule_version); | ||
| 97 | } | 56 | } |
| 98 | 57 | ||
| 99 | void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) { | 58 | Result TimeZoneService::LoadLocationNameList( |
| 100 | LOG_DEBUG(Service_Time, "called."); | 59 | Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { |
| 101 | 60 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); | |
| 102 | LocationName name{}; | ||
| 103 | SteadyClockTimePoint time_point{}; | ||
| 104 | auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name); | ||
| 105 | 61 | ||
| 106 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) + | 62 | R_RETURN(ResultNotImplemented); |
| 107 | (sizeof(SteadyClockTimePoint) / sizeof(u32))}; | ||
| 108 | rb.Push(res); | ||
| 109 | rb.PushRaw<LocationName>(name); | ||
| 110 | rb.PushRaw<SteadyClockTimePoint>(time_point); | ||
| 111 | } | 63 | } |
| 112 | 64 | ||
| 113 | void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) { | 65 | Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) { |
| 114 | LOG_DEBUG(Service_Time, "called."); | 66 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); |
| 115 | |||
| 116 | IPC::RequestParser rp{ctx}; | ||
| 117 | auto name{rp.PopRaw<LocationName>()}; | ||
| 118 | |||
| 119 | auto binary{ctx.ReadBuffer()}; | ||
| 120 | auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary); | ||
| 121 | 67 | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | 68 | R_RETURN(ResultNotImplemented); |
| 123 | rb.Push(res); | ||
| 124 | } | 69 | } |
| 125 | 70 | ||
| 126 | void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) { | 71 | Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) { |
| 127 | LOG_DEBUG(Service_Time, "called."); | 72 | SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); |
| 128 | |||
| 129 | auto binary{ctx.ReadBuffer()}; | ||
| 130 | 73 | ||
| 131 | Tz::Rule rule{}; | 74 | R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version)); |
| 132 | auto res = ParseTimeZoneBinary(rule, binary); | ||
| 133 | |||
| 134 | ctx.WriteBuffer(rule); | ||
| 135 | |||
| 136 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 137 | rb.Push(res); | ||
| 138 | } | 75 | } |
| 139 | 76 | ||
| 140 | void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle( | 77 | Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( |
| 141 | HLERequestContext& ctx) { | 78 | Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) { |
| 142 | LOG_DEBUG(Service_Time, "called."); | 79 | SCOPE_EXIT({ |
| 80 | LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}", | ||
| 81 | *out_location_name, *out_time_point); | ||
| 82 | }); | ||
| 143 | 83 | ||
| 144 | IPC::ResponseBuilder rb{ctx, 2}; | 84 | R_TRY(m_time_zone.GetLocationName(*out_location_name)); |
| 145 | rb.Push(ResultNotImplemented); | 85 | R_RETURN(m_time_zone.GetTimePoint(*out_time_point)); |
| 146 | } | 86 | } |
| 147 | 87 | ||
| 148 | void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) { | 88 | Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( |
| 149 | LOG_DEBUG(Service_Time, "called."); | 89 | LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { |
| 150 | 90 | LOG_DEBUG(Service_Time, "called. location_name={}", location_name); | |
| 151 | IPC::RequestParser rp{ctx}; | ||
| 152 | auto time{rp.Pop<s64>()}; | ||
| 153 | 91 | ||
| 154 | auto rule_buffer{ctx.ReadBuffer()}; | 92 | R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); |
| 155 | Tz::Rule rule{}; | 93 | R_TRY(m_time_zone.ParseBinary(location_name, binary)); |
| 156 | std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule)); | ||
| 157 | |||
| 158 | CalendarTime calendar_time{}; | ||
| 159 | CalendarAdditionalInfo additional_info{}; | ||
| 160 | auto res = ToCalendarTime(calendar_time, additional_info, time, rule); | ||
| 161 | |||
| 162 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) + | ||
| 163 | (sizeof(CalendarAdditionalInfo) / sizeof(u32))}; | ||
| 164 | rb.Push(res); | ||
| 165 | rb.PushRaw<CalendarTime>(calendar_time); | ||
| 166 | rb.PushRaw<CalendarAdditionalInfo>(additional_info); | ||
| 167 | } | ||
| 168 | |||
| 169 | void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) { | ||
| 170 | LOG_DEBUG(Service_Time, "called."); | ||
| 171 | |||
| 172 | IPC::RequestParser rp{ctx}; | ||
| 173 | auto time{rp.Pop<s64>()}; | ||
| 174 | 94 | ||
| 175 | CalendarTime calendar_time{}; | 95 | SteadyClockTimePoint time_point{}; |
| 176 | CalendarAdditionalInfo additional_info{}; | 96 | R_TRY(m_clock_core.GetCurrentTimePoint(time_point)); |
| 177 | auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time); | ||
| 178 | 97 | ||
| 179 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) + | 98 | m_time_zone.SetTimePoint(time_point); |
| 180 | (sizeof(CalendarAdditionalInfo) / sizeof(u32))}; | 99 | R_SUCCEED(); |
| 181 | rb.Push(res); | ||
| 182 | rb.PushRaw<CalendarTime>(calendar_time); | ||
| 183 | rb.PushRaw<CalendarAdditionalInfo>(additional_info); | ||
| 184 | } | 100 | } |
| 185 | 101 | ||
| 186 | void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) { | 102 | Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule, |
| 103 | InBuffer<BufferAttr_HipcAutoSelect> binary) { | ||
| 187 | LOG_DEBUG(Service_Time, "called."); | 104 | LOG_DEBUG(Service_Time, "called."); |
| 188 | 105 | ||
| 189 | IPC::RequestParser rp{ctx}; | 106 | R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary)); |
| 190 | auto calendar{rp.PopRaw<CalendarTime>()}; | ||
| 191 | |||
| 192 | auto binary{ctx.ReadBuffer()}; | ||
| 193 | |||
| 194 | Tz::Rule rule{}; | ||
| 195 | std::memcpy(&rule, binary.data(), sizeof(Tz::Rule)); | ||
| 196 | |||
| 197 | u32 count{}; | ||
| 198 | std::array<s64, 2> times{}; | ||
| 199 | u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; | ||
| 200 | |||
| 201 | auto res = ToPosixTime(count, times, times_count, calendar, rule); | ||
| 202 | |||
| 203 | ctx.WriteBuffer(times); | ||
| 204 | |||
| 205 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 206 | rb.Push(res); | ||
| 207 | rb.Push(count); | ||
| 208 | } | 107 | } |
| 209 | 108 | ||
| 210 | void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) { | 109 | Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( |
| 211 | LOG_DEBUG(Service_Time, "called."); | 110 | OutCopyHandle<Kernel::KReadableEvent> out_event) { |
| 212 | 111 | LOG_DEBUG(Service_Time, "called. This function is not implemented!"); | |
| 213 | IPC::RequestParser rp{ctx}; | ||
| 214 | auto calendar{rp.PopRaw<CalendarTime>()}; | ||
| 215 | 112 | ||
| 216 | u32 count{}; | 113 | R_RETURN(ResultNotImplemented); |
| 217 | std::array<s64, 2> times{}; | ||
| 218 | u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))}; | ||
| 219 | |||
| 220 | auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar); | ||
| 221 | |||
| 222 | ctx.WriteBuffer(times); | ||
| 223 | |||
| 224 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 225 | rb.Push(res); | ||
| 226 | rb.Push(count); | ||
| 227 | } | 114 | } |
| 228 | 115 | ||
| 229 | // =============================== Implementations =========================== | 116 | Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time, |
| 230 | 117 | Out<CalendarAdditionalInfo> out_additional_info, s64 time, | |
| 231 | Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) { | 118 | InRule rule) { |
| 232 | R_RETURN(m_time_zone.GetLocationName(out_location_name)); | 119 | SCOPE_EXIT({ |
| 233 | } | 120 | LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, |
| 121 | *out_calendar_time, *out_additional_info); | ||
| 122 | }); | ||
| 234 | 123 | ||
| 235 | Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { | 124 | R_RETURN( |
| 236 | R_RETURN(m_time_zone.GetTotalLocationCount(out_count)); | 125 | m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get())); |
| 237 | } | ||
| 238 | |||
| 239 | Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) { | ||
| 240 | R_RETURN(m_time_zone.GetRuleVersion(out_rule_version)); | ||
| 241 | } | ||
| 242 | |||
| 243 | Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point, | ||
| 244 | LocationName& location_name) { | ||
| 245 | R_TRY(m_time_zone.GetLocationName(location_name)); | ||
| 246 | R_RETURN(m_time_zone.GetTimePoint(out_time_point)); | ||
| 247 | } | 126 | } |
| 248 | 127 | ||
| 249 | Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, | 128 | Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, |
| 250 | std::span<const u8> binary) { | 129 | Out<CalendarAdditionalInfo> out_additional_info, |
| 251 | R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); | 130 | s64 time) { |
| 252 | R_TRY(m_time_zone.ParseBinary(location_name, binary)); | 131 | SCOPE_EXIT({ |
| 253 | 132 | LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, | |
| 254 | SteadyClockTimePoint time_point{}; | 133 | *out_calendar_time, *out_additional_info); |
| 255 | R_TRY(m_clock_core.GetCurrentTimePoint(time_point)); | 134 | }); |
| 256 | 135 | ||
| 257 | m_time_zone.SetTimePoint(time_point); | 136 | R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time)); |
| 258 | R_SUCCEED(); | ||
| 259 | } | 137 | } |
| 260 | 138 | ||
| 261 | Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) { | 139 | Result TimeZoneService::ToPosixTime(Out<u32> out_count, |
| 262 | R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary)); | 140 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 263 | } | 141 | const CalendarTime& calendar_time, InRule rule) { |
| 142 | SCOPE_EXIT({ | ||
| 143 | LOG_DEBUG(Service_Time, | ||
| 144 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", | ||
| 145 | calendar_time, *out_count, out_times[0], out_times[1]); | ||
| 146 | }); | ||
| 264 | 147 | ||
| 265 | Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time, | 148 | R_RETURN( |
| 266 | CalendarAdditionalInfo& out_additional_info, s64 time, | 149 | m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule)); |
| 267 | Tz::Rule& rule) { | ||
| 268 | R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); | ||
| 269 | } | ||
| 270 | |||
| 271 | Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time, | ||
| 272 | CalendarAdditionalInfo& out_additional_info, | ||
| 273 | s64 time) { | ||
| 274 | R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); | ||
| 275 | } | 150 | } |
| 276 | 151 | ||
| 277 | Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, | 152 | Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, |
| 278 | u32 out_times_count, CalendarTime& calendar_time, | 153 | OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 279 | Tz::Rule& rule) { | 154 | const CalendarTime& calendar_time) { |
| 280 | R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); | 155 | SCOPE_EXIT({ |
| 281 | } | 156 | LOG_DEBUG(Service_Time, |
| 157 | "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", | ||
| 158 | calendar_time, *out_count, out_times[0], out_times[1]); | ||
| 159 | }); | ||
| 282 | 160 | ||
| 283 | Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, | ||
| 284 | u32 out_times_count, CalendarTime& calendar_time) { | ||
| 285 | R_RETURN( | 161 | R_RETURN( |
| 286 | m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time)); | 162 | m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time)); |
| 287 | } | 163 | } |
| 288 | 164 | ||
| 289 | } // namespace Service::PSC::Time | 165 | } // namespace Service::PSC::Time |
diff --git a/src/core/hle/service/psc/time/time_zone_service.h b/src/core/hle/service/psc/time/time_zone_service.h index 074c1d4ae..6eb9ddc4b 100644 --- a/src/core/hle/service/psc/time/time_zone_service.h +++ b/src/core/hle/service/psc/time/time_zone_service.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hle/service/cmif_types.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 7 | #include "core/hle/service/psc/time/common.h" | 8 | #include "core/hle/service/psc/time/common.h" |
| 8 | #include "core/hle/service/psc/time/manager.h" | 9 | #include "core/hle/service/psc/time/manager.h" |
| @@ -20,45 +21,41 @@ struct Rule; | |||
| 20 | namespace Service::PSC::Time { | 21 | namespace Service::PSC::Time { |
| 21 | 22 | ||
| 22 | class TimeZoneService final : public ServiceFramework<TimeZoneService> { | 23 | class TimeZoneService final : public ServiceFramework<TimeZoneService> { |
| 24 | using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; | ||
| 25 | using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>; | ||
| 26 | |||
| 23 | public: | 27 | public: |
| 24 | explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core, | 28 | explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core, |
| 25 | TimeZone& time_zone, bool can_write_timezone_device_location); | 29 | TimeZone& time_zone, bool can_write_timezone_device_location); |
| 26 | 30 | ||
| 27 | ~TimeZoneService() override = default; | 31 | ~TimeZoneService() override = default; |
| 28 | 32 | ||
| 29 | Result GetDeviceLocationName(LocationName& out_location_name); | 33 | Result GetDeviceLocationName(Out<LocationName> out_location_name); |
| 30 | Result GetTotalLocationNameCount(u32& out_count); | 34 | Result SetDeviceLocationName(LocationName& location_name); |
| 31 | Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version); | 35 | Result GetTotalLocationNameCount(Out<u32> out_count); |
| 32 | Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point, | 36 | Result LoadLocationNameList(Out<u32> out_count, |
| 33 | LocationName& location_name); | 37 | OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, |
| 38 | u32 index); | ||
| 39 | Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name); | ||
| 40 | Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version); | ||
| 41 | Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name, | ||
| 42 | Out<SteadyClockTimePoint> out_time_point); | ||
| 34 | Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, | 43 | Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, |
| 35 | std::span<const u8> binary); | 44 | InBuffer<BufferAttr_HipcAutoSelect> binary); |
| 36 | Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary); | 45 | Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); |
| 37 | Result ToCalendarTime(CalendarTime& out_calendar_time, | 46 | Result GetDeviceLocationNameOperationEventReadableHandle( |
| 38 | CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); | 47 | OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 39 | Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time, | 48 | Result ToCalendarTime(Out<CalendarTime> out_calendar_time, |
| 40 | CalendarAdditionalInfo& out_additional_info, s64 time); | 49 | Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule); |
| 41 | Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 50 | Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, |
| 42 | CalendarTime& calendar_time, Tz::Rule& rule); | 51 | Out<CalendarAdditionalInfo> out_additional_info, s64 time); |
| 43 | Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, | 52 | Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, |
| 44 | CalendarTime& calendar_time); | 53 | const CalendarTime& calendar_time, InRule rule); |
| 54 | Result ToPosixTimeWithMyRule(Out<u32> out_count, | ||
| 55 | OutArray<s64, BufferAttr_HipcPointer> out_times, | ||
| 56 | const CalendarTime& calendar_time); | ||
| 45 | 57 | ||
| 46 | private: | 58 | private: |
| 47 | void Handle_GetDeviceLocationName(HLERequestContext& ctx); | ||
| 48 | void Handle_SetDeviceLocationName(HLERequestContext& ctx); | ||
| 49 | void Handle_GetTotalLocationNameCount(HLERequestContext& ctx); | ||
| 50 | void Handle_LoadLocationNameList(HLERequestContext& ctx); | ||
| 51 | void Handle_LoadTimeZoneRule(HLERequestContext& ctx); | ||
| 52 | void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx); | ||
| 53 | void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx); | ||
| 54 | void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx); | ||
| 55 | void Handle_ParseTimeZoneBinary(HLERequestContext& ctx); | ||
| 56 | void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx); | ||
| 57 | void Handle_ToCalendarTime(HLERequestContext& ctx); | ||
| 58 | void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx); | ||
| 59 | void Handle_ToPosixTime(HLERequestContext& ctx); | ||
| 60 | void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx); | ||
| 61 | |||
| 62 | Core::System& m_system; | 59 | Core::System& m_system; |
| 63 | 60 | ||
| 64 | StandardSteadyClockCore& m_clock_core; | 61 | StandardSteadyClockCore& m_clock_core; |
diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp index 16ded43bf..7231ff78e 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.cpp +++ b/src/core/hle/service/set/setting_formats/system_settings.cpp | |||
| @@ -45,7 +45,7 @@ SystemSettings DefaultSystemSettings() { | |||
| 45 | .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, | 45 | .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | settings.device_time_zone_location_name = {"UTC"}; | 48 | settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"}; |
| 49 | settings.user_system_clock_automatic_correction_enabled = true; | 49 | settings.user_system_clock_automatic_correction_enabled = true; |
| 50 | 50 | ||
| 51 | settings.primary_album_storage = PrimaryAlbumStorage::SdCard; | 51 | settings.primary_album_storage = PrimaryAlbumStorage::SdCard; |
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index c889aec47..7ef4a0ded 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | namespace Service::Set { | 25 | namespace Service::Set { |
| 26 | 26 | ||
| 27 | namespace { | 27 | namespace { |
| 28 | constexpr u32 SETTINGS_VERSION{2u}; | 28 | constexpr u32 SETTINGS_VERSION{3u}; |
| 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); | 29 | constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); |
| 30 | struct SettingsHeader { | 30 | struct SettingsHeader { |
| 31 | u64 magic; | 31 | u64 magic; |
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h index f86af01a4..f3ea31bde 100644 --- a/src/core/hle/service/sockets/sockets.h +++ b/src/core/hle/service/sockets/sockets.h | |||
| @@ -24,6 +24,7 @@ enum class Errno : u32 { | |||
| 24 | CONNRESET = 104, | 24 | CONNRESET = 104, |
| 25 | NOTCONN = 107, | 25 | NOTCONN = 107, |
| 26 | TIMEDOUT = 110, | 26 | TIMEDOUT = 110, |
| 27 | CONNREFUSED = 111, | ||
| 27 | INPROGRESS = 115, | 28 | INPROGRESS = 115, |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index aed05250c..21bb3e776 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp | |||
| @@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) { | |||
| 25 | return Errno::MFILE; | 25 | return Errno::MFILE; |
| 26 | case Network::Errno::PIPE: | 26 | case Network::Errno::PIPE: |
| 27 | return Errno::PIPE; | 27 | return Errno::PIPE; |
| 28 | case Network::Errno::CONNREFUSED: | ||
| 29 | return Errno::CONNREFUSED; | ||
| 28 | case Network::Errno::NOTCONN: | 30 | case Network::Errno::NOTCONN: |
| 29 | return Errno::NOTCONN; | 31 | return Errno::NOTCONN; |
| 30 | case Network::Errno::TIMEDOUT: | 32 | case Network::Errno::TIMEDOUT: |
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 725311c53..dab1905cc 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -53,7 +53,7 @@ Display::~Display() { | |||
| 53 | Layer& Display::GetLayer(std::size_t index) { | 53 | Layer& Display::GetLayer(std::size_t index) { |
| 54 | size_t i = 0; | 54 | size_t i = 0; |
| 55 | for (auto& layer : layers) { | 55 | for (auto& layer : layers) { |
| 56 | if (!layer->IsOpen()) { | 56 | if (!layer->IsOpen() || !layer->IsVisible()) { |
| 57 | continue; | 57 | continue; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -68,7 +68,7 @@ Layer& Display::GetLayer(std::size_t index) { | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | size_t Display::GetNumLayers() const { | 70 | size_t Display::GetNumLayers() const { |
| 71 | return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); }); | 71 | return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); }); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | Kernel::KReadableEvent* Display::GetVSyncEvent() { | 74 | Kernel::KReadableEvent* Display::GetVSyncEvent() { |
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp index 04e52a23b..493bd6e9e 100644 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ b/src/core/hle/service/vi/layer/vi_layer.cpp | |||
| @@ -9,7 +9,7 @@ Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, | |||
| 9 | android::BufferQueueProducer& binder_, | 9 | android::BufferQueueProducer& binder_, |
| 10 | std::shared_ptr<android::BufferItemConsumer>&& consumer_) | 10 | std::shared_ptr<android::BufferItemConsumer>&& consumer_) |
| 11 | : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, | 11 | : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, |
| 12 | consumer{std::move(consumer_)}, open{false} {} | 12 | consumer{std::move(consumer_)}, open{false}, visible{true} {} |
| 13 | 13 | ||
| 14 | Layer::~Layer() = default; | 14 | Layer::~Layer() = default; |
| 15 | 15 | ||
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index f95e2dc71..b4b031ee7 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h | |||
| @@ -72,6 +72,14 @@ public: | |||
| 72 | return core; | 72 | return core; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | bool IsVisible() const { | ||
| 76 | return visible; | ||
| 77 | } | ||
| 78 | |||
| 79 | void SetVisibility(bool v) { | ||
| 80 | visible = v; | ||
| 81 | } | ||
| 82 | |||
| 75 | bool IsOpen() const { | 83 | bool IsOpen() const { |
| 76 | return open; | 84 | return open; |
| 77 | } | 85 | } |
| @@ -91,6 +99,7 @@ private: | |||
| 91 | android::BufferQueueProducer& binder; | 99 | android::BufferQueueProducer& binder; |
| 92 | std::shared_ptr<android::BufferItemConsumer> consumer; | 100 | std::shared_ptr<android::BufferItemConsumer> consumer; |
| 93 | bool open; | 101 | bool open; |
| 102 | bool visible; | ||
| 94 | }; | 103 | }; |
| 95 | 104 | ||
| 96 | } // namespace Service::VI | 105 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1f3d82c57..73058db9a 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -535,6 +535,12 @@ public: | |||
| 535 | RegisterHandlers(functions); | 535 | RegisterHandlers(functions); |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | ~IApplicationDisplayService() { | ||
| 539 | for (const auto layer_id : stray_layer_ids) { | ||
| 540 | nvnflinger.DestroyLayer(layer_id); | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 538 | private: | 544 | private: |
| 539 | enum class ConvertedScaleMode : u64 { | 545 | enum class ConvertedScaleMode : u64 { |
| 540 | Freeze = 0, | 546 | Freeze = 0, |
| @@ -770,6 +776,7 @@ private: | |||
| 770 | return; | 776 | return; |
| 771 | } | 777 | } |
| 772 | 778 | ||
| 779 | stray_layer_ids.push_back(*layer_id); | ||
| 773 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); | 780 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); |
| 774 | if (!buffer_queue_id) { | 781 | if (!buffer_queue_id) { |
| 775 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | 782 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); |
| @@ -916,6 +923,7 @@ private: | |||
| 916 | 923 | ||
| 917 | Nvnflinger::Nvnflinger& nvnflinger; | 924 | Nvnflinger::Nvnflinger& nvnflinger; |
| 918 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | 925 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; |
| 926 | std::vector<u64> stray_layer_ids; | ||
| 919 | bool vsync_event_fetched{false}; | 927 | bool vsync_event_fetched{false}; |
| 920 | }; | 928 | }; |
| 921 | 929 | ||
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index a983f23ea..7785c1d16 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp | |||
| @@ -693,20 +693,23 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { | |||
| 693 | sockaddr_in addr; | 693 | sockaddr_in addr; |
| 694 | socklen_t addrlen = sizeof(addr); | 694 | socklen_t addrlen = sizeof(addr); |
| 695 | 695 | ||
| 696 | std::vector<WSAPOLLFD> host_pollfds{ | 696 | const bool wait_for_accept = !is_non_blocking; |
| 697 | WSAPOLLFD{fd, POLLIN, 0}, | 697 | if (wait_for_accept) { |
| 698 | WSAPOLLFD{GetInterruptSocket(), POLLIN, 0}, | 698 | std::vector<WSAPOLLFD> host_pollfds{ |
| 699 | }; | 699 | WSAPOLLFD{fd, POLLIN, 0}, |
| 700 | 700 | WSAPOLLFD{GetInterruptSocket(), POLLIN, 0}, | |
| 701 | while (true) { | 701 | }; |
| 702 | const int pollres = | 702 | |
| 703 | WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1); | 703 | while (true) { |
| 704 | if (host_pollfds[1].revents != 0) { | 704 | const int pollres = |
| 705 | // Interrupt signaled before a client could be accepted, break | 705 | WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1); |
| 706 | return {AcceptResult{}, Errno::AGAIN}; | 706 | if (host_pollfds[1].revents != 0) { |
| 707 | } | 707 | // Interrupt signaled before a client could be accepted, break |
| 708 | if (pollres > 0) { | 708 | return {AcceptResult{}, Errno::AGAIN}; |
| 709 | break; | 709 | } |
| 710 | if (pollres > 0) { | ||
| 711 | break; | ||
| 712 | } | ||
| 710 | } | 713 | } |
| 711 | } | 714 | } |
| 712 | 715 | ||
| @@ -913,6 +916,7 @@ Errno Socket::SetRcvTimeo(u32 value) { | |||
| 913 | 916 | ||
| 914 | Errno Socket::SetNonBlock(bool enable) { | 917 | Errno Socket::SetNonBlock(bool enable) { |
| 915 | if (EnableNonBlock(fd, enable)) { | 918 | if (EnableNonBlock(fd, enable)) { |
| 919 | is_non_blocking = enable; | ||
| 916 | return Errno::SUCCESS; | 920 | return Errno::SUCCESS; |
| 917 | } | 921 | } |
| 918 | return GetAndLogLastError(); | 922 | return GetAndLogLastError(); |
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 4ba51f62c..3a32dff75 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h | |||
| @@ -166,6 +166,9 @@ public: | |||
| 166 | bool IsOpened() const override; | 166 | bool IsOpened() const override; |
| 167 | 167 | ||
| 168 | void HandleProxyPacket(const ProxyPacket& packet) override; | 168 | void HandleProxyPacket(const ProxyPacket& packet) override; |
| 169 | |||
| 170 | private: | ||
| 171 | bool is_non_blocking = false; | ||
| 169 | }; | 172 | }; |
| 170 | 173 | ||
| 171 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); | 174 | std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout); |
diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 136109a0c..c0dcc0241 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt | |||
| @@ -7,8 +7,6 @@ add_executable(yuzu-room | |||
| 7 | yuzu_room.rc | 7 | yuzu_room.rc |
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | create_target_directory_groups(yuzu-room) | ||
| 11 | |||
| 12 | target_link_libraries(yuzu-room PRIVATE common network) | 10 | target_link_libraries(yuzu-room PRIVATE common network) |
| 13 | if (ENABLE_WEB_SERVICE) | 11 | if (ENABLE_WEB_SERVICE) |
| 14 | target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) | 12 | target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) |
| @@ -28,3 +26,5 @@ endif() | |||
| 28 | if (YUZU_USE_PRECOMPILED_HEADERS) | 26 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 29 | target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) | 27 | target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) |
| 30 | endif() | 28 | endif() |
| 29 | |||
| 30 | create_target_directory_groups(yuzu-room) | ||
diff --git a/src/hid_core/CMakeLists.txt b/src/hid_core/CMakeLists.txt index 055954224..2699e1599 100644 --- a/src/hid_core/CMakeLists.txt +++ b/src/hid_core/CMakeLists.txt | |||
| @@ -96,6 +96,7 @@ add_library(hid_core STATIC | |||
| 96 | resources/system_buttons/home_button.h | 96 | resources/system_buttons/home_button.h |
| 97 | resources/system_buttons/sleep_button.cpp | 97 | resources/system_buttons/sleep_button.cpp |
| 98 | resources/system_buttons/sleep_button.h | 98 | resources/system_buttons/sleep_button.h |
| 99 | resources/system_buttons/system_button_types.h | ||
| 99 | resources/touch_screen/gesture.cpp | 100 | resources/touch_screen/gesture.cpp |
| 100 | resources/touch_screen/gesture.h | 101 | resources/touch_screen/gesture.h |
| 101 | resources/touch_screen/gesture_handler.cpp | 102 | resources/touch_screen/gesture_handler.cpp |
diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index 3cf12f6e5..1b2fc6295 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h | |||
| @@ -404,7 +404,10 @@ struct NpadPowerInfo { | |||
| 404 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); | 404 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); |
| 405 | 405 | ||
| 406 | struct LedPattern { | 406 | struct LedPattern { |
| 407 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | 407 | LedPattern() { |
| 408 | raw = 0; | ||
| 409 | } | ||
| 410 | LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | ||
| 408 | position1.Assign(light1); | 411 | position1.Assign(light1); |
| 409 | position2.Assign(light2); | 412 | position2.Assign(light2); |
| 410 | position3.Assign(light3); | 413 | position3.Assign(light3); |
| @@ -419,6 +422,16 @@ struct LedPattern { | |||
| 419 | }; | 422 | }; |
| 420 | }; | 423 | }; |
| 421 | 424 | ||
| 425 | struct SleepButtonState { | ||
| 426 | union { | ||
| 427 | u64 raw{}; | ||
| 428 | |||
| 429 | // Buttons | ||
| 430 | BitField<0, 1, u64> sleep; | ||
| 431 | }; | ||
| 432 | }; | ||
| 433 | static_assert(sizeof(SleepButtonState) == 0x8, "SleepButtonState has incorrect size."); | ||
| 434 | |||
| 422 | struct HomeButtonState { | 435 | struct HomeButtonState { |
| 423 | union { | 436 | union { |
| 424 | u64 raw{}; | 437 | u64 raw{}; |
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 8ab26bc36..1a58eff4a 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -956,17 +956,6 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | |||
| 956 | return ResultSuccess; | 956 | return ResultSuccess; |
| 957 | } | 957 | } |
| 958 | 958 | ||
| 959 | Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { | ||
| 960 | if (!IsNpadIdValid(npad_id)) { | ||
| 961 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 962 | return ResultInvalidNpadId; | ||
| 963 | } | ||
| 964 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 965 | const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device; | ||
| 966 | pattern = controller->GetLedPattern(); | ||
| 967 | return ResultSuccess; | ||
| 968 | } | ||
| 969 | |||
| 970 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | 959 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, |
| 971 | Core::HID::NpadIdType npad_id) const { | 960 | Core::HID::NpadIdType npad_id) const { |
| 972 | std::scoped_lock lock{mutex}; | 961 | std::scoped_lock lock{mutex}; |
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index e81cc3abe..4e26ed2e8 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h | |||
| @@ -97,8 +97,6 @@ public: | |||
| 97 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( | 97 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( |
| 98 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); | 98 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); |
| 99 | 99 | ||
| 100 | Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; | ||
| 101 | |||
| 102 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | 100 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, |
| 103 | Core::HID::NpadIdType npad_id) const; | 101 | Core::HID::NpadIdType npad_id) const; |
| 104 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | 102 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, |
diff --git a/src/hid_core/resources/shared_memory_format.h b/src/hid_core/resources/shared_memory_format.h index 2ae0004ba..49755c8dc 100644 --- a/src/hid_core/resources/shared_memory_format.h +++ b/src/hid_core/resources/shared_memory_format.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "hid_core/resources/mouse/mouse_types.h" | 12 | #include "hid_core/resources/mouse/mouse_types.h" |
| 13 | #include "hid_core/resources/npad/npad_types.h" | 13 | #include "hid_core/resources/npad/npad_types.h" |
| 14 | #include "hid_core/resources/ring_lifo.h" | 14 | #include "hid_core/resources/ring_lifo.h" |
| 15 | #include "hid_core/resources/system_buttons/system_button_types.h" | ||
| 15 | #include "hid_core/resources/touch_screen/touch_types.h" | 16 | #include "hid_core/resources/touch_screen/touch_types.h" |
| 16 | 17 | ||
| 17 | namespace Service::HID { | 18 | namespace Service::HID { |
| @@ -75,24 +76,24 @@ static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, | |||
| 75 | 76 | ||
| 76 | // This is nn::hid::detail::HomeButtonSharedMemoryFormat | 77 | // This is nn::hid::detail::HomeButtonSharedMemoryFormat |
| 77 | struct HomeButtonSharedMemoryFormat { | 78 | struct HomeButtonSharedMemoryFormat { |
| 78 | CommonHeader header; | 79 | Lifo<HomeButtonState, HidEntryCount> home_lifo{}; |
| 79 | INSERT_PADDING_BYTES(0x1E0); | 80 | INSERT_PADDING_BYTES(0x48); |
| 80 | }; | 81 | }; |
| 81 | static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, | 82 | static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, |
| 82 | "HomeButtonSharedMemoryFormat is an invalid size"); | 83 | "HomeButtonSharedMemoryFormat is an invalid size"); |
| 83 | 84 | ||
| 84 | // This is nn::hid::detail::SleepButtonSharedMemoryFormat | 85 | // This is nn::hid::detail::SleepButtonSharedMemoryFormat |
| 85 | struct SleepButtonSharedMemoryFormat { | 86 | struct SleepButtonSharedMemoryFormat { |
| 86 | CommonHeader header; | 87 | Lifo<SleepButtonState, HidEntryCount> sleep_lifo{}; |
| 87 | INSERT_PADDING_BYTES(0x1E0); | 88 | INSERT_PADDING_BYTES(0x48); |
| 88 | }; | 89 | }; |
| 89 | static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, | 90 | static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, |
| 90 | "SleepButtonSharedMemoryFormat is an invalid size"); | 91 | "SleepButtonSharedMemoryFormat is an invalid size"); |
| 91 | 92 | ||
| 92 | // This is nn::hid::detail::CaptureButtonSharedMemoryFormat | 93 | // This is nn::hid::detail::CaptureButtonSharedMemoryFormat |
| 93 | struct CaptureButtonSharedMemoryFormat { | 94 | struct CaptureButtonSharedMemoryFormat { |
| 94 | CommonHeader header; | 95 | Lifo<CaptureButtonState, HidEntryCount> capture_lifo{}; |
| 95 | INSERT_PADDING_BYTES(0x1E0); | 96 | INSERT_PADDING_BYTES(0x48); |
| 96 | }; | 97 | }; |
| 97 | static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, | 98 | static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, |
| 98 | "CaptureButtonSharedMemoryFormat is an invalid size"); | 99 | "CaptureButtonSharedMemoryFormat is an invalid size"); |
diff --git a/src/hid_core/resources/system_buttons/capture_button.cpp b/src/hid_core/resources/system_buttons/capture_button.cpp index 70973ae25..95eb60424 100644 --- a/src/hid_core/resources/system_buttons/capture_button.cpp +++ b/src/hid_core/resources/system_buttons/capture_button.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/core_timing.h" | 4 | #include "core/core_timing.h" |
| 5 | #include "hid_core/frontend/emulated_controller.h" | ||
| 6 | #include "hid_core/hid_core.h" | ||
| 5 | #include "hid_core/resources/applet_resource.h" | 7 | #include "hid_core/resources/applet_resource.h" |
| 6 | #include "hid_core/resources/shared_memory_format.h" | 8 | #include "hid_core/resources/shared_memory_format.h" |
| 7 | #include "hid_core/resources/system_buttons/capture_button.h" | 9 | #include "hid_core/resources/system_buttons/capture_button.h" |
| @@ -17,10 +19,6 @@ void CaptureButton::OnInit() {} | |||
| 17 | void CaptureButton::OnRelease() {} | 19 | void CaptureButton::OnRelease() {} |
| 18 | 20 | ||
| 19 | void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | 21 | void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { |
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | 22 | std::scoped_lock shared_lock{*shared_mutex}; |
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | 23 | const u64 aruid = applet_resource->GetActiveAruid(); |
| 26 | auto* data = applet_resource->GetAruidData(aruid); | 24 | auto* data = applet_resource->GetAruidData(aruid); |
| @@ -29,11 +27,21 @@ void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 29 | return; | 27 | return; |
| 30 | } | 28 | } |
| 31 | 29 | ||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | 30 | auto& shared_memory = data->shared_memory_format->capture_button; |
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | 31 | |
| 34 | header.total_entry_count = 17; | 32 | if (!IsControllerActivated()) { |
| 35 | header.entry_count = 0; | 33 | shared_memory.capture_lifo.buffer_count = 0; |
| 36 | header.last_entry_index = 0; | 34 | shared_memory.capture_lifo.buffer_tail = 0; |
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | const auto& last_entry = shared_memory.capture_lifo.ReadCurrentEntry().state; | ||
| 39 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 40 | |||
| 41 | auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); | ||
| 42 | next_state.buttons.raw = controller->GetHomeButtons().raw; | ||
| 43 | |||
| 44 | shared_memory.capture_lifo.WriteNextEntry(next_state); | ||
| 37 | } | 45 | } |
| 38 | 46 | ||
| 39 | } // namespace Service::HID | 47 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/capture_button.h b/src/hid_core/resources/system_buttons/capture_button.h index ad95d7cad..f362ef90b 100644 --- a/src/hid_core/resources/system_buttons/capture_button.h +++ b/src/hid_core/resources/system_buttons/capture_button.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "hid_core/resources/controller_base.h" | 6 | #include "hid_core/resources/controller_base.h" |
| 7 | #include "hid_core/resources/system_buttons/system_button_types.h" | ||
| 7 | 8 | ||
| 8 | namespace Service::HID { | 9 | namespace Service::HID { |
| 9 | 10 | ||
| @@ -22,6 +23,6 @@ public: | |||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | 23 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; |
| 23 | 24 | ||
| 24 | private: | 25 | private: |
| 25 | bool smart_update{}; | 26 | CaptureButtonState next_state{}; |
| 26 | }; | 27 | }; |
| 27 | } // namespace Service::HID | 28 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/home_button.cpp b/src/hid_core/resources/system_buttons/home_button.cpp index f9c1f44b5..f665338f3 100644 --- a/src/hid_core/resources/system_buttons/home_button.cpp +++ b/src/hid_core/resources/system_buttons/home_button.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/core_timing.h" | 4 | #include "core/core_timing.h" |
| 5 | #include "hid_core/frontend/emulated_controller.h" | ||
| 6 | #include "hid_core/hid_core.h" | ||
| 5 | #include "hid_core/resources/applet_resource.h" | 7 | #include "hid_core/resources/applet_resource.h" |
| 6 | #include "hid_core/resources/shared_memory_format.h" | 8 | #include "hid_core/resources/shared_memory_format.h" |
| 7 | #include "hid_core/resources/system_buttons/home_button.h" | 9 | #include "hid_core/resources/system_buttons/home_button.h" |
| @@ -17,10 +19,6 @@ void HomeButton::OnInit() {} | |||
| 17 | void HomeButton::OnRelease() {} | 19 | void HomeButton::OnRelease() {} |
| 18 | 20 | ||
| 19 | void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | 21 | void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { |
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | 22 | std::scoped_lock shared_lock{*shared_mutex}; |
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | 23 | const u64 aruid = applet_resource->GetActiveAruid(); |
| 26 | auto* data = applet_resource->GetAruidData(aruid); | 24 | auto* data = applet_resource->GetAruidData(aruid); |
| @@ -29,11 +27,21 @@ void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 29 | return; | 27 | return; |
| 30 | } | 28 | } |
| 31 | 29 | ||
| 32 | auto& header = data->shared_memory_format->home_button.header; | 30 | auto& shared_memory = data->shared_memory_format->home_button; |
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | 31 | |
| 34 | header.total_entry_count = 17; | 32 | if (!IsControllerActivated()) { |
| 35 | header.entry_count = 0; | 33 | shared_memory.home_lifo.buffer_count = 0; |
| 36 | header.last_entry_index = 0; | 34 | shared_memory.home_lifo.buffer_tail = 0; |
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | const auto& last_entry = shared_memory.home_lifo.ReadCurrentEntry().state; | ||
| 39 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 40 | |||
| 41 | auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); | ||
| 42 | next_state.buttons.raw = controller->GetHomeButtons().raw; | ||
| 43 | |||
| 44 | shared_memory.home_lifo.WriteNextEntry(next_state); | ||
| 37 | } | 45 | } |
| 38 | 46 | ||
| 39 | } // namespace Service::HID | 47 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/home_button.h b/src/hid_core/resources/system_buttons/home_button.h index ecf8327f4..a9374828d 100644 --- a/src/hid_core/resources/system_buttons/home_button.h +++ b/src/hid_core/resources/system_buttons/home_button.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "hid_core/resources/controller_base.h" | 6 | #include "hid_core/resources/controller_base.h" |
| 7 | #include "hid_core/resources/system_buttons/system_button_types.h" | ||
| 7 | 8 | ||
| 8 | namespace Service::HID { | 9 | namespace Service::HID { |
| 9 | 10 | ||
| @@ -22,6 +23,6 @@ public: | |||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | 23 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; |
| 23 | 24 | ||
| 24 | private: | 25 | private: |
| 25 | bool smart_update{}; | 26 | HomeButtonState next_state{}; |
| 26 | }; | 27 | }; |
| 27 | } // namespace Service::HID | 28 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/sleep_button.cpp b/src/hid_core/resources/system_buttons/sleep_button.cpp index 22adf501f..159663246 100644 --- a/src/hid_core/resources/system_buttons/sleep_button.cpp +++ b/src/hid_core/resources/system_buttons/sleep_button.cpp | |||
| @@ -17,10 +17,6 @@ void SleepButton::OnInit() {} | |||
| 17 | void SleepButton::OnRelease() {} | 17 | void SleepButton::OnRelease() {} |
| 18 | 18 | ||
| 19 | void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | 19 | void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { |
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | 20 | std::scoped_lock shared_lock{*shared_mutex}; |
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | 21 | const u64 aruid = applet_resource->GetActiveAruid(); |
| 26 | auto* data = applet_resource->GetAruidData(aruid); | 22 | auto* data = applet_resource->GetAruidData(aruid); |
| @@ -29,11 +25,20 @@ void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 29 | return; | 25 | return; |
| 30 | } | 26 | } |
| 31 | 27 | ||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | 28 | auto& shared_memory = data->shared_memory_format->sleep_button; |
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | 29 | |
| 34 | header.total_entry_count = 17; | 30 | if (!IsControllerActivated()) { |
| 35 | header.entry_count = 0; | 31 | shared_memory.sleep_lifo.buffer_count = 0; |
| 36 | header.last_entry_index = 0; | 32 | shared_memory.sleep_lifo.buffer_tail = 0; |
| 33 | return; | ||
| 34 | } | ||
| 35 | |||
| 36 | const auto& last_entry = shared_memory.sleep_lifo.ReadCurrentEntry().state; | ||
| 37 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 38 | |||
| 39 | next_state.buttons.raw = 0; | ||
| 40 | |||
| 41 | shared_memory.sleep_lifo.WriteNextEntry(next_state); | ||
| 37 | } | 42 | } |
| 38 | 43 | ||
| 39 | } // namespace Service::HID | 44 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/sleep_button.h b/src/hid_core/resources/system_buttons/sleep_button.h index f9ed38c33..f8ac5031b 100644 --- a/src/hid_core/resources/system_buttons/sleep_button.h +++ b/src/hid_core/resources/system_buttons/sleep_button.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "hid_core/resources/controller_base.h" | 6 | #include "hid_core/resources/controller_base.h" |
| 7 | #include "hid_core/resources/system_buttons/system_button_types.h" | ||
| 7 | 8 | ||
| 8 | namespace Service::HID { | 9 | namespace Service::HID { |
| 9 | 10 | ||
| @@ -22,6 +23,6 @@ public: | |||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | 23 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; |
| 23 | 24 | ||
| 24 | private: | 25 | private: |
| 25 | bool smart_update{}; | 26 | SleepButtonState next_state{}; |
| 26 | }; | 27 | }; |
| 27 | } // namespace Service::HID | 28 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/system_buttons/system_button_types.h b/src/hid_core/resources/system_buttons/system_button_types.h new file mode 100644 index 000000000..929e1dc4c --- /dev/null +++ b/src/hid_core/resources/system_buttons/system_button_types.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "hid_core/hid_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | // This is nn::hid::system::SleepButtonState | ||
| 11 | struct SleepButtonState { | ||
| 12 | s64 sampling_number{}; | ||
| 13 | Core::HID::SleepButtonState buttons; | ||
| 14 | }; | ||
| 15 | static_assert(sizeof(SleepButtonState) == 0x10, "SleepButtonState is an invalid size"); | ||
| 16 | |||
| 17 | // This is nn::hid::system::HomeButtonState | ||
| 18 | struct HomeButtonState { | ||
| 19 | s64 sampling_number{}; | ||
| 20 | Core::HID::HomeButtonState buttons; | ||
| 21 | }; | ||
| 22 | static_assert(sizeof(HomeButtonState) == 0x10, "HomeButtonState is an invalid size"); | ||
| 23 | |||
| 24 | // This is nn::hid::system::SleepButtonState | ||
| 25 | struct CaptureButtonState { | ||
| 26 | s64 sampling_number{}; | ||
| 27 | Core::HID::CaptureButtonState buttons; | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(CaptureButtonState) == 0x10, "CaptureButtonState is an invalid size"); | ||
| 30 | |||
| 31 | } // namespace Service::HID | ||
diff --git a/src/hid_core/resources/unique_pad/unique_pad.cpp b/src/hid_core/resources/unique_pad/unique_pad.cpp index 892bbe3c9..89fc57269 100644 --- a/src/hid_core/resources/unique_pad/unique_pad.cpp +++ b/src/hid_core/resources/unique_pad/unique_pad.cpp | |||
| @@ -28,7 +28,7 @@ void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 28 | return; | 28 | return; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | auto& header = data->shared_memory_format->capture_button.header; | 31 | auto& header = data->shared_memory_format->unique_pad.header; |
| 32 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | 32 | header.timestamp = core_timing.GetGlobalTimeNs().count(); |
| 33 | header.total_entry_count = 17; | 33 | header.total_entry_count = 17; |
| 34 | header.entry_count = 0; | 34 | header.entry_count = 0; |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5ed0ad0ed..0755ba772 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -289,8 +289,6 @@ add_library(video_core STATIC | |||
| 289 | vulkan_common/vulkan.h | 289 | vulkan_common/vulkan.h |
| 290 | ) | 290 | ) |
| 291 | 291 | ||
| 292 | create_target_directory_groups(video_core) | ||
| 293 | |||
| 294 | target_link_libraries(video_core PUBLIC common core) | 292 | target_link_libraries(video_core PUBLIC common core) |
| 295 | target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder) | 293 | target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder) |
| 296 | 294 | ||
| @@ -304,7 +302,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) | |||
| 304 | 302 | ||
| 305 | add_dependencies(video_core host_shaders) | 303 | add_dependencies(video_core host_shaders) |
| 306 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | 304 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) |
| 307 | target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator) | 305 | target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator) |
| 308 | 306 | ||
| 309 | if (ENABLE_NSIGHT_AFTERMATH) | 307 | if (ENABLE_NSIGHT_AFTERMATH) |
| 310 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) | 308 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) |
| @@ -365,3 +363,5 @@ endif() | |||
| 365 | if (ANDROID AND ARCHITECTURE_arm64) | 363 | if (ANDROID AND ARCHITECTURE_arm64) |
| 366 | target_link_libraries(video_core PRIVATE adrenotools) | 364 | target_link_libraries(video_core PRIVATE adrenotools) |
| 367 | endif() | 365 | endif() |
| 366 | |||
| 367 | create_target_directory_groups(video_core) | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 86a30dcd1..4f1d3b4e3 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 13 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 14 | #include "video_core/renderer_vulkan/vk_swapchain.h" | 14 | #include "video_core/renderer_vulkan/vk_swapchain.h" |
| 15 | #include "video_core/vulkan_common/vk_enum_string_helper.h" | ||
| 15 | #include "video_core/vulkan_common/vulkan_device.h" | 16 | #include "video_core/vulkan_common/vulkan_device.h" |
| 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 17 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 17 | #include "vulkan/vulkan_core.h" | 18 | #include "vulkan/vulkan_core.h" |
| @@ -151,7 +152,7 @@ bool Swapchain::AcquireNextImage() { | |||
| 151 | vk::Check(result); | 152 | vk::Check(result); |
| 152 | break; | 153 | break; |
| 153 | default: | 154 | default: |
| 154 | LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result)); | 155 | LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", string_VkResult(result)); |
| 155 | break; | 156 | break; |
| 156 | } | 157 | } |
| 157 | 158 | ||
| @@ -187,7 +188,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) { | |||
| 187 | vk::Check(result); | 188 | vk::Check(result); |
| 188 | break; | 189 | break; |
| 189 | default: | 190 | default: |
| 190 | LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result)); | 191 | LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", string_VkResult(result)); |
| 191 | break; | 192 | break; |
| 192 | } | 193 | } |
| 193 | ++frame_index; | 194 | ++frame_index; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7398ed2ec..a7400adfa 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1431,7 +1431,8 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA | |||
| 1431 | } | 1431 | } |
| 1432 | } | 1432 | } |
| 1433 | }; | 1433 | }; |
| 1434 | ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); | 1434 | ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes, |
| 1435 | region_check_gpu); | ||
| 1435 | 1436 | ||
| 1436 | bool can_rescale = info.rescaleable; | 1437 | bool can_rescale = info.rescaleable; |
| 1437 | bool any_rescaled = false; | 1438 | bool any_rescaled = false; |
| @@ -1842,7 +1843,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s | |||
| 1842 | if (!storage_id) { | 1843 | if (!storage_id) { |
| 1843 | return; | 1844 | return; |
| 1844 | } | 1845 | } |
| 1845 | auto& gpu_page_table = gpu_page_table_storage[*storage_id]; | 1846 | auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2]; |
| 1846 | ForEachGPUPage(gpu_addr, size, | 1847 | ForEachGPUPage(gpu_addr, size, |
| 1847 | [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { | 1848 | [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { |
| 1848 | const auto it = gpu_page_table.find(page); | 1849 | const auto it = gpu_page_table.find(page); |
| @@ -1882,41 +1883,48 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s | |||
| 1882 | 1883 | ||
| 1883 | template <class P> | 1884 | template <class P> |
| 1884 | template <typename Func> | 1885 | template <typename Func> |
| 1885 | void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) { | 1886 | void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, |
| 1887 | Func&& func) { | ||
| 1886 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; | 1888 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; |
| 1887 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; | 1889 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; |
| 1888 | boost::container::small_vector<ImageId, 8> images; | 1890 | boost::container::small_vector<ImageId, 8> images; |
| 1889 | ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) { | 1891 | auto storage_id = getStorageID(as_id); |
| 1890 | const auto it = sparse_page_table.find(page); | 1892 | if (!storage_id) { |
| 1891 | if (it == sparse_page_table.end()) { | 1893 | return; |
| 1892 | if constexpr (BOOL_BREAK) { | 1894 | } |
| 1893 | return false; | 1895 | auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1]; |
| 1894 | } else { | 1896 | ForEachGPUPage(gpu_addr, size, |
| 1895 | return; | 1897 | [this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) { |
| 1896 | } | 1898 | const auto it = sparse_page_table.find(page); |
| 1897 | } | 1899 | if (it == sparse_page_table.end()) { |
| 1898 | for (const ImageId image_id : it->second) { | 1900 | if constexpr (BOOL_BREAK) { |
| 1899 | Image& image = slot_images[image_id]; | 1901 | return false; |
| 1900 | if (True(image.flags & ImageFlagBits::Picked)) { | 1902 | } else { |
| 1901 | continue; | 1903 | return; |
| 1902 | } | 1904 | } |
| 1903 | if (!image.OverlapsGPU(gpu_addr, size)) { | 1905 | } |
| 1904 | continue; | 1906 | for (const ImageId image_id : it->second) { |
| 1905 | } | 1907 | Image& image = slot_images[image_id]; |
| 1906 | image.flags |= ImageFlagBits::Picked; | 1908 | if (True(image.flags & ImageFlagBits::Picked)) { |
| 1907 | images.push_back(image_id); | 1909 | continue; |
| 1908 | if constexpr (BOOL_BREAK) { | 1910 | } |
| 1909 | if (func(image_id, image)) { | 1911 | if (!image.OverlapsGPU(gpu_addr, size)) { |
| 1910 | return true; | 1912 | continue; |
| 1911 | } | 1913 | } |
| 1912 | } else { | 1914 | image.flags |= ImageFlagBits::Picked; |
| 1913 | func(image_id, image); | 1915 | images.push_back(image_id); |
| 1914 | } | 1916 | if constexpr (BOOL_BREAK) { |
| 1915 | } | 1917 | if (func(image_id, image)) { |
| 1916 | if constexpr (BOOL_BREAK) { | 1918 | return true; |
| 1917 | return false; | 1919 | } |
| 1918 | } | 1920 | } else { |
| 1919 | }); | 1921 | func(image_id, image); |
| 1922 | } | ||
| 1923 | } | ||
| 1924 | if constexpr (BOOL_BREAK) { | ||
| 1925 | return false; | ||
| 1926 | } | ||
| 1927 | }); | ||
| 1920 | for (const ImageId image_id : images) { | 1928 | for (const ImageId image_id : images) { |
| 1921 | slot_images[image_id].flags &= ~ImageFlagBits::Picked; | 1929 | slot_images[image_id].flags &= ~ImageFlagBits::Picked; |
| 1922 | } | 1930 | } |
| @@ -1988,8 +1996,9 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { | |||
| 1988 | sparse_maps.push_back(map_id); | 1996 | sparse_maps.push_back(map_id); |
| 1989 | }); | 1997 | }); |
| 1990 | sparse_views.emplace(image_id, std::move(sparse_maps)); | 1998 | sparse_views.emplace(image_id, std::move(sparse_maps)); |
| 1991 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, | 1999 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { |
| 1992 | [this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); }); | 2000 | (*channel_state->sparse_page_table)[page].push_back(image_id); |
| 2001 | }); | ||
| 1993 | } | 2002 | } |
| 1994 | 2003 | ||
| 1995 | template <class P> | 2004 | template <class P> |
| @@ -2042,7 +2051,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 2042 | return; | 2051 | return; |
| 2043 | } | 2052 | } |
| 2044 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { | 2053 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { |
| 2045 | clear_page_table(page, sparse_page_table); | 2054 | clear_page_table(page, (*channel_state->sparse_page_table)); |
| 2046 | }); | 2055 | }); |
| 2047 | auto it = sparse_views.find(image_id); | 2056 | auto it = sparse_views.find(image_id); |
| 2048 | ASSERT(it != sparse_views.end()); | 2057 | ASSERT(it != sparse_views.end()); |
| @@ -2496,13 +2505,15 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel | |||
| 2496 | const auto it = channel_map.find(channel.bind_id); | 2505 | const auto it = channel_map.find(channel.bind_id); |
| 2497 | auto* this_state = &channel_storage[it->second]; | 2506 | auto* this_state = &channel_storage[it->second]; |
| 2498 | const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; | 2507 | const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; |
| 2499 | this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id]; | 2508 | this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2]; |
| 2509 | this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1]; | ||
| 2500 | } | 2510 | } |
| 2501 | 2511 | ||
| 2502 | /// Bind a channel for execution. | 2512 | /// Bind a channel for execution. |
| 2503 | template <class P> | 2513 | template <class P> |
| 2504 | void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { | 2514 | void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { |
| 2505 | gpu_page_table_storage.emplace_back(); | 2515 | gpu_page_table_storage.emplace_back(); |
| 2516 | gpu_page_table_storage.emplace_back(); | ||
| 2506 | } | 2517 | } |
| 2507 | 2518 | ||
| 2508 | } // namespace VideoCommon | 2519 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 8699d40d4..f9aebb293 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -86,6 +86,7 @@ public: | |||
| 86 | std::unordered_map<TSCEntry, SamplerId> samplers; | 86 | std::unordered_map<TSCEntry, SamplerId> samplers; |
| 87 | 87 | ||
| 88 | TextureCacheGPUMap* gpu_page_table; | 88 | TextureCacheGPUMap* gpu_page_table; |
| 89 | TextureCacheGPUMap* sparse_page_table; | ||
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | template <class P> | 92 | template <class P> |
| @@ -357,7 +358,7 @@ private: | |||
| 357 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); | 358 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); |
| 358 | 359 | ||
| 359 | template <typename Func> | 360 | template <typename Func> |
| 360 | void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func); | 361 | void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); |
| 361 | 362 | ||
| 362 | /// Iterates over all the images in a region calling func | 363 | /// Iterates over all the images in a region calling func |
| 363 | template <typename Func> | 364 | template <typename Func> |
| @@ -431,7 +432,6 @@ private: | |||
| 431 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; | 432 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; |
| 432 | 433 | ||
| 433 | std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; | 434 | std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; |
| 434 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; | ||
| 435 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; | 435 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; |
| 436 | 436 | ||
| 437 | DAddr virtual_invalid_space{}; | 437 | DAddr virtual_invalid_space{}; |
diff --git a/src/video_core/vulkan_common/vk_enum_string_helper.h b/src/video_core/vulkan_common/vk_enum_string_helper.h new file mode 100644 index 000000000..a1515814c --- /dev/null +++ b/src/video_core/vulkan_common/vk_enum_string_helper.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "video_core/vulkan_common/vulkan.h" | ||
| 7 | |||
| 8 | #include <vulkan/vk_enum_string_helper.h> | ||
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 3966bd61e..f1aa45551 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "video_core/vulkan_common/vk_enum_string_helper.h" | ||
| 12 | #include "video_core/vulkan_common/vma.h" | 13 | #include "video_core/vulkan_common/vma.h" |
| 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 14 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 14 | 15 | ||
| @@ -298,109 +299,7 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept { | |||
| 298 | } | 299 | } |
| 299 | 300 | ||
| 300 | const char* Exception::what() const noexcept { | 301 | const char* Exception::what() const noexcept { |
| 301 | return ToString(result); | 302 | return string_VkResult(result); |
| 302 | } | ||
| 303 | |||
| 304 | const char* ToString(VkResult result) noexcept { | ||
| 305 | switch (result) { | ||
| 306 | case VkResult::VK_SUCCESS: | ||
| 307 | return "VK_SUCCESS"; | ||
| 308 | case VkResult::VK_NOT_READY: | ||
| 309 | return "VK_NOT_READY"; | ||
| 310 | case VkResult::VK_TIMEOUT: | ||
| 311 | return "VK_TIMEOUT"; | ||
| 312 | case VkResult::VK_EVENT_SET: | ||
| 313 | return "VK_EVENT_SET"; | ||
| 314 | case VkResult::VK_EVENT_RESET: | ||
| 315 | return "VK_EVENT_RESET"; | ||
| 316 | case VkResult::VK_INCOMPLETE: | ||
| 317 | return "VK_INCOMPLETE"; | ||
| 318 | case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY: | ||
| 319 | return "VK_ERROR_OUT_OF_HOST_MEMORY"; | ||
| 320 | case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY: | ||
| 321 | return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; | ||
| 322 | case VkResult::VK_ERROR_INITIALIZATION_FAILED: | ||
| 323 | return "VK_ERROR_INITIALIZATION_FAILED"; | ||
| 324 | case VkResult::VK_ERROR_DEVICE_LOST: | ||
| 325 | return "VK_ERROR_DEVICE_LOST"; | ||
| 326 | case VkResult::VK_ERROR_MEMORY_MAP_FAILED: | ||
| 327 | return "VK_ERROR_MEMORY_MAP_FAILED"; | ||
| 328 | case VkResult::VK_ERROR_LAYER_NOT_PRESENT: | ||
| 329 | return "VK_ERROR_LAYER_NOT_PRESENT"; | ||
| 330 | case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT: | ||
| 331 | return "VK_ERROR_EXTENSION_NOT_PRESENT"; | ||
| 332 | case VkResult::VK_ERROR_FEATURE_NOT_PRESENT: | ||
| 333 | return "VK_ERROR_FEATURE_NOT_PRESENT"; | ||
| 334 | case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER: | ||
| 335 | return "VK_ERROR_INCOMPATIBLE_DRIVER"; | ||
| 336 | case VkResult::VK_ERROR_TOO_MANY_OBJECTS: | ||
| 337 | return "VK_ERROR_TOO_MANY_OBJECTS"; | ||
| 338 | case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED: | ||
| 339 | return "VK_ERROR_FORMAT_NOT_SUPPORTED"; | ||
| 340 | case VkResult::VK_ERROR_FRAGMENTED_POOL: | ||
| 341 | return "VK_ERROR_FRAGMENTED_POOL"; | ||
| 342 | case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY: | ||
| 343 | return "VK_ERROR_OUT_OF_POOL_MEMORY"; | ||
| 344 | case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE: | ||
| 345 | return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; | ||
| 346 | case VkResult::VK_ERROR_SURFACE_LOST_KHR: | ||
| 347 | return "VK_ERROR_SURFACE_LOST_KHR"; | ||
| 348 | case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: | ||
| 349 | return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; | ||
| 350 | case VkResult::VK_SUBOPTIMAL_KHR: | ||
| 351 | return "VK_SUBOPTIMAL_KHR"; | ||
| 352 | case VkResult::VK_ERROR_OUT_OF_DATE_KHR: | ||
| 353 | return "VK_ERROR_OUT_OF_DATE_KHR"; | ||
| 354 | case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: | ||
| 355 | return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; | ||
| 356 | case VkResult::VK_ERROR_VALIDATION_FAILED_EXT: | ||
| 357 | return "VK_ERROR_VALIDATION_FAILED_EXT"; | ||
| 358 | case VkResult::VK_ERROR_INVALID_SHADER_NV: | ||
| 359 | return "VK_ERROR_INVALID_SHADER_NV"; | ||
| 360 | case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: | ||
| 361 | return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR"; | ||
| 362 | case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: | ||
| 363 | return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR"; | ||
| 364 | case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: | ||
| 365 | return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR"; | ||
| 366 | case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: | ||
| 367 | return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR"; | ||
| 368 | case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: | ||
| 369 | return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR"; | ||
| 370 | case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: | ||
| 371 | return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR"; | ||
| 372 | case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: | ||
| 373 | return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; | ||
| 374 | case VkResult::VK_ERROR_FRAGMENTATION_EXT: | ||
| 375 | return "VK_ERROR_FRAGMENTATION_EXT"; | ||
| 376 | case VkResult::VK_ERROR_NOT_PERMITTED_EXT: | ||
| 377 | return "VK_ERROR_NOT_PERMITTED_EXT"; | ||
| 378 | case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT: | ||
| 379 | return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT"; | ||
| 380 | case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: | ||
| 381 | return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; | ||
| 382 | case VkResult::VK_ERROR_UNKNOWN: | ||
| 383 | return "VK_ERROR_UNKNOWN"; | ||
| 384 | case VkResult::VK_THREAD_IDLE_KHR: | ||
| 385 | return "VK_THREAD_IDLE_KHR"; | ||
| 386 | case VkResult::VK_THREAD_DONE_KHR: | ||
| 387 | return "VK_THREAD_DONE_KHR"; | ||
| 388 | case VkResult::VK_OPERATION_DEFERRED_KHR: | ||
| 389 | return "VK_OPERATION_DEFERRED_KHR"; | ||
| 390 | case VkResult::VK_OPERATION_NOT_DEFERRED_KHR: | ||
| 391 | return "VK_OPERATION_NOT_DEFERRED_KHR"; | ||
| 392 | case VkResult::VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR: | ||
| 393 | return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR"; | ||
| 394 | case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT: | ||
| 395 | return "VK_PIPELINE_COMPILE_REQUIRED_EXT"; | ||
| 396 | case VkResult::VK_RESULT_MAX_ENUM: | ||
| 397 | return "VK_RESULT_MAX_ENUM"; | ||
| 398 | case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT: | ||
| 399 | return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; | ||
| 400 | case VkResult::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT: | ||
| 401 | return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT"; | ||
| 402 | } | ||
| 403 | return "Unknown"; | ||
| 404 | } | 303 | } |
| 405 | 304 | ||
| 406 | void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept { | 305 | void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept { |
| @@ -1067,7 +966,7 @@ u32 AvailableVersion(const InstanceDispatch& dld) noexcept { | |||
| 1067 | u32 version; | 966 | u32 version; |
| 1068 | if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) { | 967 | if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) { |
| 1069 | LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1", | 968 | LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1", |
| 1070 | ToString(result)); | 969 | string_VkResult(result)); |
| 1071 | return VK_API_VERSION_1_1; | 970 | return VK_API_VERSION_1_1; |
| 1072 | } | 971 | } |
| 1073 | return version; | 972 | return version; |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index a0c70797f..757f3c8af 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -125,9 +125,6 @@ private: | |||
| 125 | VkResult result; | 125 | VkResult result; |
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | /// Converts a VkResult enum into a rodata string | ||
| 129 | const char* ToString(VkResult) noexcept; | ||
| 130 | |||
| 131 | /// Throws a Vulkan exception if result is not success. | 128 | /// Throws a Vulkan exception if result is not success. |
| 132 | inline void Check(VkResult result) { | 129 | inline void Check(VkResult result) { |
| 133 | if (result != VK_SUCCESS) { | 130 | if (result != VK_SUCCESS) { |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index bc667b39f..76f06da12 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -378,8 +378,6 @@ elseif(WIN32) | |||
| 378 | endif() | 378 | endif() |
| 379 | endif() | 379 | endif() |
| 380 | 380 | ||
| 381 | create_target_directory_groups(yuzu) | ||
| 382 | |||
| 383 | target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) | 381 | target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) |
| 384 | target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) | 382 | target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) |
| 385 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) | 383 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) |
| @@ -475,3 +473,5 @@ endif() | |||
| 475 | if (YUZU_USE_PRECOMPILED_HEADERS) | 473 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 476 | target_precompile_headers(yuzu PRIVATE precompiled_headers.h) | 474 | target_precompile_headers(yuzu PRIVATE precompiled_headers.h) |
| 477 | endif() | 475 | endif() |
| 476 | |||
| 477 | create_target_directory_groups(yuzu) | ||
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index 79162a491..66edd6acd 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp | |||
| @@ -162,7 +162,7 @@ void QtProfileSelectionDialog::SelectUser(const QModelIndex& index) { | |||
| 162 | 162 | ||
| 163 | void QtProfileSelectionDialog::SetWindowTitle( | 163 | void QtProfileSelectionDialog::SetWindowTitle( |
| 164 | const Core::Frontend::ProfileSelectParameters& parameters) { | 164 | const Core::Frontend::ProfileSelectParameters& parameters) { |
| 165 | using Service::AM::Applets::UiMode; | 165 | using Service::AM::Frontend::UiMode; |
| 166 | switch (parameters.mode) { | 166 | switch (parameters.mode) { |
| 167 | case UiMode::UserCreator: | 167 | case UiMode::UserCreator: |
| 168 | case UiMode::UserCreatorForStarter: | 168 | case UiMode::UserCreatorForStarter: |
| @@ -193,7 +193,7 @@ void QtProfileSelectionDialog::SetWindowTitle( | |||
| 193 | 193 | ||
| 194 | void QtProfileSelectionDialog::SetDialogPurpose( | 194 | void QtProfileSelectionDialog::SetDialogPurpose( |
| 195 | const Core::Frontend::ProfileSelectParameters& parameters) { | 195 | const Core::Frontend::ProfileSelectParameters& parameters) { |
| 196 | using Service::AM::Applets::UserSelectionPurpose; | 196 | using Service::AM::Frontend::UserSelectionPurpose; |
| 197 | 197 | ||
| 198 | switch (parameters.purpose) { | 198 | switch (parameters.purpose) { |
| 199 | case UserSelectionPurpose::GameCardRegistration: | 199 | case UserSelectionPurpose::GameCardRegistration: |
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index ac81ace9e..2749e6ed3 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | namespace { | 21 | namespace { |
| 22 | 22 | ||
| 23 | using namespace Service::AM::Applets; | 23 | using namespace Service::AM::Frontend; |
| 24 | 24 | ||
| 25 | constexpr float BASE_HEADER_FONT_SIZE = 23.0f; | 25 | constexpr float BASE_HEADER_FONT_SIZE = 23.0f; |
| 26 | constexpr float BASE_SUB_FONT_SIZE = 17.0f; | 26 | constexpr float BASE_SUB_FONT_SIZE = 17.0f; |
| @@ -389,7 +389,7 @@ void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { | |||
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | void QtSoftwareKeyboardDialog::ShowTextCheckDialog( | 391 | void QtSoftwareKeyboardDialog::ShowTextCheckDialog( |
| 392 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 392 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 393 | std::u16string text_check_message) { | 393 | std::u16string text_check_message) { |
| 394 | switch (text_check_result) { | 394 | switch (text_check_result) { |
| 395 | case SwkbdTextCheckResult::Success: | 395 | case SwkbdTextCheckResult::Success: |
| @@ -1612,7 +1612,7 @@ void QtSoftwareKeyboard::ShowNormalKeyboard() const { | |||
| 1612 | } | 1612 | } |
| 1613 | 1613 | ||
| 1614 | void QtSoftwareKeyboard::ShowTextCheckDialog( | 1614 | void QtSoftwareKeyboard::ShowTextCheckDialog( |
| 1615 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 1615 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 1616 | std::u16string text_check_message) const { | 1616 | std::u16string text_check_message) const { |
| 1617 | emit MainWindowShowTextCheckDialog(text_check_result, std::move(text_check_message)); | 1617 | emit MainWindowShowTextCheckDialog(text_check_result, std::move(text_check_message)); |
| 1618 | } | 1618 | } |
| @@ -1662,12 +1662,12 @@ void QtSoftwareKeyboard::ExitKeyboard() const { | |||
| 1662 | emit MainWindowExitKeyboard(); | 1662 | emit MainWindowExitKeyboard(); |
| 1663 | } | 1663 | } |
| 1664 | 1664 | ||
| 1665 | void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result, | 1665 | void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Frontend::SwkbdResult result, |
| 1666 | std::u16string submitted_text, bool confirmed) const { | 1666 | std::u16string submitted_text, bool confirmed) const { |
| 1667 | submit_normal_callback(result, submitted_text, confirmed); | 1667 | submit_normal_callback(result, submitted_text, confirmed); |
| 1668 | } | 1668 | } |
| 1669 | 1669 | ||
| 1670 | void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 1670 | void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, |
| 1671 | std::u16string submitted_text, | 1671 | std::u16string submitted_text, |
| 1672 | s32 cursor_position) const { | 1672 | s32 cursor_position) const { |
| 1673 | submit_inline_callback(reply_type, submitted_text, cursor_position); | 1673 | submit_inline_callback(reply_type, submitted_text, cursor_position); |
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h index ac23ce047..7e2fdf09e 100644 --- a/src/yuzu/applets/qt_software_keyboard.h +++ b/src/yuzu/applets/qt_software_keyboard.h | |||
| @@ -39,7 +39,7 @@ public: | |||
| 39 | 39 | ||
| 40 | void ShowNormalKeyboard(QPoint pos, QSize size); | 40 | void ShowNormalKeyboard(QPoint pos, QSize size); |
| 41 | 41 | ||
| 42 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 42 | void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 43 | std::u16string text_check_message); | 43 | std::u16string text_check_message); |
| 44 | 44 | ||
| 45 | void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, | 45 | void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, |
| @@ -52,10 +52,10 @@ public: | |||
| 52 | void ExitKeyboard(); | 52 | void ExitKeyboard(); |
| 53 | 53 | ||
| 54 | signals: | 54 | signals: |
| 55 | void SubmitNormalText(Service::AM::Applets::SwkbdResult result, std::u16string submitted_text, | 55 | void SubmitNormalText(Service::AM::Frontend::SwkbdResult result, std::u16string submitted_text, |
| 56 | bool confirmed = false) const; | 56 | bool confirmed = false) const; |
| 57 | 57 | ||
| 58 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 58 | void SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, |
| 59 | std::u16string submitted_text, s32 cursor_position) const; | 59 | std::u16string submitted_text, s32 cursor_position) const; |
| 60 | 60 | ||
| 61 | public slots: | 61 | public slots: |
| @@ -244,7 +244,7 @@ public: | |||
| 244 | 244 | ||
| 245 | void ShowNormalKeyboard() const override; | 245 | void ShowNormalKeyboard() const override; |
| 246 | 246 | ||
| 247 | void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 247 | void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 248 | std::u16string text_check_message) const override; | 248 | std::u16string text_check_message) const override; |
| 249 | 249 | ||
| 250 | void ShowInlineKeyboard( | 250 | void ShowInlineKeyboard( |
| @@ -262,8 +262,9 @@ signals: | |||
| 262 | 262 | ||
| 263 | void MainWindowShowNormalKeyboard() const; | 263 | void MainWindowShowNormalKeyboard() const; |
| 264 | 264 | ||
| 265 | void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 265 | void MainWindowShowTextCheckDialog( |
| 266 | std::u16string text_check_message) const; | 266 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 267 | std::u16string text_check_message) const; | ||
| 267 | 268 | ||
| 268 | void MainWindowShowInlineKeyboard( | 269 | void MainWindowShowInlineKeyboard( |
| 269 | Core::Frontend::InlineAppearParameters appear_parameters) const; | 270 | Core::Frontend::InlineAppearParameters appear_parameters) const; |
| @@ -275,10 +276,10 @@ signals: | |||
| 275 | void MainWindowExitKeyboard() const; | 276 | void MainWindowExitKeyboard() const; |
| 276 | 277 | ||
| 277 | private: | 278 | private: |
| 278 | void SubmitNormalText(Service::AM::Applets::SwkbdResult result, std::u16string submitted_text, | 279 | void SubmitNormalText(Service::AM::Frontend::SwkbdResult result, std::u16string submitted_text, |
| 279 | bool confirmed) const; | 280 | bool confirmed) const; |
| 280 | 281 | ||
| 281 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 282 | void SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, |
| 282 | std::u16string submitted_text, s32 cursor_position) const; | 283 | std::u16string submitted_text, s32 cursor_position) const; |
| 283 | 284 | ||
| 284 | mutable SubmitNormalCallback submit_normal_callback; | 285 | mutable SubmitNormalCallback submit_normal_callback; |
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index 34c5fd3be..cce9b2efb 100644 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp | |||
| @@ -96,7 +96,7 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system, | |||
| 96 | [this] { | 96 | [this] { |
| 97 | if (page()->url() == url_interceptor->GetRequestedURL()) { | 97 | if (page()->url() == url_interceptor->GetRequestedURL()) { |
| 98 | SetFinished(true); | 98 | SetFinished(true); |
| 99 | SetExitReason(Service::AM::Applets::WebExitReason::WindowClosed); | 99 | SetExitReason(Service::AM::Frontend::WebExitReason::WindowClosed); |
| 100 | } | 100 | } |
| 101 | }, | 101 | }, |
| 102 | Qt::QueuedConnection); | 102 | Qt::QueuedConnection); |
| @@ -115,7 +115,7 @@ void QtNXWebEngineView::LoadLocalWebPage(const std::string& main_url, | |||
| 115 | FocusFirstLinkElement(); | 115 | FocusFirstLinkElement(); |
| 116 | SetUserAgent(UserAgent::WebApplet); | 116 | SetUserAgent(UserAgent::WebApplet); |
| 117 | SetFinished(false); | 117 | SetFinished(false); |
| 118 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); | 118 | SetExitReason(Service::AM::Frontend::WebExitReason::EndButtonPressed); |
| 119 | SetLastURL("http://localhost/"); | 119 | SetLastURL("http://localhost/"); |
| 120 | StartInputThread(); | 120 | StartInputThread(); |
| 121 | 121 | ||
| @@ -130,7 +130,7 @@ void QtNXWebEngineView::LoadExternalWebPage(const std::string& main_url, | |||
| 130 | FocusFirstLinkElement(); | 130 | FocusFirstLinkElement(); |
| 131 | SetUserAgent(UserAgent::WebApplet); | 131 | SetUserAgent(UserAgent::WebApplet); |
| 132 | SetFinished(false); | 132 | SetFinished(false); |
| 133 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); | 133 | SetExitReason(Service::AM::Frontend::WebExitReason::EndButtonPressed); |
| 134 | SetLastURL("http://localhost/"); | 134 | SetLastURL("http://localhost/"); |
| 135 | StartInputThread(); | 135 | StartInputThread(); |
| 136 | 136 | ||
| @@ -170,11 +170,11 @@ void QtNXWebEngineView::SetFinished(bool finished_) { | |||
| 170 | finished = finished_; | 170 | finished = finished_; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | Service::AM::Applets::WebExitReason QtNXWebEngineView::GetExitReason() const { | 173 | Service::AM::Frontend::WebExitReason QtNXWebEngineView::GetExitReason() const { |
| 174 | return exit_reason; | 174 | return exit_reason; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | void QtNXWebEngineView::SetExitReason(Service::AM::Applets::WebExitReason exit_reason_) { | 177 | void QtNXWebEngineView::SetExitReason(Service::AM::Frontend::WebExitReason exit_reason_) { |
| 178 | exit_reason = exit_reason_; | 178 | exit_reason = exit_reason_; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| @@ -441,7 +441,7 @@ void QtWebBrowser::MainWindowExtractOfflineRomFS() { | |||
| 441 | extract_romfs_callback(); | 441 | extract_romfs_callback(); |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, | 444 | void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Frontend::WebExitReason exit_reason, |
| 445 | std::string last_url) { | 445 | std::string last_url) { |
| 446 | if (callback) { | 446 | if (callback) { |
| 447 | callback(exit_reason, last_url); | 447 | callback(exit_reason, last_url); |
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h index 1234108ae..e8a0b6931 100644 --- a/src/yuzu/applets/qt_web_browser.h +++ b/src/yuzu/applets/qt_web_browser.h | |||
| @@ -85,8 +85,8 @@ public: | |||
| 85 | [[nodiscard]] bool IsFinished() const; | 85 | [[nodiscard]] bool IsFinished() const; |
| 86 | void SetFinished(bool finished_); | 86 | void SetFinished(bool finished_); |
| 87 | 87 | ||
| 88 | [[nodiscard]] Service::AM::Applets::WebExitReason GetExitReason() const; | 88 | [[nodiscard]] Service::AM::Frontend::WebExitReason GetExitReason() const; |
| 89 | void SetExitReason(Service::AM::Applets::WebExitReason exit_reason_); | 89 | void SetExitReason(Service::AM::Frontend::WebExitReason exit_reason_); |
| 90 | 90 | ||
| 91 | [[nodiscard]] const std::string& GetLastURL() const; | 91 | [[nodiscard]] const std::string& GetLastURL() const; |
| 92 | void SetLastURL(std::string last_url_); | 92 | void SetLastURL(std::string last_url_); |
| @@ -176,8 +176,8 @@ private: | |||
| 176 | 176 | ||
| 177 | std::atomic<bool> finished{}; | 177 | std::atomic<bool> finished{}; |
| 178 | 178 | ||
| 179 | Service::AM::Applets::WebExitReason exit_reason{ | 179 | Service::AM::Frontend::WebExitReason exit_reason{ |
| 180 | Service::AM::Applets::WebExitReason::EndButtonPressed}; | 180 | Service::AM::Frontend::WebExitReason::EndButtonPressed}; |
| 181 | 181 | ||
| 182 | std::string last_url{"http://localhost/"}; | 182 | std::string last_url{"http://localhost/"}; |
| 183 | 183 | ||
| @@ -212,7 +212,7 @@ signals: | |||
| 212 | private: | 212 | private: |
| 213 | void MainWindowExtractOfflineRomFS(); | 213 | void MainWindowExtractOfflineRomFS(); |
| 214 | 214 | ||
| 215 | void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, | 215 | void MainWindowWebBrowserClosed(Service::AM::Frontend::WebExitReason exit_reason, |
| 216 | std::string last_url); | 216 | std::string last_url); |
| 217 | 217 | ||
| 218 | mutable ExtractROMFSCallback extract_romfs_callback; | 218 | mutable ExtractROMFSCallback extract_romfs_callback; |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 9b6ef47a7..c235b0fca 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include <QComboBox> | 7 | #include <QComboBox> |
| 8 | #include <QPushButton> | ||
| 8 | 9 | ||
| 9 | #include "audio_core/sink/sink.h" | 10 | #include "audio_core/sink/sink.h" |
| 10 | #include "audio_core/sink/sink_details.h" | 11 | #include "audio_core/sink/sink_details.h" |
| @@ -67,19 +68,99 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 67 | 68 | ||
| 68 | hold.emplace(std::pair{setting->Id(), widget}); | 69 | hold.emplace(std::pair{setting->Id(), widget}); |
| 69 | 70 | ||
| 71 | auto global_sink_match = [this] { | ||
| 72 | return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) == | ||
| 73 | Settings::values.sink_id.GetValue(true); | ||
| 74 | }; | ||
| 70 | if (setting->Id() == Settings::values.sink_id.Id()) { | 75 | if (setting->Id() == Settings::values.sink_id.Id()) { |
| 71 | // TODO (lat9nq): Let the system manage sink_id | 76 | // TODO (lat9nq): Let the system manage sink_id |
| 72 | sink_combo_box = widget->combobox; | 77 | sink_combo_box = widget->combobox; |
| 73 | InitializeAudioSinkComboBox(); | 78 | InitializeAudioSinkComboBox(); |
| 74 | 79 | ||
| 75 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | 80 | if (Settings::IsConfiguringGlobal()) { |
| 76 | &ConfigureAudio::UpdateAudioDevices); | 81 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 82 | &ConfigureAudio::UpdateAudioDevices); | ||
| 83 | } else { | ||
| 84 | restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 85 | Settings::values.sink_id.UsingGlobal(), widget); | ||
| 86 | widget->layout()->addWidget(restore_sink_button); | ||
| 87 | connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) { | ||
| 88 | Settings::values.sink_id.SetGlobal(true); | ||
| 89 | const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue()); | ||
| 90 | sink_combo_box->setCurrentIndex(sink_index); | ||
| 91 | ConfigureAudio::UpdateAudioDevices(sink_index); | ||
| 92 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 93 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 94 | restore_sink_button->setVisible(false); | ||
| 95 | }); | ||
| 96 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 97 | [this, global_sink_match](const int slot) { | ||
| 98 | Settings::values.sink_id.SetGlobal(false); | ||
| 99 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 100 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 101 | |||
| 102 | restore_sink_button->setVisible(true); | ||
| 103 | restore_sink_button->setEnabled(true); | ||
| 104 | output_device_combo_box->setCurrentIndex(0); | ||
| 105 | restore_output_device_button->setVisible(true); | ||
| 106 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 107 | input_device_combo_box->setCurrentIndex(0); | ||
| 108 | restore_input_device_button->setVisible(true); | ||
| 109 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 110 | ConfigureAudio::UpdateAudioDevices(slot); | ||
| 111 | }); | ||
| 112 | } | ||
| 77 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { | 113 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { |
| 78 | // Keep track of output (and input) device comboboxes to populate them with system | 114 | // Keep track of output (and input) device comboboxes to populate them with system |
| 79 | // devices, which are determined at run time | 115 | // devices, which are determined at run time |
| 80 | output_device_combo_box = widget->combobox; | 116 | output_device_combo_box = widget->combobox; |
| 117 | |||
| 118 | if (!Settings::IsConfiguringGlobal()) { | ||
| 119 | restore_output_device_button = | ||
| 120 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 121 | Settings::values.audio_output_device_id.UsingGlobal(), widget); | ||
| 122 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 123 | restore_output_device_button->setVisible( | ||
| 124 | !Settings::values.audio_output_device_id.UsingGlobal()); | ||
| 125 | widget->layout()->addWidget(restore_output_device_button); | ||
| 126 | connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 127 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 128 | SetOutputDevicesFromDeviceID(); | ||
| 129 | restore_output_device_button->setVisible(false); | ||
| 130 | }); | ||
| 131 | connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 132 | [this, global_sink_match](int) { | ||
| 133 | if (updating_devices) { | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 137 | restore_output_device_button->setVisible(true); | ||
| 138 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 139 | }); | ||
| 140 | } | ||
| 81 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { | 141 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { |
| 82 | input_device_combo_box = widget->combobox; | 142 | input_device_combo_box = widget->combobox; |
| 143 | |||
| 144 | if (!Settings::IsConfiguringGlobal()) { | ||
| 145 | restore_input_device_button = | ||
| 146 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 147 | Settings::values.audio_input_device_id.UsingGlobal(), widget); | ||
| 148 | widget->layout()->addWidget(restore_input_device_button); | ||
| 149 | connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 150 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 151 | SetInputDevicesFromDeviceID(); | ||
| 152 | restore_input_device_button->setVisible(false); | ||
| 153 | }); | ||
| 154 | connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 155 | [this, global_sink_match](int) { | ||
| 156 | if (updating_devices) { | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 160 | restore_input_device_button->setVisible(true); | ||
| 161 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 162 | }); | ||
| 163 | } | ||
| 83 | } | 164 | } |
| 84 | } | 165 | } |
| 85 | 166 | ||
| @@ -89,16 +170,13 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 89 | } | 170 | } |
| 90 | 171 | ||
| 91 | void ConfigureAudio::SetConfiguration() { | 172 | void ConfigureAudio::SetConfiguration() { |
| 92 | if (!Settings::IsConfiguringGlobal()) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | SetOutputSinkFromSinkID(); | 173 | SetOutputSinkFromSinkID(); |
| 97 | 174 | ||
| 98 | // The device list cannot be pre-populated (nor listed) until the output sink is known. | 175 | // The device list cannot be pre-populated (nor listed) until the output sink is known. |
| 99 | UpdateAudioDevices(sink_combo_box->currentIndex()); | 176 | UpdateAudioDevices(sink_combo_box->currentIndex()); |
| 100 | 177 | ||
| 101 | SetAudioDevicesFromDeviceID(); | 178 | SetOutputDevicesFromDeviceID(); |
| 179 | SetInputDevicesFromDeviceID(); | ||
| 102 | } | 180 | } |
| 103 | 181 | ||
| 104 | void ConfigureAudio::SetOutputSinkFromSinkID() { | 182 | void ConfigureAudio::SetOutputSinkFromSinkID() { |
| @@ -116,8 +194,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| 116 | sink_combo_box->setCurrentIndex(new_sink_index); | 194 | sink_combo_box->setCurrentIndex(new_sink_index); |
| 117 | } | 195 | } |
| 118 | 196 | ||
| 119 | void ConfigureAudio::SetAudioDevicesFromDeviceID() { | 197 | void ConfigureAudio::SetOutputDevicesFromDeviceID() { |
| 120 | int new_device_index = -1; | 198 | int new_device_index = 0; |
| 121 | 199 | ||
| 122 | const QString output_device_id = | 200 | const QString output_device_id = |
| 123 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); | 201 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); |
| @@ -129,8 +207,10 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() { | |||
| 129 | } | 207 | } |
| 130 | 208 | ||
| 131 | output_device_combo_box->setCurrentIndex(new_device_index); | 209 | output_device_combo_box->setCurrentIndex(new_device_index); |
| 210 | } | ||
| 132 | 211 | ||
| 133 | new_device_index = -1; | 212 | void ConfigureAudio::SetInputDevicesFromDeviceID() { |
| 213 | int new_device_index = 0; | ||
| 134 | const QString input_device_id = | 214 | const QString input_device_id = |
| 135 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); | 215 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); |
| 136 | for (int index = 0; index < input_device_combo_box->count(); index++) { | 216 | for (int index = 0; index < input_device_combo_box->count(); index++) { |
| @@ -149,15 +229,12 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 149 | apply_func(is_powered_on); | 229 | apply_func(is_powered_on); |
| 150 | } | 230 | } |
| 151 | 231 | ||
| 152 | if (Settings::IsConfiguringGlobal()) { | 232 | Settings::values.sink_id.LoadString( |
| 153 | Settings::values.sink_id.LoadString( | 233 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); |
| 154 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); | 234 | Settings::values.audio_output_device_id.SetValue( |
| 155 | Settings::values.audio_output_device_id.SetValue( | 235 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString()); |
| 156 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()) | 236 | Settings::values.audio_input_device_id.SetValue( |
| 157 | .toStdString()); | 237 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); |
| 158 | Settings::values.audio_input_device_id.SetValue( | ||
| 159 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); | ||
| 160 | } | ||
| 161 | } | 238 | } |
| 162 | 239 | ||
| 163 | void ConfigureAudio::changeEvent(QEvent* event) { | 240 | void ConfigureAudio::changeEvent(QEvent* event) { |
| @@ -169,6 +246,7 @@ void ConfigureAudio::changeEvent(QEvent* event) { | |||
| 169 | } | 246 | } |
| 170 | 247 | ||
| 171 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { | 248 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { |
| 249 | updating_devices = true; | ||
| 172 | output_device_combo_box->clear(); | 250 | output_device_combo_box->clear(); |
| 173 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 251 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 174 | 252 | ||
| @@ -183,6 +261,7 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) { | |||
| 183 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { | 261 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { |
| 184 | input_device_combo_box->addItem(QString::fromStdString(device)); | 262 | input_device_combo_box->addItem(QString::fromStdString(device)); |
| 185 | } | 263 | } |
| 264 | updating_devices = false; | ||
| 186 | } | 265 | } |
| 187 | 266 | ||
| 188 | void ConfigureAudio::InitializeAudioSinkComboBox() { | 267 | void ConfigureAudio::InitializeAudioSinkComboBox() { |
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 82d7f6524..32a2fa5f0 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -45,7 +45,8 @@ private: | |||
| 45 | void UpdateAudioDevices(int sink_index); | 45 | void UpdateAudioDevices(int sink_index); |
| 46 | 46 | ||
| 47 | void SetOutputSinkFromSinkID(); | 47 | void SetOutputSinkFromSinkID(); |
| 48 | void SetAudioDevicesFromDeviceID(); | 48 | void SetOutputDevicesFromDeviceID(); |
| 49 | void SetInputDevicesFromDeviceID(); | ||
| 49 | 50 | ||
| 50 | void Setup(const ConfigurationShared::Builder& builder); | 51 | void Setup(const ConfigurationShared::Builder& builder); |
| 51 | 52 | ||
| @@ -55,7 +56,11 @@ private: | |||
| 55 | 56 | ||
| 56 | std::vector<std::function<void(bool)>> apply_funcs{}; | 57 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 57 | 58 | ||
| 59 | bool updating_devices = false; | ||
| 58 | QComboBox* sink_combo_box; | 60 | QComboBox* sink_combo_box; |
| 61 | QPushButton* restore_sink_button; | ||
| 59 | QComboBox* output_device_combo_box; | 62 | QComboBox* output_device_combo_box; |
| 63 | QPushButton* restore_output_device_button; | ||
| 60 | QComboBox* input_device_combo_box; | 64 | QComboBox* input_device_combo_box; |
| 65 | QPushButton* restore_input_device_button; | ||
| 61 | }; | 66 | }; |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 49ec52546..e28df10bd 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applet_ae.h" | 11 | #include "core/hle/service/am/applet_ae.h" |
| 12 | #include "core/hle/service/am/applet_manager.h" | ||
| 13 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 12 | #include "core/hle/service/am/applet_oe.h" | 14 | #include "core/hle/service/am/applet_oe.h" |
| 13 | #include "core/hle/service/sm/sm.h" | 15 | #include "core/hle/service/sm/sm.h" |
| 14 | #include "hid_core/frontend/emulated_controller.h" | 16 | #include "hid_core/frontend/emulated_controller.h" |
| @@ -47,22 +49,8 @@ void OnDockedModeChanged(bool last_state, bool new_state, Core::System& system) | |||
| 47 | if (!system.IsPoweredOn()) { | 49 | if (!system.IsPoweredOn()) { |
| 48 | return; | 50 | return; |
| 49 | } | 51 | } |
| 50 | Service::SM::ServiceManager& sm = system.ServiceManager(); | ||
| 51 | 52 | ||
| 52 | // Message queue is shared between these services, we just need to signal an operation | 53 | system.GetAppletManager().OperationModeChanged(); |
| 53 | // change to one and it will handle both automatically | ||
| 54 | auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); | ||
| 55 | auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); | ||
| 56 | bool has_signalled = false; | ||
| 57 | |||
| 58 | if (applet_oe != nullptr) { | ||
| 59 | applet_oe->GetMessageQueue()->OperationModeChanged(); | ||
| 60 | has_signalled = true; | ||
| 61 | } | ||
| 62 | |||
| 63 | if (applet_ae != nullptr && !has_signalled) { | ||
| 64 | applet_ae->GetMessageQueue()->OperationModeChanged(); | ||
| 65 | } | ||
| 66 | } | 54 | } |
| 67 | 55 | ||
| 68 | ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent) | 56 | ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent) |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 59b317135..b40af957c 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -596,14 +596,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri | |||
| 596 | connect(open_save_location, &QAction::triggered, [this, program_id, path]() { | 596 | connect(open_save_location, &QAction::triggered, [this, program_id, path]() { |
| 597 | emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); | 597 | emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); |
| 598 | }); | 598 | }); |
| 599 | connect(start_game, &QAction::triggered, [this, path]() { | 599 | connect(start_game, &QAction::triggered, |
| 600 | emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal, | 600 | [this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Normal); }); |
| 601 | AmLaunchType::UserInitiated); | 601 | connect(start_game_global, &QAction::triggered, |
| 602 | }); | 602 | [this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Global); }); |
| 603 | connect(start_game_global, &QAction::triggered, [this, path]() { | ||
| 604 | emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global, | ||
| 605 | AmLaunchType::UserInitiated); | ||
| 606 | }); | ||
| 607 | connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { | 603 | connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { |
| 608 | emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); | 604 | emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); |
| 609 | }); | 605 | }); |
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 563a3a35b..79f9c7ec0 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h | |||
| @@ -106,8 +106,7 @@ public: | |||
| 106 | static const QStringList supported_file_extensions; | 106 | static const QStringList supported_file_extensions; |
| 107 | 107 | ||
| 108 | signals: | 108 | signals: |
| 109 | void BootGame(const QString& game_path, u64 program_id, std::size_t program_index, | 109 | void BootGame(const QString& game_path, StartGameType type); |
| 110 | StartGameType type, AmLaunchType launch_type); | ||
| 111 | void GameChosen(const QString& game_path, const u64 title_id = 0); | 110 | void GameChosen(const QString& game_path, const u64 title_id = 0); |
| 112 | void OpenFolderRequested(u64 program_id, GameListOpenTarget target, | 111 | void OpenFolderRequested(u64 program_id, GameListOpenTarget target, |
| 113 | const std::string& game_path); | 112 | const std::string& game_path); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 782bcbb61..303d84a1f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <iostream> | 8 | #include <iostream> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | #include "core/hle/service/am/applet_manager.h" | ||
| 11 | #include "core/loader/nca.h" | 12 | #include "core/loader/nca.h" |
| 12 | #include "core/tools/renderdoc.h" | 13 | #include "core/tools/renderdoc.h" |
| 13 | 14 | ||
| @@ -39,13 +40,14 @@ | |||
| 39 | #include "core/file_sys/vfs/vfs_real.h" | 40 | #include "core/file_sys/vfs/vfs_real.h" |
| 40 | #include "core/frontend/applets/cabinet.h" | 41 | #include "core/frontend/applets/cabinet.h" |
| 41 | #include "core/frontend/applets/controller.h" | 42 | #include "core/frontend/applets/controller.h" |
| 42 | #include "core/frontend/applets/general_frontend.h" | 43 | #include "core/frontend/applets/general.h" |
| 43 | #include "core/frontend/applets/mii_edit.h" | 44 | #include "core/frontend/applets/mii_edit.h" |
| 44 | #include "core/frontend/applets/software_keyboard.h" | 45 | #include "core/frontend/applets/software_keyboard.h" |
| 45 | #include "core/hle/service/acc/profile_manager.h" | 46 | #include "core/hle/service/acc/profile_manager.h" |
| 46 | #include "core/hle/service/am/applet_ae.h" | 47 | #include "core/hle/service/am/applet_ae.h" |
| 48 | #include "core/hle/service/am/applet_message_queue.h" | ||
| 47 | #include "core/hle/service/am/applet_oe.h" | 49 | #include "core/hle/service/am/applet_oe.h" |
| 48 | #include "core/hle/service/am/applets/applets.h" | 50 | #include "core/hle/service/am/frontend/applets.h" |
| 49 | #include "core/hle/service/set/system_settings_server.h" | 51 | #include "core/hle/service/set/system_settings_server.h" |
| 50 | #include "frontend_common/content_manager.h" | 52 | #include "frontend_common/content_manager.h" |
| 51 | #include "hid_core/frontend/emulated_controller.h" | 53 | #include "hid_core/frontend/emulated_controller.h" |
| @@ -568,7 +570,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk | |||
| 568 | } | 570 | } |
| 569 | 571 | ||
| 570 | if (!game_path.isEmpty()) { | 572 | if (!game_path.isEmpty()) { |
| 571 | BootGame(game_path); | 573 | BootGame(game_path, ApplicationAppletParameters()); |
| 572 | } | 574 | } |
| 573 | } | 575 | } |
| 574 | 576 | ||
| @@ -630,13 +632,14 @@ void GMainWindow::RegisterMetaTypes() { | |||
| 630 | qRegisterMetaType<Core::Frontend::InlineAppearParameters>( | 632 | qRegisterMetaType<Core::Frontend::InlineAppearParameters>( |
| 631 | "Core::Frontend::InlineAppearParameters"); | 633 | "Core::Frontend::InlineAppearParameters"); |
| 632 | qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters"); | 634 | qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters"); |
| 633 | qRegisterMetaType<Service::AM::Applets::SwkbdResult>("Service::AM::Applets::SwkbdResult"); | 635 | qRegisterMetaType<Service::AM::Frontend::SwkbdResult>("Service::AM::Frontend::SwkbdResult"); |
| 634 | qRegisterMetaType<Service::AM::Applets::SwkbdTextCheckResult>( | 636 | qRegisterMetaType<Service::AM::Frontend::SwkbdTextCheckResult>( |
| 635 | "Service::AM::Applets::SwkbdTextCheckResult"); | 637 | "Service::AM::Frontend::SwkbdTextCheckResult"); |
| 636 | qRegisterMetaType<Service::AM::Applets::SwkbdReplyType>("Service::AM::Applets::SwkbdReplyType"); | 638 | qRegisterMetaType<Service::AM::Frontend::SwkbdReplyType>( |
| 639 | "Service::AM::Frontend::SwkbdReplyType"); | ||
| 637 | 640 | ||
| 638 | // Web Browser Applet | 641 | // Web Browser Applet |
| 639 | qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason"); | 642 | qRegisterMetaType<Service::AM::Frontend::WebExitReason>("Service::AM::Frontend::WebExitReason"); |
| 640 | 643 | ||
| 641 | // Register loader types | 644 | // Register loader types |
| 642 | qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus"); | 645 | qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus"); |
| @@ -746,7 +749,7 @@ void GMainWindow::SoftwareKeyboardInitialize( | |||
| 746 | if (is_inline) { | 749 | if (is_inline) { |
| 747 | connect( | 750 | connect( |
| 748 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this, | 751 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this, |
| 749 | [this](Service::AM::Applets::SwkbdReplyType reply_type, std::u16string submitted_text, | 752 | [this](Service::AM::Frontend::SwkbdReplyType reply_type, std::u16string submitted_text, |
| 750 | s32 cursor_position) { | 753 | s32 cursor_position) { |
| 751 | emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position); | 754 | emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position); |
| 752 | }, | 755 | }, |
| @@ -754,7 +757,7 @@ void GMainWindow::SoftwareKeyboardInitialize( | |||
| 754 | } else { | 757 | } else { |
| 755 | connect( | 758 | connect( |
| 756 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this, | 759 | software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this, |
| 757 | [this](Service::AM::Applets::SwkbdResult result, std::u16string submitted_text, | 760 | [this](Service::AM::Frontend::SwkbdResult result, std::u16string submitted_text, |
| 758 | bool confirmed) { | 761 | bool confirmed) { |
| 759 | emit SoftwareKeyboardSubmitNormalText(result, submitted_text, confirmed); | 762 | emit SoftwareKeyboardSubmitNormalText(result, submitted_text, confirmed); |
| 760 | }, | 763 | }, |
| @@ -781,7 +784,7 @@ void GMainWindow::SoftwareKeyboardShowNormal() { | |||
| 781 | } | 784 | } |
| 782 | 785 | ||
| 783 | void GMainWindow::SoftwareKeyboardShowTextCheck( | 786 | void GMainWindow::SoftwareKeyboardShowTextCheck( |
| 784 | Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 787 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 785 | std::u16string text_check_message) { | 788 | std::u16string text_check_message) { |
| 786 | if (!software_keyboard) { | 789 | if (!software_keyboard) { |
| 787 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); | 790 | LOG_ERROR(Frontend, "The software keyboard is not initialized!"); |
| @@ -852,7 +855,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, | |||
| 852 | 855 | ||
| 853 | // Raw input breaks with the web applet, Disable web applets if enabled | 856 | // Raw input breaks with the web applet, Disable web applets if enabled |
| 854 | if (UISettings::values.disable_web_applet || Settings::values.enable_raw_input) { | 857 | if (UISettings::values.disable_web_applet || Settings::values.enable_raw_input) { |
| 855 | emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, | 858 | emit WebBrowserClosed(Service::AM::Frontend::WebExitReason::WindowClosed, |
| 856 | "http://localhost/"); | 859 | "http://localhost/"); |
| 857 | return; | 860 | return; |
| 858 | } | 861 | } |
| @@ -940,7 +943,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, | |||
| 940 | if (variant.toBool()) { | 943 | if (variant.toBool()) { |
| 941 | web_applet->SetFinished(true); | 944 | web_applet->SetFinished(true); |
| 942 | web_applet->SetExitReason( | 945 | web_applet->SetExitReason( |
| 943 | Service::AM::Applets::WebExitReason::EndButtonPressed); | 946 | Service::AM::Frontend::WebExitReason::EndButtonPressed); |
| 944 | } | 947 | } |
| 945 | }); | 948 | }); |
| 946 | 949 | ||
| @@ -950,7 +953,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, | |||
| 950 | if (web_applet->GetCurrentURL().contains(QStringLiteral("localhost"))) { | 953 | if (web_applet->GetCurrentURL().contains(QStringLiteral("localhost"))) { |
| 951 | if (!web_applet->IsFinished()) { | 954 | if (!web_applet->IsFinished()) { |
| 952 | web_applet->SetFinished(true); | 955 | web_applet->SetFinished(true); |
| 953 | web_applet->SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL); | 956 | web_applet->SetExitReason(Service::AM::Frontend::WebExitReason::CallbackURL); |
| 954 | } | 957 | } |
| 955 | 958 | ||
| 956 | web_applet->SetLastURL(web_applet->GetCurrentURL().toStdString()); | 959 | web_applet->SetLastURL(web_applet->GetCurrentURL().toStdString()); |
| @@ -983,7 +986,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, | |||
| 983 | #else | 986 | #else |
| 984 | 987 | ||
| 985 | // Utilize the same fallback as the default web browser applet. | 988 | // Utilize the same fallback as the default web browser applet. |
| 986 | emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); | 989 | emit WebBrowserClosed(Service::AM::Frontend::WebExitReason::WindowClosed, "http://localhost/"); |
| 987 | 990 | ||
| 988 | #endif | 991 | #endif |
| 989 | } | 992 | } |
| @@ -991,7 +994,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, | |||
| 991 | void GMainWindow::WebBrowserRequestExit() { | 994 | void GMainWindow::WebBrowserRequestExit() { |
| 992 | #ifdef YUZU_USE_QT_WEB_ENGINE | 995 | #ifdef YUZU_USE_QT_WEB_ENGINE |
| 993 | if (web_applet) { | 996 | if (web_applet) { |
| 994 | web_applet->SetExitReason(Service::AM::Applets::WebExitReason::ExitRequested); | 997 | web_applet->SetExitReason(Service::AM::Frontend::WebExitReason::ExitRequested); |
| 995 | web_applet->SetFinished(true); | 998 | web_applet->SetFinished(true); |
| 996 | } | 999 | } |
| 997 | #endif | 1000 | #endif |
| @@ -1472,7 +1475,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { | |||
| 1472 | } | 1475 | } |
| 1473 | 1476 | ||
| 1474 | void GMainWindow::ConnectWidgetEvents() { | 1477 | void GMainWindow::ConnectWidgetEvents() { |
| 1475 | connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGame); | 1478 | connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGameFromList); |
| 1476 | connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); | 1479 | connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); |
| 1477 | connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory); | 1480 | connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory); |
| 1478 | connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); | 1481 | connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); |
| @@ -1760,8 +1763,7 @@ void GMainWindow::AllowOSSleep() { | |||
| 1760 | #endif | 1763 | #endif |
| 1761 | } | 1764 | } |
| 1762 | 1765 | ||
| 1763 | bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index, | 1766 | bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletParameters params) { |
| 1764 | AmLaunchType launch_type) { | ||
| 1765 | // Shutdown previous session if the emu thread is still active... | 1767 | // Shutdown previous session if the emu thread is still active... |
| 1766 | if (emu_thread != nullptr) { | 1768 | if (emu_thread != nullptr) { |
| 1767 | ShutdownGame(); | 1769 | ShutdownGame(); |
| @@ -1773,11 +1775,11 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p | |||
| 1773 | 1775 | ||
| 1774 | system->SetFilesystem(vfs); | 1776 | system->SetFilesystem(vfs); |
| 1775 | 1777 | ||
| 1776 | if (launch_type == AmLaunchType::UserInitiated) { | 1778 | if (params.launch_type == Service::AM::LaunchType::FrontendInitiated) { |
| 1777 | system->GetUserChannel().clear(); | 1779 | system->GetUserChannel().clear(); |
| 1778 | } | 1780 | } |
| 1779 | 1781 | ||
| 1780 | system->SetAppletFrontendSet({ | 1782 | system->SetFrontendAppletSet({ |
| 1781 | std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings | 1783 | std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings |
| 1782 | (UISettings::values.controller_applet_disabled.GetValue() == true) | 1784 | (UISettings::values.controller_applet_disabled.GetValue() == true) |
| 1783 | ? nullptr | 1785 | ? nullptr |
| @@ -1792,7 +1794,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p | |||
| 1792 | }); | 1794 | }); |
| 1793 | 1795 | ||
| 1794 | const Core::SystemResultStatus result{ | 1796 | const Core::SystemResultStatus result{ |
| 1795 | system->Load(*render_window, filename.toStdString(), program_id, program_index)}; | 1797 | system->Load(*render_window, filename.toStdString(), params)}; |
| 1796 | 1798 | ||
| 1797 | const auto drd_callout = (UISettings::values.callout_flags.GetValue() & | 1799 | const auto drd_callout = (UISettings::values.callout_flags.GetValue() & |
| 1798 | static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; | 1800 | static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; |
| @@ -1915,12 +1917,12 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { | |||
| 1915 | } | 1917 | } |
| 1916 | } | 1918 | } |
| 1917 | 1919 | ||
| 1918 | void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, | 1920 | void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletParameters params, |
| 1919 | StartGameType type, AmLaunchType launch_type) { | 1921 | StartGameType type) { |
| 1920 | LOG_INFO(Frontend, "yuzu starting..."); | 1922 | LOG_INFO(Frontend, "yuzu starting..."); |
| 1921 | 1923 | ||
| 1922 | if (program_id == 0 || | 1924 | if (params.program_id == 0 || |
| 1923 | program_id > static_cast<u64>(Service::AM::Applets::AppletProgramId::MaxProgramId)) { | 1925 | params.program_id > static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)) { |
| 1924 | StoreRecentFile(filename); // Put the filename on top of the list | 1926 | StoreRecentFile(filename); // Put the filename on top of the list |
| 1925 | } | 1927 | } |
| 1926 | 1928 | ||
| @@ -1935,7 +1937,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1935 | 1937 | ||
| 1936 | ConfigureFilesystemProvider(filename.toStdString()); | 1938 | ConfigureFilesystemProvider(filename.toStdString()); |
| 1937 | const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); | 1939 | const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); |
| 1938 | const auto loader = Loader::GetLoader(*system, v_file, program_id, program_index); | 1940 | const auto loader = Loader::GetLoader(*system, v_file, params.program_id, params.program_index); |
| 1939 | 1941 | ||
| 1940 | if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && | 1942 | if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && |
| 1941 | type == StartGameType::Normal) { | 1943 | type == StartGameType::Normal) { |
| @@ -1954,10 +1956,10 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1954 | 1956 | ||
| 1955 | if (UISettings::values.select_user_on_boot && !user_flag_cmd_line) { | 1957 | if (UISettings::values.select_user_on_boot && !user_flag_cmd_line) { |
| 1956 | const Core::Frontend::ProfileSelectParameters parameters{ | 1958 | const Core::Frontend::ProfileSelectParameters parameters{ |
| 1957 | .mode = Service::AM::Applets::UiMode::UserSelector, | 1959 | .mode = Service::AM::Frontend::UiMode::UserSelector, |
| 1958 | .invalid_uid_list = {}, | 1960 | .invalid_uid_list = {}, |
| 1959 | .display_options = {}, | 1961 | .display_options = {}, |
| 1960 | .purpose = Service::AM::Applets::UserSelectionPurpose::General, | 1962 | .purpose = Service::AM::Frontend::UserSelectionPurpose::General, |
| 1961 | }; | 1963 | }; |
| 1962 | if (SelectAndSetCurrentUser(parameters) == false) { | 1964 | if (SelectAndSetCurrentUser(parameters) == false) { |
| 1963 | return; | 1965 | return; |
| @@ -1969,7 +1971,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1969 | // behavior of asking. | 1971 | // behavior of asking. |
| 1970 | user_flag_cmd_line = false; | 1972 | user_flag_cmd_line = false; |
| 1971 | 1973 | ||
| 1972 | if (!LoadROM(filename, program_id, program_index, launch_type)) { | 1974 | if (!LoadROM(filename, params)) { |
| 1973 | return; | 1975 | return; |
| 1974 | } | 1976 | } |
| 1975 | 1977 | ||
| @@ -2059,6 +2061,10 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 2059 | OnStartGame(); | 2061 | OnStartGame(); |
| 2060 | } | 2062 | } |
| 2061 | 2063 | ||
| 2064 | void GMainWindow::BootGameFromList(const QString& filename, StartGameType with_config) { | ||
| 2065 | BootGame(filename, ApplicationAppletParameters(), with_config); | ||
| 2066 | } | ||
| 2067 | |||
| 2062 | bool GMainWindow::OnShutdownBegin() { | 2068 | bool GMainWindow::OnShutdownBegin() { |
| 2063 | if (!emulation_running) { | 2069 | if (!emulation_running) { |
| 2064 | return false; | 2070 | return false; |
| @@ -2160,7 +2166,7 @@ void GMainWindow::OnEmulationStopped() { | |||
| 2160 | OnTasStateChanged(); | 2166 | OnTasStateChanged(); |
| 2161 | render_window->FinalizeCamera(); | 2167 | render_window->FinalizeCamera(); |
| 2162 | 2168 | ||
| 2163 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None); | 2169 | system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::None); |
| 2164 | 2170 | ||
| 2165 | // Enable all controllers | 2171 | // Enable all controllers |
| 2166 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); | 2172 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); |
| @@ -2239,7 +2245,10 @@ void GMainWindow::UpdateRecentFiles() { | |||
| 2239 | } | 2245 | } |
| 2240 | 2246 | ||
| 2241 | void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) { | 2247 | void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) { |
| 2242 | BootGame(game_path, program_id); | 2248 | auto params = ApplicationAppletParameters(); |
| 2249 | params.program_id = program_id; | ||
| 2250 | |||
| 2251 | BootGame(game_path, params); | ||
| 2243 | } | 2252 | } |
| 2244 | 2253 | ||
| 2245 | void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, | 2254 | void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, |
| @@ -2280,10 +2289,10 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||
| 2280 | // User save data | 2289 | // User save data |
| 2281 | const auto select_profile = [this] { | 2290 | const auto select_profile = [this] { |
| 2282 | const Core::Frontend::ProfileSelectParameters parameters{ | 2291 | const Core::Frontend::ProfileSelectParameters parameters{ |
| 2283 | .mode = Service::AM::Applets::UiMode::UserSelector, | 2292 | .mode = Service::AM::Frontend::UiMode::UserSelector, |
| 2284 | .invalid_uid_list = {}, | 2293 | .invalid_uid_list = {}, |
| 2285 | .display_options = {}, | 2294 | .display_options = {}, |
| 2286 | .purpose = Service::AM::Applets::UserSelectionPurpose::General, | 2295 | .purpose = Service::AM::Frontend::UserSelectionPurpose::General, |
| 2287 | }; | 2296 | }; |
| 2288 | QtProfileSelectionDialog dialog(*system, this, parameters); | 2297 | QtProfileSelectionDialog dialog(*system, this, parameters); |
| 2289 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | 2298 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | |
| @@ -3171,7 +3180,7 @@ void GMainWindow::OnMenuLoadFile() { | |||
| 3171 | } | 3180 | } |
| 3172 | 3181 | ||
| 3173 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); | 3182 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 3174 | BootGame(filename); | 3183 | BootGame(filename, ApplicationAppletParameters()); |
| 3175 | } | 3184 | } |
| 3176 | 3185 | ||
| 3177 | void GMainWindow::OnMenuLoadFolder() { | 3186 | void GMainWindow::OnMenuLoadFolder() { |
| @@ -3185,7 +3194,7 @@ void GMainWindow::OnMenuLoadFolder() { | |||
| 3185 | const QDir dir{dir_path}; | 3194 | const QDir dir{dir_path}; |
| 3186 | const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files); | 3195 | const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files); |
| 3187 | if (matching_main.size() == 1) { | 3196 | if (matching_main.size() == 1) { |
| 3188 | BootGame(dir.path() + QDir::separator() + matching_main[0]); | 3197 | BootGame(dir.path() + QDir::separator() + matching_main[0], ApplicationAppletParameters()); |
| 3189 | } else { | 3198 | } else { |
| 3190 | QMessageBox::warning(this, tr("Invalid Directory Selected"), | 3199 | QMessageBox::warning(this, tr("Invalid Directory Selected"), |
| 3191 | tr("The directory you have selected does not contain a 'main' file.")); | 3200 | tr("The directory you have selected does not contain a 'main' file.")); |
| @@ -3379,7 +3388,7 @@ void GMainWindow::OnMenuRecentFile() { | |||
| 3379 | 3388 | ||
| 3380 | const QString filename = action->data().toString(); | 3389 | const QString filename = action->data().toString(); |
| 3381 | if (QFileInfo::exists(filename)) { | 3390 | if (QFileInfo::exists(filename)) { |
| 3382 | BootGame(filename); | 3391 | BootGame(filename, ApplicationAppletParameters()); |
| 3383 | } else { | 3392 | } else { |
| 3384 | // Display an error message and remove the file from the list. | 3393 | // Display an error message and remove the file from the list. |
| 3385 | QMessageBox::information(this, tr("File not found"), | 3394 | QMessageBox::information(this, tr("File not found"), |
| @@ -3417,7 +3426,7 @@ void GMainWindow::OnRestartGame() { | |||
| 3417 | // Make a copy since ShutdownGame edits game_path | 3426 | // Make a copy since ShutdownGame edits game_path |
| 3418 | const auto current_game = QString(current_game_path); | 3427 | const auto current_game = QString(current_game_path); |
| 3419 | ShutdownGame(); | 3428 | ShutdownGame(); |
| 3420 | BootGame(current_game); | 3429 | BootGame(current_game, ApplicationAppletParameters()); |
| 3421 | } | 3430 | } |
| 3422 | } | 3431 | } |
| 3423 | 3432 | ||
| @@ -3485,8 +3494,11 @@ void GMainWindow::OnLoadComplete() { | |||
| 3485 | 3494 | ||
| 3486 | void GMainWindow::OnExecuteProgram(std::size_t program_index) { | 3495 | void GMainWindow::OnExecuteProgram(std::size_t program_index) { |
| 3487 | ShutdownGame(); | 3496 | ShutdownGame(); |
| 3488 | BootGame(last_filename_booted, 0, program_index, StartGameType::Normal, | 3497 | |
| 3489 | AmLaunchType::ApplicationInitiated); | 3498 | auto params = ApplicationAppletParameters(); |
| 3499 | params.program_index = static_cast<s32>(program_index); | ||
| 3500 | params.launch_type = Service::AM::LaunchType::ApplicationInitiated; | ||
| 3501 | BootGame(last_filename_booted, params); | ||
| 3490 | } | 3502 | } |
| 3491 | 3503 | ||
| 3492 | void GMainWindow::OnExit() { | 3504 | void GMainWindow::OnExit() { |
| @@ -4153,7 +4165,7 @@ void GMainWindow::OnToggleStatusBar() { | |||
| 4153 | } | 4165 | } |
| 4154 | 4166 | ||
| 4155 | void GMainWindow::OnAlbum() { | 4167 | void GMainWindow::OnAlbum() { |
| 4156 | constexpr u64 AlbumId = static_cast<u64>(Service::AM::Applets::AppletProgramId::PhotoViewer); | 4168 | constexpr u64 AlbumId = static_cast<u64>(Service::AM::AppletProgramId::PhotoViewer); |
| 4157 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4169 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4158 | if (!bis_system) { | 4170 | if (!bis_system) { |
| 4159 | QMessageBox::warning(this, tr("No firmware available"), | 4171 | QMessageBox::warning(this, tr("No firmware available"), |
| @@ -4168,15 +4180,15 @@ void GMainWindow::OnAlbum() { | |||
| 4168 | return; | 4180 | return; |
| 4169 | } | 4181 | } |
| 4170 | 4182 | ||
| 4171 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer); | 4183 | system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::PhotoViewer); |
| 4172 | 4184 | ||
| 4173 | const auto filename = QString::fromStdString(album_nca->GetFullPath()); | 4185 | const auto filename = QString::fromStdString(album_nca->GetFullPath()); |
| 4174 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); | 4186 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4175 | BootGame(filename, AlbumId); | 4187 | BootGame(filename, LibraryAppletParameters(AlbumId, Service::AM::AppletId::PhotoViewer)); |
| 4176 | } | 4188 | } |
| 4177 | 4189 | ||
| 4178 | void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | 4190 | void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { |
| 4179 | constexpr u64 CabinetId = static_cast<u64>(Service::AM::Applets::AppletProgramId::Cabinet); | 4191 | constexpr u64 CabinetId = static_cast<u64>(Service::AM::AppletProgramId::Cabinet); |
| 4180 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4192 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4181 | if (!bis_system) { | 4193 | if (!bis_system) { |
| 4182 | QMessageBox::warning(this, tr("No firmware available"), | 4194 | QMessageBox::warning(this, tr("No firmware available"), |
| @@ -4191,16 +4203,16 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | |||
| 4191 | return; | 4203 | return; |
| 4192 | } | 4204 | } |
| 4193 | 4205 | ||
| 4194 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet); | 4206 | system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Cabinet); |
| 4195 | system->GetAppletManager().SetCabinetMode(mode); | 4207 | system->GetFrontendAppletHolder().SetCabinetMode(mode); |
| 4196 | 4208 | ||
| 4197 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); | 4209 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); |
| 4198 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); | 4210 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4199 | BootGame(filename, CabinetId); | 4211 | BootGame(filename, LibraryAppletParameters(CabinetId, Service::AM::AppletId::Cabinet)); |
| 4200 | } | 4212 | } |
| 4201 | 4213 | ||
| 4202 | void GMainWindow::OnMiiEdit() { | 4214 | void GMainWindow::OnMiiEdit() { |
| 4203 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); | 4215 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::AppletProgramId::MiiEdit); |
| 4204 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4216 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4205 | if (!bis_system) { | 4217 | if (!bis_system) { |
| 4206 | QMessageBox::warning(this, tr("No firmware available"), | 4218 | QMessageBox::warning(this, tr("No firmware available"), |
| @@ -4215,16 +4227,15 @@ void GMainWindow::OnMiiEdit() { | |||
| 4215 | return; | 4227 | return; |
| 4216 | } | 4228 | } |
| 4217 | 4229 | ||
| 4218 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); | 4230 | system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::MiiEdit); |
| 4219 | 4231 | ||
| 4220 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); | 4232 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); |
| 4221 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); | 4233 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4222 | BootGame(filename, MiiEditId); | 4234 | BootGame(filename, LibraryAppletParameters(MiiEditId, Service::AM::AppletId::MiiEdit)); |
| 4223 | } | 4235 | } |
| 4224 | 4236 | ||
| 4225 | void GMainWindow::OnOpenControllerMenu() { | 4237 | void GMainWindow::OnOpenControllerMenu() { |
| 4226 | constexpr u64 ControllerAppletId = | 4238 | constexpr u64 ControllerAppletId = static_cast<u64>(Service::AM::AppletProgramId::Controller); |
| 4227 | static_cast<u64>(Service::AM::Applets::AppletProgramId::Controller); | ||
| 4228 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4239 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4229 | if (!bis_system) { | 4240 | if (!bis_system) { |
| 4230 | QMessageBox::warning(this, tr("No firmware available"), | 4241 | QMessageBox::warning(this, tr("No firmware available"), |
| @@ -4240,11 +4251,12 @@ void GMainWindow::OnOpenControllerMenu() { | |||
| 4240 | return; | 4251 | return; |
| 4241 | } | 4252 | } |
| 4242 | 4253 | ||
| 4243 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); | 4254 | system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Controller); |
| 4244 | 4255 | ||
| 4245 | const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); | 4256 | const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); |
| 4246 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); | 4257 | UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); |
| 4247 | BootGame(filename, ControllerAppletId); | 4258 | BootGame(filename, |
| 4259 | LibraryAppletParameters(ControllerAppletId, Service::AM::AppletId::Controller)); | ||
| 4248 | } | 4260 | } |
| 4249 | 4261 | ||
| 4250 | void GMainWindow::OnCaptureScreenshot() { | 4262 | void GMainWindow::OnCaptureScreenshot() { |
| @@ -4564,7 +4576,7 @@ void GMainWindow::OnCheckFirmwareDecryption() { | |||
| 4564 | } | 4576 | } |
| 4565 | 4577 | ||
| 4566 | bool GMainWindow::CheckFirmwarePresence() { | 4578 | bool GMainWindow::CheckFirmwarePresence() { |
| 4567 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); | 4579 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::AppletProgramId::MiiEdit); |
| 4568 | 4580 | ||
| 4569 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4581 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4570 | if (!bis_system) { | 4582 | if (!bis_system) { |
| @@ -4727,7 +4739,7 @@ bool GMainWindow::DropAction(QDropEvent* event) { | |||
| 4727 | } else { | 4739 | } else { |
| 4728 | // Game | 4740 | // Game |
| 4729 | if (ConfirmChangeGame()) { | 4741 | if (ConfirmChangeGame()) { |
| 4730 | BootGame(filename); | 4742 | BootGame(filename, ApplicationAppletParameters()); |
| 4731 | } | 4743 | } |
| 4732 | } | 4744 | } |
| 4733 | return true; | 4745 | return true; |
| @@ -4771,36 +4783,12 @@ void GMainWindow::RequestGameExit() { | |||
| 4771 | return; | 4783 | return; |
| 4772 | } | 4784 | } |
| 4773 | 4785 | ||
| 4774 | auto& sm{system->ServiceManager()}; | ||
| 4775 | auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); | ||
| 4776 | auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); | ||
| 4777 | bool has_signalled = false; | ||
| 4778 | |||
| 4779 | system->SetExitRequested(true); | 4786 | system->SetExitRequested(true); |
| 4780 | 4787 | system->GetAppletManager().RequestExit(); | |
| 4781 | if (applet_oe != nullptr) { | ||
| 4782 | applet_oe->GetMessageQueue()->RequestExit(); | ||
| 4783 | has_signalled = true; | ||
| 4784 | } | ||
| 4785 | |||
| 4786 | if (applet_ae != nullptr && !has_signalled) { | ||
| 4787 | applet_ae->GetMessageQueue()->RequestExit(); | ||
| 4788 | } | ||
| 4789 | } | 4788 | } |
| 4790 | 4789 | ||
| 4791 | void GMainWindow::RequestGameResume() { | 4790 | void GMainWindow::RequestGameResume() { |
| 4792 | auto& sm{system->ServiceManager()}; | 4791 | system->GetAppletManager().RequestResume(); |
| 4793 | auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); | ||
| 4794 | auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); | ||
| 4795 | |||
| 4796 | if (applet_oe != nullptr) { | ||
| 4797 | applet_oe->GetMessageQueue()->RequestResume(); | ||
| 4798 | return; | ||
| 4799 | } | ||
| 4800 | |||
| 4801 | if (applet_ae != nullptr) { | ||
| 4802 | applet_ae->GetMessageQueue()->RequestResume(); | ||
| 4803 | } | ||
| 4804 | } | 4792 | } |
| 4805 | 4793 | ||
| 4806 | void GMainWindow::filterBarSetChecked(bool state) { | 4794 | void GMainWindow::filterBarSetChecked(bool state) { |
| @@ -4942,6 +4930,22 @@ void GMainWindow::changeEvent(QEvent* event) { | |||
| 4942 | QWidget::changeEvent(event); | 4930 | QWidget::changeEvent(event); |
| 4943 | } | 4931 | } |
| 4944 | 4932 | ||
| 4933 | Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() { | ||
| 4934 | return Service::AM::FrontendAppletParameters{ | ||
| 4935 | .applet_id = Service::AM::AppletId::Application, | ||
| 4936 | .applet_type = Service::AM::AppletType::Application, | ||
| 4937 | }; | ||
| 4938 | } | ||
| 4939 | |||
| 4940 | Service::AM::FrontendAppletParameters GMainWindow::LibraryAppletParameters( | ||
| 4941 | u64 program_id, Service::AM::AppletId applet_id) { | ||
| 4942 | return Service::AM::FrontendAppletParameters{ | ||
| 4943 | .program_id = program_id, | ||
| 4944 | .applet_id = applet_id, | ||
| 4945 | .applet_type = Service::AM::AppletType::LibraryApplet, | ||
| 4946 | }; | ||
| 4947 | } | ||
| 4948 | |||
| 4945 | void VolumeButton::wheelEvent(QWheelEvent* event) { | 4949 | void VolumeButton::wheelEvent(QWheelEvent* event) { |
| 4946 | 4950 | ||
| 4947 | int num_degrees = event->angleDelta().y() / 8; | 4951 | int num_degrees = event->angleDelta().y() / 8; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 6b72094ff..aba61e388 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -64,11 +64,6 @@ enum class StartGameType { | |||
| 64 | Global, // Only uses global configuration | 64 | Global, // Only uses global configuration |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | enum class AmLaunchType { | ||
| 68 | UserInitiated, | ||
| 69 | ApplicationInitiated, | ||
| 70 | }; | ||
| 71 | |||
| 72 | namespace Core { | 67 | namespace Core { |
| 73 | enum class SystemResultStatus : u32; | 68 | enum class SystemResultStatus : u32; |
| 74 | class System; | 69 | class System; |
| @@ -101,12 +96,17 @@ namespace InputCommon { | |||
| 101 | class InputSubsystem; | 96 | class InputSubsystem; |
| 102 | } | 97 | } |
| 103 | 98 | ||
| 104 | namespace Service::AM::Applets { | 99 | namespace Service::AM { |
| 100 | struct FrontendAppletParameters; | ||
| 101 | enum class AppletId : u32; | ||
| 102 | } // namespace Service::AM | ||
| 103 | |||
| 104 | namespace Service::AM::Frontend { | ||
| 105 | enum class SwkbdResult : u32; | 105 | enum class SwkbdResult : u32; |
| 106 | enum class SwkbdTextCheckResult : u32; | 106 | enum class SwkbdTextCheckResult : u32; |
| 107 | enum class SwkbdReplyType : u32; | 107 | enum class SwkbdReplyType : u32; |
| 108 | enum class WebExitReason : u32; | 108 | enum class WebExitReason : u32; |
| 109 | } // namespace Service::AM::Applets | 109 | } // namespace Service::AM::Frontend |
| 110 | 110 | ||
| 111 | namespace Service::NFC { | 111 | namespace Service::NFC { |
| 112 | class NfcDevice; | 112 | class NfcDevice; |
| @@ -204,13 +204,13 @@ signals: | |||
| 204 | 204 | ||
| 205 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); | 205 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); |
| 206 | 206 | ||
| 207 | void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result, | 207 | void SoftwareKeyboardSubmitNormalText(Service::AM::Frontend::SwkbdResult result, |
| 208 | std::u16string submitted_text, bool confirmed); | 208 | std::u16string submitted_text, bool confirmed); |
| 209 | void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 209 | void SoftwareKeyboardSubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, |
| 210 | std::u16string submitted_text, s32 cursor_position); | 210 | std::u16string submitted_text, s32 cursor_position); |
| 211 | 211 | ||
| 212 | void WebBrowserExtractOfflineRomFS(); | 212 | void WebBrowserExtractOfflineRomFS(); |
| 213 | void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); | 213 | void WebBrowserClosed(Service::AM::Frontend::WebExitReason exit_reason, std::string last_url); |
| 214 | 214 | ||
| 215 | void SigInterrupt(); | 215 | void SigInterrupt(); |
| 216 | 216 | ||
| @@ -228,8 +228,9 @@ public slots: | |||
| 228 | void SoftwareKeyboardInitialize( | 228 | void SoftwareKeyboardInitialize( |
| 229 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters); | 229 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters); |
| 230 | void SoftwareKeyboardShowNormal(); | 230 | void SoftwareKeyboardShowNormal(); |
| 231 | void SoftwareKeyboardShowTextCheck(Service::AM::Applets::SwkbdTextCheckResult text_check_result, | 231 | void SoftwareKeyboardShowTextCheck( |
| 232 | std::u16string text_check_message); | 232 | Service::AM::Frontend::SwkbdTextCheckResult text_check_result, |
| 233 | std::u16string text_check_message); | ||
| 233 | void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters); | 234 | void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters); |
| 234 | void SoftwareKeyboardHideInline(); | 235 | void SoftwareKeyboardHideInline(); |
| 235 | void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); | 236 | void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); |
| @@ -267,11 +268,10 @@ private: | |||
| 267 | void PreventOSSleep(); | 268 | void PreventOSSleep(); |
| 268 | void AllowOSSleep(); | 269 | void AllowOSSleep(); |
| 269 | 270 | ||
| 270 | bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index, | 271 | bool LoadROM(const QString& filename, Service::AM::FrontendAppletParameters params); |
| 271 | AmLaunchType launch_type); | 272 | void BootGame(const QString& filename, Service::AM::FrontendAppletParameters params, |
| 272 | void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0, | 273 | StartGameType with_config = StartGameType::Normal); |
| 273 | StartGameType with_config = StartGameType::Normal, | 274 | void BootGameFromList(const QString& filename, StartGameType with_config); |
| 274 | AmLaunchType launch_type = AmLaunchType::UserInitiated); | ||
| 275 | void ShutdownGame(); | 275 | void ShutdownGame(); |
| 276 | 276 | ||
| 277 | void ShowTelemetryCallout(); | 277 | void ShowTelemetryCallout(); |
| @@ -324,6 +324,10 @@ private: | |||
| 324 | void SetGamemodeEnabled(bool state); | 324 | void SetGamemodeEnabled(bool state); |
| 325 | #endif | 325 | #endif |
| 326 | 326 | ||
| 327 | Service::AM::FrontendAppletParameters ApplicationAppletParameters(); | ||
| 328 | Service::AM::FrontendAppletParameters LibraryAppletParameters(u64 program_id, | ||
| 329 | Service::AM::AppletId applet_id); | ||
| 330 | |||
| 327 | private slots: | 331 | private slots: |
| 328 | void OnStartGame(); | 332 | void OnStartGame(); |
| 329 | void OnRestartGame(); | 333 | void OnRestartGame(); |
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index fbeba8813..ebd8fd738 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt | |||
| @@ -28,8 +28,6 @@ add_executable(yuzu-cmd | |||
| 28 | yuzu.rc | 28 | yuzu.rc |
| 29 | ) | 29 | ) |
| 30 | 30 | ||
| 31 | create_target_directory_groups(yuzu-cmd) | ||
| 32 | |||
| 33 | target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) | 31 | target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) |
| 34 | target_link_libraries(yuzu-cmd PRIVATE glad) | 32 | target_link_libraries(yuzu-cmd PRIVATE glad) |
| 35 | if (MSVC) | 33 | if (MSVC) |
| @@ -63,3 +61,5 @@ endif() | |||
| 63 | if (YUZU_USE_PRECOMPILED_HEADERS) | 61 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 64 | target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h) | 62 | target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h) |
| 65 | endif() | 63 | endif() |
| 64 | |||
| 65 | create_target_directory_groups(yuzu-cmd) | ||
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index c39ace2ec..3b321dad1 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "core/crypto/key_manager.h" | 26 | #include "core/crypto/key_manager.h" |
| 27 | #include "core/file_sys/registered_cache.h" | 27 | #include "core/file_sys/registered_cache.h" |
| 28 | #include "core/file_sys/vfs/vfs_real.h" | 28 | #include "core/file_sys/vfs/vfs_real.h" |
| 29 | #include "core/hle/service/am/applet_manager.h" | ||
| 29 | #include "core/hle/service/filesystem/filesystem.h" | 30 | #include "core/hle/service/filesystem/filesystem.h" |
| 30 | #include "core/loader/loader.h" | 31 | #include "core/loader/loader.h" |
| 31 | #include "core/telemetry_session.h" | 32 | #include "core/telemetry_session.h" |
| @@ -366,7 +367,10 @@ int main(int argc, char** argv) { | |||
| 366 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); | 367 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); |
| 367 | system.GetUserChannel().clear(); | 368 | system.GetUserChannel().clear(); |
| 368 | 369 | ||
| 369 | const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath)}; | 370 | Service::AM::FrontendAppletParameters load_parameters{ |
| 371 | .applet_id = Service::AM::AppletId::Application, | ||
| 372 | }; | ||
| 373 | const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath, load_parameters)}; | ||
| 370 | 374 | ||
| 371 | switch (load_result) { | 375 | switch (load_result) { |
| 372 | case Core::SystemResultStatus::ErrorGetLoader: | 376 | case Core::SystemResultStatus::ErrorGetLoader: |