diff options
403 files changed, 7575 insertions, 4647 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index 1af5ded3d..9b451d3ab 100755 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh | |||
| @@ -30,10 +30,10 @@ make install DESTDIR=AppDir | |||
| 30 | rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester | 30 | rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester |
| 31 | 31 | ||
| 32 | # Download tools needed to build an AppImage | 32 | # Download tools needed to build an AppImage |
| 33 | wget -nc https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage | 33 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage |
| 34 | wget -nc https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage | 34 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage |
| 35 | wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 | 35 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64 |
| 36 | wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so | 36 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so |
| 37 | # Set executable bit | 37 | # Set executable bit |
| 38 | chmod 755 \ | 38 | chmod 755 \ |
| 39 | AppRun-patched-x86_64 \ | 39 | AppRun-patched-x86_64 \ |
diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh index b2ea07388..208cd0d04 100644 --- a/.ci/scripts/linux/upload.sh +++ b/.ci/scripts/linux/upload.sh | |||
| @@ -21,7 +21,7 @@ cp build/bin/yuzu "$DIR_NAME" | |||
| 21 | # Build an AppImage | 21 | # Build an AppImage |
| 22 | cd build | 22 | cd build |
| 23 | 23 | ||
| 24 | wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage | 24 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/appimagetool-x86_64.AppImage |
| 25 | chmod 755 appimagetool-x86_64.AppImage | 25 | chmod 755 appimagetool-x86_64.AppImage |
| 26 | 26 | ||
| 27 | if [ "${RELEASE_NAME}" = "mainline" ]; then | 27 | if [ "${RELEASE_NAME}" = "mainline" ]; then |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 15ecb8a9c..3faa2b5ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -12,6 +12,8 @@ project(yuzu) | |||
| 12 | # OFF by default, but if ENABLE_SDL2 and MSVC are true then ON | 12 | # OFF by default, but if ENABLE_SDL2 and MSVC are true then ON |
| 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) | 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) |
| 14 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) | 14 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) |
| 15 | # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion | ||
| 16 | CMAKE_DEPENDENT_OPTION(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" NOT UNIX "ENABLE_SDL2" OFF) | ||
| 15 | 17 | ||
| 16 | option(ENABLE_QT "Enable the Qt frontend" ON) | 18 | option(ENABLE_QT "Enable the Qt frontend" ON) |
| 17 | option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) | 19 | option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) |
| @@ -202,7 +204,7 @@ macro(yuzu_find_packages) | |||
| 202 | endmacro() | 204 | endmacro() |
| 203 | 205 | ||
| 204 | if (NOT YUZU_USE_BUNDLED_BOOST) | 206 | if (NOT YUZU_USE_BUNDLED_BOOST) |
| 205 | find_package(Boost 1.73.0 COMPONENTS context headers QUIET) | 207 | find_package(Boost 1.73.0 CONFIG COMPONENTS context headers QUIET) |
| 206 | endif() | 208 | endif() |
| 207 | if (Boost_FOUND) | 209 | if (Boost_FOUND) |
| 208 | set(Boost_LIBRARIES Boost::boost) | 210 | set(Boost_LIBRARIES Boost::boost) |
| @@ -224,7 +226,7 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST) | |||
| 224 | download_bundled_external("boost/" ${Boost_EXT_NAME} "") | 226 | download_bundled_external("boost/" ${Boost_EXT_NAME} "") |
| 225 | set(Boost_USE_DEBUG_RUNTIME FALSE) | 227 | set(Boost_USE_DEBUG_RUNTIME FALSE) |
| 226 | set(Boost_USE_STATIC_LIBS ON) | 228 | set(Boost_USE_STATIC_LIBS ON) |
| 227 | find_package(Boost 1.75.0 REQUIRED COMPONENTS context headers PATHS ${Boost_PATH} NO_DEFAULT_PATH) | 229 | find_package(Boost 1.75.0 CONFIG REQUIRED COMPONENTS context headers PATHS ${Boost_PATH} NO_DEFAULT_PATH) |
| 228 | # Manually set the include dirs since the find_package sets it incorrectly | 230 | # Manually set the include dirs since the find_package sets it incorrectly |
| 229 | set(Boost_INCLUDE_DIRS ${Boost_PATH}/include CACHE PATH "Path to Boost headers" FORCE) | 231 | set(Boost_INCLUDE_DIRS ${Boost_PATH}/include CACHE PATH "Path to Boost headers" FORCE) |
| 230 | include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") | 232 | include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") |
| @@ -274,7 +276,7 @@ if (ENABLE_SDL2) | |||
| 274 | if (YUZU_USE_BUNDLED_SDL2) | 276 | if (YUZU_USE_BUNDLED_SDL2) |
| 275 | # Detect toolchain and platform | 277 | # Detect toolchain and platform |
| 276 | if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) | 278 | if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) |
| 277 | set(SDL2_VER "SDL2-2.0.14") | 279 | set(SDL2_VER "SDL2-2.0.15-prerelease") |
| 278 | else() | 280 | else() |
| 279 | message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.") | 281 | message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.") |
| 280 | endif() | 282 | endif() |
| @@ -292,20 +294,24 @@ if (ENABLE_SDL2) | |||
| 292 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") | 294 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") |
| 293 | target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") | 295 | target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") |
| 294 | else() | 296 | else() |
| 295 | find_package(SDL2 2.0.14 QUIET) | 297 | if (YUZU_ALLOW_SYSTEM_SDL2) |
| 296 | 298 | find_package(SDL2 2.0.15 QUIET) | |
| 297 | if (SDL2_FOUND) | 299 | |
| 298 | # Some installations don't set SDL2_LIBRARIES | 300 | if (SDL2_FOUND) |
| 299 | if("${SDL2_LIBRARIES}" STREQUAL "") | 301 | # Some installations don't set SDL2_LIBRARIES |
| 300 | message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2") | 302 | if("${SDL2_LIBRARIES}" STREQUAL "") |
| 301 | set(SDL2_LIBRARIES "SDL2::SDL2") | 303 | message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2") |
| 304 | set(SDL2_LIBRARIES "SDL2::SDL2") | ||
| 305 | endif() | ||
| 306 | |||
| 307 | include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) | ||
| 308 | add_library(SDL2 INTERFACE) | ||
| 309 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") | ||
| 310 | else() | ||
| 311 | message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.") | ||
| 302 | endif() | 312 | endif() |
| 303 | |||
| 304 | include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) | ||
| 305 | add_library(SDL2 INTERFACE) | ||
| 306 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") | ||
| 307 | else() | 313 | else() |
| 308 | message(STATUS "SDL2 2.0.14 or newer not found, falling back to externals.") | 314 | message(STATUS "Using SDL2 from externals.") |
| 309 | endif() | 315 | endif() |
| 310 | endif() | 316 | endif() |
| 311 | endif() | 317 | endif() |
diff --git a/dist/icons/overlay/osk_button_B.png b/dist/icons/overlay/osk_button_B.png index f4a041178..2664b5923 100644 --- a/dist/icons/overlay/osk_button_B.png +++ b/dist/icons/overlay/osk_button_B.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_B_dark.png b/dist/icons/overlay/osk_button_B_dark.png index 2d2bffcca..1bd374571 100644 --- a/dist/icons/overlay/osk_button_B_dark.png +++ b/dist/icons/overlay/osk_button_B_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_B_dark_disabled.png b/dist/icons/overlay/osk_button_B_dark_disabled.png index 93c102b1b..3b88e393c 100644 --- a/dist/icons/overlay/osk_button_B_dark_disabled.png +++ b/dist/icons/overlay/osk_button_B_dark_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_B_disabled.png b/dist/icons/overlay/osk_button_B_disabled.png index 5900982f6..0f35cd8f2 100644 --- a/dist/icons/overlay/osk_button_B_disabled.png +++ b/dist/icons/overlay/osk_button_B_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_Y.png b/dist/icons/overlay/osk_button_Y.png index b08b4e26b..2cd193481 100644 --- a/dist/icons/overlay/osk_button_Y.png +++ b/dist/icons/overlay/osk_button_Y.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_Y_dark.png b/dist/icons/overlay/osk_button_Y_dark.png index 1fba9ca93..0cce567d3 100644 --- a/dist/icons/overlay/osk_button_Y_dark.png +++ b/dist/icons/overlay/osk_button_Y_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_Y_dark_disabled.png b/dist/icons/overlay/osk_button_Y_dark_disabled.png index 6ce53f9e4..de619efa3 100644 --- a/dist/icons/overlay/osk_button_Y_dark_disabled.png +++ b/dist/icons/overlay/osk_button_Y_dark_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_Y_disabled.png b/dist/icons/overlay/osk_button_Y_disabled.png index 25db07f66..8d607bc12 100644 --- a/dist/icons/overlay/osk_button_Y_disabled.png +++ b/dist/icons/overlay/osk_button_Y_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_plus.png b/dist/icons/overlay/osk_button_plus.png index 5baa5201e..9f9787419 100644 --- a/dist/icons/overlay/osk_button_plus.png +++ b/dist/icons/overlay/osk_button_plus.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_plus_dark.png b/dist/icons/overlay/osk_button_plus_dark.png index 4cadb438b..dbe7b0c66 100644 --- a/dist/icons/overlay/osk_button_plus_dark.png +++ b/dist/icons/overlay/osk_button_plus_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_plus_dark_disabled.png b/dist/icons/overlay/osk_button_plus_dark_disabled.png index b8eb8dc3d..a79af6501 100644 --- a/dist/icons/overlay/osk_button_plus_dark_disabled.png +++ b/dist/icons/overlay/osk_button_plus_dark_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_plus_disabled.png b/dist/icons/overlay/osk_button_plus_disabled.png index c23e9d95d..52ace8eca 100644 --- a/dist/icons/overlay/osk_button_plus_disabled.png +++ b/dist/icons/overlay/osk_button_plus_disabled.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_shift_lock_off.png b/dist/icons/overlay/osk_button_shift_lock_off.png index 585500b3a..b506f456f 100644 --- a/dist/icons/overlay/osk_button_shift_lock_off.png +++ b/dist/icons/overlay/osk_button_shift_lock_off.png | |||
| Binary files differ | |||
diff --git a/dist/icons/overlay/osk_button_shift_lock_on.png b/dist/icons/overlay/osk_button_shift_lock_on.png index 09077ab01..eaa4e98ed 100644 --- a/dist/icons/overlay/osk_button_shift_lock_on.png +++ b/dist/icons/overlay/osk_button_shift_lock_on.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 3bc92b69d..cee219374 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss | |||
| @@ -515,45 +515,35 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { | |||
| 515 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, | 515 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, |
| 516 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, | 516 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, |
| 517 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { | 517 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { |
| 518 | background-position: right top; | 518 | image: url(:/overlay/osk_button_B.png); |
| 519 | background-repeat: no-repeat; | 519 | image-position: right; |
| 520 | background-origin: content; | ||
| 521 | background-image: url(:/overlay/osk_button_B.png); | ||
| 522 | qproperty-icon: url(:/overlay/osk_button_backspace.png); | 520 | qproperty-icon: url(:/overlay/osk_button_backspace.png); |
| 523 | qproperty-iconSize: 36px; | 521 | qproperty-iconSize: 36px; |
| 524 | } | 522 | } |
| 525 | 523 | ||
| 526 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, | 524 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, |
| 527 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { | 525 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { |
| 528 | background-position: right top; | 526 | image: url(:/overlay/osk_button_Y.png); |
| 529 | background-repeat: no-repeat; | 527 | image-position: right; |
| 530 | background-origin: content; | ||
| 531 | background-image: url(:/overlay/osk_button_Y.png); | ||
| 532 | } | 528 | } |
| 533 | 529 | ||
| 534 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, | 530 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, |
| 535 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, | 531 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, |
| 536 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { | 532 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { |
| 537 | background-position: right top; | 533 | image: url(:/overlay/osk_button_plus.png); |
| 538 | background-repeat: no-repeat; | 534 | image-position: right; |
| 539 | background-origin: content; | ||
| 540 | background-image: url(:/overlay/osk_button_plus.png); | ||
| 541 | } | 535 | } |
| 542 | 536 | ||
| 543 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { | 537 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { |
| 544 | background-position: left top; | 538 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 545 | background-repeat: no-repeat; | 539 | image-position: left; |
| 546 | background-origin: content; | ||
| 547 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 548 | qproperty-icon: url(:/overlay/osk_button_shift.png); | 540 | qproperty-icon: url(:/overlay/osk_button_shift.png); |
| 549 | qproperty-iconSize: 36px; | 541 | qproperty-iconSize: 36px; |
| 550 | } | 542 | } |
| 551 | 543 | ||
| 552 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { | 544 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { |
| 553 | background-position: left top; | 545 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 554 | background-repeat: no-repeat; | 546 | image-position: left; |
| 555 | background-origin: content; | ||
| 556 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 557 | qproperty-icon: url(:/overlay/osk_button_shift_on.png); | 547 | qproperty-icon: url(:/overlay/osk_button_shift_on.png); |
| 558 | qproperty-iconSize: 36px; | 548 | qproperty-iconSize: 36px; |
| 559 | } | 549 | } |
| @@ -645,16 +635,16 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { | |||
| 645 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, | 635 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, |
| 646 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, | 636 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, |
| 647 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { | 637 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { |
| 648 | background-image: url(:/overlay/osk_button_plus_disabled.png); | 638 | image: url(:/overlay/osk_button_plus_disabled.png); |
| 649 | } | 639 | } |
| 650 | 640 | ||
| 651 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, | 641 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, |
| 652 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, | 642 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, |
| 653 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { | 643 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { |
| 654 | background-image: url(:/overlay/osk_button_B_disabled.png); | 644 | image: url(:/overlay/osk_button_B_disabled.png); |
| 655 | } | 645 | } |
| 656 | 646 | ||
| 657 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, | 647 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, |
| 658 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { | 648 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { |
| 659 | background-image: url(:/overlay/osk_button_Y_disabled.png); | 649 | image: url(:/overlay/osk_button_Y_disabled.png); |
| 660 | } | 650 | } |
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 8ce6d75f7..3d0ccbb9e 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss | |||
| @@ -1805,46 +1805,36 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { | |||
| 1805 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, | 1805 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, |
| 1806 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, | 1806 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, |
| 1807 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { | 1807 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { |
| 1808 | background-position: right top; | 1808 | image: url(:/overlay/osk_button_B_dark.png); |
| 1809 | background-repeat: no-repeat; | 1809 | image-position: right; |
| 1810 | background-origin: content; | ||
| 1811 | background-image: url(:/overlay/osk_button_B_dark.png); | ||
| 1812 | qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); | 1810 | qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); |
| 1813 | qproperty-iconSize: 36px; | 1811 | qproperty-iconSize: 36px; |
| 1814 | } | 1812 | } |
| 1815 | 1813 | ||
| 1816 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, | 1814 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, |
| 1817 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { | 1815 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { |
| 1818 | background-position: right top; | 1816 | image: url(:/overlay/osk_button_Y_dark.png); |
| 1819 | background-repeat: no-repeat; | 1817 | image-position: right; |
| 1820 | background-origin: content; | ||
| 1821 | background-image: url(:/overlay/osk_button_Y_dark.png); | ||
| 1822 | } | 1818 | } |
| 1823 | 1819 | ||
| 1824 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, | 1820 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, |
| 1825 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, | 1821 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, |
| 1826 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { | 1822 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { |
| 1827 | color: rgba(44, 44, 44, 1); | 1823 | color: rgba(44, 44, 44, 1); |
| 1828 | background-position: right top; | 1824 | image: url(:/overlay/osk_button_plus_dark.png); |
| 1829 | background-repeat: no-repeat; | 1825 | image-position: right; |
| 1830 | background-origin: content; | ||
| 1831 | background-image: url(:/overlay/osk_button_plus_dark.png); | ||
| 1832 | } | 1826 | } |
| 1833 | 1827 | ||
| 1834 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { | 1828 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { |
| 1835 | background-position: left top; | 1829 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 1836 | background-repeat: no-repeat; | 1830 | image-position: left; |
| 1837 | background-origin: content; | ||
| 1838 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 1839 | qproperty-icon: url(:/overlay/osk_button_shift_dark.png); | 1831 | qproperty-icon: url(:/overlay/osk_button_shift_dark.png); |
| 1840 | qproperty-iconSize: 36px; | 1832 | qproperty-iconSize: 36px; |
| 1841 | } | 1833 | } |
| 1842 | 1834 | ||
| 1843 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { | 1835 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { |
| 1844 | background-position: left top; | 1836 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 1845 | background-repeat: no-repeat; | 1837 | image-position: left; |
| 1846 | background-origin: content; | ||
| 1847 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 1848 | qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); | 1838 | qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); |
| 1849 | qproperty-iconSize: 36px; | 1839 | qproperty-iconSize: 36px; |
| 1850 | } | 1840 | } |
| @@ -1936,18 +1926,18 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { | |||
| 1936 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, | 1926 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, |
| 1937 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, | 1927 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, |
| 1938 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { | 1928 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { |
| 1939 | background-image: url(:/overlay/osk_button_plus_dark_disabled.png); | 1929 | image: url(:/overlay/osk_button_plus_dark_disabled.png); |
| 1940 | } | 1930 | } |
| 1941 | 1931 | ||
| 1942 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, | 1932 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, |
| 1943 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, | 1933 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, |
| 1944 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { | 1934 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { |
| 1945 | background-image: url(:/overlay/osk_button_B_dark_disabled.png); | 1935 | image: url(:/overlay/osk_button_B_dark_disabled.png); |
| 1946 | } | 1936 | } |
| 1947 | 1937 | ||
| 1948 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, | 1938 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, |
| 1949 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { | 1939 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { |
| 1950 | background-image: url(:/overlay/osk_button_Y_dark_disabled.png); | 1940 | image: url(:/overlay/osk_button_Y_dark_disabled.png); |
| 1951 | } | 1941 | } |
| 1952 | 1942 | ||
| 1953 | QDialog#QtSoftwareKeyboardDialog QFrame, | 1943 | QDialog#QtSoftwareKeyboardDialog QFrame, |
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 64e1ecbcc..51bec2fd7 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss | |||
| @@ -2740,46 +2740,36 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { | |||
| 2740 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, | 2740 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, |
| 2741 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, | 2741 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, |
| 2742 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { | 2742 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { |
| 2743 | background-position: right top; | 2743 | image: url(:/overlay/osk_button_B_dark.png); |
| 2744 | background-repeat: no-repeat; | 2744 | image-position: right; |
| 2745 | background-origin: content; | ||
| 2746 | background-image: url(:/overlay/osk_button_B_dark.png); | ||
| 2747 | qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); | 2745 | qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); |
| 2748 | qproperty-iconSize: 36px; | 2746 | qproperty-iconSize: 36px; |
| 2749 | } | 2747 | } |
| 2750 | 2748 | ||
| 2751 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, | 2749 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, |
| 2752 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { | 2750 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { |
| 2753 | background-position: right top; | 2751 | image: url(:/overlay/osk_button_Y_dark.png); |
| 2754 | background-repeat: no-repeat; | 2752 | image-position: right; |
| 2755 | background-origin: content; | ||
| 2756 | background-image: url(:/overlay/osk_button_Y_dark.png); | ||
| 2757 | } | 2753 | } |
| 2758 | 2754 | ||
| 2759 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, | 2755 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, |
| 2760 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, | 2756 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, |
| 2761 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { | 2757 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { |
| 2762 | color: rgba(44, 44, 44, 1); | 2758 | color: rgba(44, 44, 44, 1); |
| 2763 | background-position: right top; | 2759 | image: url(:/overlay/osk_button_plus_dark.png); |
| 2764 | background-repeat: no-repeat; | 2760 | image-position: right; |
| 2765 | background-origin: content; | ||
| 2766 | background-image: url(:/overlay/osk_button_plus_dark.png); | ||
| 2767 | } | 2761 | } |
| 2768 | 2762 | ||
| 2769 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { | 2763 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { |
| 2770 | background-position: left top; | 2764 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 2771 | background-repeat: no-repeat; | 2765 | image-position: left; |
| 2772 | background-origin: content; | ||
| 2773 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 2774 | qproperty-icon: url(:/overlay/osk_button_shift_dark.png); | 2766 | qproperty-icon: url(:/overlay/osk_button_shift_dark.png); |
| 2775 | qproperty-iconSize: 36px; | 2767 | qproperty-iconSize: 36px; |
| 2776 | } | 2768 | } |
| 2777 | 2769 | ||
| 2778 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { | 2770 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { |
| 2779 | background-position: left top; | 2771 | image: url(:/overlay/osk_button_shift_lock_off.png); |
| 2780 | background-repeat: no-repeat; | 2772 | image-position: left; |
| 2781 | background-origin: content; | ||
| 2782 | background-image: url(:/overlay/osk_button_shift_lock_off.png); | ||
| 2783 | qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); | 2773 | qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); |
| 2784 | qproperty-iconSize: 36px; | 2774 | qproperty-iconSize: 36px; |
| 2785 | } | 2775 | } |
| @@ -2871,16 +2861,16 @@ QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { | |||
| 2871 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, | 2861 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, |
| 2872 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, | 2862 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, |
| 2873 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { | 2863 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { |
| 2874 | background-image: url(:/overlay/osk_button_plus_dark_disabled.png); | 2864 | image: url(:/overlay/osk_button_plus_dark_disabled.png); |
| 2875 | } | 2865 | } |
| 2876 | 2866 | ||
| 2877 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, | 2867 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, |
| 2878 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, | 2868 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, |
| 2879 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { | 2869 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { |
| 2880 | background-image: url(:/overlay/osk_button_B_dark_disabled.png); | 2870 | image: url(:/overlay/osk_button_B_dark_disabled.png); |
| 2881 | } | 2871 | } |
| 2882 | 2872 | ||
| 2883 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, | 2873 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, |
| 2884 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { | 2874 | QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { |
| 2885 | background-image: url(:/overlay/osk_button_Y_dark_disabled.png); | 2875 | image: url(:/overlay/osk_button_Y_dark_disabled.png); |
| 2886 | } | 2876 | } |
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index e044d9730..fe1c088ca 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt | |||
| @@ -47,7 +47,22 @@ target_include_directories(unicorn-headers INTERFACE ./unicorn/include) | |||
| 47 | 47 | ||
| 48 | # SDL2 | 48 | # SDL2 |
| 49 | if (NOT SDL2_FOUND AND ENABLE_SDL2) | 49 | if (NOT SDL2_FOUND AND ENABLE_SDL2) |
| 50 | # Yuzu itself needs: Events Joystick Haptic Sensor Timers | ||
| 51 | # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) | ||
| 52 | set(SDL_UNUSED_SUBSYSTEMS | ||
| 53 | Atomic Audio Render Power Threads | ||
| 54 | File CPUinfo Filesystem Locale) | ||
| 55 | foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) | ||
| 56 | string(TOUPPER ${_SUB} _OPT) | ||
| 57 | option(SDL_${_OPT} "" OFF) | ||
| 58 | endforeach() | ||
| 59 | |||
| 60 | set(SDL_STATIC ON) | ||
| 61 | set(SDL_SHARED OFF) | ||
| 62 | option(HIDAPI "" ON) | ||
| 63 | |||
| 50 | add_subdirectory(SDL EXCLUDE_FROM_ALL) | 64 | add_subdirectory(SDL EXCLUDE_FROM_ALL) |
| 65 | add_library(SDL2 ALIAS SDL2-static) | ||
| 51 | endif() | 66 | endif() |
| 52 | 67 | ||
| 53 | # SoundTouch | 68 | # SoundTouch |
diff --git a/externals/SDL b/externals/SDL | |||
| Subproject 4cd981609b50ed273d80c635c1ca4c1e5518fb2 | Subproject 107db2d89953ee7cc03417d43da1f26bd03aad5 | ||
diff --git a/externals/ffmpeg b/externals/ffmpeg | |||
| Subproject 6b6b9e593dd4d3aaf75f48d40a13ef03bdef9fd | Subproject 79e8d17024e6c6328a40fcee191ffd70798a9c6 | ||
diff --git a/externals/mbedtls b/externals/mbedtls | |||
| Subproject eac2416b8fdb2cb9c867a538100bf95326bad75 | Subproject 8c88150ca139e06aa2aae8349df8292a88148ea | ||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8bd7e5f72..f30dd49a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -54,6 +54,7 @@ if (MSVC) | |||
| 54 | /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect | 54 | /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect |
| 55 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? | 55 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? |
| 56 | /we4555 # Expression has no effect; expected expression with side-effect | 56 | /we4555 # Expression has no effect; expected expression with side-effect |
| 57 | /we4715 # 'function': not all control paths return a value | ||
| 57 | /we4834 # Discarding return value of function with 'nodiscard' attribute | 58 | /we4834 # Discarding return value of function with 'nodiscard' attribute |
| 58 | /we5038 # data member 'member1' will be initialized after data member 'member2' | 59 | /we5038 # data member 'member1' will be initialized after data member 'member2' |
| 59 | ) | 60 | ) |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 4ace2cd33..17d1ee86b 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -108,6 +108,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
| 108 | } \ | 108 | } \ |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | #define YUZU_NON_COPYABLE(cls) \ | ||
| 112 | cls(const cls&) = delete; \ | ||
| 113 | cls& operator=(const cls&) = delete | ||
| 114 | |||
| 115 | #define YUZU_NON_MOVEABLE(cls) \ | ||
| 116 | cls(cls&&) = delete; \ | ||
| 117 | cls& operator=(cls&&) = delete | ||
| 118 | |||
| 111 | #define R_SUCCEEDED(res) (res.IsSuccess()) | 119 | #define R_SUCCEEDED(res) (res.IsSuccess()) |
| 112 | 120 | ||
| 113 | /// Evaluates an expression that returns a result, and returns the result if it would fail. | 121 | /// Evaluates an expression that returns a result, and returns the result if it would fail. |
| @@ -128,4 +136,19 @@ namespace Common { | |||
| 128 | return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; | 136 | return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24; |
| 129 | } | 137 | } |
| 130 | 138 | ||
| 139 | // std::size() does not support zero-size C arrays. We're fixing that. | ||
| 140 | template <class C> | ||
| 141 | constexpr auto Size(const C& c) -> decltype(c.size()) { | ||
| 142 | return std::size(c); | ||
| 143 | } | ||
| 144 | |||
| 145 | template <class C> | ||
| 146 | constexpr std::size_t Size(const C& c) { | ||
| 147 | if constexpr (sizeof(C) == 0) { | ||
| 148 | return 0; | ||
| 149 | } else { | ||
| 150 | return std::size(c); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 131 | } // namespace Common | 154 | } // namespace Common |
diff --git a/src/common/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h index c0bbcd457..1f696fe80 100644 --- a/src/common/intrusive_red_black_tree.h +++ b/src/common/intrusive_red_black_tree.h | |||
| @@ -509,7 +509,6 @@ private: | |||
| 509 | 509 | ||
| 510 | private: | 510 | private: |
| 511 | static constexpr TypedStorage<Derived> DerivedStorage = {}; | 511 | static constexpr TypedStorage<Derived> DerivedStorage = {}; |
| 512 | static_assert(GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage)); | ||
| 513 | }; | 512 | }; |
| 514 | 513 | ||
| 515 | template <auto T, class Derived = impl::GetParentType<T>> | 514 | template <auto T, class Derived = impl::GetParentType<T>> |
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h index d9a14529d..58c70b0e7 100644 --- a/src/common/parent_of_member.h +++ b/src/common/parent_of_member.h | |||
| @@ -109,7 +109,8 @@ struct OffsetOfCalculator { | |||
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | return (next - start) * sizeof(MemberType) + Offset; | 112 | return static_cast<ptrdiff_t>(static_cast<size_t>(next - start) * sizeof(MemberType) + |
| 113 | Offset); | ||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { | 116 | static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { |
| @@ -133,27 +134,27 @@ template <auto MemberPtr> | |||
| 133 | using GetMemberType = typename GetMemberPointerTraits<decltype(MemberPtr)>::Member; | 134 | using GetMemberType = typename GetMemberPointerTraits<decltype(MemberPtr)>::Member; |
| 134 | 135 | ||
| 135 | template <auto MemberPtr, typename RealParentType = GetParentType<MemberPtr>> | 136 | template <auto MemberPtr, typename RealParentType = GetParentType<MemberPtr>> |
| 136 | static inline std::ptrdiff_t OffsetOf = [] { | 137 | constexpr std::ptrdiff_t OffsetOf() { |
| 137 | using DeducedParentType = GetParentType<MemberPtr>; | 138 | using DeducedParentType = GetParentType<MemberPtr>; |
| 138 | using MemberType = GetMemberType<MemberPtr>; | 139 | using MemberType = GetMemberType<MemberPtr>; |
| 139 | static_assert(std::is_base_of<DeducedParentType, RealParentType>::value || | 140 | static_assert(std::is_base_of<DeducedParentType, RealParentType>::value || |
| 140 | std::is_same<RealParentType, DeducedParentType>::value); | 141 | std::is_same<RealParentType, DeducedParentType>::value); |
| 141 | 142 | ||
| 142 | return OffsetOfCalculator<RealParentType, MemberType>::OffsetOf(MemberPtr); | 143 | return OffsetOfCalculator<RealParentType, MemberType>::OffsetOf(MemberPtr); |
| 143 | }(); | 144 | }; |
| 144 | 145 | ||
| 145 | } // namespace impl | 146 | } // namespace impl |
| 146 | 147 | ||
| 147 | template <auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>> | 148 | template <auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>> |
| 148 | constexpr RealParentType& GetParentReference(impl::GetMemberType<MemberPtr>* member) { | 149 | constexpr RealParentType& GetParentReference(impl::GetMemberType<MemberPtr>* member) { |
| 149 | std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>; | 150 | std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>(); |
| 150 | return *static_cast<RealParentType*>( | 151 | return *static_cast<RealParentType*>( |
| 151 | static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(member)) - Offset)); | 152 | static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(member)) - Offset)); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | template <auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>> | 155 | template <auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>> |
| 155 | constexpr RealParentType const& GetParentReference(impl::GetMemberType<MemberPtr> const* member) { | 156 | constexpr RealParentType const& GetParentReference(impl::GetMemberType<MemberPtr> const* member) { |
| 156 | std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>; | 157 | std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>(); |
| 157 | return *static_cast<const RealParentType*>(static_cast<const void*>( | 158 | return *static_cast<const RealParentType*>(static_cast<const void*>( |
| 158 | static_cast<const uint8_t*>(static_cast<const void*>(member)) - Offset)); | 159 | static_cast<const uint8_t*>(static_cast<const void*>(member)) - Offset)); |
| 159 | } | 160 | } |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 702b6598d..e29cbf506 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -42,7 +42,7 @@ void LogSettings() { | |||
| 42 | log_setting("System_RegionIndex", values.region_index.GetValue()); | 42 | log_setting("System_RegionIndex", values.region_index.GetValue()); |
| 43 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); | 43 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); |
| 44 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); | 44 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); |
| 45 | log_setting("CPU_Accuracy", values.cpu_accuracy); | 45 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); |
| 46 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); | 46 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); |
| 47 | log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); | 47 | log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); |
| 48 | log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); | 48 | log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); |
| @@ -106,6 +106,12 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 106 | // Core | 106 | // Core |
| 107 | values.use_multi_core.SetGlobal(true); | 107 | values.use_multi_core.SetGlobal(true); |
| 108 | 108 | ||
| 109 | // CPU | ||
| 110 | values.cpu_accuracy.SetGlobal(true); | ||
| 111 | values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); | ||
| 112 | values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); | ||
| 113 | values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); | ||
| 114 | |||
| 109 | // Renderer | 115 | // Renderer |
| 110 | values.renderer_backend.SetGlobal(true); | 116 | values.renderer_backend.SetGlobal(true); |
| 111 | values.vulkan_device.SetGlobal(true); | 117 | values.vulkan_device.SetGlobal(true); |
| @@ -130,7 +136,6 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 130 | values.region_index.SetGlobal(true); | 136 | values.region_index.SetGlobal(true); |
| 131 | values.time_zone_index.SetGlobal(true); | 137 | values.time_zone_index.SetGlobal(true); |
| 132 | values.rng_seed.SetGlobal(true); | 138 | values.rng_seed.SetGlobal(true); |
| 133 | values.custom_rtc.SetGlobal(true); | ||
| 134 | values.sound_index.SetGlobal(true); | 139 | values.sound_index.SetGlobal(true); |
| 135 | 140 | ||
| 136 | // Controls | 141 | // Controls |
diff --git a/src/common/settings.h b/src/common/settings.h index d39b4aa45..48085b9a9 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -115,7 +115,7 @@ struct Values { | |||
| 115 | Setting<bool> use_multi_core; | 115 | Setting<bool> use_multi_core; |
| 116 | 116 | ||
| 117 | // Cpu | 117 | // Cpu |
| 118 | CPUAccuracy cpu_accuracy; | 118 | Setting<CPUAccuracy> cpu_accuracy; |
| 119 | 119 | ||
| 120 | bool cpuopt_page_tables; | 120 | bool cpuopt_page_tables; |
| 121 | bool cpuopt_block_linking; | 121 | bool cpuopt_block_linking; |
| @@ -126,9 +126,9 @@ struct Values { | |||
| 126 | bool cpuopt_misc_ir; | 126 | bool cpuopt_misc_ir; |
| 127 | bool cpuopt_reduce_misalign_checks; | 127 | bool cpuopt_reduce_misalign_checks; |
| 128 | 128 | ||
| 129 | bool cpuopt_unsafe_unfuse_fma; | 129 | Setting<bool> cpuopt_unsafe_unfuse_fma; |
| 130 | bool cpuopt_unsafe_reduce_fp_error; | 130 | Setting<bool> cpuopt_unsafe_reduce_fp_error; |
| 131 | bool cpuopt_unsafe_inaccurate_nan; | 131 | Setting<bool> cpuopt_unsafe_inaccurate_nan; |
| 132 | 132 | ||
| 133 | // Renderer | 133 | // Renderer |
| 134 | Setting<RendererBackend> renderer_backend; | 134 | Setting<RendererBackend> renderer_backend; |
| @@ -157,7 +157,7 @@ struct Values { | |||
| 157 | // System | 157 | // System |
| 158 | Setting<std::optional<u32>> rng_seed; | 158 | Setting<std::optional<u32>> rng_seed; |
| 159 | // Measured in seconds since epoch | 159 | // Measured in seconds since epoch |
| 160 | Setting<std::optional<std::chrono::seconds>> custom_rtc; | 160 | std::optional<std::chrono::seconds> custom_rtc; |
| 161 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` | 161 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` |
| 162 | std::chrono::seconds custom_rtc_differential; | 162 | std::chrono::seconds custom_rtc_differential; |
| 163 | 163 | ||
diff --git a/src/common/tree.h b/src/common/tree.h index 3da49e422..9d2d0df4e 100644 --- a/src/common/tree.h +++ b/src/common/tree.h | |||
| @@ -322,7 +322,7 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | |||
| 322 | template <typename Node> | 322 | template <typename Node> |
| 323 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { | 323 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
| 324 | Node* tmp; | 324 | Node* tmp; |
| 325 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root()) { | 325 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { |
| 326 | if (RB_LEFT(parent) == elm) { | 326 | if (RB_LEFT(parent) == elm) { |
| 327 | tmp = RB_RIGHT(parent); | 327 | tmp = RB_RIGHT(parent); |
| 328 | if (RB_IS_RED(tmp)) { | 328 | if (RB_IS_RED(tmp)) { |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 04cf3f5b9..efb851f5a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -144,31 +144,40 @@ add_library(core STATIC | |||
| 144 | hle/kernel/board/nintendo/nx/k_system_control.cpp | 144 | hle/kernel/board/nintendo/nx/k_system_control.cpp |
| 145 | hle/kernel/board/nintendo/nx/k_system_control.h | 145 | hle/kernel/board/nintendo/nx/k_system_control.h |
| 146 | hle/kernel/board/nintendo/nx/secure_monitor.h | 146 | hle/kernel/board/nintendo/nx/secure_monitor.h |
| 147 | hle/kernel/client_port.cpp | ||
| 148 | hle/kernel/client_port.h | ||
| 149 | hle/kernel/client_session.cpp | ||
| 150 | hle/kernel/client_session.h | ||
| 151 | hle/kernel/code_set.cpp | 147 | hle/kernel/code_set.cpp |
| 152 | hle/kernel/code_set.h | 148 | hle/kernel/code_set.h |
| 153 | hle/kernel/svc_results.h | 149 | hle/kernel/svc_results.h |
| 154 | hle/kernel/global_scheduler_context.cpp | 150 | hle/kernel/global_scheduler_context.cpp |
| 155 | hle/kernel/global_scheduler_context.h | 151 | hle/kernel/global_scheduler_context.h |
| 156 | hle/kernel/handle_table.cpp | ||
| 157 | hle/kernel/handle_table.h | ||
| 158 | hle/kernel/hle_ipc.cpp | 152 | hle/kernel/hle_ipc.cpp |
| 159 | hle/kernel/hle_ipc.h | 153 | hle/kernel/hle_ipc.h |
| 154 | hle/kernel/init/init_slab_setup.cpp | ||
| 155 | hle/kernel/init/init_slab_setup.h | ||
| 160 | hle/kernel/k_address_arbiter.cpp | 156 | hle/kernel/k_address_arbiter.cpp |
| 161 | hle/kernel/k_address_arbiter.h | 157 | hle/kernel/k_address_arbiter.h |
| 162 | hle/kernel/k_address_space_info.cpp | 158 | hle/kernel/k_address_space_info.cpp |
| 163 | hle/kernel/k_address_space_info.h | 159 | hle/kernel/k_address_space_info.h |
| 160 | hle/kernel/k_auto_object.cpp | ||
| 161 | hle/kernel/k_auto_object.h | ||
| 162 | hle/kernel/k_auto_object_container.cpp | ||
| 163 | hle/kernel/k_auto_object_container.h | ||
| 164 | hle/kernel/k_affinity_mask.h | 164 | hle/kernel/k_affinity_mask.h |
| 165 | hle/kernel/k_class_token.cpp | ||
| 166 | hle/kernel/k_class_token.h | ||
| 167 | hle/kernel/k_client_port.cpp | ||
| 168 | hle/kernel/k_client_port.h | ||
| 169 | hle/kernel/k_client_session.cpp | ||
| 170 | hle/kernel/k_client_session.h | ||
| 165 | hle/kernel/k_condition_variable.cpp | 171 | hle/kernel/k_condition_variable.cpp |
| 166 | hle/kernel/k_condition_variable.h | 172 | hle/kernel/k_condition_variable.h |
| 167 | hle/kernel/k_event.cpp | 173 | hle/kernel/k_event.cpp |
| 168 | hle/kernel/k_event.h | 174 | hle/kernel/k_event.h |
| 175 | hle/kernel/k_handle_table.cpp | ||
| 176 | hle/kernel/k_handle_table.h | ||
| 169 | hle/kernel/k_light_condition_variable.h | 177 | hle/kernel/k_light_condition_variable.h |
| 170 | hle/kernel/k_light_lock.cpp | 178 | hle/kernel/k_light_lock.cpp |
| 171 | hle/kernel/k_light_lock.h | 179 | hle/kernel/k_light_lock.h |
| 180 | hle/kernel/k_linked_list.h | ||
| 172 | hle/kernel/k_memory_block.h | 181 | hle/kernel/k_memory_block.h |
| 173 | hle/kernel/k_memory_block_manager.cpp | 182 | hle/kernel/k_memory_block_manager.cpp |
| 174 | hle/kernel/k_memory_block_manager.h | 183 | hle/kernel/k_memory_block_manager.h |
| @@ -185,7 +194,11 @@ add_library(core STATIC | |||
| 185 | hle/kernel/k_page_linked_list.h | 194 | hle/kernel/k_page_linked_list.h |
| 186 | hle/kernel/k_page_table.cpp | 195 | hle/kernel/k_page_table.cpp |
| 187 | hle/kernel/k_page_table.h | 196 | hle/kernel/k_page_table.h |
| 197 | hle/kernel/k_port.cpp | ||
| 198 | hle/kernel/k_port.h | ||
| 188 | hle/kernel/k_priority_queue.h | 199 | hle/kernel/k_priority_queue.h |
| 200 | hle/kernel/k_process.cpp | ||
| 201 | hle/kernel/k_process.h | ||
| 189 | hle/kernel/k_readable_event.cpp | 202 | hle/kernel/k_readable_event.cpp |
| 190 | hle/kernel/k_readable_event.h | 203 | hle/kernel/k_readable_event.h |
| 191 | hle/kernel/k_resource_limit.cpp | 204 | hle/kernel/k_resource_limit.cpp |
| @@ -196,6 +209,12 @@ add_library(core STATIC | |||
| 196 | hle/kernel/k_scoped_lock.h | 209 | hle/kernel/k_scoped_lock.h |
| 197 | hle/kernel/k_scoped_resource_reservation.h | 210 | hle/kernel/k_scoped_resource_reservation.h |
| 198 | hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 211 | hle/kernel/k_scoped_scheduler_lock_and_sleep.h |
| 212 | hle/kernel/k_server_port.cpp | ||
| 213 | hle/kernel/k_server_port.h | ||
| 214 | hle/kernel/k_server_session.cpp | ||
| 215 | hle/kernel/k_server_session.h | ||
| 216 | hle/kernel/k_session.cpp | ||
| 217 | hle/kernel/k_session.h | ||
| 199 | hle/kernel/k_shared_memory.cpp | 218 | hle/kernel/k_shared_memory.cpp |
| 200 | hle/kernel/k_shared_memory.h | 219 | hle/kernel/k_shared_memory.h |
| 201 | hle/kernel/k_slab_heap.h | 220 | hle/kernel/k_slab_heap.h |
| @@ -208,28 +227,21 @@ add_library(core STATIC | |||
| 208 | hle/kernel/k_thread.h | 227 | hle/kernel/k_thread.h |
| 209 | hle/kernel/k_thread_queue.h | 228 | hle/kernel/k_thread_queue.h |
| 210 | hle/kernel/k_trace.h | 229 | hle/kernel/k_trace.h |
| 230 | hle/kernel/k_transfer_memory.cpp | ||
| 231 | hle/kernel/k_transfer_memory.h | ||
| 211 | hle/kernel/k_writable_event.cpp | 232 | hle/kernel/k_writable_event.cpp |
| 212 | hle/kernel/k_writable_event.h | 233 | hle/kernel/k_writable_event.h |
| 213 | hle/kernel/kernel.cpp | 234 | hle/kernel/kernel.cpp |
| 214 | hle/kernel/kernel.h | 235 | hle/kernel/kernel.h |
| 215 | hle/kernel/memory_types.h | 236 | hle/kernel/memory_types.h |
| 216 | hle/kernel/object.cpp | ||
| 217 | hle/kernel/object.h | ||
| 218 | hle/kernel/physical_core.cpp | 237 | hle/kernel/physical_core.cpp |
| 219 | hle/kernel/physical_core.h | 238 | hle/kernel/physical_core.h |
| 220 | hle/kernel/physical_memory.h | 239 | hle/kernel/physical_memory.h |
| 221 | hle/kernel/process.cpp | ||
| 222 | hle/kernel/process.h | ||
| 223 | hle/kernel/process_capability.cpp | 240 | hle/kernel/process_capability.cpp |
| 224 | hle/kernel/process_capability.h | 241 | hle/kernel/process_capability.h |
| 225 | hle/kernel/server_port.cpp | ||
| 226 | hle/kernel/server_port.h | ||
| 227 | hle/kernel/server_session.cpp | ||
| 228 | hle/kernel/server_session.h | ||
| 229 | hle/kernel/service_thread.cpp | 242 | hle/kernel/service_thread.cpp |
| 230 | hle/kernel/service_thread.h | 243 | hle/kernel/service_thread.h |
| 231 | hle/kernel/session.cpp | 244 | hle/kernel/slab_helpers.h |
| 232 | hle/kernel/session.h | ||
| 233 | hle/kernel/svc.cpp | 245 | hle/kernel/svc.cpp |
| 234 | hle/kernel/svc.h | 246 | hle/kernel/svc.h |
| 235 | hle/kernel/svc_common.h | 247 | hle/kernel/svc_common.h |
| @@ -237,8 +249,6 @@ add_library(core STATIC | |||
| 237 | hle/kernel/svc_wrap.h | 249 | hle/kernel/svc_wrap.h |
| 238 | hle/kernel/time_manager.cpp | 250 | hle/kernel/time_manager.cpp |
| 239 | hle/kernel/time_manager.h | 251 | hle/kernel/time_manager.h |
| 240 | hle/kernel/transfer_memory.cpp | ||
| 241 | hle/kernel/transfer_memory.h | ||
| 242 | hle/lock.cpp | 252 | hle/lock.cpp |
| 243 | hle/lock.h | 253 | hle/lock.h |
| 244 | hle/result.h | 254 | hle/result.h |
| @@ -393,6 +403,8 @@ add_library(core STATIC | |||
| 393 | hle/service/hid/xcd.cpp | 403 | hle/service/hid/xcd.cpp |
| 394 | hle/service/hid/xcd.h | 404 | hle/service/hid/xcd.h |
| 395 | hle/service/hid/errors.h | 405 | hle/service/hid/errors.h |
| 406 | hle/service/hid/controllers/console_sixaxis.cpp | ||
| 407 | hle/service/hid/controllers/console_sixaxis.h | ||
| 396 | hle/service/hid/controllers/controller_base.cpp | 408 | hle/service/hid/controllers/controller_base.cpp |
| 397 | hle/service/hid/controllers/controller_base.h | 409 | hle/service/hid/controllers/controller_base.h |
| 398 | hle/service/hid/controllers/debug_pad.cpp | 410 | hle/service/hid/controllers/debug_pad.cpp |
| @@ -639,20 +651,17 @@ endif() | |||
| 639 | 651 | ||
| 640 | if (MSVC) | 652 | if (MSVC) |
| 641 | target_compile_options(core PRIVATE | 653 | target_compile_options(core PRIVATE |
| 642 | # 'expression' : signed/unsigned mismatch | 654 | /we4018 # 'expression' : signed/unsigned mismatch |
| 643 | /we4018 | 655 | /we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) |
| 644 | # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) | 656 | /we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch |
| 645 | /we4244 | 657 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data |
| 646 | # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch | 658 | /we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data |
| 647 | /we4245 | 659 | /we4305 # 'context' : truncation from 'type1' to 'type2' |
| 648 | # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | 660 | /we4456 # Declaration of 'identifier' hides previous local declaration |
| 649 | /we4254 | 661 | /we4457 # Declaration of 'identifier' hides function parameter |
| 650 | # 'var' : conversion from 'size_t' to 'type', possible loss of data | 662 | /we4458 # Declaration of 'identifier' hides class member |
| 651 | /we4267 | 663 | /we4459 # Declaration of 'identifier' hides global declaration |
| 652 | # 'context' : truncation from 'type1' to 'type2' | 664 | /we4715 # 'function' : not all control paths return a value |
| 653 | /we4305 | ||
| 654 | # 'function' : not all control paths return a value | ||
| 655 | /we4715 | ||
| 656 | ) | 665 | ) |
| 657 | else() | 666 | else() |
| 658 | target_compile_options(core PRIVATE | 667 | target_compile_options(core PRIVATE |
| @@ -660,6 +669,7 @@ else() | |||
| 660 | -Werror=ignored-qualifiers | 669 | -Werror=ignored-qualifiers |
| 661 | -Werror=implicit-fallthrough | 670 | -Werror=implicit-fallthrough |
| 662 | -Werror=sign-compare | 671 | -Werror=sign-compare |
| 672 | -Werror=shadow | ||
| 663 | 673 | ||
| 664 | $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> | 674 | $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> |
| 665 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> | 675 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 7aeb2a658..93d43e22e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -24,7 +24,7 @@ namespace Core { | |||
| 24 | 24 | ||
| 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 26 | public: | 26 | public: |
| 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {} | 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) : parent{parent_} {} |
| 28 | 28 | ||
| 29 | u8 MemoryRead8(u32 vaddr) override { | 29 | u8 MemoryRead8(u32 vaddr) override { |
| 30 | return parent.system.Memory().Read8(vaddr); | 30 | return parent.system.Memory().Read8(vaddr); |
| @@ -142,7 +142,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 142 | config.far_code_offset = 256 * 1024 * 1024; | 142 | config.far_code_offset = 256 * 1024 * 1024; |
| 143 | 143 | ||
| 144 | // Safe optimizations | 144 | // Safe optimizations |
| 145 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 145 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { |
| 146 | if (!Settings::values.cpuopt_page_tables) { | 146 | if (!Settings::values.cpuopt_page_tables) { |
| 147 | config.page_table = nullptr; | 147 | config.page_table = nullptr; |
| 148 | } | 148 | } |
| @@ -170,15 +170,15 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | // Unsafe optimizations | 172 | // Unsafe optimizations |
| 173 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | 173 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 174 | config.unsafe_optimizations = true; | 174 | config.unsafe_optimizations = true; |
| 175 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 175 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { |
| 176 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 176 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 177 | } | 177 | } |
| 178 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | 178 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { |
| 179 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 179 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 180 | } | 180 | } |
| 181 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { | 181 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { |
| 182 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 182 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 183 | } | 183 | } |
| 184 | } | 184 | } |
| @@ -198,13 +198,13 @@ void ARM_Dynarmic_32::Step() { | |||
| 198 | jit->Step(); | 198 | jit->Step(); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, | 201 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, |
| 202 | bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, | 202 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 203 | std::size_t core_index) | 203 | std::size_t core_index_) |
| 204 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, | 204 | : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, |
| 205 | cb(std::make_unique<DynarmicCallbacks32>(*this)), | 205 | cb(std::make_unique<DynarmicCallbacks32>(*this)), |
| 206 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, | 206 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, |
| 207 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)}, | 207 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, |
| 208 | jit(MakeJit(nullptr)) {} | 208 | jit(MakeJit(nullptr)) {} |
| 209 | 209 | ||
| 210 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; | 210 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index d40aef7a9..42778c02c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -29,8 +29,8 @@ class System; | |||
| 29 | 29 | ||
| 30 | class ARM_Dynarmic_32 final : public ARM_Interface { | 30 | class ARM_Dynarmic_32 final : public ARM_Interface { |
| 31 | public: | 31 | public: |
| 32 | ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, | 32 | ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, |
| 33 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); | 33 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); |
| 34 | ~ARM_Dynarmic_32() override; | 34 | ~ARM_Dynarmic_32() override; |
| 35 | 35 | ||
| 36 | void SetPC(u64 pc) override; | 36 | void SetPC(u64 pc) override; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 040529f4d..08fa85904 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/core_timing.h" | 17 | #include "core/core_timing.h" |
| 18 | #include "core/hardware_properties.h" | 18 | #include "core/hardware_properties.h" |
| 19 | #include "core/hle/kernel/k_process.h" | ||
| 19 | #include "core/hle/kernel/k_scheduler.h" | 20 | #include "core/hle/kernel/k_scheduler.h" |
| 20 | #include "core/hle/kernel/process.h" | ||
| 21 | #include "core/hle/kernel/svc.h" | 21 | #include "core/hle/kernel/svc.h" |
| 22 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 23 | 23 | ||
| @@ -27,7 +27,7 @@ using Vector = Dynarmic::A64::Vector; | |||
| 27 | 27 | ||
| 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {} | 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) : parent{parent_} {} |
| 31 | 31 | ||
| 32 | u8 MemoryRead8(u64 vaddr) override { | 32 | u8 MemoryRead8(u64 vaddr) override { |
| 33 | return parent.system.Memory().Read8(vaddr); | 33 | return parent.system.Memory().Read8(vaddr); |
| @@ -182,7 +182,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 182 | config.far_code_offset = 256 * 1024 * 1024; | 182 | config.far_code_offset = 256 * 1024 * 1024; |
| 183 | 183 | ||
| 184 | // Safe optimizations | 184 | // Safe optimizations |
| 185 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 185 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { |
| 186 | if (!Settings::values.cpuopt_page_tables) { | 186 | if (!Settings::values.cpuopt_page_tables) { |
| 187 | config.page_table = nullptr; | 187 | config.page_table = nullptr; |
| 188 | } | 188 | } |
| @@ -210,15 +210,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | // Unsafe optimizations | 212 | // Unsafe optimizations |
| 213 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | 213 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 214 | config.unsafe_optimizations = true; | 214 | config.unsafe_optimizations = true; |
| 215 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 215 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { |
| 216 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 216 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 217 | } | 217 | } |
| 218 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | 218 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { |
| 219 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 219 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 220 | } | 220 | } |
| 221 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { | 221 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { |
| 222 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 222 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 223 | } | 223 | } |
| 224 | } | 224 | } |
| @@ -238,12 +238,12 @@ void ARM_Dynarmic_64::Step() { | |||
| 238 | cb->InterpreterFallback(jit->GetPC(), 1); | 238 | cb->InterpreterFallback(jit->GetPC(), 1); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, | 241 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, |
| 242 | bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, | 242 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 243 | std::size_t core_index) | 243 | std::size_t core_index_) |
| 244 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, | 244 | : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, |
| 245 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index}, | 245 | cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, |
| 246 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)}, | 246 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, |
| 247 | jit(MakeJit(nullptr, 48)) {} | 247 | jit(MakeJit(nullptr, 48)) {} |
| 248 | 248 | ||
| 249 | ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; | 249 | ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index edef04376..b81fbcc66 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -26,8 +26,8 @@ class System; | |||
| 26 | 26 | ||
| 27 | class ARM_Dynarmic_64 final : public ARM_Interface { | 27 | class ARM_Dynarmic_64 final : public ARM_Interface { |
| 28 | public: | 28 | public: |
| 29 | ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, | 29 | ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, |
| 30 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); | 30 | ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); |
| 31 | ~ARM_Dynarmic_64() override; | 31 | ~ARM_Dynarmic_64() override; |
| 32 | 32 | ||
| 33 | void SetPC(u64 pc) override; | 33 | void SetPC(u64 pc) override; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index caefc09f4..ebd506121 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp | |||
| @@ -94,12 +94,11 @@ CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, | |||
| 94 | CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { | 94 | CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { |
| 95 | if (!two && opc == 0 && CRm == CoprocReg::C14) { | 95 | if (!two && opc == 0 && CRm == CoprocReg::C14) { |
| 96 | // CNTPCT | 96 | // CNTPCT |
| 97 | const auto callback = static_cast<u64 (*)(Dynarmic::A32::Jit*, void*, u32, u32)>( | 97 | const auto callback = [](Dynarmic::A32::Jit*, void* arg, u32, u32) -> u64 { |
| 98 | [](Dynarmic::A32::Jit*, void* arg, u32, u32) -> u64 { | 98 | const auto& parent_arg = *static_cast<ARM_Dynarmic_32*>(arg); |
| 99 | ARM_Dynarmic_32& parent = *(ARM_Dynarmic_32*)arg; | 99 | return parent_arg.system.CoreTiming().GetClockTicks(); |
| 100 | return parent.system.CoreTiming().GetClockTicks(); | 100 | }; |
| 101 | }); | 101 | return Callback{callback, &parent}; |
| 102 | return Dynarmic::A32::Coprocessor::Callback{callback, (void*)&parent}; | ||
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, CRm); | 104 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, CRm); |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index dc6f4af3a..8597beddf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h | |||
| @@ -18,7 +18,7 @@ class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { | |||
| 18 | public: | 18 | public: |
| 19 | using CoprocReg = Dynarmic::A32::CoprocReg; | 19 | using CoprocReg = Dynarmic::A32::CoprocReg; |
| 20 | 20 | ||
| 21 | explicit DynarmicCP15(ARM_Dynarmic_32& parent) : parent(parent) {} | 21 | explicit DynarmicCP15(ARM_Dynarmic_32& parent_) : parent{parent_} {} |
| 22 | 22 | ||
| 23 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, | 23 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, |
| 24 | CoprocReg CRn, CoprocReg CRm, | 24 | CoprocReg CRn, CoprocReg CRm, |
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp b/src/core/arm/dynarmic/arm_exclusive_monitor.cpp index 4e209f6a5..9426a3edf 100644 --- a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp +++ b/src/core/arm/dynarmic/arm_exclusive_monitor.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | namespace Core { | 10 | namespace Core { |
| 11 | 11 | ||
| 12 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count) | 12 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_) |
| 13 | : monitor(core_count), memory{memory} {} | 13 | : monitor{core_count_}, memory{memory_} {} |
| 14 | 14 | ||
| 15 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | 15 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; |
| 16 | 16 | ||
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h index 964f4a55d..f9f056a59 100644 --- a/src/core/arm/dynarmic/arm_exclusive_monitor.h +++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h | |||
| @@ -22,7 +22,7 @@ namespace Core { | |||
| 22 | 22 | ||
| 23 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | 23 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { |
| 24 | public: | 24 | public: |
| 25 | explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count); | 25 | explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_); |
| 26 | ~DynarmicExclusiveMonitor() override; | 26 | ~DynarmicExclusiveMonitor() override; |
| 27 | 27 | ||
| 28 | u8 ExclusiveRead8(std::size_t core_index, VAddr addr) override; | 28 | u8 ExclusiveRead8(std::size_t core_index, VAddr addr) override; |
diff --git a/src/core/core.cpp b/src/core/core.cpp index d459d6c34..826a00ad6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -27,12 +27,12 @@ | |||
| 27 | #include "core/file_sys/vfs_concat.h" | 27 | #include "core/file_sys/vfs_concat.h" |
| 28 | #include "core/file_sys/vfs_real.h" | 28 | #include "core/file_sys/vfs_real.h" |
| 29 | #include "core/hardware_interrupt_manager.h" | 29 | #include "core/hardware_interrupt_manager.h" |
| 30 | #include "core/hle/kernel/client_port.h" | 30 | #include "core/hle/kernel/k_client_port.h" |
| 31 | #include "core/hle/kernel/k_process.h" | ||
| 31 | #include "core/hle/kernel/k_scheduler.h" | 32 | #include "core/hle/kernel/k_scheduler.h" |
| 32 | #include "core/hle/kernel/k_thread.h" | 33 | #include "core/hle/kernel/k_thread.h" |
| 33 | #include "core/hle/kernel/kernel.h" | 34 | #include "core/hle/kernel/kernel.h" |
| 34 | #include "core/hle/kernel/physical_core.h" | 35 | #include "core/hle/kernel/physical_core.h" |
| 35 | #include "core/hle/kernel/process.h" | ||
| 36 | #include "core/hle/service/am/applets/applets.h" | 36 | #include "core/hle/service/am/applets/applets.h" |
| 37 | #include "core/hle/service/apm/controller.h" | 37 | #include "core/hle/service/apm/controller.h" |
| 38 | #include "core/hle/service/filesystem/filesystem.h" | 38 | #include "core/hle/service/filesystem/filesystem.h" |
| @@ -166,14 +166,14 @@ struct System::Impl { | |||
| 166 | cpu_manager.SetAsyncGpu(is_async_gpu); | 166 | cpu_manager.SetAsyncGpu(is_async_gpu); |
| 167 | core_timing.SetMulticore(is_multicore); | 167 | core_timing.SetMulticore(is_multicore); |
| 168 | 168 | ||
| 169 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | ||
| 170 | kernel.Initialize(); | 169 | kernel.Initialize(); |
| 171 | cpu_manager.Initialize(); | 170 | cpu_manager.Initialize(); |
| 171 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | ||
| 172 | 172 | ||
| 173 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 173 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| 174 | std::chrono::system_clock::now().time_since_epoch()); | 174 | std::chrono::system_clock::now().time_since_epoch()); |
| 175 | Settings::values.custom_rtc_differential = | 175 | Settings::values.custom_rtc_differential = |
| 176 | Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time; | 176 | Settings::values.custom_rtc.value_or(current_time) - current_time; |
| 177 | 177 | ||
| 178 | // Create a default fs if one doesn't already exist. | 178 | // Create a default fs if one doesn't already exist. |
| 179 | if (virtual_filesystem == nullptr) | 179 | if (virtual_filesystem == nullptr) |
| @@ -233,8 +233,11 @@ struct System::Impl { | |||
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); | 235 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |
| 236 | auto main_process = | 236 | auto main_process = Kernel::KProcess::Create(system.Kernel()); |
| 237 | Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); | 237 | ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", |
| 238 | Kernel::KProcess::ProcessType::Userland) | ||
| 239 | .IsSuccess()); | ||
| 240 | main_process->Open(); | ||
| 238 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | 241 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |
| 239 | if (load_result != Loader::ResultStatus::Success) { | 242 | if (load_result != Loader::ResultStatus::Success) { |
| 240 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); | 243 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |
| @@ -244,7 +247,7 @@ struct System::Impl { | |||
| 244 | static_cast<u32>(load_result)); | 247 | static_cast<u32>(load_result)); |
| 245 | } | 248 | } |
| 246 | AddGlueRegistrationForProcess(*app_loader, *main_process); | 249 | AddGlueRegistrationForProcess(*app_loader, *main_process); |
| 247 | kernel.MakeCurrentProcess(main_process.get()); | 250 | kernel.MakeCurrentProcess(main_process); |
| 248 | kernel.InitializeCores(); | 251 | kernel.InitializeCores(); |
| 249 | 252 | ||
| 250 | // Initialize cheat engine | 253 | // Initialize cheat engine |
| @@ -286,7 +289,8 @@ struct System::Impl { | |||
| 286 | 289 | ||
| 287 | telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", | 290 | telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", |
| 288 | perf_results.emulation_speed * 100.0); | 291 | perf_results.emulation_speed * 100.0); |
| 289 | telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); | 292 | telemetry_session->AddField(performance, "Shutdown_Framerate", |
| 293 | perf_results.average_game_fps); | ||
| 290 | telemetry_session->AddField(performance, "Shutdown_Frametime", | 294 | telemetry_session->AddField(performance, "Shutdown_Frametime", |
| 291 | perf_results.frametime * 1000.0); | 295 | perf_results.frametime * 1000.0); |
| 292 | telemetry_session->AddField(performance, "Mean_Frametime_MS", | 296 | telemetry_session->AddField(performance, "Mean_Frametime_MS", |
| @@ -311,6 +315,7 @@ struct System::Impl { | |||
| 311 | gpu_core.reset(); | 315 | gpu_core.reset(); |
| 312 | perf_stats.reset(); | 316 | perf_stats.reset(); |
| 313 | kernel.Shutdown(); | 317 | kernel.Shutdown(); |
| 318 | memory.Reset(); | ||
| 314 | applet_manager.ClearAll(); | 319 | applet_manager.ClearAll(); |
| 315 | 320 | ||
| 316 | LOG_DEBUG(Core, "Shutdown OK"); | 321 | LOG_DEBUG(Core, "Shutdown OK"); |
| @@ -322,7 +327,7 @@ struct System::Impl { | |||
| 322 | return app_loader->ReadTitle(out); | 327 | return app_loader->ReadTitle(out); |
| 323 | } | 328 | } |
| 324 | 329 | ||
| 325 | void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::Process& process) { | 330 | void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::KProcess& process) { |
| 326 | std::vector<u8> nacp_data; | 331 | std::vector<u8> nacp_data; |
| 327 | FileSys::NACP nacp; | 332 | FileSys::NACP nacp; |
| 328 | if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) { | 333 | if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) { |
| @@ -513,7 +518,7 @@ const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const { | |||
| 513 | return impl->kernel.GlobalSchedulerContext(); | 518 | return impl->kernel.GlobalSchedulerContext(); |
| 514 | } | 519 | } |
| 515 | 520 | ||
| 516 | Kernel::Process* System::CurrentProcess() { | 521 | Kernel::KProcess* System::CurrentProcess() { |
| 517 | return impl->kernel.CurrentProcess(); | 522 | return impl->kernel.CurrentProcess(); |
| 518 | } | 523 | } |
| 519 | 524 | ||
| @@ -525,7 +530,7 @@ const Core::DeviceMemory& System::DeviceMemory() const { | |||
| 525 | return *impl->device_memory; | 530 | return *impl->device_memory; |
| 526 | } | 531 | } |
| 527 | 532 | ||
| 528 | const Kernel::Process* System::CurrentProcess() const { | 533 | const Kernel::KProcess* System::CurrentProcess() const { |
| 529 | return impl->kernel.CurrentProcess(); | 534 | return impl->kernel.CurrentProcess(); |
| 530 | } | 535 | } |
| 531 | 536 | ||
diff --git a/src/core/core.h b/src/core/core.h index f1068d23f..8b93ba998 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/file_sys/vfs_types.h" | 14 | #include "core/file_sys/vfs_types.h" |
| 15 | #include "core/hle/kernel/object.h" | ||
| 16 | 15 | ||
| 17 | namespace Core::Frontend { | 16 | namespace Core::Frontend { |
| 18 | class EmuWindow; | 17 | class EmuWindow; |
| @@ -29,7 +28,7 @@ namespace Kernel { | |||
| 29 | class GlobalSchedulerContext; | 28 | class GlobalSchedulerContext; |
| 30 | class KernelCore; | 29 | class KernelCore; |
| 31 | class PhysicalCore; | 30 | class PhysicalCore; |
| 32 | class Process; | 31 | class KProcess; |
| 33 | class KScheduler; | 32 | class KScheduler; |
| 34 | } // namespace Kernel | 33 | } // namespace Kernel |
| 35 | 34 | ||
| @@ -264,10 +263,10 @@ public: | |||
| 264 | [[nodiscard]] const Core::DeviceMemory& DeviceMemory() const; | 263 | [[nodiscard]] const Core::DeviceMemory& DeviceMemory() const; |
| 265 | 264 | ||
| 266 | /// Provides a pointer to the current process | 265 | /// Provides a pointer to the current process |
| 267 | [[nodiscard]] Kernel::Process* CurrentProcess(); | 266 | [[nodiscard]] Kernel::KProcess* CurrentProcess(); |
| 268 | 267 | ||
| 269 | /// Provides a constant pointer to the current process. | 268 | /// Provides a constant pointer to the current process. |
| 270 | [[nodiscard]] const Kernel::Process* CurrentProcess() const; | 269 | [[nodiscard]] const Kernel::KProcess* CurrentProcess() const; |
| 271 | 270 | ||
| 272 | /// Provides a reference to the core timing instance. | 271 | /// Provides a reference to the core timing instance. |
| 273 | [[nodiscard]] Timing::CoreTiming& CoreTiming(); | 272 | [[nodiscard]] Timing::CoreTiming& CoreTiming(); |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 874b5673a..c2f0f609f 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -133,8 +133,8 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | |||
| 133 | } | 133 | } |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | void CoreTiming::AddTicks(u64 ticks) { | 136 | void CoreTiming::AddTicks(u64 ticks_to_add) { |
| 137 | this->ticks += ticks; | 137 | ticks += ticks_to_add; |
| 138 | downcount -= static_cast<s64>(ticks); | 138 | downcount -= static_cast<s64>(ticks); |
| 139 | } | 139 | } |
| 140 | 140 | ||
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 77ff4c6fe..b64caacda 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -102,7 +102,7 @@ public: | |||
| 102 | /// We only permit one event of each type in the queue at a time. | 102 | /// We only permit one event of each type in the queue at a time. |
| 103 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); | 103 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); |
| 104 | 104 | ||
| 105 | void AddTicks(u64 ticks); | 105 | void AddTicks(u64 ticks_to_add); |
| 106 | 106 | ||
| 107 | void ResetTicks(); | 107 | void ResetTicks(); |
| 108 | 108 | ||
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index bdb374792..7e195346b 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | namespace Core { | 19 | namespace Core { |
| 20 | 20 | ||
| 21 | CpuManager::CpuManager(System& system) : system{system} {} | 21 | CpuManager::CpuManager(System& system_) : system{system_} {} |
| 22 | CpuManager::~CpuManager() = default; | 22 | CpuManager::~CpuManager() = default; |
| 23 | 23 | ||
| 24 | void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { | 24 | void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 17420c941..140263b09 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -25,7 +25,7 @@ class System; | |||
| 25 | 25 | ||
| 26 | class CpuManager { | 26 | class CpuManager { |
| 27 | public: | 27 | public: |
| 28 | explicit CpuManager(System& system); | 28 | explicit CpuManager(System& system_); |
| 29 | CpuManager(const CpuManager&) = delete; | 29 | CpuManager(const CpuManager&) = delete; |
| 30 | CpuManager(CpuManager&&) = delete; | 30 | CpuManager(CpuManager&&) = delete; |
| 31 | 31 | ||
| @@ -35,13 +35,13 @@ public: | |||
| 35 | CpuManager& operator=(CpuManager&&) = delete; | 35 | CpuManager& operator=(CpuManager&&) = delete; |
| 36 | 36 | ||
| 37 | /// Sets if emulation is multicore or single core, must be set before Initialize | 37 | /// Sets if emulation is multicore or single core, must be set before Initialize |
| 38 | void SetMulticore(bool is_multicore) { | 38 | void SetMulticore(bool is_multi) { |
| 39 | this->is_multicore = is_multicore; | 39 | is_multicore = is_multi; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | /// Sets if emulation is using an asynchronous GPU. | 42 | /// Sets if emulation is using an asynchronous GPU. |
| 43 | void SetAsyncGpu(bool is_async_gpu) { | 43 | void SetAsyncGpu(bool is_async) { |
| 44 | this->is_async_gpu = is_async_gpu; | 44 | is_async_gpu = is_async; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void Initialize(); | 47 | void Initialize(); |
diff --git a/src/core/crypto/ctr_encryption_layer.cpp b/src/core/crypto/ctr_encryption_layer.cpp index 5c84bb0a4..1231da8e3 100644 --- a/src/core/crypto/ctr_encryption_layer.cpp +++ b/src/core/crypto/ctr_encryption_layer.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | namespace Core::Crypto { | 10 | namespace Core::Crypto { |
| 11 | 11 | ||
| 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, | 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, |
| 13 | std::size_t base_offset) | 13 | std::size_t base_offset_) |
| 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR) {} | 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset_), cipher(key_, Mode::CTR) {} |
| 15 | 15 | ||
| 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { | 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 17 | if (length == 0) | 17 | if (length == 0) |
diff --git a/src/core/crypto/ctr_encryption_layer.h b/src/core/crypto/ctr_encryption_layer.h index a2429f001..f86f01b6f 100644 --- a/src/core/crypto/ctr_encryption_layer.h +++ b/src/core/crypto/ctr_encryption_layer.h | |||
| @@ -17,7 +17,7 @@ class CTREncryptionLayer : public EncryptionLayer { | |||
| 17 | public: | 17 | public: |
| 18 | using IVData = std::array<u8, 16>; | 18 | using IVData = std::array<u8, 16>; |
| 19 | 19 | ||
| 20 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); | 20 | CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, std::size_t base_offset_); |
| 21 | 21 | ||
| 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; | 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; |
| 23 | 23 | ||
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 070ed439e..a4b739c63 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -458,7 +458,7 @@ static std::array<u8, size> operator^(const std::array<u8, size>& lhs, | |||
| 458 | const std::array<u8, size>& rhs) { | 458 | const std::array<u8, size>& rhs) { |
| 459 | std::array<u8, size> out; | 459 | std::array<u8, size> out; |
| 460 | std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), | 460 | std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), |
| 461 | [](u8 lhs, u8 rhs) { return u8(lhs ^ rhs); }); | 461 | [](u8 lhs_elem, u8 rhs_elem) { return u8(lhs_elem ^ rhs_elem); }); |
| 462 | return out; | 462 | return out; |
| 463 | } | 463 | } |
| 464 | 464 | ||
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 8dee5590b..db2f6a955 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -176,26 +176,30 @@ u64 XCI::GetProgramTitleID() const { | |||
| 176 | 176 | ||
| 177 | u32 XCI::GetSystemUpdateVersion() { | 177 | u32 XCI::GetSystemUpdateVersion() { |
| 178 | const auto update = GetPartition(XCIPartition::Update); | 178 | const auto update = GetPartition(XCIPartition::Update); |
| 179 | if (update == nullptr) | 179 | if (update == nullptr) { |
| 180 | return 0; | 180 | return 0; |
| 181 | } | ||
| 181 | 182 | ||
| 182 | for (const auto& file : update->GetFiles()) { | 183 | for (const auto& update_file : update->GetFiles()) { |
| 183 | NCA nca{file, nullptr, 0}; | 184 | NCA nca{update_file, nullptr, 0}; |
| 184 | 185 | ||
| 185 | if (nca.GetStatus() != Loader::ResultStatus::Success) | 186 | if (nca.GetStatus() != Loader::ResultStatus::Success) { |
| 186 | continue; | 187 | continue; |
| 188 | } | ||
| 187 | 189 | ||
| 188 | if (nca.GetType() == NCAContentType::Meta && nca.GetTitleId() == 0x0100000000000816) { | 190 | if (nca.GetType() == NCAContentType::Meta && nca.GetTitleId() == 0x0100000000000816) { |
| 189 | const auto dir = nca.GetSubdirectories()[0]; | 191 | const auto dir = nca.GetSubdirectories()[0]; |
| 190 | const auto cnmt = dir->GetFile("SystemUpdate_0100000000000816.cnmt"); | 192 | const auto cnmt = dir->GetFile("SystemUpdate_0100000000000816.cnmt"); |
| 191 | if (cnmt == nullptr) | 193 | if (cnmt == nullptr) { |
| 192 | continue; | 194 | continue; |
| 195 | } | ||
| 193 | 196 | ||
| 194 | CNMT cnmt_data{cnmt}; | 197 | CNMT cnmt_data{cnmt}; |
| 195 | 198 | ||
| 196 | const auto metas = cnmt_data.GetMetaRecords(); | 199 | const auto metas = cnmt_data.GetMetaRecords(); |
| 197 | if (metas.empty()) | 200 | if (metas.empty()) { |
| 198 | continue; | 201 | continue; |
| 202 | } | ||
| 199 | 203 | ||
| 200 | return metas[0].title_version; | 204 | return metas[0].title_version; |
| 201 | } | 205 | } |
| @@ -262,8 +266,8 @@ VirtualDir XCI::ConcatenatedPseudoDirectory() { | |||
| 262 | if (part == nullptr) | 266 | if (part == nullptr) |
| 263 | continue; | 267 | continue; |
| 264 | 268 | ||
| 265 | for (const auto& file : part->GetFiles()) | 269 | for (const auto& part_file : part->GetFiles()) |
| 266 | out->AddFile(file); | 270 | out->AddFile(part_file); |
| 267 | } | 271 | } |
| 268 | 272 | ||
| 269 | return out; | 273 | return out; |
| @@ -283,12 +287,12 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { | |||
| 283 | return Loader::ResultStatus::ErrorXCIMissingPartition; | 287 | return Loader::ResultStatus::ErrorXCIMissingPartition; |
| 284 | } | 288 | } |
| 285 | 289 | ||
| 286 | for (const VirtualFile& file : partition->GetFiles()) { | 290 | for (const VirtualFile& partition_file : partition->GetFiles()) { |
| 287 | if (file->GetExtension() != "nca") { | 291 | if (partition_file->GetExtension() != "nca") { |
| 288 | continue; | 292 | continue; |
| 289 | } | 293 | } |
| 290 | 294 | ||
| 291 | auto nca = std::make_shared<NCA>(file, nullptr, 0); | 295 | auto nca = std::make_shared<NCA>(partition_file, nullptr, 0); |
| 292 | if (nca->IsUpdate()) { | 296 | if (nca->IsUpdate()) { |
| 293 | continue; | 297 | continue; |
| 294 | } | 298 | } |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index d12218fc2..24eff210f 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <cstring> | 6 | #include <cstring> |
| 7 | #include <optional> | 7 | #include <optional> |
| 8 | #include <ranges> | ||
| 8 | #include <utility> | 9 | #include <utility> |
| 9 | 10 | ||
| 10 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| @@ -136,12 +137,11 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_off | |||
| 136 | return; | 137 | return; |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | has_rights_id = std::any_of(header.rights_id.begin(), header.rights_id.end(), | 140 | has_rights_id = std::ranges::any_of(header.rights_id, [](char c) { return c != '\0'; }); |
| 140 | [](char c) { return c != '\0'; }); | ||
| 141 | 141 | ||
| 142 | const std::vector<NCASectionHeader> sections = ReadSectionHeaders(); | 142 | const std::vector<NCASectionHeader> sections = ReadSectionHeaders(); |
| 143 | is_update = std::any_of(sections.begin(), sections.end(), [](const NCASectionHeader& header) { | 143 | is_update = std::ranges::any_of(sections, [](const NCASectionHeader& nca_header) { |
| 144 | return header.raw.header.crypto_type == NCASectionCryptoType::BKTR; | 144 | return nca_header.raw.header.crypto_type == NCASectionCryptoType::BKTR; |
| 145 | }); | 145 | }); |
| 146 | 146 | ||
| 147 | if (!ReadSections(sections, bktr_base_ivfc_offset)) { | 147 | if (!ReadSections(sections, bktr_base_ivfc_offset)) { |
| @@ -202,8 +202,9 @@ bool NCA::HandlePotentialHeaderDecryption() { | |||
| 202 | 202 | ||
| 203 | std::vector<NCASectionHeader> NCA::ReadSectionHeaders() const { | 203 | std::vector<NCASectionHeader> NCA::ReadSectionHeaders() const { |
| 204 | const std::ptrdiff_t number_sections = | 204 | const std::ptrdiff_t number_sections = |
| 205 | std::count_if(std::begin(header.section_tables), std::end(header.section_tables), | 205 | std::ranges::count_if(header.section_tables, [](const NCASectionTableEntry& entry) { |
| 206 | [](NCASectionTableEntry entry) { return entry.media_offset > 0; }); | 206 | return entry.media_offset > 0; |
| 207 | }); | ||
| 207 | 208 | ||
| 208 | std::vector<NCASectionHeader> sections(number_sections); | 209 | std::vector<NCASectionHeader> sections(number_sections); |
| 209 | const auto length_sections = SECTION_HEADER_SIZE * number_sections; | 210 | const auto length_sections = SECTION_HEADER_SIZE * number_sections; |
| @@ -312,11 +313,11 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl | |||
| 312 | } | 313 | } |
| 313 | 314 | ||
| 314 | std::vector<RelocationBucket> relocation_buckets(relocation_buckets_raw.size()); | 315 | std::vector<RelocationBucket> relocation_buckets(relocation_buckets_raw.size()); |
| 315 | std::transform(relocation_buckets_raw.begin(), relocation_buckets_raw.end(), | 316 | std::ranges::transform(relocation_buckets_raw, relocation_buckets.begin(), |
| 316 | relocation_buckets.begin(), &ConvertRelocationBucketRaw); | 317 | &ConvertRelocationBucketRaw); |
| 317 | std::vector<SubsectionBucket> subsection_buckets(subsection_buckets_raw.size()); | 318 | std::vector<SubsectionBucket> subsection_buckets(subsection_buckets_raw.size()); |
| 318 | std::transform(subsection_buckets_raw.begin(), subsection_buckets_raw.end(), | 319 | std::ranges::transform(subsection_buckets_raw, subsection_buckets.begin(), |
| 319 | subsection_buckets.begin(), &ConvertSubsectionBucketRaw); | 320 | &ConvertSubsectionBucketRaw); |
| 320 | 321 | ||
| 321 | u32 ctr_low; | 322 | u32 ctr_low; |
| 322 | std::memcpy(&ctr_low, section.raw.section_ctr.data(), sizeof(ctr_low)); | 323 | std::memcpy(&ctr_low, section.raw.section_ctr.data(), sizeof(ctr_low)); |
diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index bb4654366..1a920b45d 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | namespace FileSys { | 9 | namespace FileSys { |
| 10 | 10 | ||
| 11 | constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1}; | 11 | constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1}; |
| 12 | constexpr ResultCode ERROR_PATH_ALREADY_EXISTS{ErrorModule::FS, 2}; | ||
| 12 | constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002}; | 13 | constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002}; |
| 13 | constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001}; | 14 | constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001}; |
| 14 | constexpr ResultCode ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005}; | 15 | constexpr ResultCode ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005}; |
diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp index c52fafb6f..1ca1d536f 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.cpp +++ b/src/core/file_sys/fsmitm_romfsbuild.cpp | |||
| @@ -126,16 +126,17 @@ static u64 romfs_get_hash_table_count(u64 num_entries) { | |||
| 126 | return count; | 126 | return count; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext, | 129 | void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext_dir, |
| 130 | std::shared_ptr<RomFSBuildDirectoryContext> parent) { | 130 | std::shared_ptr<RomFSBuildDirectoryContext> parent) { |
| 131 | std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs; | 131 | std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs; |
| 132 | 132 | ||
| 133 | VirtualDir dir; | 133 | VirtualDir dir; |
| 134 | 134 | ||
| 135 | if (parent->path_len == 0) | 135 | if (parent->path_len == 0) { |
| 136 | dir = root_romfs; | 136 | dir = root_romfs; |
| 137 | else | 137 | } else { |
| 138 | dir = root_romfs->GetDirectoryRelative(parent->path); | 138 | dir = root_romfs->GetDirectoryRelative(parent->path); |
| 139 | } | ||
| 139 | 140 | ||
| 140 | const auto entries = dir->GetEntries(); | 141 | const auto entries = dir->GetEntries(); |
| 141 | 142 | ||
| @@ -147,8 +148,9 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext, | |||
| 147 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); | 148 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); |
| 148 | child->path = parent->path + "/" + kv.first; | 149 | child->path = parent->path + "/" + kv.first; |
| 149 | 150 | ||
| 150 | if (ext != nullptr && ext->GetFileRelative(child->path + ".stub") != nullptr) | 151 | if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { |
| 151 | continue; | 152 | continue; |
| 153 | } | ||
| 152 | 154 | ||
| 153 | // Sanity check on path_len | 155 | // Sanity check on path_len |
| 154 | ASSERT(child->path_len < FS_MAX_PATH); | 156 | ASSERT(child->path_len < FS_MAX_PATH); |
| @@ -163,21 +165,20 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext, | |||
| 163 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); | 165 | child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size()); |
| 164 | child->path = parent->path + "/" + kv.first; | 166 | child->path = parent->path + "/" + kv.first; |
| 165 | 167 | ||
| 166 | if (ext != nullptr && ext->GetFileRelative(child->path + ".stub") != nullptr) | 168 | if (ext_dir != nullptr && ext_dir->GetFileRelative(child->path + ".stub") != nullptr) { |
| 167 | continue; | 169 | continue; |
| 170 | } | ||
| 168 | 171 | ||
| 169 | // Sanity check on path_len | 172 | // Sanity check on path_len |
| 170 | ASSERT(child->path_len < FS_MAX_PATH); | 173 | ASSERT(child->path_len < FS_MAX_PATH); |
| 171 | 174 | ||
| 172 | child->source = root_romfs->GetFileRelative(child->path); | 175 | child->source = root_romfs->GetFileRelative(child->path); |
| 173 | 176 | ||
| 174 | if (ext != nullptr) { | 177 | if (ext_dir != nullptr) { |
| 175 | const auto ips = ext->GetFileRelative(child->path + ".ips"); | 178 | if (const auto ips = ext_dir->GetFileRelative(child->path + ".ips")) { |
| 176 | 179 | if (auto patched = PatchIPS(child->source, ips)) { | |
| 177 | if (ips != nullptr) { | ||
| 178 | auto patched = PatchIPS(child->source, ips); | ||
| 179 | if (patched != nullptr) | ||
| 180 | child->source = std::move(patched); | 180 | child->source = std::move(patched); |
| 181 | } | ||
| 181 | } | 182 | } |
| 182 | } | 183 | } |
| 183 | 184 | ||
| @@ -188,7 +189,7 @@ void RomFSBuildContext::VisitDirectory(VirtualDir root_romfs, VirtualDir ext, | |||
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | for (auto& child : child_dirs) { | 191 | for (auto& child : child_dirs) { |
| 191 | this->VisitDirectory(root_romfs, ext, child); | 192 | this->VisitDirectory(root_romfs, ext_dir, child); |
| 192 | } | 193 | } |
| 193 | } | 194 | } |
| 194 | 195 | ||
diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h index 049de180b..8d4d89fab 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.h +++ b/src/core/file_sys/fsmitm_romfsbuild.h | |||
| @@ -59,7 +59,7 @@ private: | |||
| 59 | u64 file_hash_table_size = 0; | 59 | u64 file_hash_table_size = 0; |
| 60 | u64 file_partition_size = 0; | 60 | u64 file_partition_size = 0; |
| 61 | 61 | ||
| 62 | void VisitDirectory(VirtualDir filesys, VirtualDir ext, | 62 | void VisitDirectory(VirtualDir filesys, VirtualDir ext_dir, |
| 63 | std::shared_ptr<RomFSBuildDirectoryContext> parent); | 63 | std::shared_ptr<RomFSBuildDirectoryContext> parent); |
| 64 | 64 | ||
| 65 | bool AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, | 65 | bool AddDirectory(std::shared_ptr<RomFSBuildDirectoryContext> parent_dir_ctx, |
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index 3596541b2..f5cb4aa8c 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp | |||
| @@ -39,10 +39,10 @@ CNMT::CNMT(VirtualFile file) { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | CNMT::CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, | 42 | CNMT::CNMT(CNMTHeader header_, OptionalHeader opt_header_, |
| 43 | std::vector<MetaRecord> meta_records) | 43 | std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_) |
| 44 | : header(std::move(header)), opt_header(std::move(opt_header)), | 44 | : header(std::move(header_)), opt_header(std::move(opt_header_)), |
| 45 | content_records(std::move(content_records)), meta_records(std::move(meta_records)) {} | 45 | content_records(std::move(content_records_)), meta_records(std::move(meta_records_)) {} |
| 46 | 46 | ||
| 47 | CNMT::~CNMT() = default; | 47 | CNMT::~CNMT() = default; |
| 48 | 48 | ||
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h index 53535e5f5..ce1138a17 100644 --- a/src/core/file_sys/nca_metadata.h +++ b/src/core/file_sys/nca_metadata.h | |||
| @@ -87,8 +87,8 @@ static_assert(sizeof(CNMTHeader) == 0x20, "CNMTHeader has incorrect size."); | |||
| 87 | class CNMT { | 87 | class CNMT { |
| 88 | public: | 88 | public: |
| 89 | explicit CNMT(VirtualFile file); | 89 | explicit CNMT(VirtualFile file); |
| 90 | CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, | 90 | CNMT(CNMTHeader header_, OptionalHeader opt_header_, |
| 91 | std::vector<MetaRecord> meta_records); | 91 | std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_); |
| 92 | ~CNMT(); | 92 | ~CNMT(); |
| 93 | 93 | ||
| 94 | u64 GetTitleID() const; | 94 | u64 GetTitleID() const; |
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index a65ec6798..b36827b75 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp | |||
| @@ -83,11 +83,14 @@ BKTR::~BKTR() = default; | |||
| 83 | 83 | ||
| 84 | std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { | 84 | std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 85 | // Read out of bounds. | 85 | // Read out of bounds. |
| 86 | if (offset >= relocation.size) | 86 | if (offset >= relocation.size) { |
| 87 | return 0; | 87 | return 0; |
| 88 | const auto relocation = GetRelocationEntry(offset); | 88 | } |
| 89 | const auto section_offset = offset - relocation.address_patch + relocation.address_source; | 89 | |
| 90 | const auto bktr_read = relocation.from_patch; | 90 | const auto relocation_entry = GetRelocationEntry(offset); |
| 91 | const auto section_offset = | ||
| 92 | offset - relocation_entry.address_patch + relocation_entry.address_source; | ||
| 93 | const auto bktr_read = relocation_entry.from_patch; | ||
| 91 | 94 | ||
| 92 | const auto next_relocation = GetNextRelocationEntry(offset); | 95 | const auto next_relocation = GetNextRelocationEntry(offset); |
| 93 | 96 | ||
| @@ -106,15 +109,16 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { | |||
| 106 | return bktr_romfs->Read(data, length, section_offset); | 109 | return bktr_romfs->Read(data, length, section_offset); |
| 107 | } | 110 | } |
| 108 | 111 | ||
| 109 | const auto subsection = GetSubsectionEntry(section_offset); | 112 | const auto subsection_entry = GetSubsectionEntry(section_offset); |
| 110 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); | 113 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(key, Core::Crypto::Mode::CTR); |
| 111 | 114 | ||
| 112 | // Calculate AES IV | 115 | // Calculate AES IV |
| 113 | std::array<u8, 16> iv{}; | 116 | std::array<u8, 16> iv{}; |
| 114 | auto subsection_ctr = subsection.ctr; | 117 | auto subsection_ctr = subsection_entry.ctr; |
| 115 | auto offset_iv = section_offset + base_offset; | 118 | auto offset_iv = section_offset + base_offset; |
| 116 | for (std::size_t i = 0; i < section_ctr.size(); ++i) | 119 | for (std::size_t i = 0; i < section_ctr.size(); ++i) { |
| 117 | iv[i] = section_ctr[0x8 - i - 1]; | 120 | iv[i] = section_ctr[0x8 - i - 1]; |
| 121 | } | ||
| 118 | offset_iv >>= 4; | 122 | offset_iv >>= 4; |
| 119 | for (std::size_t i = 0; i < sizeof(u64); ++i) { | 123 | for (std::size_t i = 0; i < sizeof(u64); ++i) { |
| 120 | iv[0xF - i] = static_cast<u8>(offset_iv & 0xFF); | 124 | iv[0xF - i] = static_cast<u8>(offset_iv & 0xFF); |
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 431302f55..b0cb65952 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "core/crypto/key_manager.h" | 13 | #include "core/crypto/key_manager.h" |
| 14 | #include "core/file_sys/card_image.h" | 14 | #include "core/file_sys/card_image.h" |
| 15 | #include "core/file_sys/common_funcs.h" | ||
| 15 | #include "core/file_sys/content_archive.h" | 16 | #include "core/file_sys/content_archive.h" |
| 16 | #include "core/file_sys/nca_metadata.h" | 17 | #include "core/file_sys/nca_metadata.h" |
| 17 | #include "core/file_sys/registered_cache.h" | 18 | #include "core/file_sys/registered_cache.h" |
| @@ -281,14 +282,14 @@ NcaID PlaceholderCache::Generate() { | |||
| 281 | return out; | 282 | return out; |
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir, | 285 | VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& open_dir, |
| 285 | std::string_view path) const { | 286 | std::string_view path) const { |
| 286 | const auto file = dir->GetFileRelative(path); | 287 | const auto file = open_dir->GetFileRelative(path); |
| 287 | if (file != nullptr) { | 288 | if (file != nullptr) { |
| 288 | return file; | 289 | return file; |
| 289 | } | 290 | } |
| 290 | 291 | ||
| 291 | const auto nca_dir = dir->GetDirectoryRelative(path); | 292 | const auto nca_dir = open_dir->GetDirectoryRelative(path); |
| 292 | if (nca_dir == nullptr) { | 293 | if (nca_dir == nullptr) { |
| 293 | return nullptr; | 294 | return nullptr; |
| 294 | } | 295 | } |
| @@ -431,13 +432,15 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) { | |||
| 431 | } | 432 | } |
| 432 | 433 | ||
| 433 | void RegisteredCache::AccumulateYuzuMeta() { | 434 | void RegisteredCache::AccumulateYuzuMeta() { |
| 434 | const auto dir = this->dir->GetSubdirectory("yuzu_meta"); | 435 | const auto meta_dir = dir->GetSubdirectory("yuzu_meta"); |
| 435 | if (dir == nullptr) | 436 | if (meta_dir == nullptr) { |
| 436 | return; | 437 | return; |
| 438 | } | ||
| 437 | 439 | ||
| 438 | for (const auto& file : dir->GetFiles()) { | 440 | for (const auto& file : meta_dir->GetFiles()) { |
| 439 | if (file->GetExtension() != "cnmt") | 441 | if (file->GetExtension() != "cnmt") { |
| 440 | continue; | 442 | continue; |
| 443 | } | ||
| 441 | 444 | ||
| 442 | CNMT cnmt(file); | 445 | CNMT cnmt(file); |
| 443 | yuzu_meta.insert_or_assign(cnmt.GetTitleID(), std::move(cnmt)); | 446 | yuzu_meta.insert_or_assign(cnmt.GetTitleID(), std::move(cnmt)); |
| @@ -445,8 +448,10 @@ void RegisteredCache::AccumulateYuzuMeta() { | |||
| 445 | } | 448 | } |
| 446 | 449 | ||
| 447 | void RegisteredCache::Refresh() { | 450 | void RegisteredCache::Refresh() { |
| 448 | if (dir == nullptr) | 451 | if (dir == nullptr) { |
| 449 | return; | 452 | return; |
| 453 | } | ||
| 454 | |||
| 450 | const auto ids = AccumulateFiles(); | 455 | const auto ids = AccumulateFiles(); |
| 451 | ProcessFiles(ids); | 456 | ProcessFiles(ids); |
| 452 | AccumulateYuzuMeta(); | 457 | AccumulateYuzuMeta(); |
| @@ -566,7 +571,7 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex | |||
| 566 | } | 571 | } |
| 567 | 572 | ||
| 568 | const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32); | 573 | const auto meta_id_raw = (*meta_iter)->GetName().substr(0, 32); |
| 569 | const auto meta_id = Common::HexStringToArray<16>(meta_id_raw); | 574 | const auto meta_id_data = Common::HexStringToArray<16>(meta_id_raw); |
| 570 | 575 | ||
| 571 | if ((*meta_iter)->GetSubdirectories().empty()) { | 576 | if ((*meta_iter)->GetSubdirectories().empty()) { |
| 572 | LOG_ERROR(Loader, | 577 | LOG_ERROR(Loader, |
| @@ -588,10 +593,16 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex | |||
| 588 | const CNMT cnmt(cnmt_file); | 593 | const CNMT cnmt(cnmt_file); |
| 589 | 594 | ||
| 590 | const auto title_id = cnmt.GetTitleID(); | 595 | const auto title_id = cnmt.GetTitleID(); |
| 596 | const auto version = cnmt.GetTitleVersion(); | ||
| 597 | |||
| 598 | if (title_id == GetBaseTitleID(title_id) && version == 0) { | ||
| 599 | return InstallResult::ErrorBaseInstall; | ||
| 600 | } | ||
| 601 | |||
| 591 | const auto result = RemoveExistingEntry(title_id); | 602 | const auto result = RemoveExistingEntry(title_id); |
| 592 | 603 | ||
| 593 | // Install Metadata File | 604 | // Install Metadata File |
| 594 | const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id); | 605 | const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); |
| 595 | if (res != InstallResult::Success) { | 606 | if (res != InstallResult::Success) { |
| 596 | return res; | 607 | return res; |
| 597 | } | 608 | } |
| @@ -741,15 +752,15 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti | |||
| 741 | 752 | ||
| 742 | bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) { | 753 | bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) { |
| 743 | // Reasoning behind this method can be found in the comment for InstallEntry, NCA overload. | 754 | // Reasoning behind this method can be found in the comment for InstallEntry, NCA overload. |
| 744 | const auto dir = this->dir->CreateDirectoryRelative("yuzu_meta"); | 755 | const auto meta_dir = dir->CreateDirectoryRelative("yuzu_meta"); |
| 745 | const auto filename = GetCNMTName(cnmt.GetType(), cnmt.GetTitleID()); | 756 | const auto filename = GetCNMTName(cnmt.GetType(), cnmt.GetTitleID()); |
| 746 | if (dir->GetFile(filename) == nullptr) { | 757 | if (meta_dir->GetFile(filename) == nullptr) { |
| 747 | auto out = dir->CreateFile(filename); | 758 | auto out = meta_dir->CreateFile(filename); |
| 748 | const auto buffer = cnmt.Serialize(); | 759 | const auto buffer = cnmt.Serialize(); |
| 749 | out->Resize(buffer.size()); | 760 | out->Resize(buffer.size()); |
| 750 | out->WriteBytes(buffer); | 761 | out->WriteBytes(buffer); |
| 751 | } else { | 762 | } else { |
| 752 | auto out = dir->GetFile(filename); | 763 | auto out = meta_dir->GetFile(filename); |
| 753 | CNMT old_cnmt(out); | 764 | CNMT old_cnmt(out); |
| 754 | // Returns true on change | 765 | // Returns true on change |
| 755 | if (old_cnmt.UnionRecords(cnmt)) { | 766 | if (old_cnmt.UnionRecords(cnmt)) { |
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index b08a1687a..d042aef90 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h | |||
| @@ -38,6 +38,7 @@ enum class InstallResult { | |||
| 38 | ErrorAlreadyExists, | 38 | ErrorAlreadyExists, |
| 39 | ErrorCopyFailed, | 39 | ErrorCopyFailed, |
| 40 | ErrorMetaFailed, | 40 | ErrorMetaFailed, |
| 41 | ErrorBaseInstall, | ||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | struct ContentProviderEntry { | 44 | struct ContentProviderEntry { |
| @@ -182,7 +183,7 @@ private: | |||
| 182 | void AccumulateYuzuMeta(); | 183 | void AccumulateYuzuMeta(); |
| 183 | std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const; | 184 | std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const; |
| 184 | VirtualFile GetFileAtID(NcaID id) const; | 185 | VirtualFile GetFileAtID(NcaID id) const; |
| 185 | VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const; | 186 | VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& open_dir, std::string_view path) const; |
| 186 | InstallResult RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, | 187 | InstallResult RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, |
| 187 | bool overwrite_if_exists, std::optional<NcaID> override_id = {}); | 188 | bool overwrite_if_exists, std::optional<NcaID> override_id = {}); |
| 188 | bool RawInstallYuzuMeta(const CNMT& cnmt); | 189 | bool RawInstallYuzuMeta(const CNMT& cnmt); |
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index f4e16e4be..aa7f3072f 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/file_sys/romfs_factory.h" | 15 | #include "core/file_sys/romfs_factory.h" |
| 16 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/k_process.h" |
| 17 | #include "core/hle/service/filesystem/filesystem.h" | 17 | #include "core/hle/service/filesystem/filesystem.h" |
| 18 | #include "core/loader/loader.h" | 18 | #include "core/loader/loader.h" |
| 19 | 19 | ||
| @@ -33,8 +33,8 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provi | |||
| 33 | 33 | ||
| 34 | RomFSFactory::~RomFSFactory() = default; | 34 | RomFSFactory::~RomFSFactory() = default; |
| 35 | 35 | ||
| 36 | void RomFSFactory::SetPackedUpdate(VirtualFile update_raw) { | 36 | void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) { |
| 37 | this->update_raw = std::move(update_raw); | 37 | update_raw = std::move(update_raw_file); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { | 40 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { |
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index 96dd0d578..39db09e4e 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h | |||
| @@ -40,7 +40,7 @@ public: | |||
| 40 | Service::FileSystem::FileSystemController& controller); | 40 | Service::FileSystem::FileSystemController& controller); |
| 41 | ~RomFSFactory(); | 41 | ~RomFSFactory(); |
| 42 | 42 | ||
| 43 | void SetPackedUpdate(VirtualFile update_raw); | 43 | void SetPackedUpdate(VirtualFile update_raw_file); |
| 44 | [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const; | 44 | [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const; |
| 45 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id, | 45 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id, |
| 46 | ContentRecordType type) const; | 46 | ContentRecordType type) const; |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index b7bfe0928..f973d1d21 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/file_sys/savedata_factory.h" | 10 | #include "core/file_sys/savedata_factory.h" |
| 11 | #include "core/file_sys/vfs.h" | 11 | #include "core/file_sys/vfs.h" |
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/k_process.h" |
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| 15 | 15 | ||
| @@ -170,26 +170,30 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s | |||
| 170 | SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, | 170 | SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, |
| 171 | u128 user_id) const { | 171 | u128 user_id) const { |
| 172 | const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); | 172 | const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); |
| 173 | const auto dir = GetOrCreateDirectoryRelative(this->dir, path); | 173 | const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); |
| 174 | 174 | ||
| 175 | const auto size_file = dir->GetFile(SAVE_DATA_SIZE_FILENAME); | 175 | const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME); |
| 176 | if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize)) | 176 | if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize)) { |
| 177 | return {0, 0}; | 177 | return {0, 0}; |
| 178 | } | ||
| 178 | 179 | ||
| 179 | SaveDataSize out; | 180 | SaveDataSize out; |
| 180 | if (size_file->ReadObject(&out) != sizeof(SaveDataSize)) | 181 | if (size_file->ReadObject(&out) != sizeof(SaveDataSize)) { |
| 181 | return {0, 0}; | 182 | return {0, 0}; |
| 183 | } | ||
| 184 | |||
| 182 | return out; | 185 | return out; |
| 183 | } | 186 | } |
| 184 | 187 | ||
| 185 | void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, | 188 | void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, |
| 186 | SaveDataSize new_value) const { | 189 | SaveDataSize new_value) const { |
| 187 | const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); | 190 | const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); |
| 188 | const auto dir = GetOrCreateDirectoryRelative(this->dir, path); | 191 | const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); |
| 189 | 192 | ||
| 190 | const auto size_file = dir->CreateFile(SAVE_DATA_SIZE_FILENAME); | 193 | const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME); |
| 191 | if (size_file == nullptr) | 194 | if (size_file == nullptr) { |
| 192 | return; | 195 | return; |
| 196 | } | ||
| 193 | 197 | ||
| 194 | size_file->Resize(sizeof(SaveDataSize)); | 198 | size_file->Resize(sizeof(SaveDataSize)); |
| 195 | size_file->WriteObject(new_value); | 199 | size_file->WriteObject(new_value); |
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index c05735ddd..d51d469e3 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp | |||
| @@ -20,8 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | namespace FileSys { | 21 | namespace FileSys { |
| 22 | 22 | ||
| 23 | NSP::NSP(VirtualFile file_, std::size_t program_index) | 23 | NSP::NSP(VirtualFile file_, std::size_t program_index_) |
| 24 | : file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success}, | 24 | : file(std::move(file_)), program_index(program_index_), status{Loader::ResultStatus::Success}, |
| 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { | 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { |
| 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { | 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { |
| 27 | status = pfs->GetStatus(); | 27 | status = pfs->GetStatus(); |
| @@ -232,15 +232,15 @@ void NSP::SetTicketKeys(const std::vector<VirtualFile>& files) { | |||
| 232 | void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) { | 232 | void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) { |
| 233 | exefs = pfs; | 233 | exefs = pfs; |
| 234 | 234 | ||
| 235 | const auto romfs_iter = std::find_if(files.begin(), files.end(), [](const VirtualFile& file) { | 235 | const auto iter = std::find_if(files.begin(), files.end(), [](const VirtualFile& entry) { |
| 236 | return file->GetName().rfind(".romfs") != std::string::npos; | 236 | return entry->GetName().rfind(".romfs") != std::string::npos; |
| 237 | }); | 237 | }); |
| 238 | 238 | ||
| 239 | if (romfs_iter == files.end()) { | 239 | if (iter == files.end()) { |
| 240 | return; | 240 | return; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | romfs = *romfs_iter; | 243 | romfs = *iter; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | void NSP::ReadNCAs(const std::vector<VirtualFile>& files) { | 246 | void NSP::ReadNCAs(const std::vector<VirtualFile>& files) { |
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 54581a6f3..ecb3b6f15 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h | |||
| @@ -27,7 +27,7 @@ enum class ContentRecordType : u8; | |||
| 27 | 27 | ||
| 28 | class NSP : public ReadOnlyVfsDirectory { | 28 | class NSP : public ReadOnlyVfsDirectory { |
| 29 | public: | 29 | public: |
| 30 | explicit NSP(VirtualFile file, std::size_t program_index = 0); | 30 | explicit NSP(VirtualFile file_, std::size_t program_index_ = 0); |
| 31 | ~NSP() override; | 31 | ~NSP() override; |
| 32 | 32 | ||
| 33 | Loader::ResultStatus GetStatus() const; | 33 | Loader::ResultStatus GetStatus() const; |
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 3c5a7d87a..5f8c09124 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp | |||
| @@ -23,8 +23,8 @@ static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFil | |||
| 23 | return map.begin()->first == 0; | 23 | return map.begin()->first == 0; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name) | 26 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name_) |
| 27 | : name(std::move(name)) { | 27 | : name(std::move(name_)) { |
| 28 | std::size_t next_offset = 0; | 28 | std::size_t next_offset = 0; |
| 29 | for (const auto& file : files_) { | 29 | for (const auto& file : files_) { |
| 30 | files.emplace(next_offset, file); | 30 | files.emplace(next_offset, file); |
| @@ -32,8 +32,8 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::s | |||
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name) | 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name_) |
| 36 | : files(std::move(files_)), name(std::move(name)) { | 36 | : files(std::move(files_)), name(std::move(name_)) { |
| 37 | ASSERT(VerifyConcatenationMapContinuity(files)); | 37 | ASSERT(VerifyConcatenationMapContinuity(files)); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| @@ -136,7 +136,7 @@ std::size_t ConcatenatedVfsFile::Write(const u8* data, std::size_t length, std:: | |||
| 136 | return 0; | 136 | return 0; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | bool ConcatenatedVfsFile::Rename(std::string_view name) { | 139 | bool ConcatenatedVfsFile::Rename(std::string_view new_name) { |
| 140 | return false; | 140 | return false; |
| 141 | } | 141 | } |
| 142 | 142 | ||
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index 287c72555..cd32960a5 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h | |||
| @@ -14,8 +14,8 @@ namespace FileSys { | |||
| 14 | // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently | 14 | // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently |
| 15 | // read-only. | 15 | // read-only. |
| 16 | class ConcatenatedVfsFile : public VfsFile { | 16 | class ConcatenatedVfsFile : public VfsFile { |
| 17 | ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); | 17 | explicit ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name_); |
| 18 | ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name); | 18 | explicit ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name_); |
| 19 | 19 | ||
| 20 | public: | 20 | public: |
| 21 | ~ConcatenatedVfsFile() override; | 21 | ~ConcatenatedVfsFile() override; |
| @@ -36,7 +36,7 @@ public: | |||
| 36 | bool IsReadable() const override; | 36 | bool IsReadable() const override; |
| 37 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; | 37 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; |
| 38 | std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override; | 38 | std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override; |
| 39 | bool Rename(std::string_view name) override; | 39 | bool Rename(std::string_view new_name) override; |
| 40 | 40 | ||
| 41 | private: | 41 | private: |
| 42 | // Maps starting offset to file -- more efficient. | 42 | // Maps starting offset to file -- more efficient. |
diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp index 434b03cec..e093c4db2 100644 --- a/src/core/file_sys/vfs_layered.cpp +++ b/src/core/file_sys/vfs_layered.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace FileSys { | 9 | namespace FileSys { |
| 10 | 10 | ||
| 11 | LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name) | 11 | LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs_, std::string name_) |
| 12 | : dirs(std::move(dirs)), name(std::move(name)) {} | 12 | : dirs(std::move(dirs_)), name(std::move(name_)) {} |
| 13 | 13 | ||
| 14 | LayeredVfsDirectory::~LayeredVfsDirectory() = default; | 14 | LayeredVfsDirectory::~LayeredVfsDirectory() = default; |
| 15 | 15 | ||
| @@ -45,12 +45,12 @@ VirtualDir LayeredVfsDirectory::GetDirectoryRelative(std::string_view path) cons | |||
| 45 | return MakeLayeredDirectory(std::move(out)); | 45 | return MakeLayeredDirectory(std::move(out)); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | VirtualFile LayeredVfsDirectory::GetFile(std::string_view name) const { | 48 | VirtualFile LayeredVfsDirectory::GetFile(std::string_view file_name) const { |
| 49 | return GetFileRelative(name); | 49 | return GetFileRelative(file_name); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | VirtualDir LayeredVfsDirectory::GetSubdirectory(std::string_view name) const { | 52 | VirtualDir LayeredVfsDirectory::GetSubdirectory(std::string_view subdir_name) const { |
| 53 | return GetDirectoryRelative(name); | 53 | return GetDirectoryRelative(subdir_name); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | std::string LayeredVfsDirectory::GetFullPath() const { | 56 | std::string LayeredVfsDirectory::GetFullPath() const { |
| @@ -105,24 +105,24 @@ VirtualDir LayeredVfsDirectory::GetParentDirectory() const { | |||
| 105 | return dirs[0]->GetParentDirectory(); | 105 | return dirs[0]->GetParentDirectory(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | VirtualDir LayeredVfsDirectory::CreateSubdirectory(std::string_view name) { | 108 | VirtualDir LayeredVfsDirectory::CreateSubdirectory(std::string_view subdir_name) { |
| 109 | return nullptr; | 109 | return nullptr; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | VirtualFile LayeredVfsDirectory::CreateFile(std::string_view name) { | 112 | VirtualFile LayeredVfsDirectory::CreateFile(std::string_view file_name) { |
| 113 | return nullptr; | 113 | return nullptr; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | bool LayeredVfsDirectory::DeleteSubdirectory(std::string_view name) { | 116 | bool LayeredVfsDirectory::DeleteSubdirectory(std::string_view subdir_name) { |
| 117 | return false; | 117 | return false; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | bool LayeredVfsDirectory::DeleteFile(std::string_view name) { | 120 | bool LayeredVfsDirectory::DeleteFile(std::string_view file_name) { |
| 121 | return false; | 121 | return false; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | bool LayeredVfsDirectory::Rename(std::string_view name_) { | 124 | bool LayeredVfsDirectory::Rename(std::string_view new_name) { |
| 125 | name = name_; | 125 | name = new_name; |
| 126 | return true; | 126 | return true; |
| 127 | } | 127 | } |
| 128 | 128 | ||
diff --git a/src/core/file_sys/vfs_layered.h b/src/core/file_sys/vfs_layered.h index 6d7513ac6..cd6baf28c 100644 --- a/src/core/file_sys/vfs_layered.h +++ b/src/core/file_sys/vfs_layered.h | |||
| @@ -13,7 +13,7 @@ namespace FileSys { | |||
| 13 | // one and falling back to the one after. The highest priority directory (overwrites all others) | 13 | // one and falling back to the one after. The highest priority directory (overwrites all others) |
| 14 | // should be element 0 in the dirs vector. | 14 | // should be element 0 in the dirs vector. |
| 15 | class LayeredVfsDirectory : public VfsDirectory { | 15 | class LayeredVfsDirectory : public VfsDirectory { |
| 16 | LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name); | 16 | explicit LayeredVfsDirectory(std::vector<VirtualDir> dirs_, std::string name_); |
| 17 | 17 | ||
| 18 | public: | 18 | public: |
| 19 | ~LayeredVfsDirectory() override; | 19 | ~LayeredVfsDirectory() override; |
| @@ -23,8 +23,8 @@ public: | |||
| 23 | 23 | ||
| 24 | VirtualFile GetFileRelative(std::string_view path) const override; | 24 | VirtualFile GetFileRelative(std::string_view path) const override; |
| 25 | VirtualDir GetDirectoryRelative(std::string_view path) const override; | 25 | VirtualDir GetDirectoryRelative(std::string_view path) const override; |
| 26 | VirtualFile GetFile(std::string_view name) const override; | 26 | VirtualFile GetFile(std::string_view file_name) const override; |
| 27 | VirtualDir GetSubdirectory(std::string_view name) const override; | 27 | VirtualDir GetSubdirectory(std::string_view subdir_name) const override; |
| 28 | std::string GetFullPath() const override; | 28 | std::string GetFullPath() const override; |
| 29 | 29 | ||
| 30 | std::vector<VirtualFile> GetFiles() const override; | 30 | std::vector<VirtualFile> GetFiles() const override; |
| @@ -33,11 +33,11 @@ public: | |||
| 33 | bool IsReadable() const override; | 33 | bool IsReadable() const override; |
| 34 | std::string GetName() const override; | 34 | std::string GetName() const override; |
| 35 | VirtualDir GetParentDirectory() const override; | 35 | VirtualDir GetParentDirectory() const override; |
| 36 | VirtualDir CreateSubdirectory(std::string_view name) override; | 36 | VirtualDir CreateSubdirectory(std::string_view subdir_name) override; |
| 37 | VirtualFile CreateFile(std::string_view name) override; | 37 | VirtualFile CreateFile(std::string_view file_name) override; |
| 38 | bool DeleteSubdirectory(std::string_view name) override; | 38 | bool DeleteSubdirectory(std::string_view subdir_name) override; |
| 39 | bool DeleteFile(std::string_view name) override; | 39 | bool DeleteFile(std::string_view file_name) override; |
| 40 | bool Rename(std::string_view name) override; | 40 | bool Rename(std::string_view new_name) override; |
| 41 | 41 | ||
| 42 | private: | 42 | private: |
| 43 | std::vector<VirtualDir> dirs; | 43 | std::vector<VirtualDir> dirs; |
diff --git a/src/core/file_sys/vfs_libzip.cpp b/src/core/file_sys/vfs_libzip.cpp index 429d7bc8b..618eb658a 100644 --- a/src/core/file_sys/vfs_libzip.cpp +++ b/src/core/file_sys/vfs_libzip.cpp | |||
| @@ -3,7 +3,16 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string> | 5 | #include <string> |
| 6 | |||
| 7 | #ifdef __GNUC__ | ||
| 8 | #pragma GCC diagnostic push | ||
| 9 | #pragma GCC diagnostic ignored "-Wshadow" | ||
| 10 | #endif | ||
| 6 | #include <zip.h> | 11 | #include <zip.h> |
| 12 | #ifdef __GNUC__ | ||
| 13 | #pragma GCC diagnostic pop | ||
| 14 | #endif | ||
| 15 | |||
| 7 | #include "common/logging/backend.h" | 16 | #include "common/logging/backend.h" |
| 8 | #include "core/file_sys/vfs.h" | 17 | #include "core/file_sys/vfs.h" |
| 9 | #include "core/file_sys/vfs_libzip.h" | 18 | #include "core/file_sys/vfs_libzip.h" |
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp index 056737b54..870ed1cf8 100644 --- a/src/core/file_sys/vfs_offset.cpp +++ b/src/core/file_sys/vfs_offset.cpp | |||
| @@ -84,8 +84,8 @@ std::size_t OffsetVfsFile::WriteBytes(const std::vector<u8>& data, std::size_t r | |||
| 84 | return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset); | 84 | return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | bool OffsetVfsFile::Rename(std::string_view name) { | 87 | bool OffsetVfsFile::Rename(std::string_view new_name) { |
| 88 | return file->Rename(name); | 88 | return file->Rename(new_name); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | std::size_t OffsetVfsFile::GetOffset() const { | 91 | std::size_t OffsetVfsFile::GetOffset() const { |
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h index b2ccc5c7b..42f78b3d9 100644 --- a/src/core/file_sys/vfs_offset.h +++ b/src/core/file_sys/vfs_offset.h | |||
| @@ -35,7 +35,7 @@ public: | |||
| 35 | bool WriteByte(u8 data, std::size_t offset) override; | 35 | bool WriteByte(u8 data, std::size_t offset) override; |
| 36 | std::size_t WriteBytes(const std::vector<u8>& data, std::size_t offset) override; | 36 | std::size_t WriteBytes(const std::vector<u8>& data, std::size_t offset) override; |
| 37 | 37 | ||
| 38 | bool Rename(std::string_view name) override; | 38 | bool Rename(std::string_view new_name) override; |
| 39 | 39 | ||
| 40 | std::size_t GetOffset() const; | 40 | std::size_t GetOffset() const; |
| 41 | 41 | ||
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index a44ce6288..3d89dd644 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -358,16 +358,16 @@ RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& | |||
| 358 | 358 | ||
| 359 | RealVfsDirectory::~RealVfsDirectory() = default; | 359 | RealVfsDirectory::~RealVfsDirectory() = default; |
| 360 | 360 | ||
| 361 | VirtualFile RealVfsDirectory::GetFileRelative(std::string_view path) const { | 361 | VirtualFile RealVfsDirectory::GetFileRelative(std::string_view relative_path) const { |
| 362 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); | 362 | const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); |
| 363 | if (!FS::Exists(full_path) || FS::IsDirectory(full_path)) { | 363 | if (!FS::Exists(full_path) || FS::IsDirectory(full_path)) { |
| 364 | return nullptr; | 364 | return nullptr; |
| 365 | } | 365 | } |
| 366 | return base.OpenFile(full_path, perms); | 366 | return base.OpenFile(full_path, perms); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | VirtualDir RealVfsDirectory::GetDirectoryRelative(std::string_view path) const { | 369 | VirtualDir RealVfsDirectory::GetDirectoryRelative(std::string_view relative_path) const { |
| 370 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); | 370 | const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); |
| 371 | if (!FS::Exists(full_path) || !FS::IsDirectory(full_path)) { | 371 | if (!FS::Exists(full_path) || !FS::IsDirectory(full_path)) { |
| 372 | return nullptr; | 372 | return nullptr; |
| 373 | } | 373 | } |
| @@ -382,13 +382,13 @@ VirtualDir RealVfsDirectory::GetSubdirectory(std::string_view name) const { | |||
| 382 | return GetDirectoryRelative(name); | 382 | return GetDirectoryRelative(name); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | VirtualFile RealVfsDirectory::CreateFileRelative(std::string_view path) { | 385 | VirtualFile RealVfsDirectory::CreateFileRelative(std::string_view relative_path) { |
| 386 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); | 386 | const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); |
| 387 | return base.CreateFile(full_path, perms); | 387 | return base.CreateFile(full_path, perms); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | VirtualDir RealVfsDirectory::CreateDirectoryRelative(std::string_view path) { | 390 | VirtualDir RealVfsDirectory::CreateDirectoryRelative(std::string_view relative_path) { |
| 391 | const auto full_path = FS::SanitizePath(this->path + DIR_SEP + std::string(path)); | 391 | const auto full_path = FS::SanitizePath(path + DIR_SEP + std::string(relative_path)); |
| 392 | return base.CreateDirectory(full_path, perms); | 392 | return base.CreateDirectory(full_path, perms); |
| 393 | } | 393 | } |
| 394 | 394 | ||
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index 23e99865e..0666f2679 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -79,12 +79,12 @@ class RealVfsDirectory : public VfsDirectory { | |||
| 79 | public: | 79 | public: |
| 80 | ~RealVfsDirectory() override; | 80 | ~RealVfsDirectory() override; |
| 81 | 81 | ||
| 82 | VirtualFile GetFileRelative(std::string_view path) const override; | 82 | VirtualFile GetFileRelative(std::string_view relative_path) const override; |
| 83 | VirtualDir GetDirectoryRelative(std::string_view path) const override; | 83 | VirtualDir GetDirectoryRelative(std::string_view relative_path) const override; |
| 84 | VirtualFile GetFile(std::string_view name) const override; | 84 | VirtualFile GetFile(std::string_view name) const override; |
| 85 | VirtualDir GetSubdirectory(std::string_view name) const override; | 85 | VirtualDir GetSubdirectory(std::string_view name) const override; |
| 86 | VirtualFile CreateFileRelative(std::string_view path) override; | 86 | VirtualFile CreateFileRelative(std::string_view relative_path) override; |
| 87 | VirtualDir CreateDirectoryRelative(std::string_view path) override; | 87 | VirtualDir CreateDirectoryRelative(std::string_view relative_path) override; |
| 88 | bool DeleteSubdirectoryRecursive(std::string_view name) override; | 88 | bool DeleteSubdirectoryRecursive(std::string_view name) override; |
| 89 | std::vector<VirtualFile> GetFiles() const override; | 89 | std::vector<VirtualFile> GetFiles() const override; |
| 90 | std::vector<VirtualDir> GetSubdirectories() const override; | 90 | std::vector<VirtualDir> GetSubdirectories() const override; |
diff --git a/src/core/file_sys/vfs_static.h b/src/core/file_sys/vfs_static.h index c840b24b9..f5b66cf71 100644 --- a/src/core/file_sys/vfs_static.h +++ b/src/core/file_sys/vfs_static.h | |||
| @@ -14,9 +14,9 @@ namespace FileSys { | |||
| 14 | 14 | ||
| 15 | class StaticVfsFile : public VfsFile { | 15 | class StaticVfsFile : public VfsFile { |
| 16 | public: | 16 | public: |
| 17 | explicit StaticVfsFile(u8 value, std::size_t size = 0, std::string name = "", | 17 | explicit StaticVfsFile(u8 value_, std::size_t size_ = 0, std::string name_ = "", |
| 18 | VirtualDir parent = nullptr) | 18 | VirtualDir parent_ = nullptr) |
| 19 | : value{value}, size{size}, name{std::move(name)}, parent{std::move(parent)} {} | 19 | : value{value_}, size{size_}, name{std::move(name_)}, parent{std::move(parent_)} {} |
| 20 | 20 | ||
| 21 | std::string GetName() const override { | 21 | std::string GetName() const override { |
| 22 | return name; | 22 | return name; |
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp index c1ec1e645..f64b88639 100644 --- a/src/core/file_sys/vfs_vector.cpp +++ b/src/core/file_sys/vfs_vector.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include "core/file_sys/vfs_vector.h" | 7 | #include "core/file_sys/vfs_vector.h" |
| 8 | 8 | ||
| 9 | namespace FileSys { | 9 | namespace FileSys { |
| 10 | VectorVfsFile::VectorVfsFile(std::vector<u8> initial_data, std::string name, VirtualDir parent) | 10 | VectorVfsFile::VectorVfsFile(std::vector<u8> initial_data, std::string name_, VirtualDir parent_) |
| 11 | : data(std::move(initial_data)), parent(std::move(parent)), name(std::move(name)) {} | 11 | : data(std::move(initial_data)), parent(std::move(parent_)), name(std::move(name_)) {} |
| 12 | 12 | ||
| 13 | VectorVfsFile::~VectorVfsFile() = default; | 13 | VectorVfsFile::~VectorVfsFile() = default; |
| 14 | 14 | ||
| @@ -103,12 +103,12 @@ static bool FindAndRemoveVectorElement(std::vector<T>& vec, std::string_view nam | |||
| 103 | return true; | 103 | return true; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | bool VectorVfsDirectory::DeleteSubdirectory(std::string_view name) { | 106 | bool VectorVfsDirectory::DeleteSubdirectory(std::string_view subdir_name) { |
| 107 | return FindAndRemoveVectorElement(dirs, name); | 107 | return FindAndRemoveVectorElement(dirs, subdir_name); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | bool VectorVfsDirectory::DeleteFile(std::string_view name) { | 110 | bool VectorVfsDirectory::DeleteFile(std::string_view file_name) { |
| 111 | return FindAndRemoveVectorElement(files, name); | 111 | return FindAndRemoveVectorElement(files, file_name); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | bool VectorVfsDirectory::Rename(std::string_view name_) { | 114 | bool VectorVfsDirectory::Rename(std::string_view name_) { |
| @@ -116,11 +116,11 @@ bool VectorVfsDirectory::Rename(std::string_view name_) { | |||
| 116 | return true; | 116 | return true; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | VirtualDir VectorVfsDirectory::CreateSubdirectory(std::string_view name) { | 119 | VirtualDir VectorVfsDirectory::CreateSubdirectory(std::string_view subdir_name) { |
| 120 | return nullptr; | 120 | return nullptr; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | VirtualFile VectorVfsDirectory::CreateFile(std::string_view name) { | 123 | VirtualFile VectorVfsDirectory::CreateFile(std::string_view file_name) { |
| 124 | return nullptr; | 124 | return nullptr; |
| 125 | } | 125 | } |
| 126 | 126 | ||
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index 2aff9ca34..73f180070 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -75,8 +75,8 @@ std::shared_ptr<ArrayVfsFile<Size>> MakeArrayFile(const std::array<u8, Size>& da | |||
| 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction | 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction |
| 76 | class VectorVfsFile : public VfsFile { | 76 | class VectorVfsFile : public VfsFile { |
| 77 | public: | 77 | public: |
| 78 | explicit VectorVfsFile(std::vector<u8> initial_data = {}, std::string name = "", | 78 | explicit VectorVfsFile(std::vector<u8> initial_data = {}, std::string name_ = "", |
| 79 | VirtualDir parent = nullptr); | 79 | VirtualDir parent_ = nullptr); |
| 80 | ~VectorVfsFile() override; | 80 | ~VectorVfsFile() override; |
| 81 | 81 | ||
| 82 | std::string GetName() const override; | 82 | std::string GetName() const override; |
| @@ -112,11 +112,11 @@ public: | |||
| 112 | bool IsReadable() const override; | 112 | bool IsReadable() const override; |
| 113 | std::string GetName() const override; | 113 | std::string GetName() const override; |
| 114 | VirtualDir GetParentDirectory() const override; | 114 | VirtualDir GetParentDirectory() const override; |
| 115 | bool DeleteSubdirectory(std::string_view name) override; | 115 | bool DeleteSubdirectory(std::string_view subdir_name) override; |
| 116 | bool DeleteFile(std::string_view name) override; | 116 | bool DeleteFile(std::string_view file_name) override; |
| 117 | bool Rename(std::string_view name) override; | 117 | bool Rename(std::string_view name) override; |
| 118 | VirtualDir CreateSubdirectory(std::string_view name) override; | 118 | VirtualDir CreateSubdirectory(std::string_view subdir_name) override; |
| 119 | VirtualFile CreateFile(std::string_view name) override; | 119 | VirtualFile CreateFile(std::string_view file_name) override; |
| 120 | 120 | ||
| 121 | virtual void AddFile(VirtualFile file); | 121 | virtual void AddFile(VirtualFile file); |
| 122 | virtual void AddDirectory(VirtualDir dir); | 122 | virtual void AddDirectory(VirtualDir dir); |
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 50db6a654..be4736f47 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp | |||
| @@ -12,7 +12,7 @@ WebBrowserApplet::~WebBrowserApplet() = default; | |||
| 12 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; | 12 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; |
| 13 | 13 | ||
| 14 | void DefaultWebBrowserApplet::OpenLocalWebPage( | 14 | void DefaultWebBrowserApplet::OpenLocalWebPage( |
| 15 | std::string_view local_url, std::function<void()> extract_romfs_callback, | 15 | const std::string& local_url, std::function<void()> extract_romfs_callback, |
| 16 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { | 16 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { |
| 17 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", | 17 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", |
| 18 | local_url); | 18 | local_url); |
| @@ -21,7 +21,7 @@ void DefaultWebBrowserApplet::OpenLocalWebPage( | |||
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | void DefaultWebBrowserApplet::OpenExternalWebPage( | 23 | void DefaultWebBrowserApplet::OpenExternalWebPage( |
| 24 | std::string_view external_url, | 24 | const std::string& external_url, |
| 25 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { | 25 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { |
| 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); |
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index 1c5ef19a9..d7bd44c27 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h | |||
| @@ -16,11 +16,11 @@ public: | |||
| 16 | virtual ~WebBrowserApplet(); | 16 | virtual ~WebBrowserApplet(); |
| 17 | 17 | ||
| 18 | virtual void OpenLocalWebPage( | 18 | virtual void OpenLocalWebPage( |
| 19 | std::string_view local_url, std::function<void()> extract_romfs_callback, | 19 | const std::string& local_url, std::function<void()> extract_romfs_callback, |
| 20 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; | 20 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; |
| 21 | 21 | ||
| 22 | virtual void OpenExternalWebPage( | 22 | virtual void OpenExternalWebPage( |
| 23 | std::string_view external_url, | 23 | const std::string& external_url, |
| 24 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; | 24 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| @@ -28,11 +28,12 @@ class DefaultWebBrowserApplet final : public WebBrowserApplet { | |||
| 28 | public: | 28 | public: |
| 29 | ~DefaultWebBrowserApplet() override; | 29 | ~DefaultWebBrowserApplet() override; |
| 30 | 30 | ||
| 31 | void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback, | 31 | void OpenLocalWebPage(const std::string& local_url, |
| 32 | std::function<void()> extract_romfs_callback, | ||
| 32 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 33 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> |
| 33 | callback) const override; | 34 | callback) const override; |
| 34 | 35 | ||
| 35 | void OpenExternalWebPage(std::string_view external_url, | 36 | void OpenExternalWebPage(const std::string& external_url, |
| 36 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 37 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> |
| 37 | callback) const override; | 38 | callback) const override; |
| 38 | }; | 39 | }; |
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index cff49899a..e11ec0b0b 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | private: | 26 | private: |
| 27 | class Device : public Input::TouchDevice { | 27 | class Device : public Input::TouchDevice { |
| 28 | public: | 28 | public: |
| 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} | 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state_) : touch_state(touch_state_) {} |
| 30 | Input::TouchStatus GetStatus() const override { | 30 | Input::TouchStatus GetStatus() const override { |
| 31 | if (auto state = touch_state.lock()) { | 31 | if (auto state = touch_state.lock()) { |
| 32 | std::lock_guard guard{state->mutex}; | 32 | std::lock_guard guard{state->mutex}; |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 88ebc6497..0c5d2b3b0 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <utility> | 11 | #include <utility> |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/param_package.h" | 13 | #include "common/param_package.h" |
| 14 | #include "common/quaternion.h" | ||
| 14 | #include "common/vector_math.h" | 15 | #include "common/vector_math.h" |
| 15 | 16 | ||
| 16 | namespace Input { | 17 | namespace Input { |
| @@ -143,9 +144,10 @@ using VibrationDevice = InputDevice<u8>; | |||
| 143 | 144 | ||
| 144 | /** | 145 | /** |
| 145 | * A motion status is an object that returns a tuple of accelerometer state vector, | 146 | * A motion status is an object that returns a tuple of accelerometer state vector, |
| 146 | * gyroscope state vector, rotation state vector and orientation state matrix. | 147 | * gyroscope state vector, rotation state vector, orientation state matrix and quaterion state |
| 148 | * vector. | ||
| 147 | * | 149 | * |
| 148 | * For both vectors: | 150 | * For both 3D vectors: |
| 149 | * x+ is the same direction as RIGHT on D-pad. | 151 | * x+ is the same direction as RIGHT on D-pad. |
| 150 | * y+ is normal to the touch screen, pointing outward. | 152 | * y+ is normal to the touch screen, pointing outward. |
| 151 | * z+ is the same direction as UP on D-pad. | 153 | * z+ is the same direction as UP on D-pad. |
| @@ -164,9 +166,13 @@ using VibrationDevice = InputDevice<u8>; | |||
| 164 | * x vector | 166 | * x vector |
| 165 | * y vector | 167 | * y vector |
| 166 | * z vector | 168 | * z vector |
| 169 | * | ||
| 170 | * For quaternion state vector | ||
| 171 | * xyz vector | ||
| 172 | * w float | ||
| 167 | */ | 173 | */ |
| 168 | using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>, | 174 | using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>, |
| 169 | std::array<Common::Vec3f, 3>>; | 175 | std::array<Common::Vec3f, 3>, Common::Quaternion<f32>>; |
| 170 | 176 | ||
| 171 | /** | 177 | /** |
| 172 | * A motion device is an input device that returns a motion status object | 178 | * A motion device is an input device that returns a motion status object |
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 55b1716e4..602e12606 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -32,7 +32,8 @@ enum class CommandType : u32 { | |||
| 32 | Control = 5, | 32 | Control = 5, |
| 33 | RequestWithContext = 6, | 33 | RequestWithContext = 6, |
| 34 | ControlWithContext = 7, | 34 | ControlWithContext = 7, |
| 35 | Unspecified, | 35 | TIPC_Close = 15, |
| 36 | TIPC_CommandRegion = 16, // Start of TIPC commands, this is an offset. | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | struct CommandHeader { | 39 | struct CommandHeader { |
| @@ -57,6 +58,20 @@ struct CommandHeader { | |||
| 57 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; | 58 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; |
| 58 | BitField<31, 1, u32> enable_handle_descriptor; | 59 | BitField<31, 1, u32> enable_handle_descriptor; |
| 59 | }; | 60 | }; |
| 61 | |||
| 62 | bool IsTipc() const { | ||
| 63 | return type.Value() >= CommandType::TIPC_CommandRegion; | ||
| 64 | } | ||
| 65 | |||
| 66 | bool IsCloseCommand() const { | ||
| 67 | switch (type.Value()) { | ||
| 68 | case CommandType::Close: | ||
| 69 | case CommandType::TIPC_Close: | ||
| 70 | return true; | ||
| 71 | default: | ||
| 72 | return false; | ||
| 73 | } | ||
| 74 | } | ||
| 60 | }; | 75 | }; |
| 61 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); | 76 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); |
| 62 | 77 | ||
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 56cc911d1..497f35d23 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -13,12 +13,11 @@ | |||
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "core/hle/ipc.h" | 15 | #include "core/hle/ipc.h" |
| 16 | #include "core/hle/kernel/client_port.h" | ||
| 17 | #include "core/hle/kernel/client_session.h" | ||
| 18 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 19 | #include "core/hle/kernel/object.h" | 17 | #include "core/hle/kernel/k_client_port.h" |
| 20 | #include "core/hle/kernel/server_session.h" | 18 | #include "core/hle/kernel/k_process.h" |
| 21 | #include "core/hle/kernel/session.h" | 19 | #include "core/hle/kernel/k_resource_limit.h" |
| 20 | #include "core/hle/kernel/k_session.h" | ||
| 22 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| 23 | 22 | ||
| 24 | namespace IPC { | 23 | namespace IPC { |
| @@ -29,19 +28,19 @@ class RequestHelperBase { | |||
| 29 | protected: | 28 | protected: |
| 30 | Kernel::HLERequestContext* context = nullptr; | 29 | Kernel::HLERequestContext* context = nullptr; |
| 31 | u32* cmdbuf; | 30 | u32* cmdbuf; |
| 32 | ptrdiff_t index = 0; | 31 | u32 index = 0; |
| 33 | 32 | ||
| 34 | public: | 33 | public: |
| 35 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} | 34 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} |
| 36 | 35 | ||
| 37 | explicit RequestHelperBase(Kernel::HLERequestContext& context) | 36 | explicit RequestHelperBase(Kernel::HLERequestContext& ctx) |
| 38 | : context(&context), cmdbuf(context.CommandBuffer()) {} | 37 | : context(&ctx), cmdbuf(ctx.CommandBuffer()) {} |
| 39 | 38 | ||
| 40 | void Skip(u32 size_in_words, bool set_to_null) { | 39 | void Skip(u32 size_in_words, bool set_to_null) { |
| 41 | if (set_to_null) { | 40 | if (set_to_null) { |
| 42 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); | 41 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); |
| 43 | } | 42 | } |
| 44 | index += static_cast<ptrdiff_t>(size_in_words); | 43 | index += size_in_words; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | /** | 46 | /** |
| @@ -54,11 +53,11 @@ public: | |||
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | u32 GetCurrentOffset() const { | 55 | u32 GetCurrentOffset() const { |
| 57 | return static_cast<u32>(index); | 56 | return index; |
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | void SetCurrentOffset(u32 offset) { | 59 | void SetCurrentOffset(u32 offset) { |
| 61 | index = static_cast<ptrdiff_t>(offset); | 60 | index = offset; |
| 62 | } | 61 | } |
| 63 | }; | 62 | }; |
| 64 | 63 | ||
| @@ -72,64 +71,79 @@ public: | |||
| 72 | AlwaysMoveHandles = 1, | 71 | AlwaysMoveHandles = 1, |
| 73 | }; | 72 | }; |
| 74 | 73 | ||
| 75 | explicit ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, | 74 | explicit ResponseBuilder(Kernel::HLERequestContext& ctx, u32 normal_params_size_, |
| 76 | u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, | 75 | u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0, |
| 77 | Flags flags = Flags::None) | 76 | Flags flags = Flags::None) |
| 78 | : RequestHelperBase(context), normal_params_size(normal_params_size), | 77 | : RequestHelperBase(ctx), normal_params_size(normal_params_size_), |
| 79 | num_handles_to_copy(num_handles_to_copy), | 78 | num_handles_to_copy(num_handles_to_copy_), |
| 80 | num_objects_to_move(num_objects_to_move), kernel{context.kernel} { | 79 | num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} { |
| 81 | 80 | ||
| 82 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | 81 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); |
| 83 | 82 | ||
| 84 | context.ClearIncomingObjects(); | 83 | ctx.ClearIncomingObjects(); |
| 85 | 84 | ||
| 86 | IPC::CommandHeader header{}; | 85 | IPC::CommandHeader header{}; |
| 87 | 86 | ||
| 88 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | 87 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory |
| 89 | // padding. | 88 | // padding. |
| 90 | u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | 89 | u32 raw_data_size = ctx.IsTipc() |
| 90 | ? normal_params_size - 1 | ||
| 91 | : sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | ||
| 91 | 92 | ||
| 92 | u32 num_handles_to_move{}; | 93 | u32 num_handles_to_move{}; |
| 93 | u32 num_domain_objects{}; | 94 | u32 num_domain_objects{}; |
| 94 | const bool always_move_handles{ | 95 | const bool always_move_handles{ |
| 95 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; | 96 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; |
| 96 | if (!context.Session()->IsDomain() || always_move_handles) { | 97 | if (!ctx.Session()->IsDomain() || always_move_handles) { |
| 97 | num_handles_to_move = num_objects_to_move; | 98 | num_handles_to_move = num_objects_to_move; |
| 98 | } else { | 99 | } else { |
| 99 | num_domain_objects = num_objects_to_move; | 100 | num_domain_objects = num_objects_to_move; |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | if (context.Session()->IsDomain()) { | 103 | if (ctx.Session()->IsDomain()) { |
| 103 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | 104 | raw_data_size += static_cast<u32>(sizeof(DomainMessageHeader) / 4 + num_domain_objects); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 107 | if (ctx.IsTipc()) { | ||
| 108 | header.type.Assign(ctx.GetCommandType()); | ||
| 109 | } | ||
| 110 | |||
| 111 | ctx.data_size = static_cast<u32>(raw_data_size); | ||
| 106 | header.data_size.Assign(static_cast<u32>(raw_data_size)); | 112 | header.data_size.Assign(static_cast<u32>(raw_data_size)); |
| 107 | if (num_handles_to_copy || num_handles_to_move) { | 113 | if (num_handles_to_copy != 0 || num_handles_to_move != 0) { |
| 108 | header.enable_handle_descriptor.Assign(1); | 114 | header.enable_handle_descriptor.Assign(1); |
| 109 | } | 115 | } |
| 110 | PushRaw(header); | 116 | PushRaw(header); |
| 111 | 117 | ||
| 112 | if (header.enable_handle_descriptor) { | 118 | if (header.enable_handle_descriptor) { |
| 113 | IPC::HandleDescriptorHeader handle_descriptor_header{}; | 119 | IPC::HandleDescriptorHeader handle_descriptor_header{}; |
| 114 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy); | 120 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy_); |
| 115 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); | 121 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); |
| 116 | PushRaw(handle_descriptor_header); | 122 | PushRaw(handle_descriptor_header); |
| 123 | |||
| 124 | ctx.handles_offset = index; | ||
| 125 | |||
| 117 | Skip(num_handles_to_copy + num_handles_to_move, true); | 126 | Skip(num_handles_to_copy + num_handles_to_move, true); |
| 118 | } | 127 | } |
| 119 | 128 | ||
| 120 | AlignWithPadding(); | 129 | if (!ctx.IsTipc()) { |
| 130 | AlignWithPadding(); | ||
| 121 | 131 | ||
| 122 | if (context.Session()->IsDomain() && context.HasDomainMessageHeader()) { | 132 | if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { |
| 123 | IPC::DomainMessageHeader domain_header{}; | 133 | IPC::DomainMessageHeader domain_header{}; |
| 124 | domain_header.num_objects = num_domain_objects; | 134 | domain_header.num_objects = num_domain_objects; |
| 125 | PushRaw(domain_header); | 135 | PushRaw(domain_header); |
| 136 | } | ||
| 137 | |||
| 138 | IPC::DataPayloadHeader data_payload_header{}; | ||
| 139 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 140 | PushRaw(data_payload_header); | ||
| 126 | } | 141 | } |
| 127 | 142 | ||
| 128 | IPC::DataPayloadHeader data_payload_header{}; | 143 | data_payload_index = index; |
| 129 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 130 | PushRaw(data_payload_header); | ||
| 131 | 144 | ||
| 132 | datapayload_index = index; | 145 | ctx.data_payload_offset = index; |
| 146 | ctx.domain_offset = index + raw_data_size / 4; | ||
| 133 | } | 147 | } |
| 134 | 148 | ||
| 135 | template <class T> | 149 | template <class T> |
| @@ -137,9 +151,14 @@ public: | |||
| 137 | if (context->Session()->IsDomain()) { | 151 | if (context->Session()->IsDomain()) { |
| 138 | context->AddDomainObject(std::move(iface)); | 152 | context->AddDomainObject(std::move(iface)); |
| 139 | } else { | 153 | } else { |
| 140 | auto [client, server] = Kernel::Session::Create(kernel, iface->GetServiceName()); | 154 | // kernel.CurrentProcess()->GetResourceLimit()->Reserve( |
| 141 | context->AddMoveObject(std::move(client)); | 155 | // Kernel::LimitableResource::Sessions, 1); |
| 142 | iface->ClientConnected(std::move(server)); | 156 | |
| 157 | auto* session = Kernel::KSession::Create(kernel); | ||
| 158 | session->Initialize(nullptr, iface->GetServiceName()); | ||
| 159 | |||
| 160 | context->AddMoveObject(&session->GetClientSession()); | ||
| 161 | iface->ClientConnected(&session->GetServerSession()); | ||
| 143 | } | 162 | } |
| 144 | } | 163 | } |
| 145 | 164 | ||
| @@ -153,7 +172,7 @@ public: | |||
| 153 | const std::size_t num_move_objects = context->NumMoveObjects(); | 172 | const std::size_t num_move_objects = context->NumMoveObjects(); |
| 154 | ASSERT_MSG(!num_domain_objects || !num_move_objects, | 173 | ASSERT_MSG(!num_domain_objects || !num_move_objects, |
| 155 | "cannot move normal handles and domain objects"); | 174 | "cannot move normal handles and domain objects"); |
| 156 | ASSERT_MSG((index - datapayload_index) == normal_params_size, | 175 | ASSERT_MSG((index - data_payload_index) == normal_params_size, |
| 157 | "normal_params_size value is incorrect"); | 176 | "normal_params_size value is incorrect"); |
| 158 | ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, | 177 | ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, |
| 159 | "num_objects_to_move value is incorrect"); | 178 | "num_objects_to_move value is incorrect"); |
| @@ -215,23 +234,29 @@ public: | |||
| 215 | void PushRaw(const T& value); | 234 | void PushRaw(const T& value); |
| 216 | 235 | ||
| 217 | template <typename... O> | 236 | template <typename... O> |
| 218 | void PushMoveObjects(std::shared_ptr<O>... pointers); | 237 | void PushMoveObjects(O*... pointers); |
| 238 | |||
| 239 | template <typename... O> | ||
| 240 | void PushMoveObjects(O&... pointers); | ||
| 241 | |||
| 242 | template <typename... O> | ||
| 243 | void PushCopyObjects(O*... pointers); | ||
| 219 | 244 | ||
| 220 | template <typename... O> | 245 | template <typename... O> |
| 221 | void PushCopyObjects(std::shared_ptr<O>... pointers); | 246 | void PushCopyObjects(O&... pointers); |
| 222 | 247 | ||
| 223 | private: | 248 | private: |
| 224 | u32 normal_params_size{}; | 249 | u32 normal_params_size{}; |
| 225 | u32 num_handles_to_copy{}; | 250 | u32 num_handles_to_copy{}; |
| 226 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent | 251 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent |
| 227 | std::ptrdiff_t datapayload_index{}; | 252 | u32 data_payload_index{}; |
| 228 | Kernel::KernelCore& kernel; | 253 | Kernel::KernelCore& kernel; |
| 229 | }; | 254 | }; |
| 230 | 255 | ||
| 231 | /// Push /// | 256 | /// Push /// |
| 232 | 257 | ||
| 233 | inline void ResponseBuilder::PushImpl(s32 value) { | 258 | inline void ResponseBuilder::PushImpl(s32 value) { |
| 234 | cmdbuf[index++] = static_cast<u32>(value); | 259 | cmdbuf[index++] = value; |
| 235 | } | 260 | } |
| 236 | 261 | ||
| 237 | inline void ResponseBuilder::PushImpl(u32 value) { | 262 | inline void ResponseBuilder::PushImpl(u32 value) { |
| @@ -301,18 +326,34 @@ void ResponseBuilder::Push(const First& first_value, const Other&... other_value | |||
| 301 | } | 326 | } |
| 302 | 327 | ||
| 303 | template <typename... O> | 328 | template <typename... O> |
| 304 | inline void ResponseBuilder::PushCopyObjects(std::shared_ptr<O>... pointers) { | 329 | inline void ResponseBuilder::PushCopyObjects(O*... pointers) { |
| 305 | auto objects = {pointers...}; | 330 | auto objects = {pointers...}; |
| 306 | for (auto& object : objects) { | 331 | for (auto& object : objects) { |
| 307 | context->AddCopyObject(std::move(object)); | 332 | context->AddCopyObject(object); |
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | template <typename... O> | ||
| 337 | inline void ResponseBuilder::PushCopyObjects(O&... pointers) { | ||
| 338 | auto objects = {&pointers...}; | ||
| 339 | for (auto& object : objects) { | ||
| 340 | context->AddCopyObject(object); | ||
| 308 | } | 341 | } |
| 309 | } | 342 | } |
| 310 | 343 | ||
| 311 | template <typename... O> | 344 | template <typename... O> |
| 312 | inline void ResponseBuilder::PushMoveObjects(std::shared_ptr<O>... pointers) { | 345 | inline void ResponseBuilder::PushMoveObjects(O*... pointers) { |
| 313 | auto objects = {pointers...}; | 346 | auto objects = {pointers...}; |
| 314 | for (auto& object : objects) { | 347 | for (auto& object : objects) { |
| 315 | context->AddMoveObject(std::move(object)); | 348 | context->AddMoveObject(object); |
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | template <typename... O> | ||
| 353 | inline void ResponseBuilder::PushMoveObjects(O&... pointers) { | ||
| 354 | auto objects = {&pointers...}; | ||
| 355 | for (auto& object : objects) { | ||
| 356 | context->AddMoveObject(object); | ||
| 316 | } | 357 | } |
| 317 | } | 358 | } |
| 318 | 359 | ||
| @@ -320,9 +361,9 @@ class RequestParser : public RequestHelperBase { | |||
| 320 | public: | 361 | public: |
| 321 | explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} | 362 | explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} |
| 322 | 363 | ||
| 323 | explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { | 364 | explicit RequestParser(Kernel::HLERequestContext& ctx) : RequestHelperBase(ctx) { |
| 324 | ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); | 365 | ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete"); |
| 325 | Skip(context.GetDataPayloadOffset(), false); | 366 | Skip(ctx.GetDataPayloadOffset(), false); |
| 326 | // Skip the u64 command id, it's already stored in the context | 367 | // Skip the u64 command id, it's already stored in the context |
| 327 | static constexpr u32 CommandIdSize = 2; | 368 | static constexpr u32 CommandIdSize = 2; |
| 328 | Skip(CommandIdSize, false); | 369 | Skip(CommandIdSize, false); |
| @@ -359,12 +400,6 @@ public: | |||
| 359 | template <typename T> | 400 | template <typename T> |
| 360 | T PopRaw(); | 401 | T PopRaw(); |
| 361 | 402 | ||
| 362 | template <typename T> | ||
| 363 | std::shared_ptr<T> GetMoveObject(std::size_t index); | ||
| 364 | |||
| 365 | template <typename T> | ||
| 366 | std::shared_ptr<T> GetCopyObject(std::size_t index); | ||
| 367 | |||
| 368 | template <class T> | 403 | template <class T> |
| 369 | std::shared_ptr<T> PopIpcInterface() { | 404 | std::shared_ptr<T> PopIpcInterface() { |
| 370 | ASSERT(context->Session()->IsDomain()); | 405 | ASSERT(context->Session()->IsDomain()); |
| @@ -469,14 +504,4 @@ void RequestParser::Pop(First& first_value, Other&... other_values) { | |||
| 469 | Pop(other_values...); | 504 | Pop(other_values...); |
| 470 | } | 505 | } |
| 471 | 506 | ||
| 472 | template <typename T> | ||
| 473 | std::shared_ptr<T> RequestParser::GetMoveObject(std::size_t index) { | ||
| 474 | return context->GetMoveObject<T>(index); | ||
| 475 | } | ||
| 476 | |||
| 477 | template <typename T> | ||
| 478 | std::shared_ptr<T> RequestParser::GetCopyObject(std::size_t index) { | ||
| 479 | return context->GetCopyObject<T>(index); | ||
| 480 | } | ||
| 481 | |||
| 482 | } // namespace IPC | 507 | } // namespace IPC |
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp deleted file mode 100644 index 0b6957e31..000000000 --- a/src/core/hle/kernel/client_port.cpp +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/client_port.h" | ||
| 6 | #include "core/hle/kernel/client_session.h" | ||
| 7 | #include "core/hle/kernel/hle_ipc.h" | ||
| 8 | #include "core/hle/kernel/object.h" | ||
| 9 | #include "core/hle/kernel/server_port.h" | ||
| 10 | #include "core/hle/kernel/session.h" | ||
| 11 | #include "core/hle/kernel/svc_results.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | ClientPort::ClientPort(KernelCore& kernel) : Object{kernel} {} | ||
| 16 | ClientPort::~ClientPort() = default; | ||
| 17 | |||
| 18 | std::shared_ptr<ServerPort> ClientPort::GetServerPort() const { | ||
| 19 | return server_port; | ||
| 20 | } | ||
| 21 | |||
| 22 | ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() { | ||
| 23 | if (active_sessions >= max_sessions) { | ||
| 24 | return ResultMaxConnectionsReached; | ||
| 25 | } | ||
| 26 | active_sessions++; | ||
| 27 | |||
| 28 | auto [client, server] = Kernel::Session::Create(kernel, name); | ||
| 29 | |||
| 30 | if (server_port->HasHLEHandler()) { | ||
| 31 | server_port->GetHLEHandler()->ClientConnected(std::move(server)); | ||
| 32 | } else { | ||
| 33 | server_port->AppendPendingSession(std::move(server)); | ||
| 34 | } | ||
| 35 | |||
| 36 | return MakeResult(std::move(client)); | ||
| 37 | } | ||
| 38 | |||
| 39 | void ClientPort::ConnectionClosed() { | ||
| 40 | if (active_sessions == 0) { | ||
| 41 | return; | ||
| 42 | } | ||
| 43 | |||
| 44 | --active_sessions; | ||
| 45 | } | ||
| 46 | |||
| 47 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h deleted file mode 100644 index 77559ebf9..000000000 --- a/src/core/hle/kernel/client_port.h +++ /dev/null | |||
| @@ -1,63 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/kernel/object.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | class ClientSession; | ||
| 17 | class KernelCore; | ||
| 18 | class ServerPort; | ||
| 19 | |||
| 20 | class ClientPort final : public Object { | ||
| 21 | public: | ||
| 22 | explicit ClientPort(KernelCore& kernel); | ||
| 23 | ~ClientPort() override; | ||
| 24 | |||
| 25 | friend class ServerPort; | ||
| 26 | std::string GetTypeName() const override { | ||
| 27 | return "ClientPort"; | ||
| 28 | } | ||
| 29 | std::string GetName() const override { | ||
| 30 | return name; | ||
| 31 | } | ||
| 32 | |||
| 33 | static constexpr HandleType HANDLE_TYPE = HandleType::ClientPort; | ||
| 34 | HandleType GetHandleType() const override { | ||
| 35 | return HANDLE_TYPE; | ||
| 36 | } | ||
| 37 | |||
| 38 | std::shared_ptr<ServerPort> GetServerPort() const; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Creates a new Session pair, adds the created ServerSession to the associated ServerPort's | ||
| 42 | * list of pending sessions, and signals the ServerPort, causing any threads | ||
| 43 | * waiting on it to awake. | ||
| 44 | * @returns ClientSession The client endpoint of the created Session pair, or error code. | ||
| 45 | */ | ||
| 46 | ResultVal<std::shared_ptr<ClientSession>> Connect(); | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Signifies that a previously active connection has been closed, | ||
| 50 | * decreasing the total number of active connections to this port. | ||
| 51 | */ | ||
| 52 | void ConnectionClosed(); | ||
| 53 | |||
| 54 | void Finalize() override {} | ||
| 55 | |||
| 56 | private: | ||
| 57 | std::shared_ptr<ServerPort> server_port; ///< ServerPort associated with this client port. | ||
| 58 | u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have | ||
| 59 | u32 active_sessions = 0; ///< Number of currently open sessions to this port | ||
| 60 | std::string name; ///< Name of client port (optional) | ||
| 61 | }; | ||
| 62 | |||
| 63 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp deleted file mode 100644 index e230f365a..000000000 --- a/src/core/hle/kernel/client_session.cpp +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/client_session.h" | ||
| 6 | #include "core/hle/kernel/hle_ipc.h" | ||
| 7 | #include "core/hle/kernel/k_thread.h" | ||
| 8 | #include "core/hle/kernel/server_session.h" | ||
| 9 | #include "core/hle/kernel/session.h" | ||
| 10 | #include "core/hle/kernel/svc_results.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | ClientSession::ClientSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} | ||
| 16 | |||
| 17 | ClientSession::~ClientSession() { | ||
| 18 | // This destructor will be called automatically when the last ClientSession handle is closed by | ||
| 19 | // the emulated application. | ||
| 20 | if (parent->Server()) { | ||
| 21 | parent->Server()->ClientDisconnected(); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | bool ClientSession::IsSignaled() const { | ||
| 26 | UNIMPLEMENTED(); | ||
| 27 | return true; | ||
| 28 | } | ||
| 29 | |||
| 30 | ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel, | ||
| 31 | std::shared_ptr<Session> parent, | ||
| 32 | std::string name) { | ||
| 33 | std::shared_ptr<ClientSession> client_session{std::make_shared<ClientSession>(kernel)}; | ||
| 34 | |||
| 35 | client_session->name = std::move(name); | ||
| 36 | client_session->parent = std::move(parent); | ||
| 37 | |||
| 38 | return MakeResult(std::move(client_session)); | ||
| 39 | } | ||
| 40 | |||
| 41 | ResultCode ClientSession::SendSyncRequest(std::shared_ptr<KThread> thread, | ||
| 42 | Core::Memory::Memory& memory, | ||
| 43 | Core::Timing::CoreTiming& core_timing) { | ||
| 44 | // Keep ServerSession alive until we're done working with it. | ||
| 45 | if (!parent->Server()) { | ||
| 46 | return ResultSessionClosedByRemote; | ||
| 47 | } | ||
| 48 | |||
| 49 | // Signal the server session that new data is available | ||
| 50 | return parent->Server()->HandleSyncRequest(std::move(thread), memory, core_timing); | ||
| 51 | } | ||
| 52 | |||
| 53 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h deleted file mode 100644 index 85aafeaf4..000000000 --- a/src/core/hle/kernel/client_session.h +++ /dev/null | |||
| @@ -1,68 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | union ResultCode; | ||
| 14 | |||
| 15 | namespace Core::Memory { | ||
| 16 | class Memory; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Core::Timing { | ||
| 20 | class CoreTiming; | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace Kernel { | ||
| 24 | |||
| 25 | class KernelCore; | ||
| 26 | class Session; | ||
| 27 | class KThread; | ||
| 28 | |||
| 29 | class ClientSession final : public KSynchronizationObject { | ||
| 30 | public: | ||
| 31 | explicit ClientSession(KernelCore& kernel); | ||
| 32 | ~ClientSession() override; | ||
| 33 | |||
| 34 | friend class Session; | ||
| 35 | |||
| 36 | std::string GetTypeName() const override { | ||
| 37 | return "ClientSession"; | ||
| 38 | } | ||
| 39 | |||
| 40 | std::string GetName() const override { | ||
| 41 | return name; | ||
| 42 | } | ||
| 43 | |||
| 44 | static constexpr HandleType HANDLE_TYPE = HandleType::ClientSession; | ||
| 45 | HandleType GetHandleType() const override { | ||
| 46 | return HANDLE_TYPE; | ||
| 47 | } | ||
| 48 | |||
| 49 | ResultCode SendSyncRequest(std::shared_ptr<KThread> thread, Core::Memory::Memory& memory, | ||
| 50 | Core::Timing::CoreTiming& core_timing); | ||
| 51 | |||
| 52 | bool IsSignaled() const override; | ||
| 53 | |||
| 54 | void Finalize() override {} | ||
| 55 | |||
| 56 | private: | ||
| 57 | static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel, | ||
| 58 | std::shared_ptr<Session> parent, | ||
| 59 | std::string name = "Unknown"); | ||
| 60 | |||
| 61 | /// The parent session, which links to the server endpoint. | ||
| 62 | std::shared_ptr<Session> parent; | ||
| 63 | |||
| 64 | /// Name of the client session (optional) | ||
| 65 | std::string name; | ||
| 66 | }; | ||
| 67 | |||
| 68 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp index c6838649f..4f4e338e3 100644 --- a/src/core/hle/kernel/global_scheduler_context.cpp +++ b/src/core/hle/kernel/global_scheduler_context.cpp | |||
| @@ -12,17 +12,17 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) | 15 | GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel_) |
| 16 | : kernel{kernel}, scheduler_lock{kernel} {} | 16 | : kernel{kernel_}, scheduler_lock{kernel_} {} |
| 17 | 17 | ||
| 18 | GlobalSchedulerContext::~GlobalSchedulerContext() = default; | 18 | GlobalSchedulerContext::~GlobalSchedulerContext() = default; |
| 19 | 19 | ||
| 20 | void GlobalSchedulerContext::AddThread(std::shared_ptr<KThread> thread) { | 20 | void GlobalSchedulerContext::AddThread(KThread* thread) { |
| 21 | std::scoped_lock lock{global_list_guard}; | 21 | std::scoped_lock lock{global_list_guard}; |
| 22 | thread_list.push_back(std::move(thread)); | 22 | thread_list.push_back(thread); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | void GlobalSchedulerContext::RemoveThread(std::shared_ptr<KThread> thread) { | 25 | void GlobalSchedulerContext::RemoveThread(KThread* thread) { |
| 26 | std::scoped_lock lock{global_list_guard}; | 26 | std::scoped_lock lock{global_list_guard}; |
| 27 | thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread), | 27 | thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread), |
| 28 | thread_list.end()); | 28 | thread_list.end()); |
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index 11592843e..6f44b534f 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h | |||
| @@ -34,17 +34,17 @@ class GlobalSchedulerContext final { | |||
| 34 | public: | 34 | public: |
| 35 | using LockType = KAbstractSchedulerLock<KScheduler>; | 35 | using LockType = KAbstractSchedulerLock<KScheduler>; |
| 36 | 36 | ||
| 37 | explicit GlobalSchedulerContext(KernelCore& kernel); | 37 | explicit GlobalSchedulerContext(KernelCore& kernel_); |
| 38 | ~GlobalSchedulerContext(); | 38 | ~GlobalSchedulerContext(); |
| 39 | 39 | ||
| 40 | /// Adds a new thread to the scheduler | 40 | /// Adds a new thread to the scheduler |
| 41 | void AddThread(std::shared_ptr<KThread> thread); | 41 | void AddThread(KThread* thread); |
| 42 | 42 | ||
| 43 | /// Removes a thread from the scheduler | 43 | /// Removes a thread from the scheduler |
| 44 | void RemoveThread(std::shared_ptr<KThread> thread); | 44 | void RemoveThread(KThread* thread); |
| 45 | 45 | ||
| 46 | /// Returns a list of all threads managed by the scheduler | 46 | /// Returns a list of all threads managed by the scheduler |
| 47 | [[nodiscard]] const std::vector<std::shared_ptr<KThread>>& GetThreadList() const { | 47 | [[nodiscard]] const std::vector<KThread*>& GetThreadList() const { |
| 48 | return thread_list; | 48 | return thread_list; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| @@ -79,7 +79,7 @@ private: | |||
| 79 | LockType scheduler_lock; | 79 | LockType scheduler_lock; |
| 80 | 80 | ||
| 81 | /// Lists all thread ids that aren't deleted/etc. | 81 | /// Lists all thread ids that aren't deleted/etc. |
| 82 | std::vector<std::shared_ptr<KThread>> thread_list; | 82 | std::vector<KThread*> thread_list; |
| 83 | Common::SpinLock global_list_guard{}; | 83 | Common::SpinLock global_list_guard{}; |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp deleted file mode 100644 index f96d34078..000000000 --- a/src/core/hle/kernel/handle_table.cpp +++ /dev/null | |||
| @@ -1,131 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <utility> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/logging/log.h" | ||
| 8 | #include "core/core.h" | ||
| 9 | #include "core/hle/kernel/handle_table.h" | ||
| 10 | #include "core/hle/kernel/k_scheduler.h" | ||
| 11 | #include "core/hle/kernel/k_thread.h" | ||
| 12 | #include "core/hle/kernel/kernel.h" | ||
| 13 | #include "core/hle/kernel/process.h" | ||
| 14 | #include "core/hle/kernel/svc_results.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | namespace { | ||
| 18 | constexpr u16 GetSlot(Handle handle) { | ||
| 19 | return static_cast<u16>(handle >> 15); | ||
| 20 | } | ||
| 21 | |||
| 22 | constexpr u16 GetGeneration(Handle handle) { | ||
| 23 | return static_cast<u16>(handle & 0x7FFF); | ||
| 24 | } | ||
| 25 | } // Anonymous namespace | ||
| 26 | |||
| 27 | HandleTable::HandleTable(KernelCore& kernel) : kernel{kernel} { | ||
| 28 | Clear(); | ||
| 29 | } | ||
| 30 | |||
| 31 | HandleTable::~HandleTable() = default; | ||
| 32 | |||
| 33 | ResultCode HandleTable::SetSize(s32 handle_table_size) { | ||
| 34 | if (static_cast<u32>(handle_table_size) > MAX_COUNT) { | ||
| 35 | LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT); | ||
| 36 | return ResultOutOfMemory; | ||
| 37 | } | ||
| 38 | |||
| 39 | // Values less than or equal to zero indicate to use the maximum allowable | ||
| 40 | // size for the handle table in the actual kernel, so we ignore the given | ||
| 41 | // value in that case, since we assume this by default unless this function | ||
| 42 | // is called. | ||
| 43 | if (handle_table_size > 0) { | ||
| 44 | table_size = static_cast<u16>(handle_table_size); | ||
| 45 | } | ||
| 46 | |||
| 47 | return RESULT_SUCCESS; | ||
| 48 | } | ||
| 49 | |||
| 50 | ResultVal<Handle> HandleTable::Create(std::shared_ptr<Object> obj) { | ||
| 51 | DEBUG_ASSERT(obj != nullptr); | ||
| 52 | |||
| 53 | const u16 slot = next_free_slot; | ||
| 54 | if (slot >= table_size) { | ||
| 55 | LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); | ||
| 56 | return ResultHandleTableFull; | ||
| 57 | } | ||
| 58 | next_free_slot = generations[slot]; | ||
| 59 | |||
| 60 | const u16 generation = next_generation++; | ||
| 61 | |||
| 62 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | ||
| 63 | // Horizon OS uses zero to represent an invalid handle, so skip to 1. | ||
| 64 | if (next_generation >= (1 << 15)) { | ||
| 65 | next_generation = 1; | ||
| 66 | } | ||
| 67 | |||
| 68 | generations[slot] = generation; | ||
| 69 | objects[slot] = std::move(obj); | ||
| 70 | |||
| 71 | Handle handle = generation | (slot << 15); | ||
| 72 | return MakeResult<Handle>(handle); | ||
| 73 | } | ||
| 74 | |||
| 75 | ResultVal<Handle> HandleTable::Duplicate(Handle handle) { | ||
| 76 | std::shared_ptr<Object> object = GetGeneric(handle); | ||
| 77 | if (object == nullptr) { | ||
| 78 | LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle); | ||
| 79 | return ResultInvalidHandle; | ||
| 80 | } | ||
| 81 | return Create(std::move(object)); | ||
| 82 | } | ||
| 83 | |||
| 84 | ResultCode HandleTable::Close(Handle handle) { | ||
| 85 | if (!IsValid(handle)) { | ||
| 86 | LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle); | ||
| 87 | return ResultInvalidHandle; | ||
| 88 | } | ||
| 89 | |||
| 90 | const u16 slot = GetSlot(handle); | ||
| 91 | |||
| 92 | if (objects[slot].use_count() == 1) { | ||
| 93 | objects[slot]->Finalize(); | ||
| 94 | } | ||
| 95 | |||
| 96 | objects[slot] = nullptr; | ||
| 97 | |||
| 98 | generations[slot] = next_free_slot; | ||
| 99 | next_free_slot = slot; | ||
| 100 | return RESULT_SUCCESS; | ||
| 101 | } | ||
| 102 | |||
| 103 | bool HandleTable::IsValid(Handle handle) const { | ||
| 104 | const std::size_t slot = GetSlot(handle); | ||
| 105 | const u16 generation = GetGeneration(handle); | ||
| 106 | |||
| 107 | return slot < table_size && objects[slot] != nullptr && generations[slot] == generation; | ||
| 108 | } | ||
| 109 | |||
| 110 | std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const { | ||
| 111 | if (handle == CurrentThread) { | ||
| 112 | return SharedFrom(kernel.CurrentScheduler()->GetCurrentThread()); | ||
| 113 | } else if (handle == CurrentProcess) { | ||
| 114 | return SharedFrom(kernel.CurrentProcess()); | ||
| 115 | } | ||
| 116 | |||
| 117 | if (!IsValid(handle)) { | ||
| 118 | return nullptr; | ||
| 119 | } | ||
| 120 | return objects[GetSlot(handle)]; | ||
| 121 | } | ||
| 122 | |||
| 123 | void HandleTable::Clear() { | ||
| 124 | for (u16 i = 0; i < table_size; ++i) { | ||
| 125 | generations[i] = static_cast<u16>(i + 1); | ||
| 126 | objects[i] = nullptr; | ||
| 127 | } | ||
| 128 | next_free_slot = 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h deleted file mode 100644 index c9dab8cdd..000000000 --- a/src/core/hle/kernel/handle_table.h +++ /dev/null | |||
| @@ -1,144 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <memory> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hle/kernel/object.h" | ||
| 13 | #include "core/hle/result.h" | ||
| 14 | |||
| 15 | namespace Kernel { | ||
| 16 | |||
| 17 | class KernelCore; | ||
| 18 | |||
| 19 | enum KernelHandle : Handle { | ||
| 20 | InvalidHandle = 0, | ||
| 21 | CurrentThread = 0xFFFF8000, | ||
| 22 | CurrentProcess = 0xFFFF8001, | ||
| 23 | }; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * This class allows the creation of Handles, which are references to objects that can be tested | ||
| 27 | * for validity and looked up. Here they are used to pass references to kernel objects to/from the | ||
| 28 | * emulated process. it has been designed so that it follows the same handle format and has | ||
| 29 | * approximately the same restrictions as the handle manager in the CTR-OS. | ||
| 30 | * | ||
| 31 | * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0). | ||
| 32 | * The slot index is used to index into the arrays in this class to access the data corresponding | ||
| 33 | * to the Handle. | ||
| 34 | * | ||
| 35 | * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter | ||
| 36 | * is kept and incremented every time a Handle is created. This is the Handle's "generation". The | ||
| 37 | * value of the counter is stored into the Handle as well as in the handle table (in the | ||
| 38 | * "generations" array). When looking up a handle, the Handle's generation must match with the | ||
| 39 | * value stored on the class, otherwise the Handle is considered invalid. | ||
| 40 | * | ||
| 41 | * To find free slots when allocating a Handle without needing to scan the entire object array, the | ||
| 42 | * generations field of unallocated slots is re-purposed as a linked list of indices to free slots. | ||
| 43 | * When a Handle is created, an index is popped off the list and used for the new Handle. When it | ||
| 44 | * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is | ||
| 45 | * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been | ||
| 46 | * verified and isn't likely to cause any problems. | ||
| 47 | */ | ||
| 48 | class HandleTable final : NonCopyable { | ||
| 49 | public: | ||
| 50 | /// This is the maximum limit of handles allowed per process in Horizon | ||
| 51 | static constexpr std::size_t MAX_COUNT = 1024; | ||
| 52 | |||
| 53 | explicit HandleTable(KernelCore& kernel); | ||
| 54 | ~HandleTable(); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Sets the number of handles that may be in use at one time | ||
| 58 | * for this handle table. | ||
| 59 | * | ||
| 60 | * @param handle_table_size The desired size to limit the handle table to. | ||
| 61 | * | ||
| 62 | * @returns an error code indicating if initialization was successful. | ||
| 63 | * If initialization was not successful, then ERR_OUT_OF_MEMORY | ||
| 64 | * will be returned. | ||
| 65 | * | ||
| 66 | * @pre handle_table_size must be within the range [0, 1024] | ||
| 67 | */ | ||
| 68 | ResultCode SetSize(s32 handle_table_size); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Allocates a handle for the given object. | ||
| 72 | * @return The created Handle or one of the following errors: | ||
| 73 | * - `ERR_HANDLE_TABLE_FULL`: the maximum number of handles has been exceeded. | ||
| 74 | */ | ||
| 75 | ResultVal<Handle> Create(std::shared_ptr<Object> obj); | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Returns a new handle that points to the same object as the passed in handle. | ||
| 79 | * @return The duplicated Handle or one of the following errors: | ||
| 80 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 81 | * - Any errors returned by `Create()`. | ||
| 82 | */ | ||
| 83 | ResultVal<Handle> Duplicate(Handle handle); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Closes a handle, removing it from the table and decreasing the object's ref-count. | ||
| 87 | * @return `RESULT_SUCCESS` or one of the following errors: | ||
| 88 | * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. | ||
| 89 | */ | ||
| 90 | ResultCode Close(Handle handle); | ||
| 91 | |||
| 92 | /// Checks if a handle is valid and points to an existing object. | ||
| 93 | bool IsValid(Handle handle) const; | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Looks up a handle. | ||
| 97 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. | ||
| 98 | */ | ||
| 99 | std::shared_ptr<Object> GetGeneric(Handle handle) const; | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Looks up a handle while verifying its type. | ||
| 103 | * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its | ||
| 104 | * type differs from the requested one. | ||
| 105 | */ | ||
| 106 | template <class T> | ||
| 107 | std::shared_ptr<T> Get(Handle handle) const { | ||
| 108 | return DynamicObjectCast<T>(GetGeneric(handle)); | ||
| 109 | } | ||
| 110 | |||
| 111 | /// Closes all handles held in this table. | ||
| 112 | void Clear(); | ||
| 113 | |||
| 114 | private: | ||
| 115 | /// Stores the Object referenced by the handle or null if the slot is empty. | ||
| 116 | std::array<std::shared_ptr<Object>, MAX_COUNT> objects; | ||
| 117 | |||
| 118 | /** | ||
| 119 | * The value of `next_generation` when the handle was created, used to check for validity. For | ||
| 120 | * empty slots, contains the index of the next free slot in the list. | ||
| 121 | */ | ||
| 122 | std::array<u16, MAX_COUNT> generations; | ||
| 123 | |||
| 124 | /** | ||
| 125 | * The limited size of the handle table. This can be specified by process | ||
| 126 | * capabilities in order to restrict the overall number of handles that | ||
| 127 | * can be created in a process instance | ||
| 128 | */ | ||
| 129 | u16 table_size = static_cast<u16>(MAX_COUNT); | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Global counter of the number of created handles. Stored in `generations` when a handle is | ||
| 133 | * created, and wraps around to 1 when it hits 0x8000. | ||
| 134 | */ | ||
| 135 | u16 next_generation = 1; | ||
| 136 | |||
| 137 | /// Head of the free slots linked list. | ||
| 138 | u16 next_free_slot = 0; | ||
| 139 | |||
| 140 | /// Underlying kernel instance that this handle table operates under. | ||
| 141 | KernelCore& kernel; | ||
| 142 | }; | ||
| 143 | |||
| 144 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 2b363b1d9..24700f7a5 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -14,17 +14,16 @@ | |||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "core/hle/ipc_helpers.h" | 16 | #include "core/hle/ipc_helpers.h" |
| 17 | #include "core/hle/kernel/handle_table.h" | ||
| 18 | #include "core/hle/kernel/hle_ipc.h" | 17 | #include "core/hle/kernel/hle_ipc.h" |
| 18 | #include "core/hle/kernel/k_handle_table.h" | ||
| 19 | #include "core/hle/kernel/k_process.h" | ||
| 19 | #include "core/hle/kernel/k_readable_event.h" | 20 | #include "core/hle/kernel/k_readable_event.h" |
| 20 | #include "core/hle/kernel/k_scheduler.h" | 21 | #include "core/hle/kernel/k_scheduler.h" |
| 21 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 22 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 23 | #include "core/hle/kernel/k_server_session.h" | ||
| 22 | #include "core/hle/kernel/k_thread.h" | 24 | #include "core/hle/kernel/k_thread.h" |
| 23 | #include "core/hle/kernel/k_writable_event.h" | 25 | #include "core/hle/kernel/k_writable_event.h" |
| 24 | #include "core/hle/kernel/kernel.h" | 26 | #include "core/hle/kernel/kernel.h" |
| 25 | #include "core/hle/kernel/object.h" | ||
| 26 | #include "core/hle/kernel/process.h" | ||
| 27 | #include "core/hle/kernel/server_session.h" | ||
| 28 | #include "core/hle/kernel/svc_results.h" | 27 | #include "core/hle/kernel/svc_results.h" |
| 29 | #include "core/hle/kernel/time_manager.h" | 28 | #include "core/hle/kernel/time_manager.h" |
| 30 | #include "core/memory.h" | 29 | #include "core/memory.h" |
| @@ -35,33 +34,28 @@ SessionRequestHandler::SessionRequestHandler() = default; | |||
| 35 | 34 | ||
| 36 | SessionRequestHandler::~SessionRequestHandler() = default; | 35 | SessionRequestHandler::~SessionRequestHandler() = default; |
| 37 | 36 | ||
| 38 | void SessionRequestHandler::ClientConnected(std::shared_ptr<ServerSession> server_session) { | 37 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 39 | server_session->SetHleHandler(shared_from_this()); | 38 | session->SetHleHandler(shared_from_this()); |
| 40 | connected_sessions.push_back(std::move(server_session)); | ||
| 41 | } | 39 | } |
| 42 | 40 | ||
| 43 | void SessionRequestHandler::ClientDisconnected( | 41 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
| 44 | const std::shared_ptr<ServerSession>& server_session) { | 42 | session->SetHleHandler(nullptr); |
| 45 | server_session->SetHleHandler(nullptr); | ||
| 46 | boost::range::remove_erase(connected_sessions, server_session); | ||
| 47 | } | 43 | } |
| 48 | 44 | ||
| 49 | HLERequestContext::HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, | 45 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, |
| 50 | std::shared_ptr<ServerSession> server_session, | 46 | KServerSession* server_session_, KThread* thread_) |
| 51 | std::shared_ptr<KThread> thread) | 47 | : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { |
| 52 | : server_session(std::move(server_session)), | ||
| 53 | thread(std::move(thread)), kernel{kernel}, memory{memory} { | ||
| 54 | cmd_buf[0] = 0; | 48 | cmd_buf[0] = 0; |
| 55 | } | 49 | } |
| 56 | 50 | ||
| 57 | HLERequestContext::~HLERequestContext() = default; | 51 | HLERequestContext::~HLERequestContext() = default; |
| 58 | 52 | ||
| 59 | void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, | 53 | void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, |
| 60 | bool incoming) { | 54 | bool incoming) { |
| 61 | IPC::RequestParser rp(src_cmdbuf); | 55 | IPC::RequestParser rp(src_cmdbuf); |
| 62 | command_header = rp.PopRaw<IPC::CommandHeader>(); | 56 | command_header = rp.PopRaw<IPC::CommandHeader>(); |
| 63 | 57 | ||
| 64 | if (command_header->type == IPC::CommandType::Close) { | 58 | if (command_header->IsCloseCommand()) { |
| 65 | // Close does not populate the rest of the IPC header | 59 | // Close does not populate the rest of the IPC header |
| 66 | return; | 60 | return; |
| 67 | } | 61 | } |
| @@ -70,19 +64,19 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ | |||
| 70 | if (command_header->enable_handle_descriptor) { | 64 | if (command_header->enable_handle_descriptor) { |
| 71 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); | 65 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); |
| 72 | if (handle_descriptor_header->send_current_pid) { | 66 | if (handle_descriptor_header->send_current_pid) { |
| 73 | rp.Skip(2, false); | 67 | pid = rp.Pop<u64>(); |
| 74 | } | 68 | } |
| 75 | if (incoming) { | 69 | if (incoming) { |
| 76 | // Populate the object lists with the data in the IPC request. | 70 | // Populate the object lists with the data in the IPC request. |
| 77 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { | 71 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { |
| 78 | const u32 copy_handle{rp.Pop<Handle>()}; | 72 | const u32 copy_handle{rp.Pop<Handle>()}; |
| 79 | copy_handles.push_back(copy_handle); | 73 | copy_handles.push_back(copy_handle); |
| 80 | copy_objects.push_back(handle_table.GetGeneric(copy_handle)); | 74 | copy_objects.push_back(handle_table.GetObject(copy_handle).GetPointerUnsafe()); |
| 81 | } | 75 | } |
| 82 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { | 76 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { |
| 83 | const u32 move_handle{rp.Pop<Handle>()}; | 77 | const u32 move_handle{rp.Pop<Handle>()}; |
| 84 | move_handles.push_back(move_handle); | 78 | move_handles.push_back(move_handle); |
| 85 | move_objects.push_back(handle_table.GetGeneric(move_handle)); | 79 | move_objects.push_back(handle_table.GetObject(move_handle).GetPointerUnsafe()); |
| 86 | } | 80 | } |
| 87 | } else { | 81 | } else { |
| 88 | // For responses we just ignore the handles, they're empty and will be populated when | 82 | // For responses we just ignore the handles, they're empty and will be populated when |
| @@ -92,52 +86,56 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ | |||
| 92 | } | 86 | } |
| 93 | } | 87 | } |
| 94 | 88 | ||
| 95 | for (unsigned i = 0; i < command_header->num_buf_x_descriptors; ++i) { | 89 | for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { |
| 96 | buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); | 90 | buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); |
| 97 | } | 91 | } |
| 98 | for (unsigned i = 0; i < command_header->num_buf_a_descriptors; ++i) { | 92 | for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { |
| 99 | buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 93 | buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 100 | } | 94 | } |
| 101 | for (unsigned i = 0; i < command_header->num_buf_b_descriptors; ++i) { | 95 | for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { |
| 102 | buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 96 | buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 103 | } | 97 | } |
| 104 | for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { | 98 | for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { |
| 105 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 99 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 106 | } | 100 | } |
| 107 | 101 | ||
| 108 | buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; | 102 | const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; |
| 109 | 103 | ||
| 110 | // Padding to align to 16 bytes | 104 | if (!command_header->IsTipc()) { |
| 111 | rp.AlignWithPadding(); | 105 | // Padding to align to 16 bytes |
| 112 | 106 | rp.AlignWithPadding(); | |
| 113 | if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request || | 107 | |
| 114 | command_header->type == IPC::CommandType::RequestWithContext) || | 108 | if (Session()->IsDomain() && |
| 115 | !incoming)) { | 109 | ((command_header->type == IPC::CommandType::Request || |
| 116 | // If this is an incoming message, only CommandType "Request" has a domain header | 110 | command_header->type == IPC::CommandType::RequestWithContext) || |
| 117 | // All outgoing domain messages have the domain header, if only incoming has it | 111 | !incoming)) { |
| 118 | if (incoming || domain_message_header) { | 112 | // If this is an incoming message, only CommandType "Request" has a domain header |
| 119 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); | 113 | // All outgoing domain messages have the domain header, if only incoming has it |
| 120 | } else { | 114 | if (incoming || domain_message_header) { |
| 121 | if (Session()->IsDomain()) { | 115 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); |
| 122 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | 116 | } else { |
| 117 | if (Session()->IsDomain()) { | ||
| 118 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | ||
| 119 | } | ||
| 123 | } | 120 | } |
| 124 | } | 121 | } |
| 125 | } | ||
| 126 | 122 | ||
| 127 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); | 123 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); |
| 128 | 124 | ||
| 129 | data_payload_offset = rp.GetCurrentOffset(); | 125 | data_payload_offset = rp.GetCurrentOffset(); |
| 130 | 126 | ||
| 131 | if (domain_message_header && domain_message_header->command == | 127 | if (domain_message_header && |
| 132 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { | 128 | domain_message_header->command == |
| 133 | // CloseVirtualHandle command does not have SFC* or any data | 129 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { |
| 134 | return; | 130 | // CloseVirtualHandle command does not have SFC* or any data |
| 135 | } | 131 | return; |
| 132 | } | ||
| 136 | 133 | ||
| 137 | if (incoming) { | 134 | if (incoming) { |
| 138 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); | 135 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); |
| 139 | } else { | 136 | } else { |
| 140 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 137 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); |
| 138 | } | ||
| 141 | } | 139 | } |
| 142 | 140 | ||
| 143 | rp.SetCurrentOffset(buffer_c_offset); | 141 | rp.SetCurrentOffset(buffer_c_offset); |
| @@ -150,14 +148,14 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ | |||
| 150 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | 148 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { |
| 151 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 149 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 152 | } else { | 150 | } else { |
| 153 | unsigned num_buf_c_descriptors = | 151 | u32 num_buf_c_descriptors = |
| 154 | static_cast<unsigned>(command_header->buf_c_descriptor_flags.Value()) - 2; | 152 | static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; |
| 155 | 153 | ||
| 156 | // This is used to detect possible underflows, in case something is broken | 154 | // This is used to detect possible underflows, in case something is broken |
| 157 | // with the two ifs above and the flags value is == 0 || == 1. | 155 | // with the two ifs above and the flags value is == 0 || == 1. |
| 158 | ASSERT(num_buf_c_descriptors < 14); | 156 | ASSERT(num_buf_c_descriptors < 14); |
| 159 | 157 | ||
| 160 | for (unsigned i = 0; i < num_buf_c_descriptors; ++i) { | 158 | for (u32 i = 0; i < num_buf_c_descriptors; ++i) { |
| 161 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 159 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 162 | } | 160 | } |
| 163 | } | 161 | } |
| @@ -169,87 +167,70 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ | |||
| 169 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. | 167 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. |
| 170 | } | 168 | } |
| 171 | 169 | ||
| 172 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, | 170 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, |
| 173 | u32_le* src_cmdbuf) { | 171 | u32_le* src_cmdbuf) { |
| 174 | ParseCommandBuffer(handle_table, src_cmdbuf, true); | 172 | ParseCommandBuffer(handle_table, src_cmdbuf, true); |
| 175 | if (command_header->type == IPC::CommandType::Close) { | 173 | |
| 174 | if (command_header->IsCloseCommand()) { | ||
| 176 | // Close does not populate the rest of the IPC header | 175 | // Close does not populate the rest of the IPC header |
| 177 | return RESULT_SUCCESS; | 176 | return RESULT_SUCCESS; |
| 178 | } | 177 | } |
| 179 | 178 | ||
| 180 | // The data_size already includes the payload header, the padding and the domain header. | 179 | std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); |
| 181 | std::size_t size = data_payload_offset + command_header->data_size - | 180 | |
| 182 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 183 | if (domain_message_header) | ||
| 184 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 185 | std::copy_n(src_cmdbuf, size, cmd_buf.begin()); | ||
| 186 | return RESULT_SUCCESS; | 181 | return RESULT_SUCCESS; |
| 187 | } | 182 | } |
| 188 | 183 | ||
| 189 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& thread) { | 184 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { |
| 190 | auto& owner_process = *thread.GetOwnerProcess(); | 185 | auto current_offset = handles_offset; |
| 186 | auto& owner_process = *requesting_thread.GetOwnerProcess(); | ||
| 191 | auto& handle_table = owner_process.GetHandleTable(); | 187 | auto& handle_table = owner_process.GetHandleTable(); |
| 192 | 188 | ||
| 193 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf; | ||
| 194 | memory.ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), | ||
| 195 | dst_cmdbuf.size() * sizeof(u32)); | ||
| 196 | |||
| 197 | // The header was already built in the internal command buffer. Attempt to parse it to verify | ||
| 198 | // the integrity and then copy it over to the target command buffer. | ||
| 199 | ParseCommandBuffer(handle_table, cmd_buf.data(), false); | ||
| 200 | |||
| 201 | // The data_size already includes the payload header, the padding and the domain header. | 189 | // The data_size already includes the payload header, the padding and the domain header. |
| 202 | std::size_t size = data_payload_offset + command_header->data_size - | 190 | std::size_t size{}; |
| 203 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 204 | if (domain_message_header) | ||
| 205 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 206 | |||
| 207 | std::copy_n(cmd_buf.begin(), size, dst_cmdbuf.data()); | ||
| 208 | 191 | ||
| 209 | if (command_header->enable_handle_descriptor) { | 192 | if (IsTipc()) { |
| 210 | ASSERT_MSG(!move_objects.empty() || !copy_objects.empty(), | 193 | size = cmd_buf.size(); |
| 211 | "Handle descriptor bit set but no handles to translate"); | 194 | } else { |
| 212 | // We write the translated handles at a specific offset in the command buffer, this space | 195 | size = data_payload_offset + data_size - sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; |
| 213 | // was already reserved when writing the header. | 196 | if (Session()->IsDomain()) { |
| 214 | std::size_t current_offset = | 197 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); |
| 215 | (sizeof(IPC::CommandHeader) + sizeof(IPC::HandleDescriptorHeader)) / sizeof(u32); | ||
| 216 | ASSERT_MSG(!handle_descriptor_header->send_current_pid, "Sending PID is not implemented"); | ||
| 217 | |||
| 218 | ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy); | ||
| 219 | ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move); | ||
| 220 | |||
| 221 | // We don't make a distinction between copy and move handles when translating since HLE | ||
| 222 | // services don't deal with handles directly. However, the guest applications might check | ||
| 223 | // for specific values in each of these descriptors. | ||
| 224 | for (auto& object : copy_objects) { | ||
| 225 | ASSERT(object != nullptr); | ||
| 226 | dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap(); | ||
| 227 | } | 198 | } |
| 199 | } | ||
| 228 | 200 | ||
| 229 | for (auto& object : move_objects) { | 201 | for (auto& object : copy_objects) { |
| 230 | ASSERT(object != nullptr); | 202 | Handle handle{}; |
| 231 | dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap(); | 203 | if (object) { |
| 204 | R_TRY(handle_table.Add(&handle, object)); | ||
| 232 | } | 205 | } |
| 206 | cmd_buf[current_offset++] = handle; | ||
| 233 | } | 207 | } |
| 208 | for (auto& object : move_objects) { | ||
| 209 | Handle handle{}; | ||
| 210 | if (object) { | ||
| 211 | R_TRY(handle_table.Add(&handle, object)); | ||
| 234 | 212 | ||
| 235 | // TODO(Subv): Translate the X/A/B/W buffers. | 213 | // Close our reference to the object, as it is being moved to the caller. |
| 214 | object->Close(); | ||
| 215 | } | ||
| 216 | cmd_buf[current_offset++] = handle; | ||
| 217 | } | ||
| 236 | 218 | ||
| 237 | if (Session()->IsDomain() && domain_message_header) { | 219 | // Write the domain objects to the command buffer, these go after the raw untranslated data. |
| 238 | ASSERT(domain_message_header->num_objects == domain_objects.size()); | 220 | // TODO(Subv): This completely ignores C buffers. |
| 239 | // Write the domain objects to the command buffer, these go after the raw untranslated data. | ||
| 240 | // TODO(Subv): This completely ignores C buffers. | ||
| 241 | std::size_t domain_offset = size - domain_message_header->num_objects; | ||
| 242 | 221 | ||
| 222 | if (Session()->IsDomain()) { | ||
| 223 | current_offset = domain_offset - static_cast<u32>(domain_objects.size()); | ||
| 243 | for (const auto& object : domain_objects) { | 224 | for (const auto& object : domain_objects) { |
| 244 | server_session->AppendDomainRequestHandler(object); | 225 | server_session->AppendDomainRequestHandler(object); |
| 245 | dst_cmdbuf[domain_offset++] = | 226 | cmd_buf[current_offset++] = |
| 246 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); | 227 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); |
| 247 | } | 228 | } |
| 248 | } | 229 | } |
| 249 | 230 | ||
| 250 | // Copy the translated command buffer back into the thread's command buffer area. | 231 | // Copy the translated command buffer back into the thread's command buffer area. |
| 251 | memory.WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), | 232 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), |
| 252 | dst_cmdbuf.size() * sizeof(u32)); | 233 | size * sizeof(u32)); |
| 253 | 234 | ||
| 254 | return RESULT_SUCCESS; | 235 | return RESULT_SUCCESS; |
| 255 | } | 236 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 6fba42615..e1b128281 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -16,7 +16,8 @@ | |||
| 16 | #include "common/concepts.h" | 16 | #include "common/concepts.h" |
| 17 | #include "common/swap.h" | 17 | #include "common/swap.h" |
| 18 | #include "core/hle/ipc.h" | 18 | #include "core/hle/ipc.h" |
| 19 | #include "core/hle/kernel/object.h" | 19 | #include "core/hle/kernel/k_auto_object.h" |
| 20 | #include "core/hle/kernel/svc_common.h" | ||
| 20 | 21 | ||
| 21 | union ResultCode; | 22 | union ResultCode; |
| 22 | 23 | ||
| @@ -35,13 +36,14 @@ class ServiceFrameworkBase; | |||
| 35 | namespace Kernel { | 36 | namespace Kernel { |
| 36 | 37 | ||
| 37 | class Domain; | 38 | class Domain; |
| 38 | class HandleTable; | ||
| 39 | class HLERequestContext; | 39 | class HLERequestContext; |
| 40 | class KernelCore; | 40 | class KernelCore; |
| 41 | class Process; | 41 | class KHandleTable; |
| 42 | class ServerSession; | 42 | class KProcess; |
| 43 | class KServerSession; | ||
| 43 | class KThread; | 44 | class KThread; |
| 44 | class KReadableEvent; | 45 | class KReadableEvent; |
| 46 | class KSession; | ||
| 45 | class KWritableEvent; | 47 | class KWritableEvent; |
| 46 | 48 | ||
| 47 | enum class ThreadWakeupReason; | 49 | enum class ThreadWakeupReason; |
| @@ -64,27 +66,22 @@ public: | |||
| 64 | * this request (ServerSession, Originator thread, Translated command buffer, etc). | 66 | * this request (ServerSession, Originator thread, Translated command buffer, etc). |
| 65 | * @returns ResultCode the result code of the translate operation. | 67 | * @returns ResultCode the result code of the translate operation. |
| 66 | */ | 68 | */ |
| 67 | virtual ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) = 0; | 69 | virtual ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 70 | Kernel::HLERequestContext& context) = 0; | ||
| 68 | 71 | ||
| 69 | /** | 72 | /** |
| 70 | * Signals that a client has just connected to this HLE handler and keeps the | 73 | * Signals that a client has just connected to this HLE handler and keeps the |
| 71 | * associated ServerSession alive for the duration of the connection. | 74 | * associated ServerSession alive for the duration of the connection. |
| 72 | * @param server_session Owning pointer to the ServerSession associated with the connection. | 75 | * @param server_session Owning pointer to the ServerSession associated with the connection. |
| 73 | */ | 76 | */ |
| 74 | void ClientConnected(std::shared_ptr<ServerSession> server_session); | 77 | void ClientConnected(KServerSession* session); |
| 75 | 78 | ||
| 76 | /** | 79 | /** |
| 77 | * Signals that a client has just disconnected from this HLE handler and releases the | 80 | * Signals that a client has just disconnected from this HLE handler and releases the |
| 78 | * associated ServerSession. | 81 | * associated ServerSession. |
| 79 | * @param server_session ServerSession associated with the connection. | 82 | * @param server_session ServerSession associated with the connection. |
| 80 | */ | 83 | */ |
| 81 | void ClientDisconnected(const std::shared_ptr<ServerSession>& server_session); | 84 | void ClientDisconnected(KServerSession* session); |
| 82 | |||
| 83 | protected: | ||
| 84 | /// List of sessions that are connected to this handler. | ||
| 85 | /// A ServerSession whose server endpoint is an HLE implementation is kept alive by this list | ||
| 86 | /// for the duration of the connection. | ||
| 87 | std::vector<std::shared_ptr<ServerSession>> connected_sessions; | ||
| 88 | }; | 85 | }; |
| 89 | 86 | ||
| 90 | /** | 87 | /** |
| @@ -109,8 +106,7 @@ protected: | |||
| 109 | class HLERequestContext { | 106 | class HLERequestContext { |
| 110 | public: | 107 | public: |
| 111 | explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, | 108 | explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, |
| 112 | std::shared_ptr<ServerSession> session, | 109 | KServerSession* session, KThread* thread); |
| 113 | std::shared_ptr<KThread> thread); | ||
| 114 | ~HLERequestContext(); | 110 | ~HLERequestContext(); |
| 115 | 111 | ||
| 116 | /// Returns a pointer to the IPC command buffer for this request. | 112 | /// Returns a pointer to the IPC command buffer for this request. |
| @@ -122,26 +118,43 @@ public: | |||
| 122 | * Returns the session through which this request was made. This can be used as a map key to | 118 | * Returns the session through which this request was made. This can be used as a map key to |
| 123 | * access per-client data on services. | 119 | * access per-client data on services. |
| 124 | */ | 120 | */ |
| 125 | const std::shared_ptr<Kernel::ServerSession>& Session() const { | 121 | Kernel::KServerSession* Session() { |
| 126 | return server_session; | 122 | return server_session; |
| 127 | } | 123 | } |
| 128 | 124 | ||
| 129 | /// Populates this context with data from the requesting process/thread. | 125 | /// Populates this context with data from the requesting process/thread. |
| 130 | ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, | 126 | ResultCode PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, |
| 131 | u32_le* src_cmdbuf); | 127 | u32_le* src_cmdbuf); |
| 132 | 128 | ||
| 133 | /// Writes data from this context back to the requesting process/thread. | 129 | /// Writes data from this context back to the requesting process/thread. |
| 134 | ResultCode WriteToOutgoingCommandBuffer(KThread& thread); | 130 | ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread); |
| 135 | 131 | ||
| 136 | u32_le GetCommand() const { | 132 | u32_le GetHipcCommand() const { |
| 137 | return command; | 133 | return command; |
| 138 | } | 134 | } |
| 139 | 135 | ||
| 136 | u32_le GetTipcCommand() const { | ||
| 137 | return static_cast<u32_le>(command_header->type.Value()) - | ||
| 138 | static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion); | ||
| 139 | } | ||
| 140 | |||
| 141 | u32_le GetCommand() const { | ||
| 142 | return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); | ||
| 143 | } | ||
| 144 | |||
| 145 | bool IsTipc() const { | ||
| 146 | return command_header->IsTipc(); | ||
| 147 | } | ||
| 148 | |||
| 140 | IPC::CommandType GetCommandType() const { | 149 | IPC::CommandType GetCommandType() const { |
| 141 | return command_header->type; | 150 | return command_header->type; |
| 142 | } | 151 | } |
| 143 | 152 | ||
| 144 | unsigned GetDataPayloadOffset() const { | 153 | u64 GetPID() const { |
| 154 | return pid; | ||
| 155 | } | ||
| 156 | |||
| 157 | u32 GetDataPayloadOffset() const { | ||
| 145 | return data_payload_offset; | 158 | return data_payload_offset; |
| 146 | } | 159 | } |
| 147 | 160 | ||
| @@ -218,22 +231,12 @@ public: | |||
| 218 | return move_handles.at(index); | 231 | return move_handles.at(index); |
| 219 | } | 232 | } |
| 220 | 233 | ||
| 221 | template <typename T> | 234 | void AddMoveObject(KAutoObject* object) { |
| 222 | std::shared_ptr<T> GetCopyObject(std::size_t index) { | 235 | move_objects.emplace_back(object); |
| 223 | return DynamicObjectCast<T>(copy_objects.at(index)); | ||
| 224 | } | ||
| 225 | |||
| 226 | template <typename T> | ||
| 227 | std::shared_ptr<T> GetMoveObject(std::size_t index) { | ||
| 228 | return DynamicObjectCast<T>(move_objects.at(index)); | ||
| 229 | } | ||
| 230 | |||
| 231 | void AddMoveObject(std::shared_ptr<Object> object) { | ||
| 232 | move_objects.emplace_back(std::move(object)); | ||
| 233 | } | 236 | } |
| 234 | 237 | ||
| 235 | void AddCopyObject(std::shared_ptr<Object> object) { | 238 | void AddCopyObject(KAutoObject* object) { |
| 236 | copy_objects.emplace_back(std::move(object)); | 239 | copy_objects.emplace_back(object); |
| 237 | } | 240 | } |
| 238 | 241 | ||
| 239 | void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) { | 242 | void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) { |
| @@ -276,10 +279,6 @@ public: | |||
| 276 | return *thread; | 279 | return *thread; |
| 277 | } | 280 | } |
| 278 | 281 | ||
| 279 | const KThread& GetThread() const { | ||
| 280 | return *thread; | ||
| 281 | } | ||
| 282 | |||
| 283 | bool IsThreadWaiting() const { | 282 | bool IsThreadWaiting() const { |
| 284 | return is_thread_waiting; | 283 | return is_thread_waiting; |
| 285 | } | 284 | } |
| @@ -287,16 +286,17 @@ public: | |||
| 287 | private: | 286 | private: |
| 288 | friend class IPC::ResponseBuilder; | 287 | friend class IPC::ResponseBuilder; |
| 289 | 288 | ||
| 290 | void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); | 289 | void ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); |
| 291 | 290 | ||
| 292 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | 291 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; |
| 293 | std::shared_ptr<Kernel::ServerSession> server_session; | 292 | Kernel::KServerSession* server_session{}; |
| 294 | std::shared_ptr<KThread> thread; | 293 | KThread* thread; |
| 294 | |||
| 295 | // TODO(yuriks): Check common usage of this and optimize size accordingly | 295 | // TODO(yuriks): Check common usage of this and optimize size accordingly |
| 296 | boost::container::small_vector<Handle, 8> move_handles; | 296 | boost::container::small_vector<Handle, 8> move_handles; |
| 297 | boost::container::small_vector<Handle, 8> copy_handles; | 297 | boost::container::small_vector<Handle, 8> copy_handles; |
| 298 | boost::container::small_vector<std::shared_ptr<Object>, 8> move_objects; | 298 | boost::container::small_vector<KAutoObject*, 8> move_objects; |
| 299 | boost::container::small_vector<std::shared_ptr<Object>, 8> copy_objects; | 299 | boost::container::small_vector<KAutoObject*, 8> copy_objects; |
| 300 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; | 300 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; |
| 301 | 301 | ||
| 302 | std::optional<IPC::CommandHeader> command_header; | 302 | std::optional<IPC::CommandHeader> command_header; |
| @@ -309,9 +309,12 @@ private: | |||
| 309 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; | 309 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; |
| 310 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; | 310 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; |
| 311 | 311 | ||
| 312 | unsigned data_payload_offset{}; | ||
| 313 | unsigned buffer_c_offset{}; | ||
| 314 | u32_le command{}; | 312 | u32_le command{}; |
| 313 | u64 pid{}; | ||
| 314 | u32 data_payload_offset{}; | ||
| 315 | u32 handles_offset{}; | ||
| 316 | u32 domain_offset{}; | ||
| 317 | u32 data_size{}; | ||
| 315 | 318 | ||
| 316 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | 319 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; |
| 317 | bool is_thread_waiting{}; | 320 | bool is_thread_waiting{}; |
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp new file mode 100644 index 000000000..69ae405e6 --- /dev/null +++ b/src/core/hle/kernel/init/init_slab_setup.cpp | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/alignment.h" | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/core.h" | ||
| 10 | #include "core/hardware_properties.h" | ||
| 11 | #include "core/hle/kernel/init/init_slab_setup.h" | ||
| 12 | #include "core/hle/kernel/k_event.h" | ||
| 13 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 14 | #include "core/hle/kernel/k_memory_manager.h" | ||
| 15 | #include "core/hle/kernel/k_port.h" | ||
| 16 | #include "core/hle/kernel/k_process.h" | ||
| 17 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 18 | #include "core/hle/kernel/k_session.h" | ||
| 19 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 20 | #include "core/hle/kernel/k_system_control.h" | ||
| 21 | #include "core/hle/kernel/k_thread.h" | ||
| 22 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 23 | #include "core/hle/kernel/memory_types.h" | ||
| 24 | #include "core/memory.h" | ||
| 25 | |||
| 26 | namespace Kernel::Init { | ||
| 27 | |||
| 28 | #define SLAB_COUNT(CLASS) kernel.SlabResourceCounts().num_##CLASS | ||
| 29 | |||
| 30 | #define FOREACH_SLAB_TYPE(HANDLER, ...) \ | ||
| 31 | HANDLER(KProcess, (SLAB_COUNT(KProcess)), ##__VA_ARGS__) \ | ||
| 32 | HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ | ||
| 33 | HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ | ||
| 34 | HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ | ||
| 35 | HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ | ||
| 36 | HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ | ||
| 37 | HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ | ||
| 38 | HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) | ||
| 39 | |||
| 40 | namespace { | ||
| 41 | |||
| 42 | #define DEFINE_SLAB_TYPE_ENUM_MEMBER(NAME, COUNT, ...) KSlabType_##NAME, | ||
| 43 | |||
| 44 | enum KSlabType : u32 { | ||
| 45 | FOREACH_SLAB_TYPE(DEFINE_SLAB_TYPE_ENUM_MEMBER) KSlabType_Count, | ||
| 46 | }; | ||
| 47 | |||
| 48 | #undef DEFINE_SLAB_TYPE_ENUM_MEMBER | ||
| 49 | |||
| 50 | // Constexpr counts. | ||
| 51 | constexpr size_t SlabCountKProcess = 80; | ||
| 52 | constexpr size_t SlabCountKThread = 800; | ||
| 53 | constexpr size_t SlabCountKEvent = 700; | ||
| 54 | constexpr size_t SlabCountKInterruptEvent = 100; | ||
| 55 | constexpr size_t SlabCountKPort = 256 + 0x20; // Extra 0x20 ports over Nintendo for homebrew. | ||
| 56 | constexpr size_t SlabCountKSharedMemory = 80; | ||
| 57 | constexpr size_t SlabCountKTransferMemory = 200; | ||
| 58 | constexpr size_t SlabCountKCodeMemory = 10; | ||
| 59 | constexpr size_t SlabCountKDeviceAddressSpace = 300; | ||
| 60 | constexpr size_t SlabCountKSession = 933; | ||
| 61 | constexpr size_t SlabCountKLightSession = 100; | ||
| 62 | constexpr size_t SlabCountKObjectName = 7; | ||
| 63 | constexpr size_t SlabCountKResourceLimit = 5; | ||
| 64 | constexpr size_t SlabCountKDebug = Core::Hardware::NUM_CPU_CORES; | ||
| 65 | constexpr size_t SlabCountKAlpha = 1; | ||
| 66 | constexpr size_t SlabCountKBeta = 6; | ||
| 67 | |||
| 68 | constexpr size_t SlabCountExtraKThread = 160; | ||
| 69 | |||
| 70 | template <typename T> | ||
| 71 | VAddr InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout, VAddr address, | ||
| 72 | size_t num_objects) { | ||
| 73 | const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*)); | ||
| 74 | VAddr start = Common::AlignUp(address, alignof(T)); | ||
| 75 | |||
| 76 | if (size > 0) { | ||
| 77 | const KMemoryRegion* region = memory_layout.FindVirtual(start + size - 1); | ||
| 78 | ASSERT(region != nullptr); | ||
| 79 | ASSERT(region->IsDerivedFrom(KMemoryRegionType_KernelSlab)); | ||
| 80 | T::InitializeSlabHeap(system.Kernel(), system.Memory().GetKernelBuffer(start, size), size); | ||
| 81 | } | ||
| 82 | |||
| 83 | return start + size; | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace | ||
| 87 | |||
| 88 | KSlabResourceCounts KSlabResourceCounts::CreateDefault() { | ||
| 89 | return { | ||
| 90 | .num_KProcess = SlabCountKProcess, | ||
| 91 | .num_KThread = SlabCountKThread, | ||
| 92 | .num_KEvent = SlabCountKEvent, | ||
| 93 | .num_KInterruptEvent = SlabCountKInterruptEvent, | ||
| 94 | .num_KPort = SlabCountKPort, | ||
| 95 | .num_KSharedMemory = SlabCountKSharedMemory, | ||
| 96 | .num_KTransferMemory = SlabCountKTransferMemory, | ||
| 97 | .num_KCodeMemory = SlabCountKCodeMemory, | ||
| 98 | .num_KDeviceAddressSpace = SlabCountKDeviceAddressSpace, | ||
| 99 | .num_KSession = SlabCountKSession, | ||
| 100 | .num_KLightSession = SlabCountKLightSession, | ||
| 101 | .num_KObjectName = SlabCountKObjectName, | ||
| 102 | .num_KResourceLimit = SlabCountKResourceLimit, | ||
| 103 | .num_KDebug = SlabCountKDebug, | ||
| 104 | .num_KAlpha = SlabCountKAlpha, | ||
| 105 | .num_KBeta = SlabCountKBeta, | ||
| 106 | }; | ||
| 107 | } | ||
| 108 | |||
| 109 | void InitializeSlabResourceCounts(KernelCore& kernel) { | ||
| 110 | kernel.SlabResourceCounts() = KSlabResourceCounts::CreateDefault(); | ||
| 111 | if (KSystemControl::Init::ShouldIncreaseThreadResourceLimit()) { | ||
| 112 | kernel.SlabResourceCounts().num_KThread += SlabCountExtraKThread; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | size_t CalculateTotalSlabHeapSize(const KernelCore& kernel) { | ||
| 117 | size_t size = 0; | ||
| 118 | |||
| 119 | #define ADD_SLAB_SIZE(NAME, COUNT, ...) \ | ||
| 120 | { \ | ||
| 121 | size += alignof(NAME); \ | ||
| 122 | size += Common::AlignUp(sizeof(NAME) * (COUNT), alignof(void*)); \ | ||
| 123 | }; | ||
| 124 | |||
| 125 | // Add the size required for each slab. | ||
| 126 | FOREACH_SLAB_TYPE(ADD_SLAB_SIZE) | ||
| 127 | |||
| 128 | #undef ADD_SLAB_SIZE | ||
| 129 | |||
| 130 | // Add the reserved size. | ||
| 131 | size += KernelSlabHeapGapsSize; | ||
| 132 | |||
| 133 | return size; | ||
| 134 | } | ||
| 135 | |||
| 136 | void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout) { | ||
| 137 | auto& kernel = system.Kernel(); | ||
| 138 | |||
| 139 | // Get the start of the slab region, since that's where we'll be working. | ||
| 140 | VAddr address = memory_layout.GetSlabRegionAddress(); | ||
| 141 | |||
| 142 | // Initialize slab type array to be in sorted order. | ||
| 143 | std::array<KSlabType, KSlabType_Count> slab_types; | ||
| 144 | for (size_t i = 0; i < slab_types.size(); i++) { | ||
| 145 | slab_types[i] = static_cast<KSlabType>(i); | ||
| 146 | } | ||
| 147 | |||
| 148 | // N shuffles the slab type array with the following simple algorithm. | ||
| 149 | for (size_t i = 0; i < slab_types.size(); i++) { | ||
| 150 | const size_t rnd = KSystemControl::GenerateRandomRange(0, slab_types.size() - 1); | ||
| 151 | std::swap(slab_types[i], slab_types[rnd]); | ||
| 152 | } | ||
| 153 | |||
| 154 | // Create an array to represent the gaps between the slabs. | ||
| 155 | const size_t total_gap_size = KernelSlabHeapGapsSize; | ||
| 156 | std::array<size_t, slab_types.size()> slab_gaps; | ||
| 157 | for (size_t i = 0; i < slab_gaps.size(); i++) { | ||
| 158 | // Note: This is an off-by-one error from Nintendo's intention, because GenerateRandomRange | ||
| 159 | // is inclusive. However, Nintendo also has the off-by-one error, and it's "harmless", so we | ||
| 160 | // will include it ourselves. | ||
| 161 | slab_gaps[i] = KSystemControl::GenerateRandomRange(0, total_gap_size); | ||
| 162 | } | ||
| 163 | |||
| 164 | // Sort the array, so that we can treat differences between values as offsets to the starts of | ||
| 165 | // slabs. | ||
| 166 | for (size_t i = 1; i < slab_gaps.size(); i++) { | ||
| 167 | for (size_t j = i; j > 0 && slab_gaps[j - 1] > slab_gaps[j]; j--) { | ||
| 168 | std::swap(slab_gaps[j], slab_gaps[j - 1]); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | for (size_t i = 0; i < slab_types.size(); i++) { | ||
| 173 | // Add the random gap to the address. | ||
| 174 | address += (i == 0) ? slab_gaps[0] : slab_gaps[i] - slab_gaps[i - 1]; | ||
| 175 | |||
| 176 | #define INITIALIZE_SLAB_HEAP(NAME, COUNT, ...) \ | ||
| 177 | case KSlabType_##NAME: \ | ||
| 178 | address = InitializeSlabHeap<NAME>(system, memory_layout, address, COUNT); \ | ||
| 179 | break; | ||
| 180 | |||
| 181 | // Initialize the slabheap. | ||
| 182 | switch (slab_types[i]) { | ||
| 183 | // For each of the slab types, we want to initialize that heap. | ||
| 184 | FOREACH_SLAB_TYPE(INITIALIZE_SLAB_HEAP) | ||
| 185 | // If we somehow get an invalid type, abort. | ||
| 186 | default: | ||
| 187 | UNREACHABLE(); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | } // namespace Kernel::Init | ||
diff --git a/src/core/hle/kernel/init/init_slab_setup.h b/src/core/hle/kernel/init/init_slab_setup.h new file mode 100644 index 000000000..a8f7e0918 --- /dev/null +++ b/src/core/hle/kernel/init/init_slab_setup.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Core { | ||
| 8 | class System; | ||
| 9 | } // namespace Core | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | class KernelCore; | ||
| 13 | class KMemoryLayout; | ||
| 14 | } // namespace Kernel | ||
| 15 | |||
| 16 | namespace Kernel::Init { | ||
| 17 | |||
| 18 | struct KSlabResourceCounts { | ||
| 19 | static KSlabResourceCounts CreateDefault(); | ||
| 20 | |||
| 21 | size_t num_KProcess; | ||
| 22 | size_t num_KThread; | ||
| 23 | size_t num_KEvent; | ||
| 24 | size_t num_KInterruptEvent; | ||
| 25 | size_t num_KPort; | ||
| 26 | size_t num_KSharedMemory; | ||
| 27 | size_t num_KTransferMemory; | ||
| 28 | size_t num_KCodeMemory; | ||
| 29 | size_t num_KDeviceAddressSpace; | ||
| 30 | size_t num_KSession; | ||
| 31 | size_t num_KLightSession; | ||
| 32 | size_t num_KObjectName; | ||
| 33 | size_t num_KResourceLimit; | ||
| 34 | size_t num_KDebug; | ||
| 35 | size_t num_KAlpha; | ||
| 36 | size_t num_KBeta; | ||
| 37 | }; | ||
| 38 | |||
| 39 | void InitializeSlabResourceCounts(KernelCore& kernel); | ||
| 40 | size_t CalculateTotalSlabHeapSize(const KernelCore& kernel); | ||
| 41 | void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout); | ||
| 42 | |||
| 43 | } // namespace Kernel::Init | ||
diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp new file mode 100644 index 000000000..dbe237f09 --- /dev/null +++ b/src/core/hle/kernel/k_auto_object.cpp | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_auto_object.h" | ||
| 6 | |||
| 7 | namespace Kernel { | ||
| 8 | |||
| 9 | KAutoObject* KAutoObject::Create(KAutoObject* obj) { | ||
| 10 | obj->m_ref_count = 1; | ||
| 11 | return obj; | ||
| 12 | } | ||
| 13 | |||
| 14 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h new file mode 100644 index 000000000..bc18582be --- /dev/null +++ b/src/core/hle/kernel/k_auto_object.h | |||
| @@ -0,0 +1,302 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/common_funcs.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/intrusive_red_black_tree.h" | ||
| 14 | #include "core/hle/kernel/k_class_token.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | class KernelCore; | ||
| 19 | class KProcess; | ||
| 20 | |||
| 21 | #define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \ | ||
| 22 | YUZU_NON_COPYABLE(CLASS); \ | ||
| 23 | YUZU_NON_MOVEABLE(CLASS); \ | ||
| 24 | \ | ||
| 25 | private: \ | ||
| 26 | friend class ::Kernel::KClassTokenGenerator; \ | ||
| 27 | static constexpr inline auto ObjectType = ::Kernel::KClassTokenGenerator::ObjectType::CLASS; \ | ||
| 28 | static constexpr inline const char* const TypeName = #CLASS; \ | ||
| 29 | static constexpr inline ClassTokenType ClassToken() { \ | ||
| 30 | return ::Kernel::ClassToken<CLASS>; \ | ||
| 31 | } \ | ||
| 32 | \ | ||
| 33 | public: \ | ||
| 34 | using BaseClass = BASE_CLASS; \ | ||
| 35 | static constexpr TypeObj GetStaticTypeObj() { \ | ||
| 36 | constexpr ClassTokenType Token = ClassToken(); \ | ||
| 37 | return TypeObj(TypeName, Token); \ | ||
| 38 | } \ | ||
| 39 | static constexpr const char* GetStaticTypeName() { \ | ||
| 40 | return TypeName; \ | ||
| 41 | } \ | ||
| 42 | virtual TypeObj GetTypeObj() const { \ | ||
| 43 | return GetStaticTypeObj(); \ | ||
| 44 | } \ | ||
| 45 | virtual const char* GetTypeName() const { \ | ||
| 46 | return GetStaticTypeName(); \ | ||
| 47 | } \ | ||
| 48 | \ | ||
| 49 | private: \ | ||
| 50 | constexpr bool operator!=(const TypeObj& rhs) | ||
| 51 | |||
| 52 | class KAutoObject { | ||
| 53 | protected: | ||
| 54 | class TypeObj { | ||
| 55 | public: | ||
| 56 | constexpr explicit TypeObj(const char* n, ClassTokenType tok) | ||
| 57 | : m_name(n), m_class_token(tok) {} | ||
| 58 | |||
| 59 | constexpr const char* GetName() const { | ||
| 60 | return m_name; | ||
| 61 | } | ||
| 62 | constexpr ClassTokenType GetClassToken() const { | ||
| 63 | return m_class_token; | ||
| 64 | } | ||
| 65 | |||
| 66 | constexpr bool operator==(const TypeObj& rhs) const { | ||
| 67 | return this->GetClassToken() == rhs.GetClassToken(); | ||
| 68 | } | ||
| 69 | |||
| 70 | constexpr bool operator!=(const TypeObj& rhs) const { | ||
| 71 | return this->GetClassToken() != rhs.GetClassToken(); | ||
| 72 | } | ||
| 73 | |||
| 74 | constexpr bool IsDerivedFrom(const TypeObj& rhs) const { | ||
| 75 | return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken(); | ||
| 76 | } | ||
| 77 | |||
| 78 | private: | ||
| 79 | const char* m_name; | ||
| 80 | ClassTokenType m_class_token; | ||
| 81 | }; | ||
| 82 | |||
| 83 | private: | ||
| 84 | KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject); | ||
| 85 | |||
| 86 | public: | ||
| 87 | explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {} | ||
| 88 | virtual ~KAutoObject() = default; | ||
| 89 | |||
| 90 | static KAutoObject* Create(KAutoObject* ptr); | ||
| 91 | |||
| 92 | // Destroy is responsible for destroying the auto object's resources when ref_count hits zero. | ||
| 93 | virtual void Destroy() { | ||
| 94 | UNIMPLEMENTED(); | ||
| 95 | } | ||
| 96 | |||
| 97 | // Finalize is responsible for cleaning up resource, but does not destroy the object. | ||
| 98 | virtual void Finalize() {} | ||
| 99 | |||
| 100 | virtual KProcess* GetOwner() const { | ||
| 101 | return nullptr; | ||
| 102 | } | ||
| 103 | |||
| 104 | u32 GetReferenceCount() const { | ||
| 105 | return m_ref_count.load(); | ||
| 106 | } | ||
| 107 | |||
| 108 | bool IsDerivedFrom(const TypeObj& rhs) const { | ||
| 109 | return this->GetTypeObj().IsDerivedFrom(rhs); | ||
| 110 | } | ||
| 111 | |||
| 112 | bool IsDerivedFrom(const KAutoObject& rhs) const { | ||
| 113 | return this->IsDerivedFrom(rhs.GetTypeObj()); | ||
| 114 | } | ||
| 115 | |||
| 116 | template <typename Derived> | ||
| 117 | Derived DynamicCast() { | ||
| 118 | static_assert(std::is_pointer_v<Derived>); | ||
| 119 | using DerivedType = std::remove_pointer_t<Derived>; | ||
| 120 | |||
| 121 | if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { | ||
| 122 | return static_cast<Derived>(this); | ||
| 123 | } else { | ||
| 124 | return nullptr; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | template <typename Derived> | ||
| 129 | const Derived DynamicCast() const { | ||
| 130 | static_assert(std::is_pointer_v<Derived>); | ||
| 131 | using DerivedType = std::remove_pointer_t<Derived>; | ||
| 132 | |||
| 133 | if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { | ||
| 134 | return static_cast<Derived>(this); | ||
| 135 | } else { | ||
| 136 | return nullptr; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | bool Open() { | ||
| 141 | // Atomically increment the reference count, only if it's positive. | ||
| 142 | u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); | ||
| 143 | do { | ||
| 144 | if (cur_ref_count == 0) { | ||
| 145 | return false; | ||
| 146 | } | ||
| 147 | ASSERT(cur_ref_count < cur_ref_count + 1); | ||
| 148 | } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, | ||
| 149 | std::memory_order_relaxed)); | ||
| 150 | |||
| 151 | return true; | ||
| 152 | } | ||
| 153 | |||
| 154 | void Close() { | ||
| 155 | // Atomically decrement the reference count, not allowing it to become negative. | ||
| 156 | u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); | ||
| 157 | do { | ||
| 158 | ASSERT(cur_ref_count > 0); | ||
| 159 | } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, | ||
| 160 | std::memory_order_relaxed)); | ||
| 161 | |||
| 162 | // If ref count hits zero, destroy the object. | ||
| 163 | if (cur_ref_count - 1 == 0) { | ||
| 164 | this->Destroy(); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | protected: | ||
| 169 | KernelCore& kernel; | ||
| 170 | std::string name; | ||
| 171 | |||
| 172 | private: | ||
| 173 | std::atomic<u32> m_ref_count{}; | ||
| 174 | }; | ||
| 175 | |||
| 176 | class KAutoObjectWithListContainer; | ||
| 177 | |||
| 178 | class KAutoObjectWithList : public KAutoObject { | ||
| 179 | public: | ||
| 180 | explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {} | ||
| 181 | |||
| 182 | static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { | ||
| 183 | const u64 lid = lhs.GetId(); | ||
| 184 | const u64 rid = rhs.GetId(); | ||
| 185 | |||
| 186 | if (lid < rid) { | ||
| 187 | return -1; | ||
| 188 | } else if (lid > rid) { | ||
| 189 | return 1; | ||
| 190 | } else { | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | public: | ||
| 196 | virtual u64 GetId() const { | ||
| 197 | return reinterpret_cast<u64>(this); | ||
| 198 | } | ||
| 199 | |||
| 200 | virtual const std::string& GetName() const { | ||
| 201 | return name; | ||
| 202 | } | ||
| 203 | |||
| 204 | private: | ||
| 205 | friend class KAutoObjectWithListContainer; | ||
| 206 | |||
| 207 | Common::IntrusiveRedBlackTreeNode list_node; | ||
| 208 | }; | ||
| 209 | |||
| 210 | template <typename T> | ||
| 211 | class KScopedAutoObject { | ||
| 212 | YUZU_NON_COPYABLE(KScopedAutoObject); | ||
| 213 | |||
| 214 | public: | ||
| 215 | constexpr KScopedAutoObject() = default; | ||
| 216 | |||
| 217 | constexpr KScopedAutoObject(T* o) : m_obj(o) { | ||
| 218 | if (m_obj != nullptr) { | ||
| 219 | m_obj->Open(); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | ~KScopedAutoObject() { | ||
| 224 | if (m_obj != nullptr) { | ||
| 225 | m_obj->Close(); | ||
| 226 | } | ||
| 227 | m_obj = nullptr; | ||
| 228 | } | ||
| 229 | |||
| 230 | template <typename U> | ||
| 231 | requires(std::derived_from<T, U> || | ||
| 232 | std::derived_from<U, T>) constexpr KScopedAutoObject(KScopedAutoObject<U>&& rhs) { | ||
| 233 | if constexpr (std::derived_from<U, T>) { | ||
| 234 | // Upcast. | ||
| 235 | m_obj = rhs.m_obj; | ||
| 236 | rhs.m_obj = nullptr; | ||
| 237 | } else { | ||
| 238 | // Downcast. | ||
| 239 | T* derived = nullptr; | ||
| 240 | if (rhs.m_obj != nullptr) { | ||
| 241 | derived = rhs.m_obj->template DynamicCast<T*>(); | ||
| 242 | if (derived == nullptr) { | ||
| 243 | rhs.m_obj->Close(); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | m_obj = derived; | ||
| 248 | rhs.m_obj = nullptr; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | constexpr KScopedAutoObject<T>& operator=(KScopedAutoObject<T>&& rhs) { | ||
| 253 | rhs.Swap(*this); | ||
| 254 | return *this; | ||
| 255 | } | ||
| 256 | |||
| 257 | constexpr T* operator->() { | ||
| 258 | return m_obj; | ||
| 259 | } | ||
| 260 | constexpr T& operator*() { | ||
| 261 | return *m_obj; | ||
| 262 | } | ||
| 263 | |||
| 264 | constexpr void Reset(T* o) { | ||
| 265 | KScopedAutoObject(o).Swap(*this); | ||
| 266 | } | ||
| 267 | |||
| 268 | constexpr T* GetPointerUnsafe() { | ||
| 269 | return m_obj; | ||
| 270 | } | ||
| 271 | |||
| 272 | constexpr T* GetPointerUnsafe() const { | ||
| 273 | return m_obj; | ||
| 274 | } | ||
| 275 | |||
| 276 | constexpr T* ReleasePointerUnsafe() { | ||
| 277 | T* ret = m_obj; | ||
| 278 | m_obj = nullptr; | ||
| 279 | return ret; | ||
| 280 | } | ||
| 281 | |||
| 282 | constexpr bool IsNull() const { | ||
| 283 | return m_obj == nullptr; | ||
| 284 | } | ||
| 285 | constexpr bool IsNotNull() const { | ||
| 286 | return m_obj != nullptr; | ||
| 287 | } | ||
| 288 | |||
| 289 | private: | ||
| 290 | template <typename U> | ||
| 291 | friend class KScopedAutoObject; | ||
| 292 | |||
| 293 | private: | ||
| 294 | T* m_obj{}; | ||
| 295 | |||
| 296 | private: | ||
| 297 | constexpr void Swap(KScopedAutoObject& rhs) noexcept { | ||
| 298 | std::swap(m_obj, rhs.m_obj); | ||
| 299 | } | ||
| 300 | }; | ||
| 301 | |||
| 302 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_auto_object_container.cpp b/src/core/hle/kernel/k_auto_object_container.cpp new file mode 100644 index 000000000..fc0c28874 --- /dev/null +++ b/src/core/hle/kernel/k_auto_object_container.cpp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_auto_object_container.h" | ||
| 6 | |||
| 7 | namespace Kernel { | ||
| 8 | |||
| 9 | void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { | ||
| 10 | KScopedLightLock lk(m_lock); | ||
| 11 | |||
| 12 | m_object_list.insert(*obj); | ||
| 13 | } | ||
| 14 | |||
| 15 | void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { | ||
| 16 | KScopedLightLock lk(m_lock); | ||
| 17 | |||
| 18 | m_object_list.erase(m_object_list.iterator_to(*obj)); | ||
| 19 | } | ||
| 20 | |||
| 21 | size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { | ||
| 22 | KScopedLightLock lk(m_lock); | ||
| 23 | |||
| 24 | return std::count_if(m_object_list.begin(), m_object_list.end(), | ||
| 25 | [&](const auto& obj) { return obj.GetOwner() == owner; }); | ||
| 26 | } | ||
| 27 | |||
| 28 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_auto_object_container.h b/src/core/hle/kernel/k_auto_object_container.h new file mode 100644 index 000000000..ff40cf5a7 --- /dev/null +++ b/src/core/hle/kernel/k_auto_object_container.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/intrusive_red_black_tree.h" | ||
| 13 | #include "core/hle/kernel/k_auto_object.h" | ||
| 14 | #include "core/hle/kernel/k_light_lock.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | class KernelCore; | ||
| 19 | class KProcess; | ||
| 20 | |||
| 21 | class KAutoObjectWithListContainer { | ||
| 22 | YUZU_NON_COPYABLE(KAutoObjectWithListContainer); | ||
| 23 | YUZU_NON_MOVEABLE(KAutoObjectWithListContainer); | ||
| 24 | |||
| 25 | public: | ||
| 26 | using ListType = Common::IntrusiveRedBlackTreeMemberTraits< | ||
| 27 | &KAutoObjectWithList::list_node>::TreeType<KAutoObjectWithList>; | ||
| 28 | |||
| 29 | public: | ||
| 30 | class ListAccessor : public KScopedLightLock { | ||
| 31 | public: | ||
| 32 | explicit ListAccessor(KAutoObjectWithListContainer* container) | ||
| 33 | : KScopedLightLock(container->m_lock), m_list(container->m_object_list) {} | ||
| 34 | explicit ListAccessor(KAutoObjectWithListContainer& container) | ||
| 35 | : KScopedLightLock(container.m_lock), m_list(container.m_object_list) {} | ||
| 36 | |||
| 37 | typename ListType::iterator begin() const { | ||
| 38 | return m_list.begin(); | ||
| 39 | } | ||
| 40 | |||
| 41 | typename ListType::iterator end() const { | ||
| 42 | return m_list.end(); | ||
| 43 | } | ||
| 44 | |||
| 45 | typename ListType::iterator find(typename ListType::const_reference ref) const { | ||
| 46 | return m_list.find(ref); | ||
| 47 | } | ||
| 48 | |||
| 49 | private: | ||
| 50 | ListType& m_list; | ||
| 51 | }; | ||
| 52 | |||
| 53 | friend class ListAccessor; | ||
| 54 | |||
| 55 | public: | ||
| 56 | KAutoObjectWithListContainer(KernelCore& kernel) : m_lock(kernel), m_object_list() {} | ||
| 57 | |||
| 58 | void Initialize() {} | ||
| 59 | void Finalize() {} | ||
| 60 | |||
| 61 | void Register(KAutoObjectWithList* obj); | ||
| 62 | void Unregister(KAutoObjectWithList* obj); | ||
| 63 | size_t GetOwnedCount(KProcess* owner); | ||
| 64 | |||
| 65 | private: | ||
| 66 | KLightLock m_lock; | ||
| 67 | ListType m_object_list; | ||
| 68 | }; | ||
| 69 | |||
| 70 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp new file mode 100644 index 000000000..beb8a2a05 --- /dev/null +++ b/src/core/hle/kernel/k_class_token.cpp | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_auto_object.h" | ||
| 6 | #include "core/hle/kernel/k_class_token.h" | ||
| 7 | #include "core/hle/kernel/k_client_port.h" | ||
| 8 | #include "core/hle/kernel/k_client_session.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | ||
| 10 | #include "core/hle/kernel/k_port.h" | ||
| 11 | #include "core/hle/kernel/k_process.h" | ||
| 12 | #include "core/hle/kernel/k_readable_event.h" | ||
| 13 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 14 | #include "core/hle/kernel/k_server_port.h" | ||
| 15 | #include "core/hle/kernel/k_server_session.h" | ||
| 16 | #include "core/hle/kernel/k_session.h" | ||
| 17 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 18 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 19 | #include "core/hle/kernel/k_thread.h" | ||
| 20 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 21 | #include "core/hle/kernel/k_writable_event.h" | ||
| 22 | |||
| 23 | namespace Kernel { | ||
| 24 | |||
| 25 | // Ensure that we generate correct class tokens for all types. | ||
| 26 | |||
| 27 | // Ensure that the absolute token values are correct. | ||
| 28 | static_assert(ClassToken<KAutoObject> == 0b00000000'00000000); | ||
| 29 | static_assert(ClassToken<KSynchronizationObject> == 0b00000000'00000001); | ||
| 30 | static_assert(ClassToken<KReadableEvent> == 0b00000000'00000011); | ||
| 31 | // static_assert(ClassToken<KInterruptEvent> == 0b00000111'00000011); | ||
| 32 | // static_assert(ClassToken<KDebug> == 0b00001011'00000001); | ||
| 33 | static_assert(ClassToken<KThread> == 0b00010011'00000001); | ||
| 34 | static_assert(ClassToken<KServerPort> == 0b00100011'00000001); | ||
| 35 | static_assert(ClassToken<KServerSession> == 0b01000011'00000001); | ||
| 36 | static_assert(ClassToken<KClientPort> == 0b10000011'00000001); | ||
| 37 | static_assert(ClassToken<KClientSession> == 0b00001101'00000000); | ||
| 38 | static_assert(ClassToken<KProcess> == 0b00010101'00000001); | ||
| 39 | static_assert(ClassToken<KResourceLimit> == 0b00100101'00000000); | ||
| 40 | // static_assert(ClassToken<KLightSession> == 0b01000101'00000000); | ||
| 41 | static_assert(ClassToken<KPort> == 0b10000101'00000000); | ||
| 42 | static_assert(ClassToken<KSession> == 0b00011001'00000000); | ||
| 43 | static_assert(ClassToken<KSharedMemory> == 0b00101001'00000000); | ||
| 44 | static_assert(ClassToken<KEvent> == 0b01001001'00000000); | ||
| 45 | static_assert(ClassToken<KWritableEvent> == 0b10001001'00000000); | ||
| 46 | // static_assert(ClassToken<KLightClientSession> == 0b00110001'00000000); | ||
| 47 | // static_assert(ClassToken<KLightServerSession> == 0b01010001'00000000); | ||
| 48 | static_assert(ClassToken<KTransferMemory> == 0b10010001'00000000); | ||
| 49 | // static_assert(ClassToken<KDeviceAddressSpace> == 0b01100001'00000000); | ||
| 50 | // static_assert(ClassToken<KSessionRequest> == 0b10100001'00000000); | ||
| 51 | // static_assert(ClassToken<KCodeMemory> == 0b11000001'00000000); | ||
| 52 | |||
| 53 | // Ensure that the token hierarchy is correct. | ||
| 54 | |||
| 55 | // Base classes | ||
| 56 | static_assert(ClassToken<KAutoObject> == (0b00000000)); | ||
| 57 | static_assert(ClassToken<KSynchronizationObject> == (0b00000001 | ClassToken<KAutoObject>)); | ||
| 58 | static_assert(ClassToken<KReadableEvent> == (0b00000010 | ClassToken<KSynchronizationObject>)); | ||
| 59 | |||
| 60 | // Final classes | ||
| 61 | // static_assert(ClassToken<KInterruptEvent> == ((0b00000111 << 8) | ClassToken<KReadableEvent>)); | ||
| 62 | // static_assert(ClassToken<KDebug> == ((0b00001011 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 63 | static_assert(ClassToken<KThread> == ((0b00010011 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 64 | static_assert(ClassToken<KServerPort> == ((0b00100011 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 65 | static_assert(ClassToken<KServerSession> == | ||
| 66 | ((0b01000011 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 67 | static_assert(ClassToken<KClientPort> == ((0b10000011 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 68 | static_assert(ClassToken<KClientSession> == ((0b00001101 << 8) | ClassToken<KAutoObject>)); | ||
| 69 | static_assert(ClassToken<KProcess> == ((0b00010101 << 8) | ClassToken<KSynchronizationObject>)); | ||
| 70 | static_assert(ClassToken<KResourceLimit> == ((0b00100101 << 8) | ClassToken<KAutoObject>)); | ||
| 71 | // static_assert(ClassToken<KLightSession> == ((0b01000101 << 8) | ClassToken<KAutoObject>)); | ||
| 72 | static_assert(ClassToken<KPort> == ((0b10000101 << 8) | ClassToken<KAutoObject>)); | ||
| 73 | static_assert(ClassToken<KSession> == ((0b00011001 << 8) | ClassToken<KAutoObject>)); | ||
| 74 | static_assert(ClassToken<KSharedMemory> == ((0b00101001 << 8) | ClassToken<KAutoObject>)); | ||
| 75 | static_assert(ClassToken<KEvent> == ((0b01001001 << 8) | ClassToken<KAutoObject>)); | ||
| 76 | static_assert(ClassToken<KWritableEvent> == ((0b10001001 << 8) | ClassToken<KAutoObject>)); | ||
| 77 | // static_assert(ClassToken<KLightClientSession> == ((0b00110001 << 8) | ClassToken<KAutoObject>)); | ||
| 78 | // static_assert(ClassToken<KLightServerSession> == ((0b01010001 << 8) | ClassToken<KAutoObject>)); | ||
| 79 | static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAutoObject>)); | ||
| 80 | // static_assert(ClassToken<KDeviceAddressSpace> == ((0b01100001 << 8) | ClassToken<KAutoObject>)); | ||
| 81 | // static_assert(ClassToken<KSessionRequest> == ((0b10100001 << 8) | ClassToken<KAutoObject>)); | ||
| 82 | // static_assert(ClassToken<KCodeMemory> == ((0b11000001 << 8) | ClassToken<KAutoObject>)); | ||
| 83 | |||
| 84 | // Ensure that the token hierarchy reflects the class hierarchy. | ||
| 85 | |||
| 86 | // Base classes. | ||
| 87 | static_assert(!std::is_final<KSynchronizationObject>::value && | ||
| 88 | std::is_base_of<KAutoObject, KSynchronizationObject>::value); | ||
| 89 | static_assert(!std::is_final<KReadableEvent>::value && | ||
| 90 | std::is_base_of<KSynchronizationObject, KReadableEvent>::value); | ||
| 91 | |||
| 92 | // Final classes | ||
| 93 | // static_assert(std::is_final<KInterruptEvent>::value && | ||
| 94 | // std::is_base_of<KReadableEvent, KInterruptEvent>::value); | ||
| 95 | // static_assert(std::is_final<KDebug>::value && | ||
| 96 | // std::is_base_of<KSynchronizationObject, KDebug>::value); | ||
| 97 | static_assert(std::is_final<KThread>::value && | ||
| 98 | std::is_base_of<KSynchronizationObject, KThread>::value); | ||
| 99 | static_assert(std::is_final<KServerPort>::value && | ||
| 100 | std::is_base_of<KSynchronizationObject, KServerPort>::value); | ||
| 101 | static_assert(std::is_final<KServerSession>::value && | ||
| 102 | std::is_base_of<KSynchronizationObject, KServerSession>::value); | ||
| 103 | static_assert(std::is_final<KClientPort>::value && | ||
| 104 | std::is_base_of<KSynchronizationObject, KClientPort>::value); | ||
| 105 | static_assert(std::is_final<KClientSession>::value && | ||
| 106 | std::is_base_of<KAutoObject, KClientSession>::value); | ||
| 107 | static_assert(std::is_final<KProcess>::value && | ||
| 108 | std::is_base_of<KSynchronizationObject, KProcess>::value); | ||
| 109 | static_assert(std::is_final<KResourceLimit>::value && | ||
| 110 | std::is_base_of<KAutoObject, KResourceLimit>::value); | ||
| 111 | // static_assert(std::is_final<KLightSession>::value && | ||
| 112 | // std::is_base_of<KAutoObject, KLightSession>::value); | ||
| 113 | static_assert(std::is_final<KPort>::value && std::is_base_of<KAutoObject, KPort>::value); | ||
| 114 | static_assert(std::is_final<KSession>::value && std::is_base_of<KAutoObject, KSession>::value); | ||
| 115 | static_assert(std::is_final<KSharedMemory>::value && | ||
| 116 | std::is_base_of<KAutoObject, KSharedMemory>::value); | ||
| 117 | static_assert(std::is_final<KEvent>::value && std::is_base_of<KAutoObject, KEvent>::value); | ||
| 118 | static_assert(std::is_final<KWritableEvent>::value && | ||
| 119 | std::is_base_of<KAutoObject, KWritableEvent>::value); | ||
| 120 | // static_assert(std::is_final<KLightClientSession>::value && | ||
| 121 | // std::is_base_of<KAutoObject, KLightClientSession>::value); | ||
| 122 | // static_assert(std::is_final<KLightServerSession>::value && | ||
| 123 | // std::is_base_of<KAutoObject, KLightServerSession>::value); | ||
| 124 | static_assert(std::is_final<KTransferMemory>::value && | ||
| 125 | std::is_base_of<KAutoObject, KTransferMemory>::value); | ||
| 126 | // static_assert(std::is_final<KDeviceAddressSpace>::value && | ||
| 127 | // std::is_base_of<KAutoObject, KDeviceAddressSpace>::value); | ||
| 128 | // static_assert(std::is_final<KSessionRequest>::value && | ||
| 129 | // std::is_base_of<KAutoObject, KSessionRequest>::value); | ||
| 130 | // static_assert(std::is_final<KCodeMemory>::value && | ||
| 131 | // std::is_base_of<KAutoObject, KCodeMemory>::value); | ||
| 132 | |||
| 133 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_class_token.h b/src/core/hle/kernel/k_class_token.h new file mode 100644 index 000000000..c28db49ec --- /dev/null +++ b/src/core/hle/kernel/k_class_token.h | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_util.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class KAutoObject; | ||
| 16 | |||
| 17 | class KClassTokenGenerator { | ||
| 18 | public: | ||
| 19 | using TokenBaseType = u16; | ||
| 20 | |||
| 21 | public: | ||
| 22 | static constexpr size_t BaseClassBits = 8; | ||
| 23 | static constexpr size_t FinalClassBits = (sizeof(TokenBaseType) * CHAR_BIT) - BaseClassBits; | ||
| 24 | // One bit per base class. | ||
| 25 | static constexpr size_t NumBaseClasses = BaseClassBits; | ||
| 26 | // Final classes are permutations of three bits. | ||
| 27 | static constexpr size_t NumFinalClasses = [] { | ||
| 28 | TokenBaseType index = 0; | ||
| 29 | for (size_t i = 0; i < FinalClassBits; i++) { | ||
| 30 | for (size_t j = i + 1; j < FinalClassBits; j++) { | ||
| 31 | for (size_t k = j + 1; k < FinalClassBits; k++) { | ||
| 32 | index++; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | return index; | ||
| 37 | }(); | ||
| 38 | |||
| 39 | private: | ||
| 40 | template <TokenBaseType Index> | ||
| 41 | static constexpr inline TokenBaseType BaseClassToken = 1U << Index; | ||
| 42 | |||
| 43 | template <TokenBaseType Index> | ||
| 44 | static constexpr inline TokenBaseType FinalClassToken = [] { | ||
| 45 | TokenBaseType index = 0; | ||
| 46 | for (size_t i = 0; i < FinalClassBits; i++) { | ||
| 47 | for (size_t j = i + 1; j < FinalClassBits; j++) { | ||
| 48 | for (size_t k = j + 1; k < FinalClassBits; k++) { | ||
| 49 | if ((index++) == Index) { | ||
| 50 | return static_cast<TokenBaseType>(((1ULL << i) | (1ULL << j) | (1ULL << k)) | ||
| 51 | << BaseClassBits); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | }(); | ||
| 57 | |||
| 58 | template <typename T> | ||
| 59 | static constexpr inline TokenBaseType GetClassToken() { | ||
| 60 | static_assert(std::is_base_of<KAutoObject, T>::value); | ||
| 61 | if constexpr (std::is_same<T, KAutoObject>::value) { | ||
| 62 | static_assert(T::ObjectType == ObjectType::KAutoObject); | ||
| 63 | return 0; | ||
| 64 | } else if constexpr (!std::is_final<T>::value) { | ||
| 65 | static_assert(ObjectType::BaseClassesStart <= T::ObjectType && | ||
| 66 | T::ObjectType < ObjectType::BaseClassesEnd); | ||
| 67 | constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - | ||
| 68 | static_cast<TokenBaseType>(ObjectType::BaseClassesStart); | ||
| 69 | return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>(); | ||
| 70 | } else if constexpr (ObjectType::FinalClassesStart <= T::ObjectType && | ||
| 71 | T::ObjectType < ObjectType::FinalClassesEnd) { | ||
| 72 | constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - | ||
| 73 | static_cast<TokenBaseType>(ObjectType::FinalClassesStart); | ||
| 74 | return FinalClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>(); | ||
| 75 | } else { | ||
| 76 | static_assert(!std::is_same<T, T>::value, "GetClassToken: Invalid Type"); | ||
| 77 | } | ||
| 78 | }; | ||
| 79 | |||
| 80 | public: | ||
| 81 | enum class ObjectType { | ||
| 82 | KAutoObject, | ||
| 83 | |||
| 84 | BaseClassesStart, | ||
| 85 | |||
| 86 | KSynchronizationObject = BaseClassesStart, | ||
| 87 | KReadableEvent, | ||
| 88 | |||
| 89 | BaseClassesEnd, | ||
| 90 | |||
| 91 | FinalClassesStart = BaseClassesEnd, | ||
| 92 | |||
| 93 | KInterruptEvent = FinalClassesStart, | ||
| 94 | KDebug, | ||
| 95 | KThread, | ||
| 96 | KServerPort, | ||
| 97 | KServerSession, | ||
| 98 | KClientPort, | ||
| 99 | KClientSession, | ||
| 100 | KProcess, | ||
| 101 | KResourceLimit, | ||
| 102 | KLightSession, | ||
| 103 | KPort, | ||
| 104 | KSession, | ||
| 105 | KSharedMemory, | ||
| 106 | KEvent, | ||
| 107 | KWritableEvent, | ||
| 108 | KLightClientSession, | ||
| 109 | KLightServerSession, | ||
| 110 | KTransferMemory, | ||
| 111 | KDeviceAddressSpace, | ||
| 112 | KSessionRequest, | ||
| 113 | KCodeMemory, | ||
| 114 | |||
| 115 | // NOTE: True order for these has not been determined yet. | ||
| 116 | KAlpha, | ||
| 117 | KBeta, | ||
| 118 | |||
| 119 | FinalClassesEnd = FinalClassesStart + NumFinalClasses, | ||
| 120 | }; | ||
| 121 | |||
| 122 | template <typename T> | ||
| 123 | static constexpr inline TokenBaseType ClassToken = GetClassToken<T>(); | ||
| 124 | }; | ||
| 125 | |||
| 126 | using ClassTokenType = KClassTokenGenerator::TokenBaseType; | ||
| 127 | |||
| 128 | template <typename T> | ||
| 129 | static constexpr inline ClassTokenType ClassToken = KClassTokenGenerator::ClassToken<T>; | ||
| 130 | |||
| 131 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp new file mode 100644 index 000000000..ad01cf67e --- /dev/null +++ b/src/core/hle/kernel/k_client_port.cpp | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | // Copyright 2021 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/scope_exit.h" | ||
| 6 | #include "core/hle/kernel/hle_ipc.h" | ||
| 7 | #include "core/hle/kernel/k_client_port.h" | ||
| 8 | #include "core/hle/kernel/k_port.h" | ||
| 9 | #include "core/hle/kernel/k_scheduler.h" | ||
| 10 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 11 | #include "core/hle/kernel/k_session.h" | ||
| 12 | #include "core/hle/kernel/svc_results.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||
| 17 | KClientPort::~KClientPort() = default; | ||
| 18 | |||
| 19 | void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { | ||
| 20 | // Set member variables. | ||
| 21 | num_sessions = 0; | ||
| 22 | peak_sessions = 0; | ||
| 23 | parent = parent_; | ||
| 24 | max_sessions = max_sessions_; | ||
| 25 | name = std::move(name_); | ||
| 26 | } | ||
| 27 | |||
| 28 | void KClientPort::OnSessionFinalized() { | ||
| 29 | KScopedSchedulerLock sl{kernel}; | ||
| 30 | |||
| 31 | const auto prev = num_sessions--; | ||
| 32 | if (prev == max_sessions) { | ||
| 33 | this->NotifyAvailable(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | void KClientPort::OnServerClosed() {} | ||
| 38 | |||
| 39 | bool KClientPort::IsLight() const { | ||
| 40 | return this->GetParent()->IsLight(); | ||
| 41 | } | ||
| 42 | |||
| 43 | bool KClientPort::IsServerClosed() const { | ||
| 44 | return this->GetParent()->IsServerClosed(); | ||
| 45 | } | ||
| 46 | |||
| 47 | void KClientPort::Destroy() { | ||
| 48 | // Note with our parent that we're closed. | ||
| 49 | parent->OnClientClosed(); | ||
| 50 | |||
| 51 | // Close our reference to our parent. | ||
| 52 | parent->Close(); | ||
| 53 | } | ||
| 54 | |||
| 55 | bool KClientPort::IsSignaled() const { | ||
| 56 | return num_sessions < max_sessions; | ||
| 57 | } | ||
| 58 | |||
| 59 | ResultCode KClientPort::CreateSession(KClientSession** out) { | ||
| 60 | // Reserve a new session from the resource limit. | ||
| 61 | // KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), | ||
| 62 | // LimitableResource::Sessions); | ||
| 63 | // R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); | ||
| 64 | |||
| 65 | // Update the session counts. | ||
| 66 | { | ||
| 67 | // Atomically increment the number of sessions. | ||
| 68 | s32 new_sessions; | ||
| 69 | { | ||
| 70 | const auto max = max_sessions; | ||
| 71 | auto cur_sessions = num_sessions.load(std::memory_order_acquire); | ||
| 72 | do { | ||
| 73 | R_UNLESS(cur_sessions < max, ResultOutOfSessions); | ||
| 74 | new_sessions = cur_sessions + 1; | ||
| 75 | } while (!num_sessions.compare_exchange_weak(cur_sessions, new_sessions, | ||
| 76 | std::memory_order_relaxed)); | ||
| 77 | } | ||
| 78 | |||
| 79 | // Atomically update the peak session tracking. | ||
| 80 | { | ||
| 81 | auto peak = peak_sessions.load(std::memory_order_acquire); | ||
| 82 | do { | ||
| 83 | if (peak >= new_sessions) { | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | } while (!peak_sessions.compare_exchange_weak(peak, new_sessions, | ||
| 87 | std::memory_order_relaxed)); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | // Create a new session. | ||
| 92 | KSession* session = KSession::Create(kernel); | ||
| 93 | if (session == nullptr) { | ||
| 94 | // Decrement the session count. | ||
| 95 | const auto prev = num_sessions--; | ||
| 96 | if (prev == max_sessions) { | ||
| 97 | this->NotifyAvailable(); | ||
| 98 | } | ||
| 99 | |||
| 100 | return ResultOutOfResource; | ||
| 101 | } | ||
| 102 | |||
| 103 | // Initialize the session. | ||
| 104 | session->Initialize(this, parent->GetName()); | ||
| 105 | |||
| 106 | // Commit the session reservation. | ||
| 107 | // session_reservation.Commit(); | ||
| 108 | |||
| 109 | // Register the session. | ||
| 110 | KSession::Register(kernel, session); | ||
| 111 | auto session_guard = SCOPE_GUARD({ | ||
| 112 | session->GetClientSession().Close(); | ||
| 113 | session->GetServerSession().Close(); | ||
| 114 | }); | ||
| 115 | |||
| 116 | // Enqueue the session with our parent. | ||
| 117 | R_TRY(parent->EnqueueSession(std::addressof(session->GetServerSession()))); | ||
| 118 | |||
| 119 | // We succeeded, so set the output. | ||
| 120 | session_guard.Cancel(); | ||
| 121 | *out = std::addressof(session->GetClientSession()); | ||
| 122 | return RESULT_SUCCESS; | ||
| 123 | } | ||
| 124 | |||
| 125 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h new file mode 100644 index 000000000..d00ce3ddd --- /dev/null +++ b/src/core/hle/kernel/k_client_port.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | class KClientSession; | ||
| 17 | class KernelCore; | ||
| 18 | class KPort; | ||
| 19 | |||
| 20 | class KClientPort final : public KSynchronizationObject { | ||
| 21 | KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); | ||
| 22 | |||
| 23 | public: | ||
| 24 | explicit KClientPort(KernelCore& kernel_); | ||
| 25 | virtual ~KClientPort() override; | ||
| 26 | |||
| 27 | void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); | ||
| 28 | void OnSessionFinalized(); | ||
| 29 | void OnServerClosed(); | ||
| 30 | |||
| 31 | const KPort* GetParent() const { | ||
| 32 | return parent; | ||
| 33 | } | ||
| 34 | |||
| 35 | s32 GetNumSessions() const { | ||
| 36 | return num_sessions; | ||
| 37 | } | ||
| 38 | s32 GetPeakSessions() const { | ||
| 39 | return peak_sessions; | ||
| 40 | } | ||
| 41 | s32 GetMaxSessions() const { | ||
| 42 | return max_sessions; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool IsLight() const; | ||
| 46 | bool IsServerClosed() const; | ||
| 47 | |||
| 48 | // Overridden virtual functions. | ||
| 49 | virtual void Destroy() override; | ||
| 50 | virtual bool IsSignaled() const override; | ||
| 51 | |||
| 52 | ResultCode CreateSession(KClientSession** out); | ||
| 53 | |||
| 54 | private: | ||
| 55 | std::atomic<s32> num_sessions{}; | ||
| 56 | std::atomic<s32> peak_sessions{}; | ||
| 57 | s32 max_sessions{}; | ||
| 58 | KPort* parent{}; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp new file mode 100644 index 000000000..8ad1be762 --- /dev/null +++ b/src/core/hle/kernel/k_client_session.cpp | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/hle_ipc.h" | ||
| 6 | #include "core/hle/kernel/k_client_session.h" | ||
| 7 | #include "core/hle/kernel/k_server_session.h" | ||
| 8 | #include "core/hle/kernel/k_session.h" | ||
| 9 | #include "core/hle/kernel/k_thread.h" | ||
| 10 | #include "core/hle/kernel/svc_results.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | KClientSession::KClientSession(KernelCore& kernel_) | ||
| 16 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||
| 17 | KClientSession::~KClientSession() = default; | ||
| 18 | |||
| 19 | void KClientSession::Destroy() { | ||
| 20 | parent->OnClientClosed(); | ||
| 21 | parent->Close(); | ||
| 22 | } | ||
| 23 | |||
| 24 | void KClientSession::OnServerClosed() {} | ||
| 25 | |||
| 26 | ResultCode KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, | ||
| 27 | Core::Timing::CoreTiming& core_timing) { | ||
| 28 | // Signal the server session that new data is available | ||
| 29 | return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing); | ||
| 30 | } | ||
| 31 | |||
| 32 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h new file mode 100644 index 000000000..720a8c243 --- /dev/null +++ b/src/core/hle/kernel/k_client_session.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "core/hle/kernel/k_auto_object.h" | ||
| 11 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 12 | #include "core/hle/kernel/slab_helpers.h" | ||
| 13 | #include "core/hle/result.h" | ||
| 14 | |||
| 15 | union ResultCode; | ||
| 16 | |||
| 17 | namespace Core::Memory { | ||
| 18 | class Memory; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Core::Timing { | ||
| 22 | class CoreTiming; | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace Kernel { | ||
| 26 | |||
| 27 | class KernelCore; | ||
| 28 | class KSession; | ||
| 29 | class KThread; | ||
| 30 | |||
| 31 | class KClientSession final | ||
| 32 | : public KAutoObjectWithSlabHeapAndContainer<KClientSession, KAutoObjectWithList> { | ||
| 33 | KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); | ||
| 34 | |||
| 35 | public: | ||
| 36 | explicit KClientSession(KernelCore& kernel_); | ||
| 37 | virtual ~KClientSession(); | ||
| 38 | |||
| 39 | void Initialize(KSession* parent_, std::string&& name_) { | ||
| 40 | // Set member variables. | ||
| 41 | parent = parent_; | ||
| 42 | name = std::move(name_); | ||
| 43 | } | ||
| 44 | |||
| 45 | virtual void Destroy() override; | ||
| 46 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||
| 47 | |||
| 48 | KSession* GetParent() const { | ||
| 49 | return parent; | ||
| 50 | } | ||
| 51 | |||
| 52 | ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, | ||
| 53 | Core::Timing::CoreTiming& core_timing); | ||
| 54 | |||
| 55 | void OnServerClosed(); | ||
| 56 | |||
| 57 | private: | ||
| 58 | KSession* parent{}; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 170d8fa0d..ce3bade60 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp | |||
| @@ -7,12 +7,13 @@ | |||
| 7 | #include "core/arm/exclusive_monitor.h" | 7 | #include "core/arm/exclusive_monitor.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/k_condition_variable.h" | 9 | #include "core/hle/kernel/k_condition_variable.h" |
| 10 | #include "core/hle/kernel/k_linked_list.h" | ||
| 11 | #include "core/hle/kernel/k_process.h" | ||
| 10 | #include "core/hle/kernel/k_scheduler.h" | 12 | #include "core/hle/kernel/k_scheduler.h" |
| 11 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 13 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 12 | #include "core/hle/kernel/k_synchronization_object.h" | 14 | #include "core/hle/kernel/k_synchronization_object.h" |
| 13 | #include "core/hle/kernel/k_thread.h" | 15 | #include "core/hle/kernel/k_thread.h" |
| 14 | #include "core/hle/kernel/kernel.h" | 16 | #include "core/hle/kernel/kernel.h" |
| 15 | #include "core/hle/kernel/process.h" | ||
| 16 | #include "core/hle/kernel/svc_common.h" | 17 | #include "core/hle/kernel/svc_common.h" |
| 17 | #include "core/hle/kernel/svc_results.h" | 18 | #include "core/hle/kernel/svc_results.h" |
| 18 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| @@ -107,8 +108,8 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val | |||
| 107 | 108 | ||
| 108 | // Wait for the address. | 109 | // Wait for the address. |
| 109 | { | 110 | { |
| 110 | std::shared_ptr<KThread> owner_thread; | 111 | KScopedAutoObject<KThread> owner_thread; |
| 111 | ASSERT(!owner_thread); | 112 | ASSERT(owner_thread.IsNull()); |
| 112 | { | 113 | { |
| 113 | KScopedSchedulerLock sl(kernel); | 114 | KScopedSchedulerLock sl(kernel); |
| 114 | cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); | 115 | cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); |
| @@ -126,8 +127,10 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val | |||
| 126 | R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS); | 127 | R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS); |
| 127 | 128 | ||
| 128 | // Get the lock owner thread. | 129 | // Get the lock owner thread. |
| 129 | owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>(handle); | 130 | owner_thread = |
| 130 | R_UNLESS(owner_thread, ResultInvalidHandle); | 131 | kernel.CurrentProcess()->GetHandleTable().GetObjectWithoutPseudoHandle<KThread>( |
| 132 | handle); | ||
| 133 | R_UNLESS(owner_thread.IsNotNull(), ResultInvalidHandle); | ||
| 131 | 134 | ||
| 132 | // Update the lock. | 135 | // Update the lock. |
| 133 | cur_thread->SetAddressKey(addr, value); | 136 | cur_thread->SetAddressKey(addr, value); |
| @@ -137,7 +140,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val | |||
| 137 | cur_thread->SetMutexWaitAddressForDebugging(addr); | 140 | cur_thread->SetMutexWaitAddressForDebugging(addr); |
| 138 | } | 141 | } |
| 139 | } | 142 | } |
| 140 | ASSERT(owner_thread); | 143 | ASSERT(owner_thread.IsNotNull()); |
| 141 | } | 144 | } |
| 142 | 145 | ||
| 143 | // Remove the thread as a waiter from the lock owner. | 146 | // Remove the thread as a waiter from the lock owner. |
| @@ -176,19 +179,22 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { | |||
| 176 | 179 | ||
| 177 | KThread* thread_to_close = nullptr; | 180 | KThread* thread_to_close = nullptr; |
| 178 | if (can_access) { | 181 | if (can_access) { |
| 179 | if (prev_tag == InvalidHandle) { | 182 | if (prev_tag == Svc::InvalidHandle) { |
| 180 | // If nobody held the lock previously, we're all good. | 183 | // If nobody held the lock previously, we're all good. |
| 181 | thread->SetSyncedObject(nullptr, RESULT_SUCCESS); | 184 | thread->SetSyncedObject(nullptr, RESULT_SUCCESS); |
| 182 | thread->Wakeup(); | 185 | thread->Wakeup(); |
| 183 | } else { | 186 | } else { |
| 184 | // Get the previous owner. | 187 | // Get the previous owner. |
| 185 | auto owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>( | 188 | KThread* owner_thread = kernel.CurrentProcess() |
| 186 | prev_tag & ~Svc::HandleWaitMask); | 189 | ->GetHandleTable() |
| 190 | .GetObjectWithoutPseudoHandle<KThread>( | ||
| 191 | static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask)) | ||
| 192 | .ReleasePointerUnsafe(); | ||
| 187 | 193 | ||
| 188 | if (owner_thread) { | 194 | if (owner_thread) { |
| 189 | // Add the thread as a waiter on the owner. | 195 | // Add the thread as a waiter on the owner. |
| 190 | owner_thread->AddWaiter(thread); | 196 | owner_thread->AddWaiter(thread); |
| 191 | thread_to_close = owner_thread.get(); | 197 | thread_to_close = owner_thread; |
| 192 | } else { | 198 | } else { |
| 193 | // The lock was tagged with a thread that doesn't exist. | 199 | // The lock was tagged with a thread that doesn't exist. |
| 194 | thread->SetSyncedObject(nullptr, ResultInvalidState); | 200 | thread->SetSyncedObject(nullptr, ResultInvalidState); |
| @@ -208,9 +214,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 208 | // Prepare for signaling. | 214 | // Prepare for signaling. |
| 209 | constexpr int MaxThreads = 16; | 215 | constexpr int MaxThreads = 16; |
| 210 | 216 | ||
| 211 | // TODO(bunnei): This should just be Thread once we implement KAutoObject instead of using | 217 | KLinkedList<KThread> thread_list{kernel}; |
| 212 | // std::shared_ptr. | ||
| 213 | std::vector<std::shared_ptr<KThread>> thread_list; | ||
| 214 | std::array<KThread*, MaxThreads> thread_array; | 218 | std::array<KThread*, MaxThreads> thread_array; |
| 215 | s32 num_to_close{}; | 219 | s32 num_to_close{}; |
| 216 | 220 | ||
| @@ -228,7 +232,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 228 | if (num_to_close < MaxThreads) { | 232 | if (num_to_close < MaxThreads) { |
| 229 | thread_array[num_to_close++] = thread; | 233 | thread_array[num_to_close++] = thread; |
| 230 | } else { | 234 | } else { |
| 231 | thread_list.push_back(SharedFrom(thread)); | 235 | thread_list.push_back(*thread); |
| 232 | } | 236 | } |
| 233 | } | 237 | } |
| 234 | 238 | ||
| @@ -251,7 +255,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 251 | 255 | ||
| 252 | // Close threads in the list. | 256 | // Close threads in the list. |
| 253 | for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) { | 257 | for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) { |
| 254 | (*it)->Close(); | 258 | (*it).Close(); |
| 255 | } | 259 | } |
| 256 | } | 260 | } |
| 257 | 261 | ||
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index bb2fa4ad5..0720efece 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp | |||
| @@ -3,30 +3,54 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/kernel/k_event.h" | 5 | #include "core/hle/kernel/k_event.h" |
| 6 | #include "core/hle/kernel/k_readable_event.h" | 6 | #include "core/hle/kernel/k_process.h" |
| 7 | #include "core/hle/kernel/k_writable_event.h" | 7 | #include "core/hle/kernel/k_resource_limit.h" |
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {} | 11 | KEvent::KEvent(KernelCore& kernel_) |
| 12 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, readable_event{kernel_}, writable_event{ | ||
| 13 | kernel_} {} | ||
| 12 | 14 | ||
| 13 | KEvent::~KEvent() = default; | 15 | KEvent::~KEvent() = default; |
| 14 | 16 | ||
| 15 | std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) { | 17 | void KEvent::Initialize(std::string&& name_) { |
| 16 | return std::make_shared<KEvent>(kernel, std::move(name)); | 18 | // Increment reference count. |
| 17 | } | 19 | // Because reference count is one on creation, this will result |
| 20 | // in a reference count of two. Thus, when both readable and | ||
| 21 | // writable events are closed this object will be destroyed. | ||
| 22 | Open(); | ||
| 18 | 23 | ||
| 19 | void KEvent::Initialize() { | ||
| 20 | // Create our sub events. | 24 | // Create our sub events. |
| 21 | readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable"); | 25 | KAutoObject::Create(std::addressof(readable_event)); |
| 22 | writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable"); | 26 | KAutoObject::Create(std::addressof(writable_event)); |
| 23 | 27 | ||
| 24 | // Initialize our sub sessions. | 28 | // Initialize our sub sessions. |
| 25 | readable_event->Initialize(this); | 29 | readable_event.Initialize(this, name_ + ":Readable"); |
| 26 | writable_event->Initialize(this); | 30 | writable_event.Initialize(this, name_ + ":Writable"); |
| 31 | |||
| 32 | // Set our owner process. | ||
| 33 | owner = kernel.CurrentProcess(); | ||
| 34 | if (owner) { | ||
| 35 | owner->Open(); | ||
| 36 | } | ||
| 27 | 37 | ||
| 28 | // Mark initialized. | 38 | // Mark initialized. |
| 39 | name = std::move(name_); | ||
| 29 | initialized = true; | 40 | initialized = true; |
| 30 | } | 41 | } |
| 31 | 42 | ||
| 43 | void KEvent::Finalize() { | ||
| 44 | KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList>::Finalize(); | ||
| 45 | } | ||
| 46 | |||
| 47 | void KEvent::PostDestroy(uintptr_t arg) { | ||
| 48 | // Release the event count resource the owner process holds. | ||
| 49 | KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||
| 50 | if (owner) { | ||
| 51 | owner->GetResourceLimit()->Release(LimitableResource::Events, 1); | ||
| 52 | owner->Close(); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 32 | } // namespace Kernel | 56 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 2fb887129..9a59ffb70 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h | |||
| @@ -4,53 +4,54 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/object.h" | 7 | #include "core/hle/kernel/k_readable_event.h" |
| 8 | #include "core/hle/kernel/k_writable_event.h" | ||
| 9 | #include "core/hle/kernel/slab_helpers.h" | ||
| 8 | 10 | ||
| 9 | namespace Kernel { | 11 | namespace Kernel { |
| 10 | 12 | ||
| 11 | class KernelCore; | 13 | class KernelCore; |
| 12 | class KReadableEvent; | 14 | class KReadableEvent; |
| 13 | class KWritableEvent; | 15 | class KWritableEvent; |
| 16 | class KProcess; | ||
| 14 | 17 | ||
| 15 | class KEvent final : public Object { | 18 | class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList> { |
| 16 | public: | 19 | KERNEL_AUTOOBJECT_TRAITS(KEvent, KAutoObject); |
| 17 | explicit KEvent(KernelCore& kernel, std::string&& name); | ||
| 18 | ~KEvent() override; | ||
| 19 | 20 | ||
| 20 | static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name); | 21 | public: |
| 22 | explicit KEvent(KernelCore& kernel_); | ||
| 23 | virtual ~KEvent(); | ||
| 21 | 24 | ||
| 22 | void Initialize(); | 25 | void Initialize(std::string&& name); |
| 23 | 26 | ||
| 24 | void Finalize() override {} | 27 | virtual void Finalize() override; |
| 25 | 28 | ||
| 26 | std::string GetTypeName() const override { | 29 | virtual bool IsInitialized() const override { |
| 27 | return "KEvent"; | 30 | return initialized; |
| 28 | } | 31 | } |
| 29 | 32 | ||
| 30 | static constexpr HandleType HANDLE_TYPE = HandleType::Event; | 33 | virtual uintptr_t GetPostDestroyArgument() const override { |
| 31 | HandleType GetHandleType() const override { | 34 | return reinterpret_cast<uintptr_t>(owner); |
| 32 | return HANDLE_TYPE; | ||
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | std::shared_ptr<KReadableEvent>& GetReadableEvent() { | 37 | static void PostDestroy(uintptr_t arg); |
| 36 | return readable_event; | ||
| 37 | } | ||
| 38 | 38 | ||
| 39 | std::shared_ptr<KWritableEvent>& GetWritableEvent() { | 39 | virtual KProcess* GetOwner() const override { |
| 40 | return writable_event; | 40 | return owner; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | const std::shared_ptr<KReadableEvent>& GetReadableEvent() const { | 43 | KReadableEvent& GetReadableEvent() { |
| 44 | return readable_event; | 44 | return readable_event; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | const std::shared_ptr<KWritableEvent>& GetWritableEvent() const { | 47 | KWritableEvent& GetWritableEvent() { |
| 48 | return writable_event; | 48 | return writable_event; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | private: | 51 | private: |
| 52 | std::shared_ptr<KReadableEvent> readable_event; | 52 | KReadableEvent readable_event; |
| 53 | std::shared_ptr<KWritableEvent> writable_event; | 53 | KWritableEvent writable_event; |
| 54 | KProcess* owner{}; | ||
| 54 | bool initialized{}; | 55 | bool initialized{}; |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp new file mode 100644 index 000000000..0378447f6 --- /dev/null +++ b/src/core/hle/kernel/k_handle_table.cpp | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_handle_table.h" | ||
| 6 | |||
| 7 | namespace Kernel { | ||
| 8 | |||
| 9 | KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {} | ||
| 10 | KHandleTable ::~KHandleTable() = default; | ||
| 11 | |||
| 12 | ResultCode KHandleTable::Finalize() { | ||
| 13 | // Get the table and clear our record of it. | ||
| 14 | u16 saved_table_size = 0; | ||
| 15 | { | ||
| 16 | KScopedSpinLock lk(m_lock); | ||
| 17 | |||
| 18 | std::swap(m_table_size, saved_table_size); | ||
| 19 | } | ||
| 20 | |||
| 21 | // Close and free all entries. | ||
| 22 | for (size_t i = 0; i < saved_table_size; i++) { | ||
| 23 | if (KAutoObject* obj = m_objects[i]; obj != nullptr) { | ||
| 24 | obj->Close(); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | return RESULT_SUCCESS; | ||
| 29 | } | ||
| 30 | |||
| 31 | bool KHandleTable::Remove(Handle handle) { | ||
| 32 | // Don't allow removal of a pseudo-handle. | ||
| 33 | if (Svc::IsPseudoHandle(handle)) { | ||
| 34 | return false; | ||
| 35 | } | ||
| 36 | |||
| 37 | // Handles must not have reserved bits set. | ||
| 38 | const auto handle_pack = HandlePack(handle); | ||
| 39 | if (handle_pack.reserved != 0) { | ||
| 40 | return false; | ||
| 41 | } | ||
| 42 | |||
| 43 | // Find the object and free the entry. | ||
| 44 | KAutoObject* obj = nullptr; | ||
| 45 | { | ||
| 46 | KScopedSpinLock lk(m_lock); | ||
| 47 | |||
| 48 | if (this->IsValidHandle(handle)) { | ||
| 49 | const auto index = handle_pack.index; | ||
| 50 | |||
| 51 | obj = m_objects[index]; | ||
| 52 | this->FreeEntry(index); | ||
| 53 | } else { | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | // Close the object. | ||
| 59 | obj->Close(); | ||
| 60 | return true; | ||
| 61 | } | ||
| 62 | |||
| 63 | ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { | ||
| 64 | KScopedSpinLock lk(m_lock); | ||
| 65 | |||
| 66 | // Never exceed our capacity. | ||
| 67 | R_UNLESS(m_count < m_table_size, ResultOutOfHandles); | ||
| 68 | |||
| 69 | // Allocate entry, set output handle. | ||
| 70 | { | ||
| 71 | const auto linear_id = this->AllocateLinearId(); | ||
| 72 | const auto index = this->AllocateEntry(); | ||
| 73 | |||
| 74 | m_entry_infos[index].info = {.linear_id = linear_id, .type = type}; | ||
| 75 | m_objects[index] = obj; | ||
| 76 | |||
| 77 | obj->Open(); | ||
| 78 | |||
| 79 | *out_handle = EncodeHandle(static_cast<u16>(index), linear_id); | ||
| 80 | } | ||
| 81 | |||
| 82 | return RESULT_SUCCESS; | ||
| 83 | } | ||
| 84 | |||
| 85 | ResultCode KHandleTable::Reserve(Handle* out_handle) { | ||
| 86 | KScopedSpinLock lk(m_lock); | ||
| 87 | |||
| 88 | // Never exceed our capacity. | ||
| 89 | R_UNLESS(m_count < m_table_size, ResultOutOfHandles); | ||
| 90 | |||
| 91 | *out_handle = EncodeHandle(static_cast<u16>(this->AllocateEntry()), this->AllocateLinearId()); | ||
| 92 | return RESULT_SUCCESS; | ||
| 93 | } | ||
| 94 | |||
| 95 | void KHandleTable::Unreserve(Handle handle) { | ||
| 96 | KScopedSpinLock lk(m_lock); | ||
| 97 | |||
| 98 | // Unpack the handle. | ||
| 99 | const auto handle_pack = HandlePack(handle); | ||
| 100 | const auto index = handle_pack.index; | ||
| 101 | const auto linear_id = handle_pack.linear_id; | ||
| 102 | const auto reserved = handle_pack.reserved; | ||
| 103 | ASSERT(reserved == 0); | ||
| 104 | ASSERT(linear_id != 0); | ||
| 105 | |||
| 106 | if (index < m_table_size) { | ||
| 107 | // NOTE: This code does not check the linear id. | ||
| 108 | ASSERT(m_objects[index] == nullptr); | ||
| 109 | this->FreeEntry(index); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) { | ||
| 114 | KScopedSpinLock lk(m_lock); | ||
| 115 | |||
| 116 | // Unpack the handle. | ||
| 117 | const auto handle_pack = HandlePack(handle); | ||
| 118 | const auto index = handle_pack.index; | ||
| 119 | const auto linear_id = handle_pack.linear_id; | ||
| 120 | const auto reserved = handle_pack.reserved; | ||
| 121 | ASSERT(reserved == 0); | ||
| 122 | ASSERT(linear_id != 0); | ||
| 123 | |||
| 124 | if (index < m_table_size) { | ||
| 125 | // Set the entry. | ||
| 126 | ASSERT(m_objects[index] == nullptr); | ||
| 127 | |||
| 128 | m_entry_infos[index].info = {.linear_id = static_cast<u16>(linear_id), .type = type}; | ||
| 129 | m_objects[index] = obj; | ||
| 130 | |||
| 131 | obj->Open(); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h new file mode 100644 index 000000000..ba9dd061d --- /dev/null +++ b/src/core/hle/kernel/k_handle_table.h | |||
| @@ -0,0 +1,310 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/bit_util.h" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "core/hle/kernel/k_auto_object.h" | ||
| 14 | #include "core/hle/kernel/k_spin_lock.h" | ||
| 15 | #include "core/hle/kernel/k_thread.h" | ||
| 16 | #include "core/hle/kernel/kernel.h" | ||
| 17 | #include "core/hle/kernel/svc_common.h" | ||
| 18 | #include "core/hle/kernel/svc_results.h" | ||
| 19 | #include "core/hle/result.h" | ||
| 20 | |||
| 21 | namespace Kernel { | ||
| 22 | |||
| 23 | class KernelCore; | ||
| 24 | |||
| 25 | class KHandleTable { | ||
| 26 | YUZU_NON_COPYABLE(KHandleTable); | ||
| 27 | YUZU_NON_MOVEABLE(KHandleTable); | ||
| 28 | |||
| 29 | public: | ||
| 30 | static constexpr size_t MaxTableSize = 1024; | ||
| 31 | |||
| 32 | public: | ||
| 33 | explicit KHandleTable(KernelCore& kernel_); | ||
| 34 | ~KHandleTable(); | ||
| 35 | |||
| 36 | ResultCode Initialize(s32 size) { | ||
| 37 | R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); | ||
| 38 | |||
| 39 | // Initialize all fields. | ||
| 40 | m_max_count = 0; | ||
| 41 | m_table_size = static_cast<u16>((size <= 0) ? MaxTableSize : size); | ||
| 42 | m_next_linear_id = MinLinearId; | ||
| 43 | m_count = 0; | ||
| 44 | m_free_head_index = -1; | ||
| 45 | |||
| 46 | // Free all entries. | ||
| 47 | for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) { | ||
| 48 | m_objects[i] = nullptr; | ||
| 49 | m_entry_infos[i].next_free_index = i - 1; | ||
| 50 | m_free_head_index = i; | ||
| 51 | } | ||
| 52 | |||
| 53 | return RESULT_SUCCESS; | ||
| 54 | } | ||
| 55 | |||
| 56 | size_t GetTableSize() const { | ||
| 57 | return m_table_size; | ||
| 58 | } | ||
| 59 | size_t GetCount() const { | ||
| 60 | return m_count; | ||
| 61 | } | ||
| 62 | size_t GetMaxCount() const { | ||
| 63 | return m_max_count; | ||
| 64 | } | ||
| 65 | |||
| 66 | ResultCode Finalize(); | ||
| 67 | bool Remove(Handle handle); | ||
| 68 | |||
| 69 | template <typename T = KAutoObject> | ||
| 70 | KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const { | ||
| 71 | // Lock and look up in table. | ||
| 72 | KScopedSpinLock lk(m_lock); | ||
| 73 | |||
| 74 | if constexpr (std::is_same_v<T, KAutoObject>) { | ||
| 75 | return this->GetObjectImpl(handle); | ||
| 76 | } else { | ||
| 77 | if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) { | ||
| 78 | return obj->DynamicCast<T*>(); | ||
| 79 | } else { | ||
| 80 | return nullptr; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | template <typename T = KAutoObject> | ||
| 86 | KScopedAutoObject<T> GetObject(Handle handle) const { | ||
| 87 | // Handle pseudo-handles. | ||
| 88 | if constexpr (std::derived_from<KProcess, T>) { | ||
| 89 | if (handle == Svc::PseudoHandle::CurrentProcess) { | ||
| 90 | auto* const cur_process = kernel.CurrentProcess(); | ||
| 91 | ASSERT(cur_process != nullptr); | ||
| 92 | return cur_process; | ||
| 93 | } | ||
| 94 | } else if constexpr (std::derived_from<KThread, T>) { | ||
| 95 | if (handle == Svc::PseudoHandle::CurrentThread) { | ||
| 96 | auto* const cur_thread = GetCurrentThreadPointer(kernel); | ||
| 97 | ASSERT(cur_thread != nullptr); | ||
| 98 | return cur_thread; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | return this->template GetObjectWithoutPseudoHandle<T>(handle); | ||
| 103 | } | ||
| 104 | |||
| 105 | ResultCode Reserve(Handle* out_handle); | ||
| 106 | void Unreserve(Handle handle); | ||
| 107 | |||
| 108 | template <typename T> | ||
| 109 | ResultCode Add(Handle* out_handle, T* obj) { | ||
| 110 | static_assert(std::is_base_of_v<KAutoObject, T>); | ||
| 111 | return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken()); | ||
| 112 | } | ||
| 113 | |||
| 114 | template <typename T> | ||
| 115 | void Register(Handle handle, T* obj) { | ||
| 116 | static_assert(std::is_base_of_v<KAutoObject, T>); | ||
| 117 | return this->Register(handle, obj, obj->GetTypeObj().GetClassToken()); | ||
| 118 | } | ||
| 119 | |||
| 120 | template <typename T> | ||
| 121 | bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const { | ||
| 122 | // Try to convert and open all the handles. | ||
| 123 | size_t num_opened; | ||
| 124 | { | ||
| 125 | // Lock the table. | ||
| 126 | KScopedSpinLock lk(m_lock); | ||
| 127 | for (num_opened = 0; num_opened < num_handles; num_opened++) { | ||
| 128 | // Get the current handle. | ||
| 129 | const auto cur_handle = handles[num_opened]; | ||
| 130 | |||
| 131 | // Get the object for the current handle. | ||
| 132 | KAutoObject* cur_object = this->GetObjectImpl(cur_handle); | ||
| 133 | if (cur_object == nullptr) { | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | |||
| 137 | // Cast the current object to the desired type. | ||
| 138 | T* cur_t = cur_object->DynamicCast<T*>(); | ||
| 139 | if (cur_t == nullptr) { | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | // Open a reference to the current object. | ||
| 144 | cur_t->Open(); | ||
| 145 | out[num_opened] = cur_t; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | // If we converted every object, succeed. | ||
| 150 | if (num_opened == num_handles) { | ||
| 151 | return true; | ||
| 152 | } | ||
| 153 | |||
| 154 | // If we didn't convert entry object, close the ones we opened. | ||
| 155 | for (size_t i = 0; i < num_opened; i++) { | ||
| 156 | out[i]->Close(); | ||
| 157 | } | ||
| 158 | |||
| 159 | return false; | ||
| 160 | } | ||
| 161 | |||
| 162 | private: | ||
| 163 | ResultCode Add(Handle* out_handle, KAutoObject* obj, u16 type); | ||
| 164 | void Register(Handle handle, KAutoObject* obj, u16 type); | ||
| 165 | |||
| 166 | s32 AllocateEntry() { | ||
| 167 | ASSERT(m_count < m_table_size); | ||
| 168 | |||
| 169 | const auto index = m_free_head_index; | ||
| 170 | |||
| 171 | m_free_head_index = m_entry_infos[index].GetNextFreeIndex(); | ||
| 172 | |||
| 173 | m_max_count = std::max(m_max_count, ++m_count); | ||
| 174 | |||
| 175 | return index; | ||
| 176 | } | ||
| 177 | |||
| 178 | void FreeEntry(s32 index) { | ||
| 179 | ASSERT(m_count > 0); | ||
| 180 | |||
| 181 | m_objects[index] = nullptr; | ||
| 182 | m_entry_infos[index].next_free_index = m_free_head_index; | ||
| 183 | |||
| 184 | m_free_head_index = index; | ||
| 185 | |||
| 186 | --m_count; | ||
| 187 | } | ||
| 188 | |||
| 189 | u16 AllocateLinearId() { | ||
| 190 | const u16 id = m_next_linear_id++; | ||
| 191 | if (m_next_linear_id > MaxLinearId) { | ||
| 192 | m_next_linear_id = MinLinearId; | ||
| 193 | } | ||
| 194 | return id; | ||
| 195 | } | ||
| 196 | |||
| 197 | bool IsValidHandle(Handle handle) const { | ||
| 198 | // Unpack the handle. | ||
| 199 | const auto handle_pack = HandlePack(handle); | ||
| 200 | const auto raw_value = handle_pack.raw; | ||
| 201 | const auto index = handle_pack.index; | ||
| 202 | const auto linear_id = handle_pack.linear_id; | ||
| 203 | const auto reserved = handle_pack.reserved; | ||
| 204 | ASSERT(reserved == 0); | ||
| 205 | |||
| 206 | // Validate our indexing information. | ||
| 207 | if (raw_value == 0) { | ||
| 208 | return false; | ||
| 209 | } | ||
| 210 | if (linear_id == 0) { | ||
| 211 | return false; | ||
| 212 | } | ||
| 213 | if (index >= m_table_size) { | ||
| 214 | return false; | ||
| 215 | } | ||
| 216 | |||
| 217 | // Check that there's an object, and our serial id is correct. | ||
| 218 | if (m_objects[index] == nullptr) { | ||
| 219 | return false; | ||
| 220 | } | ||
| 221 | if (m_entry_infos[index].GetLinearId() != linear_id) { | ||
| 222 | return false; | ||
| 223 | } | ||
| 224 | |||
| 225 | return true; | ||
| 226 | } | ||
| 227 | |||
| 228 | KAutoObject* GetObjectImpl(Handle handle) const { | ||
| 229 | // Handles must not have reserved bits set. | ||
| 230 | const auto handle_pack = HandlePack(handle); | ||
| 231 | if (handle_pack.reserved != 0) { | ||
| 232 | return nullptr; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (this->IsValidHandle(handle)) { | ||
| 236 | return m_objects[handle_pack.index]; | ||
| 237 | } else { | ||
| 238 | return nullptr; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | KAutoObject* GetObjectByIndexImpl(Handle* out_handle, size_t index) const { | ||
| 243 | |||
| 244 | // Index must be in bounds. | ||
| 245 | if (index >= m_table_size) { | ||
| 246 | return nullptr; | ||
| 247 | } | ||
| 248 | |||
| 249 | // Ensure entry has an object. | ||
| 250 | if (KAutoObject* obj = m_objects[index]; obj != nullptr) { | ||
| 251 | *out_handle = EncodeHandle(static_cast<u16>(index), m_entry_infos[index].GetLinearId()); | ||
| 252 | return obj; | ||
| 253 | } else { | ||
| 254 | return nullptr; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | private: | ||
| 259 | union HandlePack { | ||
| 260 | HandlePack() = default; | ||
| 261 | HandlePack(Handle handle) : raw{static_cast<u32>(handle)} {} | ||
| 262 | |||
| 263 | u32 raw; | ||
| 264 | BitField<0, 15, u32> index; | ||
| 265 | BitField<15, 15, u32> linear_id; | ||
| 266 | BitField<30, 2, u32> reserved; | ||
| 267 | }; | ||
| 268 | |||
| 269 | static constexpr u16 MinLinearId = 1; | ||
| 270 | static constexpr u16 MaxLinearId = 0x7FFF; | ||
| 271 | |||
| 272 | static constexpr Handle EncodeHandle(u16 index, u16 linear_id) { | ||
| 273 | HandlePack handle{}; | ||
| 274 | handle.index.Assign(index); | ||
| 275 | handle.linear_id.Assign(linear_id); | ||
| 276 | handle.reserved.Assign(0); | ||
| 277 | return handle.raw; | ||
| 278 | } | ||
| 279 | |||
| 280 | union EntryInfo { | ||
| 281 | struct { | ||
| 282 | u16 linear_id; | ||
| 283 | u16 type; | ||
| 284 | } info; | ||
| 285 | s32 next_free_index; | ||
| 286 | |||
| 287 | constexpr u16 GetLinearId() const { | ||
| 288 | return info.linear_id; | ||
| 289 | } | ||
| 290 | constexpr u16 GetType() const { | ||
| 291 | return info.type; | ||
| 292 | } | ||
| 293 | constexpr s32 GetNextFreeIndex() const { | ||
| 294 | return next_free_index; | ||
| 295 | } | ||
| 296 | }; | ||
| 297 | |||
| 298 | private: | ||
| 299 | std::array<EntryInfo, MaxTableSize> m_entry_infos{}; | ||
| 300 | std::array<KAutoObject*, MaxTableSize> m_objects{}; | ||
| 301 | s32 m_free_head_index{-1}; | ||
| 302 | u16 m_table_size{}; | ||
| 303 | u16 m_max_count{}; | ||
| 304 | u16 m_next_linear_id{MinLinearId}; | ||
| 305 | u16 m_count{}; | ||
| 306 | mutable KSpinLock m_lock; | ||
| 307 | KernelCore& kernel; | ||
| 308 | }; | ||
| 309 | |||
| 310 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index 362d0db28..ca2e539a7 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h | |||
| @@ -18,7 +18,8 @@ class KernelCore; | |||
| 18 | 18 | ||
| 19 | class KLightConditionVariable { | 19 | class KLightConditionVariable { |
| 20 | public: | 20 | public: |
| 21 | explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {} | 21 | explicit KLightConditionVariable(KernelCore& kernel_) |
| 22 | : thread_queue(kernel_), kernel(kernel_) {} | ||
| 22 | 23 | ||
| 23 | void Wait(KLightLock* lock, s64 timeout = -1) { | 24 | void Wait(KLightLock* lock, s64 timeout = -1) { |
| 24 | WaitImpl(lock, timeout); | 25 | WaitImpl(lock, timeout); |
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h new file mode 100644 index 000000000..6adfe1e34 --- /dev/null +++ b/src/core/hle/kernel/k_linked_list.h | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <boost/intrusive/list.hpp> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "core/hle/kernel/slab_helpers.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | class KernelCore; | ||
| 15 | |||
| 16 | class KLinkedListNode : public boost::intrusive::list_base_hook<>, | ||
| 17 | public KSlabAllocated<KLinkedListNode> { | ||
| 18 | |||
| 19 | public: | ||
| 20 | KLinkedListNode() = default; | ||
| 21 | |||
| 22 | void Initialize(void* it) { | ||
| 23 | m_item = it; | ||
| 24 | } | ||
| 25 | |||
| 26 | void* GetItem() const { | ||
| 27 | return m_item; | ||
| 28 | } | ||
| 29 | |||
| 30 | private: | ||
| 31 | void* m_item = nullptr; | ||
| 32 | }; | ||
| 33 | |||
| 34 | template <typename T> | ||
| 35 | class KLinkedList : private boost::intrusive::list<KLinkedListNode> { | ||
| 36 | private: | ||
| 37 | using BaseList = boost::intrusive::list<KLinkedListNode>; | ||
| 38 | |||
| 39 | public: | ||
| 40 | template <bool Const> | ||
| 41 | class Iterator; | ||
| 42 | |||
| 43 | using value_type = T; | ||
| 44 | using size_type = size_t; | ||
| 45 | using difference_type = ptrdiff_t; | ||
| 46 | using pointer = value_type*; | ||
| 47 | using const_pointer = const value_type*; | ||
| 48 | using reference = value_type&; | ||
| 49 | using const_reference = const value_type&; | ||
| 50 | using iterator = Iterator<false>; | ||
| 51 | using const_iterator = Iterator<true>; | ||
| 52 | using reverse_iterator = std::reverse_iterator<iterator>; | ||
| 53 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; | ||
| 54 | |||
| 55 | template <bool Const> | ||
| 56 | class Iterator { | ||
| 57 | private: | ||
| 58 | using BaseIterator = BaseList::iterator; | ||
| 59 | friend class KLinkedList; | ||
| 60 | |||
| 61 | public: | ||
| 62 | using iterator_category = std::bidirectional_iterator_tag; | ||
| 63 | using value_type = typename KLinkedList::value_type; | ||
| 64 | using difference_type = typename KLinkedList::difference_type; | ||
| 65 | using pointer = std::conditional_t<Const, KLinkedList::const_pointer, KLinkedList::pointer>; | ||
| 66 | using reference = | ||
| 67 | std::conditional_t<Const, KLinkedList::const_reference, KLinkedList::reference>; | ||
| 68 | |||
| 69 | public: | ||
| 70 | explicit Iterator(BaseIterator it) : m_base_it(it) {} | ||
| 71 | |||
| 72 | pointer GetItem() const { | ||
| 73 | return static_cast<pointer>(m_base_it->GetItem()); | ||
| 74 | } | ||
| 75 | |||
| 76 | bool operator==(const Iterator& rhs) const { | ||
| 77 | return m_base_it == rhs.m_base_it; | ||
| 78 | } | ||
| 79 | |||
| 80 | bool operator!=(const Iterator& rhs) const { | ||
| 81 | return !(*this == rhs); | ||
| 82 | } | ||
| 83 | |||
| 84 | pointer operator->() const { | ||
| 85 | return this->GetItem(); | ||
| 86 | } | ||
| 87 | |||
| 88 | reference operator*() const { | ||
| 89 | return *this->GetItem(); | ||
| 90 | } | ||
| 91 | |||
| 92 | Iterator& operator++() { | ||
| 93 | ++m_base_it; | ||
| 94 | return *this; | ||
| 95 | } | ||
| 96 | |||
| 97 | Iterator& operator--() { | ||
| 98 | --m_base_it; | ||
| 99 | return *this; | ||
| 100 | } | ||
| 101 | |||
| 102 | Iterator operator++(int) { | ||
| 103 | const Iterator it{*this}; | ||
| 104 | ++(*this); | ||
| 105 | return it; | ||
| 106 | } | ||
| 107 | |||
| 108 | Iterator operator--(int) { | ||
| 109 | const Iterator it{*this}; | ||
| 110 | --(*this); | ||
| 111 | return it; | ||
| 112 | } | ||
| 113 | |||
| 114 | operator Iterator<true>() const { | ||
| 115 | return Iterator<true>(m_base_it); | ||
| 116 | } | ||
| 117 | |||
| 118 | private: | ||
| 119 | BaseIterator m_base_it; | ||
| 120 | }; | ||
| 121 | |||
| 122 | public: | ||
| 123 | constexpr KLinkedList(KernelCore& kernel_) : BaseList(), kernel{kernel_} {} | ||
| 124 | |||
| 125 | ~KLinkedList() { | ||
| 126 | // Erase all elements. | ||
| 127 | for (auto it = begin(); it != end(); it = erase(it)) { | ||
| 128 | } | ||
| 129 | |||
| 130 | // Ensure we succeeded. | ||
| 131 | ASSERT(this->empty()); | ||
| 132 | } | ||
| 133 | |||
| 134 | // Iterator accessors. | ||
| 135 | iterator begin() { | ||
| 136 | return iterator(BaseList::begin()); | ||
| 137 | } | ||
| 138 | |||
| 139 | const_iterator begin() const { | ||
| 140 | return const_iterator(BaseList::begin()); | ||
| 141 | } | ||
| 142 | |||
| 143 | iterator end() { | ||
| 144 | return iterator(BaseList::end()); | ||
| 145 | } | ||
| 146 | |||
| 147 | const_iterator end() const { | ||
| 148 | return const_iterator(BaseList::end()); | ||
| 149 | } | ||
| 150 | |||
| 151 | const_iterator cbegin() const { | ||
| 152 | return this->begin(); | ||
| 153 | } | ||
| 154 | |||
| 155 | const_iterator cend() const { | ||
| 156 | return this->end(); | ||
| 157 | } | ||
| 158 | |||
| 159 | reverse_iterator rbegin() { | ||
| 160 | return reverse_iterator(this->end()); | ||
| 161 | } | ||
| 162 | |||
| 163 | const_reverse_iterator rbegin() const { | ||
| 164 | return const_reverse_iterator(this->end()); | ||
| 165 | } | ||
| 166 | |||
| 167 | reverse_iterator rend() { | ||
| 168 | return reverse_iterator(this->begin()); | ||
| 169 | } | ||
| 170 | |||
| 171 | const_reverse_iterator rend() const { | ||
| 172 | return const_reverse_iterator(this->begin()); | ||
| 173 | } | ||
| 174 | |||
| 175 | const_reverse_iterator crbegin() const { | ||
| 176 | return this->rbegin(); | ||
| 177 | } | ||
| 178 | |||
| 179 | const_reverse_iterator crend() const { | ||
| 180 | return this->rend(); | ||
| 181 | } | ||
| 182 | |||
| 183 | // Content management. | ||
| 184 | using BaseList::empty; | ||
| 185 | using BaseList::size; | ||
| 186 | |||
| 187 | reference back() { | ||
| 188 | return *(--this->end()); | ||
| 189 | } | ||
| 190 | |||
| 191 | const_reference back() const { | ||
| 192 | return *(--this->end()); | ||
| 193 | } | ||
| 194 | |||
| 195 | reference front() { | ||
| 196 | return *this->begin(); | ||
| 197 | } | ||
| 198 | |||
| 199 | const_reference front() const { | ||
| 200 | return *this->begin(); | ||
| 201 | } | ||
| 202 | |||
| 203 | iterator insert(const_iterator pos, reference ref) { | ||
| 204 | KLinkedListNode* new_node = KLinkedListNode::Allocate(kernel); | ||
| 205 | ASSERT(new_node != nullptr); | ||
| 206 | new_node->Initialize(std::addressof(ref)); | ||
| 207 | return iterator(BaseList::insert(pos.m_base_it, *new_node)); | ||
| 208 | } | ||
| 209 | |||
| 210 | void push_back(reference ref) { | ||
| 211 | this->insert(this->end(), ref); | ||
| 212 | } | ||
| 213 | |||
| 214 | void push_front(reference ref) { | ||
| 215 | this->insert(this->begin(), ref); | ||
| 216 | } | ||
| 217 | |||
| 218 | void pop_back() { | ||
| 219 | this->erase(--this->end()); | ||
| 220 | } | ||
| 221 | |||
| 222 | void pop_front() { | ||
| 223 | this->erase(this->begin()); | ||
| 224 | } | ||
| 225 | |||
| 226 | iterator erase(const iterator pos) { | ||
| 227 | KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); | ||
| 228 | iterator ret = iterator(BaseList::erase(pos.m_base_it)); | ||
| 229 | KLinkedListNode::Free(kernel, freed_node); | ||
| 230 | |||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | private: | ||
| 235 | KernelCore& kernel; | ||
| 236 | }; | ||
| 237 | |||
| 238 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index c5b9c5e85..a7fdb5fb8 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -134,6 +134,10 @@ enum class KMemoryPermission : u8 { | |||
| 134 | }; | 134 | }; |
| 135 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); | 135 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); |
| 136 | 136 | ||
| 137 | constexpr KMemoryPermission ConvertToKMemoryPermission(Svc::MemoryPermission perm) { | ||
| 138 | return static_cast<KMemoryPermission>(perm); | ||
| 139 | } | ||
| 140 | |||
| 137 | enum class KMemoryAttribute : u8 { | 141 | enum class KMemoryAttribute : u8 { |
| 138 | None = 0x00, | 142 | None = 0x00, |
| 139 | Mask = 0x7F, | 143 | Mask = 0x7F, |
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 4a2d88008..fc7033564 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | namespace Kernel { | 8 | namespace Kernel { |
| 9 | 9 | ||
| 10 | KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) | 10 | KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr_, VAddr end_addr_) |
| 11 | : start_addr{start_addr}, end_addr{end_addr} { | 11 | : start_addr{start_addr_}, end_addr{end_addr_} { |
| 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; | 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; |
| 13 | memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free, | 13 | memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free, |
| 14 | KMemoryPermission::None, KMemoryAttribute::None); | 14 | KMemoryPermission::None, KMemoryAttribute::None); |
| @@ -17,8 +17,8 @@ KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) | |||
| 17 | KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { | 17 | KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { |
| 18 | auto node{memory_block_tree.begin()}; | 18 | auto node{memory_block_tree.begin()}; |
| 19 | while (node != end()) { | 19 | while (node != end()) { |
| 20 | const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; | 20 | const VAddr node_end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; |
| 21 | if (node->GetAddress() <= addr && end_addr - 1 >= addr) { | 21 | if (node->GetAddress() <= addr && node_end_addr - 1 >= addr) { |
| 22 | return node; | 22 | return node; |
| 23 | } | 23 | } |
| 24 | node = std::next(node); | 24 | node = std::next(node); |
| @@ -67,7 +67,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 67 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, | 67 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, |
| 68 | KMemoryState state, KMemoryPermission perm, | 68 | KMemoryState state, KMemoryPermission perm, |
| 69 | KMemoryAttribute attribute) { | 69 | KMemoryAttribute attribute) { |
| 70 | const VAddr end_addr{addr + num_pages * PageSize}; | 70 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 71 | iterator node{memory_block_tree.begin()}; | 71 | iterator node{memory_block_tree.begin()}; |
| 72 | 72 | ||
| 73 | prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; | 73 | prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; |
| @@ -78,7 +78,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 78 | const VAddr cur_addr{block->GetAddress()}; | 78 | const VAddr cur_addr{block->GetAddress()}; |
| 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 80 | 80 | ||
| 81 | if (addr < cur_end_addr && cur_addr < end_addr) { | 81 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 82 | if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) { | 82 | if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) { |
| 83 | node = next_node; | 83 | node = next_node; |
| 84 | continue; | 84 | continue; |
| @@ -89,8 +89,8 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 89 | memory_block_tree.insert(node, block->Split(addr)); | 89 | memory_block_tree.insert(node, block->Split(addr)); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | if (end_addr < cur_end_addr) { | 92 | if (update_end_addr < cur_end_addr) { |
| 93 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 93 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | new_node->Update(state, perm, attribute); | 96 | new_node->Update(state, perm, attribute); |
| @@ -98,7 +98,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 98 | MergeAdjacent(new_node, next_node); | 98 | MergeAdjacent(new_node, next_node); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | if (cur_end_addr - 1 >= end_addr - 1) { | 101 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 102 | break; | 102 | break; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| @@ -108,7 +108,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 108 | 108 | ||
| 109 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, | 109 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 110 | KMemoryPermission perm, KMemoryAttribute attribute) { | 110 | KMemoryPermission perm, KMemoryAttribute attribute) { |
| 111 | const VAddr end_addr{addr + num_pages * PageSize}; | 111 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 112 | iterator node{memory_block_tree.begin()}; | 112 | iterator node{memory_block_tree.begin()}; |
| 113 | 113 | ||
| 114 | while (node != memory_block_tree.end()) { | 114 | while (node != memory_block_tree.end()) { |
| @@ -117,15 +117,15 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 117 | const VAddr cur_addr{block->GetAddress()}; | 117 | const VAddr cur_addr{block->GetAddress()}; |
| 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 119 | 119 | ||
| 120 | if (addr < cur_end_addr && cur_addr < end_addr) { | 120 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 121 | iterator new_node{node}; | 121 | iterator new_node{node}; |
| 122 | 122 | ||
| 123 | if (addr > cur_addr) { | 123 | if (addr > cur_addr) { |
| 124 | memory_block_tree.insert(node, block->Split(addr)); | 124 | memory_block_tree.insert(node, block->Split(addr)); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | if (end_addr < cur_end_addr) { | 127 | if (update_end_addr < cur_end_addr) { |
| 128 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 128 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | new_node->Update(state, perm, attribute); | 131 | new_node->Update(state, perm, attribute); |
| @@ -133,7 +133,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 133 | MergeAdjacent(new_node, next_node); | 133 | MergeAdjacent(new_node, next_node); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | if (cur_end_addr - 1 >= end_addr - 1) { | 136 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 137 | break; | 137 | break; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| @@ -143,7 +143,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 143 | 143 | ||
| 144 | void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, | 144 | void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, |
| 145 | KMemoryPermission perm) { | 145 | KMemoryPermission perm) { |
| 146 | const VAddr end_addr{addr + num_pages * PageSize}; | 146 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 147 | iterator node{memory_block_tree.begin()}; | 147 | iterator node{memory_block_tree.begin()}; |
| 148 | 148 | ||
| 149 | while (node != memory_block_tree.end()) { | 149 | while (node != memory_block_tree.end()) { |
| @@ -152,15 +152,15 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc | |||
| 152 | const VAddr cur_addr{block->GetAddress()}; | 152 | const VAddr cur_addr{block->GetAddress()}; |
| 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 154 | 154 | ||
| 155 | if (addr < cur_end_addr && cur_addr < end_addr) { | 155 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 156 | iterator new_node{node}; | 156 | iterator new_node{node}; |
| 157 | 157 | ||
| 158 | if (addr > cur_addr) { | 158 | if (addr > cur_addr) { |
| 159 | memory_block_tree.insert(node, block->Split(addr)); | 159 | memory_block_tree.insert(node, block->Split(addr)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | if (end_addr < cur_end_addr) { | 162 | if (update_end_addr < cur_end_addr) { |
| 163 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 163 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | lock_func(new_node, perm); | 166 | lock_func(new_node, perm); |
| @@ -168,7 +168,7 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc | |||
| 168 | MergeAdjacent(new_node, next_node); | 168 | MergeAdjacent(new_node, next_node); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | if (cur_end_addr - 1 >= end_addr - 1) { | 171 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 172 | break; | 172 | break; |
| 173 | } | 173 | } |
| 174 | 174 | ||
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index e11cc70c8..d222da919 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | using const_iterator = MemoryBlockTree::const_iterator; | 19 | using const_iterator = MemoryBlockTree::const_iterator; |
| 20 | 20 | ||
| 21 | public: | 21 | public: |
| 22 | KMemoryBlockManager(VAddr start_addr, VAddr end_addr); | 22 | KMemoryBlockManager(VAddr start_addr_, VAddr end_addr_); |
| 23 | 23 | ||
| 24 | iterator end() { | 24 | iterator end() { |
| 25 | return memory_block_tree.end(); | 25 | return memory_block_tree.end(); |
diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h index a861c04ab..90ab8fd62 100644 --- a/src/core/hle/kernel/k_memory_region.h +++ b/src/core/hle/kernel/k_memory_region.h | |||
| @@ -82,9 +82,9 @@ public: | |||
| 82 | type_id = type; | 82 | type_id = type; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | constexpr bool Contains(u64 address) const { | 85 | constexpr bool Contains(u64 addr) const { |
| 86 | ASSERT(this->GetEndAddress() != 0); | 86 | ASSERT(this->GetEndAddress() != 0); |
| 87 | return this->GetAddress() <= address && address <= this->GetLastAddress(); | 87 | return this->GetAddress() <= addr && addr <= this->GetLastAddress(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | constexpr bool IsDerivedFrom(u32 type) const { | 90 | constexpr bool IsDerivedFrom(u32 type) const { |
diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h index 64024d01f..dfdac5321 100644 --- a/src/core/hle/kernel/k_page_linked_list.h +++ b/src/core/hle/kernel/k_page_linked_list.h | |||
| @@ -17,7 +17,7 @@ class KPageLinkedList final { | |||
| 17 | public: | 17 | public: |
| 18 | class Node final { | 18 | class Node final { |
| 19 | public: | 19 | public: |
| 20 | constexpr Node(u64 addr, std::size_t num_pages) : addr{addr}, num_pages{num_pages} {} | 20 | constexpr Node(u64 addr_, std::size_t num_pages_) : addr{addr_}, num_pages{num_pages_} {} |
| 21 | 21 | ||
| 22 | constexpr u64 GetAddress() const { | 22 | constexpr u64 GetAddress() const { |
| 23 | return addr; | 23 | return addr; |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index d09d5ce48..27dbf0ebc 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -11,11 +11,11 @@ | |||
| 11 | #include "core/hle/kernel/k_memory_block_manager.h" | 11 | #include "core/hle/kernel/k_memory_block_manager.h" |
| 12 | #include "core/hle/kernel/k_page_linked_list.h" | 12 | #include "core/hle/kernel/k_page_linked_list.h" |
| 13 | #include "core/hle/kernel/k_page_table.h" | 13 | #include "core/hle/kernel/k_page_table.h" |
| 14 | #include "core/hle/kernel/k_process.h" | ||
| 14 | #include "core/hle/kernel/k_resource_limit.h" | 15 | #include "core/hle/kernel/k_resource_limit.h" |
| 15 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 16 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 16 | #include "core/hle/kernel/k_system_control.h" | 17 | #include "core/hle/kernel/k_system_control.h" |
| 17 | #include "core/hle/kernel/kernel.h" | 18 | #include "core/hle/kernel/kernel.h" |
| 18 | #include "core/hle/kernel/process.h" | ||
| 19 | #include "core/hle/kernel/svc_results.h" | 19 | #include "core/hle/kernel/svc_results.h" |
| 20 | #include "core/memory.h" | 20 | #include "core/memory.h" |
| 21 | 21 | ||
| @@ -58,7 +58,7 @@ constexpr std::size_t GetSizeInRange(const KMemoryInfo& info, VAddr start, VAddr | |||
| 58 | 58 | ||
| 59 | } // namespace | 59 | } // namespace |
| 60 | 60 | ||
| 61 | KPageTable::KPageTable(Core::System& system) : system{system} {} | 61 | KPageTable::KPageTable(Core::System& system_) : system{system_} {} |
| 62 | 62 | ||
| 63 | ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, | 63 | ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, |
| 64 | bool enable_aslr, VAddr code_addr, | 64 | bool enable_aslr, VAddr code_addr, |
| @@ -420,7 +420,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 420 | remaining_size); | 420 | remaining_size); |
| 421 | if (!memory_reservation.Succeeded()) { | 421 | if (!memory_reservation.Succeeded()) { |
| 422 | LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size); | 422 | LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size); |
| 423 | return ResultResourceLimitedExceeded; | 423 | return ResultLimitReached; |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | KPageLinkedList page_linked_list; | 426 | KPageLinkedList page_linked_list; |
| @@ -578,7 +578,7 @@ ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { | |||
| 578 | AddRegionToPages(dst_addr, num_pages, dst_pages); | 578 | AddRegionToPages(dst_addr, num_pages, dst_pages); |
| 579 | 579 | ||
| 580 | if (!dst_pages.IsEqual(src_pages)) { | 580 | if (!dst_pages.IsEqual(src_pages)) { |
| 581 | return ResultInvalidMemoryRange; | 581 | return ResultInvalidMemoryRegion; |
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | { | 584 | { |
| @@ -641,6 +641,45 @@ ResultCode KPageTable::MapPages(VAddr addr, KPageLinkedList& page_linked_list, K | |||
| 641 | return RESULT_SUCCESS; | 641 | return RESULT_SUCCESS; |
| 642 | } | 642 | } |
| 643 | 643 | ||
| 644 | ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) { | ||
| 645 | VAddr cur_addr{addr}; | ||
| 646 | |||
| 647 | for (const auto& node : page_linked_list.Nodes()) { | ||
| 648 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; | ||
| 649 | if (const auto result{ | ||
| 650 | Operate(addr, num_pages, KMemoryPermission::None, OperationType::Unmap)}; | ||
| 651 | result.IsError()) { | ||
| 652 | return result; | ||
| 653 | } | ||
| 654 | |||
| 655 | cur_addr += node.GetNumPages() * PageSize; | ||
| 656 | } | ||
| 657 | |||
| 658 | return RESULT_SUCCESS; | ||
| 659 | } | ||
| 660 | |||
| 661 | ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, | ||
| 662 | KMemoryState state) { | ||
| 663 | std::lock_guard lock{page_table_lock}; | ||
| 664 | |||
| 665 | const std::size_t num_pages{page_linked_list.GetNumPages()}; | ||
| 666 | const std::size_t size{num_pages * PageSize}; | ||
| 667 | |||
| 668 | if (!CanContain(addr, size, state)) { | ||
| 669 | return ResultInvalidCurrentMemory; | ||
| 670 | } | ||
| 671 | |||
| 672 | if (IsRegionMapped(addr, num_pages * PageSize)) { | ||
| 673 | return ResultInvalidCurrentMemory; | ||
| 674 | } | ||
| 675 | |||
| 676 | CASCADE_CODE(UnmapPages(addr, page_linked_list)); | ||
| 677 | |||
| 678 | block_manager->Update(addr, num_pages, state, KMemoryPermission::None); | ||
| 679 | |||
| 680 | return RESULT_SUCCESS; | ||
| 681 | } | ||
| 682 | |||
| 644 | ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, | 683 | ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, |
| 645 | KMemoryPermission perm) { | 684 | KMemoryPermission perm) { |
| 646 | 685 | ||
| @@ -790,7 +829,7 @@ ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) { | |||
| 790 | 829 | ||
| 791 | if (!memory_reservation.Succeeded()) { | 830 | if (!memory_reservation.Succeeded()) { |
| 792 | LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta); | 831 | LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta); |
| 793 | return ResultResourceLimitedExceeded; | 832 | return ResultLimitReached; |
| 794 | } | 833 | } |
| 795 | 834 | ||
| 796 | KPageLinkedList page_linked_list; | 835 | KPageLinkedList page_linked_list; |
| @@ -867,8 +906,8 @@ ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { | |||
| 867 | 906 | ||
| 868 | block_manager->UpdateLock( | 907 | block_manager->UpdateLock( |
| 869 | addr, size / PageSize, | 908 | addr, size / PageSize, |
| 870 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { | 909 | [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { |
| 871 | block->ShareToDevice(perm); | 910 | block->ShareToDevice(permission); |
| 872 | }, | 911 | }, |
| 873 | perm); | 912 | perm); |
| 874 | 913 | ||
| @@ -890,8 +929,8 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) | |||
| 890 | 929 | ||
| 891 | block_manager->UpdateLock( | 930 | block_manager->UpdateLock( |
| 892 | addr, size / PageSize, | 931 | addr, size / PageSize, |
| 893 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { | 932 | [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { |
| 894 | block->UnshareToDevice(perm); | 933 | block->UnshareToDevice(permission); |
| 895 | }, | 934 | }, |
| 896 | perm); | 935 | perm); |
| 897 | 936 | ||
| @@ -1067,7 +1106,7 @@ constexpr std::size_t KPageTable::GetRegionSize(KMemoryState state) const { | |||
| 1067 | } | 1106 | } |
| 1068 | } | 1107 | } |
| 1069 | 1108 | ||
| 1070 | constexpr bool KPageTable::CanContain(VAddr addr, std::size_t size, KMemoryState state) const { | 1109 | bool KPageTable::CanContain(VAddr addr, std::size_t size, KMemoryState state) const { |
| 1071 | const VAddr end{addr + size}; | 1110 | const VAddr end{addr + size}; |
| 1072 | const VAddr last{end - 1}; | 1111 | const VAddr last{end - 1}; |
| 1073 | const VAddr region_start{GetRegionAddress(state)}; | 1112 | const VAddr region_start{GetRegionAddress(state)}; |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 49b824379..770c4841c 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -24,7 +24,7 @@ class KMemoryBlockManager; | |||
| 24 | 24 | ||
| 25 | class KPageTable final : NonCopyable { | 25 | class KPageTable final : NonCopyable { |
| 26 | public: | 26 | public: |
| 27 | explicit KPageTable(Core::System& system); | 27 | explicit KPageTable(Core::System& system_); |
| 28 | 28 | ||
| 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, | 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, |
| 30 | VAddr code_addr, std::size_t code_size, | 30 | VAddr code_addr, std::size_t code_size, |
| @@ -40,6 +40,7 @@ public: | |||
| 40 | ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); | 40 | ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 41 | ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, | 41 | ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, |
| 42 | KMemoryPermission perm); | 42 | KMemoryPermission perm); |
| 43 | ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state); | ||
| 43 | ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); | 44 | ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); |
| 44 | KMemoryInfo QueryInfo(VAddr addr); | 45 | KMemoryInfo QueryInfo(VAddr addr); |
| 45 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); | 46 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); |
| @@ -63,6 +64,8 @@ public: | |||
| 63 | return page_table_impl; | 64 | return page_table_impl; |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 67 | bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const; | ||
| 68 | |||
| 66 | private: | 69 | private: |
| 67 | enum class OperationType : u32 { | 70 | enum class OperationType : u32 { |
| 68 | Map, | 71 | Map, |
| @@ -79,6 +82,7 @@ private: | |||
| 79 | ResultCode InitializeMemoryLayout(VAddr start, VAddr end); | 82 | ResultCode InitializeMemoryLayout(VAddr start, VAddr end); |
| 80 | ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, | 83 | ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, |
| 81 | KMemoryPermission perm); | 84 | KMemoryPermission perm); |
| 85 | ResultCode UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list); | ||
| 82 | void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end); | 86 | void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end); |
| 83 | bool IsRegionMapped(VAddr address, u64 size); | 87 | bool IsRegionMapped(VAddr address, u64 size); |
| 84 | bool IsRegionContiguous(VAddr addr, u64 size) const; | 88 | bool IsRegionContiguous(VAddr addr, u64 size) const; |
| @@ -92,7 +96,6 @@ private: | |||
| 92 | OperationType operation, PAddr map_addr = 0); | 96 | OperationType operation, PAddr map_addr = 0); |
| 93 | constexpr VAddr GetRegionAddress(KMemoryState state) const; | 97 | constexpr VAddr GetRegionAddress(KMemoryState state) const; |
| 94 | constexpr std::size_t GetRegionSize(KMemoryState state) const; | 98 | constexpr std::size_t GetRegionSize(KMemoryState state) const; |
| 95 | constexpr bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const; | ||
| 96 | 99 | ||
| 97 | constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, | 100 | constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, |
| 98 | KMemoryState state, KMemoryPermission perm_mask, | 101 | KMemoryState state, KMemoryPermission perm_mask, |
| @@ -216,8 +219,6 @@ public: | |||
| 216 | constexpr PAddr GetPhysicalAddr(VAddr addr) { | 219 | constexpr PAddr GetPhysicalAddr(VAddr addr) { |
| 217 | return page_table_impl.backing_addr[addr >> PageBits] + addr; | 220 | return page_table_impl.backing_addr[addr >> PageBits] + addr; |
| 218 | } | 221 | } |
| 219 | |||
| 220 | private: | ||
| 221 | constexpr bool Contains(VAddr addr) const { | 222 | constexpr bool Contains(VAddr addr) const { |
| 222 | return address_space_start <= addr && addr <= address_space_end - 1; | 223 | return address_space_start <= addr && addr <= address_space_end - 1; |
| 223 | } | 224 | } |
| @@ -225,6 +226,8 @@ private: | |||
| 225 | return address_space_start <= addr && addr < addr + size && | 226 | return address_space_start <= addr && addr < addr + size && |
| 226 | addr + size - 1 <= address_space_end - 1; | 227 | addr + size - 1 <= address_space_end - 1; |
| 227 | } | 228 | } |
| 229 | |||
| 230 | private: | ||
| 228 | constexpr bool IsKernel() const { | 231 | constexpr bool IsKernel() const { |
| 229 | return is_kernel; | 232 | return is_kernel; |
| 230 | } | 233 | } |
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp new file mode 100644 index 000000000..feb2bb11f --- /dev/null +++ b/src/core/hle/kernel/k_port.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/hle_ipc.h" | ||
| 6 | #include "core/hle/kernel/k_port.h" | ||
| 7 | #include "core/hle/kernel/k_scheduler.h" | ||
| 8 | #include "core/hle/kernel/svc_results.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | KPort::KPort(KernelCore& kernel_) | ||
| 13 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} | ||
| 14 | |||
| 15 | KPort::~KPort() = default; | ||
| 16 | |||
| 17 | void KPort::Initialize(s32 max_sessions_, bool is_light_, const std::string& name_) { | ||
| 18 | // Open a new reference count to the initialized port. | ||
| 19 | Open(); | ||
| 20 | |||
| 21 | // Create and initialize our server/client pair. | ||
| 22 | KAutoObject::Create(std::addressof(server)); | ||
| 23 | KAutoObject::Create(std::addressof(client)); | ||
| 24 | server.Initialize(this, name_ + ":Server"); | ||
| 25 | client.Initialize(this, max_sessions_, name_ + ":Client"); | ||
| 26 | |||
| 27 | // Set our member variables. | ||
| 28 | is_light = is_light_; | ||
| 29 | name = name_; | ||
| 30 | state = State::Normal; | ||
| 31 | } | ||
| 32 | |||
| 33 | void KPort::OnClientClosed() { | ||
| 34 | KScopedSchedulerLock sl{kernel}; | ||
| 35 | |||
| 36 | if (state == State::Normal) { | ||
| 37 | state = State::ClientClosed; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | void KPort::OnServerClosed() { | ||
| 42 | KScopedSchedulerLock sl{kernel}; | ||
| 43 | |||
| 44 | if (state == State::Normal) { | ||
| 45 | state = State::ServerClosed; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | bool KPort::IsServerClosed() const { | ||
| 50 | KScopedSchedulerLock sl{kernel}; | ||
| 51 | return state == State::ServerClosed; | ||
| 52 | } | ||
| 53 | |||
| 54 | ResultCode KPort::EnqueueSession(KServerSession* session) { | ||
| 55 | KScopedSchedulerLock sl{kernel}; | ||
| 56 | |||
| 57 | R_UNLESS(state == State::Normal, ResultPortClosed); | ||
| 58 | |||
| 59 | if (server.HasHLEHandler()) { | ||
| 60 | server.GetHLEHandler()->ClientConnected(session); | ||
| 61 | } else { | ||
| 62 | server.EnqueueSession(session); | ||
| 63 | } | ||
| 64 | |||
| 65 | return RESULT_SUCCESS; | ||
| 66 | } | ||
| 67 | |||
| 68 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h new file mode 100644 index 000000000..960f1f3a3 --- /dev/null +++ b/src/core/hle/kernel/k_port.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/kernel/k_client_port.h" | ||
| 12 | #include "core/hle/kernel/k_server_port.h" | ||
| 13 | #include "core/hle/kernel/slab_helpers.h" | ||
| 14 | #include "core/hle/result.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | class KServerSession; | ||
| 19 | |||
| 20 | class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjectWithList> { | ||
| 21 | KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject); | ||
| 22 | |||
| 23 | public: | ||
| 24 | explicit KPort(KernelCore& kernel_); | ||
| 25 | virtual ~KPort(); | ||
| 26 | |||
| 27 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||
| 28 | |||
| 29 | void Initialize(s32 max_sessions_, bool is_light_, const std::string& name_); | ||
| 30 | void OnClientClosed(); | ||
| 31 | void OnServerClosed(); | ||
| 32 | |||
| 33 | bool IsLight() const { | ||
| 34 | return is_light; | ||
| 35 | } | ||
| 36 | |||
| 37 | bool IsServerClosed() const; | ||
| 38 | |||
| 39 | ResultCode EnqueueSession(KServerSession* session); | ||
| 40 | |||
| 41 | KClientPort& GetClientPort() { | ||
| 42 | return client; | ||
| 43 | } | ||
| 44 | KServerPort& GetServerPort() { | ||
| 45 | return server; | ||
| 46 | } | ||
| 47 | const KClientPort& GetClientPort() const { | ||
| 48 | return client; | ||
| 49 | } | ||
| 50 | const KServerPort& GetServerPort() const { | ||
| 51 | return server; | ||
| 52 | } | ||
| 53 | |||
| 54 | private: | ||
| 55 | enum class State : u8 { | ||
| 56 | Invalid = 0, | ||
| 57 | Normal = 1, | ||
| 58 | ClientClosed = 2, | ||
| 59 | ServerClosed = 3, | ||
| 60 | }; | ||
| 61 | |||
| 62 | private: | ||
| 63 | KServerPort server; | ||
| 64 | KClientPort client; | ||
| 65 | State state{State::Invalid}; | ||
| 66 | bool is_light{}; | ||
| 67 | }; | ||
| 68 | |||
| 69 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/k_process.cpp index e35deb8e2..bdcbaeeaa 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -17,13 +17,14 @@ | |||
| 17 | #include "core/hle/kernel/code_set.h" | 17 | #include "core/hle/kernel/code_set.h" |
| 18 | #include "core/hle/kernel/k_memory_block_manager.h" | 18 | #include "core/hle/kernel/k_memory_block_manager.h" |
| 19 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 20 | #include "core/hle/kernel/k_process.h" | ||
| 20 | #include "core/hle/kernel/k_resource_limit.h" | 21 | #include "core/hle/kernel/k_resource_limit.h" |
| 21 | #include "core/hle/kernel/k_scheduler.h" | 22 | #include "core/hle/kernel/k_scheduler.h" |
| 22 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 23 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 24 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 23 | #include "core/hle/kernel/k_slab_heap.h" | 25 | #include "core/hle/kernel/k_slab_heap.h" |
| 24 | #include "core/hle/kernel/k_thread.h" | 26 | #include "core/hle/kernel/k_thread.h" |
| 25 | #include "core/hle/kernel/kernel.h" | 27 | #include "core/hle/kernel/kernel.h" |
| 26 | #include "core/hle/kernel/process.h" | ||
| 27 | #include "core/hle/kernel/svc_results.h" | 28 | #include "core/hle/kernel/svc_results.h" |
| 28 | #include "core/hle/lock.h" | 29 | #include "core/hle/lock.h" |
| 29 | #include "core/memory.h" | 30 | #include "core/memory.h" |
| @@ -37,17 +38,20 @@ namespace { | |||
| 37 | * @param owner_process The parent process for the main thread | 38 | * @param owner_process The parent process for the main thread |
| 38 | * @param priority The priority to give the main thread | 39 | * @param priority The priority to give the main thread |
| 39 | */ | 40 | */ |
| 40 | void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { | 41 | void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { |
| 41 | const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); | 42 | const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); |
| 42 | ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); | 43 | ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); |
| 43 | auto thread_res = | ||
| 44 | KThread::CreateUserThread(system, ThreadType::User, "main", entry_point, priority, 0, | ||
| 45 | owner_process.GetIdealCoreId(), stack_top, &owner_process); | ||
| 46 | 44 | ||
| 47 | std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap(); | 45 | KThread* thread = KThread::Create(system.Kernel()); |
| 46 | ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority, | ||
| 47 | owner_process.GetIdealCoreId(), &owner_process) | ||
| 48 | .IsSuccess()); | ||
| 48 | 49 | ||
| 49 | // Register 1 must be a handle to the main thread | 50 | // Register 1 must be a handle to the main thread |
| 50 | const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); | 51 | Handle thread_handle{}; |
| 52 | owner_process.GetHandleTable().Add(&thread_handle, thread); | ||
| 53 | |||
| 54 | thread->SetName("main"); | ||
| 51 | thread->GetContext32().cpu_registers[0] = 0; | 55 | thread->GetContext32().cpu_registers[0] = 0; |
| 52 | thread->GetContext64().cpu_registers[0] = 0; | 56 | thread->GetContext64().cpu_registers[0] = 0; |
| 53 | thread->GetContext32().cpu_registers[1] = thread_handle; | 57 | thread->GetContext32().cpu_registers[1] = thread_handle; |
| @@ -114,11 +118,11 @@ private: | |||
| 114 | std::bitset<num_slot_entries> is_slot_used; | 118 | std::bitset<num_slot_entries> is_slot_used; |
| 115 | }; | 119 | }; |
| 116 | 120 | ||
| 117 | std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, ProcessType type) { | 121 | ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, |
| 122 | ProcessType type) { | ||
| 118 | auto& kernel = system.Kernel(); | 123 | auto& kernel = system.Kernel(); |
| 119 | 124 | ||
| 120 | std::shared_ptr<Process> process = std::make_shared<Process>(system); | 125 | process->name = std::move(process_name); |
| 121 | process->name = std::move(name); | ||
| 122 | 126 | ||
| 123 | process->resource_limit = kernel.GetSystemResourceLimit(); | 127 | process->resource_limit = kernel.GetSystemResourceLimit(); |
| 124 | process->status = ProcessStatus::Created; | 128 | process->status = ProcessStatus::Created; |
| @@ -126,6 +130,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 126 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() | 130 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() |
| 127 | : kernel.CreateNewUserProcessID(); | 131 | : kernel.CreateNewUserProcessID(); |
| 128 | process->capabilities.InitializeForMetadatalessProcess(); | 132 | process->capabilities.InitializeForMetadatalessProcess(); |
| 133 | process->is_initialized = true; | ||
| 129 | 134 | ||
| 130 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); | 135 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); |
| 131 | std::uniform_int_distribution<u64> distribution; | 136 | std::uniform_int_distribution<u64> distribution; |
| @@ -133,14 +138,18 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 133 | [&] { return distribution(rng); }); | 138 | [&] { return distribution(rng); }); |
| 134 | 139 | ||
| 135 | kernel.AppendNewProcess(process); | 140 | kernel.AppendNewProcess(process); |
| 136 | return process; | 141 | |
| 142 | // Open a reference to the resource limit. | ||
| 143 | process->resource_limit->Open(); | ||
| 144 | |||
| 145 | return RESULT_SUCCESS; | ||
| 137 | } | 146 | } |
| 138 | 147 | ||
| 139 | std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const { | 148 | KResourceLimit* KProcess::GetResourceLimit() const { |
| 140 | return resource_limit; | 149 | return resource_limit; |
| 141 | } | 150 | } |
| 142 | 151 | ||
| 143 | void Process::IncrementThreadCount() { | 152 | void KProcess::IncrementThreadCount() { |
| 144 | ASSERT(num_threads >= 0); | 153 | ASSERT(num_threads >= 0); |
| 145 | num_created_threads++; | 154 | num_created_threads++; |
| 146 | 155 | ||
| @@ -149,7 +158,7 @@ void Process::IncrementThreadCount() { | |||
| 149 | } | 158 | } |
| 150 | } | 159 | } |
| 151 | 160 | ||
| 152 | void Process::DecrementThreadCount() { | 161 | void KProcess::DecrementThreadCount() { |
| 153 | ASSERT(num_threads > 0); | 162 | ASSERT(num_threads > 0); |
| 154 | 163 | ||
| 155 | if (const auto count = --num_threads; count == 0) { | 164 | if (const auto count = --num_threads; count == 0) { |
| @@ -157,31 +166,34 @@ void Process::DecrementThreadCount() { | |||
| 157 | } | 166 | } |
| 158 | } | 167 | } |
| 159 | 168 | ||
| 160 | u64 Process::GetTotalPhysicalMemoryAvailable() const { | 169 | u64 KProcess::GetTotalPhysicalMemoryAvailable() const { |
| 161 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 170 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 162 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | 171 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + |
| 163 | main_thread_stack_size}; | 172 | main_thread_stack_size}; |
| 164 | ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | 173 | if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); |
| 174 | capacity != pool_size) { | ||
| 175 | LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size); | ||
| 176 | } | ||
| 165 | if (capacity < memory_usage_capacity) { | 177 | if (capacity < memory_usage_capacity) { |
| 166 | return capacity; | 178 | return capacity; |
| 167 | } | 179 | } |
| 168 | return memory_usage_capacity; | 180 | return memory_usage_capacity; |
| 169 | } | 181 | } |
| 170 | 182 | ||
| 171 | u64 Process::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const { | 183 | u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const { |
| 172 | return GetTotalPhysicalMemoryAvailable() - GetSystemResourceSize(); | 184 | return GetTotalPhysicalMemoryAvailable() - GetSystemResourceSize(); |
| 173 | } | 185 | } |
| 174 | 186 | ||
| 175 | u64 Process::GetTotalPhysicalMemoryUsed() const { | 187 | u64 KProcess::GetTotalPhysicalMemoryUsed() const { |
| 176 | return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() + | 188 | return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() + |
| 177 | GetSystemResourceSize(); | 189 | GetSystemResourceSize(); |
| 178 | } | 190 | } |
| 179 | 191 | ||
| 180 | u64 Process::GetTotalPhysicalMemoryUsedWithoutSystemResource() const { | 192 | u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() const { |
| 181 | return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage(); | 193 | return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage(); |
| 182 | } | 194 | } |
| 183 | 195 | ||
| 184 | bool Process::ReleaseUserException(KThread* thread) { | 196 | bool KProcess::ReleaseUserException(KThread* thread) { |
| 185 | KScopedSchedulerLock sl{kernel}; | 197 | KScopedSchedulerLock sl{kernel}; |
| 186 | 198 | ||
| 187 | if (exception_thread == thread) { | 199 | if (exception_thread == thread) { |
| @@ -206,7 +218,7 @@ bool Process::ReleaseUserException(KThread* thread) { | |||
| 206 | } | 218 | } |
| 207 | } | 219 | } |
| 208 | 220 | ||
| 209 | void Process::PinCurrentThread() { | 221 | void KProcess::PinCurrentThread() { |
| 210 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 222 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 211 | 223 | ||
| 212 | // Get the current thread. | 224 | // Get the current thread. |
| @@ -221,7 +233,7 @@ void Process::PinCurrentThread() { | |||
| 221 | KScheduler::SetSchedulerUpdateNeeded(kernel); | 233 | KScheduler::SetSchedulerUpdateNeeded(kernel); |
| 222 | } | 234 | } |
| 223 | 235 | ||
| 224 | void Process::UnpinCurrentThread() { | 236 | void KProcess::UnpinCurrentThread() { |
| 225 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 237 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 226 | 238 | ||
| 227 | // Get the current thread. | 239 | // Get the current thread. |
| @@ -236,15 +248,39 @@ void Process::UnpinCurrentThread() { | |||
| 236 | KScheduler::SetSchedulerUpdateNeeded(kernel); | 248 | KScheduler::SetSchedulerUpdateNeeded(kernel); |
| 237 | } | 249 | } |
| 238 | 250 | ||
| 239 | void Process::RegisterThread(const KThread* thread) { | 251 | ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, |
| 252 | [[maybe_unused]] size_t size) { | ||
| 253 | // Lock ourselves, to prevent concurrent access. | ||
| 254 | KScopedLightLock lk(state_lock); | ||
| 255 | |||
| 256 | // TODO(bunnei): Manage KSharedMemoryInfo list here. | ||
| 257 | |||
| 258 | // Open a reference to the shared memory. | ||
| 259 | shmem->Open(); | ||
| 260 | |||
| 261 | return RESULT_SUCCESS; | ||
| 262 | } | ||
| 263 | |||
| 264 | void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, | ||
| 265 | [[maybe_unused]] size_t size) { | ||
| 266 | // Lock ourselves, to prevent concurrent access. | ||
| 267 | KScopedLightLock lk(state_lock); | ||
| 268 | |||
| 269 | // TODO(bunnei): Manage KSharedMemoryInfo list here. | ||
| 270 | |||
| 271 | // Close a reference to the shared memory. | ||
| 272 | shmem->Close(); | ||
| 273 | } | ||
| 274 | |||
| 275 | void KProcess::RegisterThread(const KThread* thread) { | ||
| 240 | thread_list.push_back(thread); | 276 | thread_list.push_back(thread); |
| 241 | } | 277 | } |
| 242 | 278 | ||
| 243 | void Process::UnregisterThread(const KThread* thread) { | 279 | void KProcess::UnregisterThread(const KThread* thread) { |
| 244 | thread_list.remove(thread); | 280 | thread_list.remove(thread); |
| 245 | } | 281 | } |
| 246 | 282 | ||
| 247 | ResultCode Process::Reset() { | 283 | ResultCode KProcess::Reset() { |
| 248 | // Lock the process and the scheduler. | 284 | // Lock the process and the scheduler. |
| 249 | KScopedLightLock lk(state_lock); | 285 | KScopedLightLock lk(state_lock); |
| 250 | KScopedSchedulerLock sl{kernel}; | 286 | KScopedSchedulerLock sl{kernel}; |
| @@ -258,8 +294,8 @@ ResultCode Process::Reset() { | |||
| 258 | return RESULT_SUCCESS; | 294 | return RESULT_SUCCESS; |
| 259 | } | 295 | } |
| 260 | 296 | ||
| 261 | ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | 297 | ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, |
| 262 | std::size_t code_size) { | 298 | std::size_t code_size) { |
| 263 | program_id = metadata.GetTitleID(); | 299 | program_id = metadata.GetTitleID(); |
| 264 | ideal_core = metadata.GetMainThreadCore(); | 300 | ideal_core = metadata.GetMainThreadCore(); |
| 265 | is_64bit_process = metadata.Is64BitProgram(); | 301 | is_64bit_process = metadata.Is64BitProgram(); |
| @@ -271,7 +307,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 271 | if (!memory_reservation.Succeeded()) { | 307 | if (!memory_reservation.Succeeded()) { |
| 272 | LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", | 308 | LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", |
| 273 | code_size + system_resource_size); | 309 | code_size + system_resource_size); |
| 274 | return ResultResourceLimitedExceeded; | 310 | return ResultLimitReached; |
| 275 | } | 311 | } |
| 276 | // Initialize proces address space | 312 | // Initialize proces address space |
| 277 | if (const ResultCode result{ | 313 | if (const ResultCode result{ |
| @@ -318,10 +354,10 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 318 | tls_region_address = CreateTLSRegion(); | 354 | tls_region_address = CreateTLSRegion(); |
| 319 | memory_reservation.Commit(); | 355 | memory_reservation.Commit(); |
| 320 | 356 | ||
| 321 | return handle_table.SetSize(capabilities.GetHandleTableSize()); | 357 | return handle_table.Initialize(capabilities.GetHandleTableSize()); |
| 322 | } | 358 | } |
| 323 | 359 | ||
| 324 | void Process::Run(s32 main_thread_priority, u64 stack_size) { | 360 | void KProcess::Run(s32 main_thread_priority, u64 stack_size) { |
| 325 | AllocateMainThreadStack(stack_size); | 361 | AllocateMainThreadStack(stack_size); |
| 326 | resource_limit->Reserve(LimitableResource::Threads, 1); | 362 | resource_limit->Reserve(LimitableResource::Threads, 1); |
| 327 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); | 363 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); |
| @@ -331,18 +367,18 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { | |||
| 331 | 367 | ||
| 332 | ChangeStatus(ProcessStatus::Running); | 368 | ChangeStatus(ProcessStatus::Running); |
| 333 | 369 | ||
| 334 | SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); | 370 | SetupMainThread(kernel.System(), *this, main_thread_priority, main_thread_stack_top); |
| 335 | } | 371 | } |
| 336 | 372 | ||
| 337 | void Process::PrepareForTermination() { | 373 | void KProcess::PrepareForTermination() { |
| 338 | ChangeStatus(ProcessStatus::Exiting); | 374 | ChangeStatus(ProcessStatus::Exiting); |
| 339 | 375 | ||
| 340 | const auto stop_threads = [this](const std::vector<std::shared_ptr<KThread>>& thread_list) { | 376 | const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) { |
| 341 | for (auto& thread : thread_list) { | 377 | for (auto& thread : in_thread_list) { |
| 342 | if (thread->GetOwnerProcess() != this) | 378 | if (thread->GetOwnerProcess() != this) |
| 343 | continue; | 379 | continue; |
| 344 | 380 | ||
| 345 | if (thread.get() == kernel.CurrentScheduler()->GetCurrentThread()) | 381 | if (thread == kernel.CurrentScheduler()->GetCurrentThread()) |
| 346 | continue; | 382 | continue; |
| 347 | 383 | ||
| 348 | // TODO(Subv): When are the other running/ready threads terminated? | 384 | // TODO(Subv): When are the other running/ready threads terminated? |
| @@ -353,7 +389,7 @@ void Process::PrepareForTermination() { | |||
| 353 | } | 389 | } |
| 354 | }; | 390 | }; |
| 355 | 391 | ||
| 356 | stop_threads(system.GlobalSchedulerContext().GetThreadList()); | 392 | stop_threads(kernel.System().GlobalSchedulerContext().GetThreadList()); |
| 357 | 393 | ||
| 358 | FreeTLSRegion(tls_region_address); | 394 | FreeTLSRegion(tls_region_address); |
| 359 | tls_region_address = 0; | 395 | tls_region_address = 0; |
| @@ -366,6 +402,16 @@ void Process::PrepareForTermination() { | |||
| 366 | ChangeStatus(ProcessStatus::Exited); | 402 | ChangeStatus(ProcessStatus::Exited); |
| 367 | } | 403 | } |
| 368 | 404 | ||
| 405 | void KProcess::Finalize() { | ||
| 406 | // Release memory to the resource limit. | ||
| 407 | if (resource_limit != nullptr) { | ||
| 408 | resource_limit->Close(); | ||
| 409 | } | ||
| 410 | |||
| 411 | // Perform inherited finalization. | ||
| 412 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | ||
| 413 | } | ||
| 414 | |||
| 369 | /** | 415 | /** |
| 370 | * Attempts to find a TLS page that contains a free slot for | 416 | * Attempts to find a TLS page that contains a free slot for |
| 371 | * use by a thread. | 417 | * use by a thread. |
| @@ -379,8 +425,8 @@ static auto FindTLSPageWithAvailableSlots(std::vector<TLSPage>& tls_pages) { | |||
| 379 | [](const auto& page) { return page.HasAvailableSlots(); }); | 425 | [](const auto& page) { return page.HasAvailableSlots(); }); |
| 380 | } | 426 | } |
| 381 | 427 | ||
| 382 | VAddr Process::CreateTLSRegion() { | 428 | VAddr KProcess::CreateTLSRegion() { |
| 383 | KScopedSchedulerLock lock(system.Kernel()); | 429 | KScopedSchedulerLock lock(kernel); |
| 384 | if (auto tls_page_iter{FindTLSPageWithAvailableSlots(tls_pages)}; | 430 | if (auto tls_page_iter{FindTLSPageWithAvailableSlots(tls_pages)}; |
| 385 | tls_page_iter != tls_pages.cend()) { | 431 | tls_page_iter != tls_pages.cend()) { |
| 386 | return *tls_page_iter->ReserveSlot(); | 432 | return *tls_page_iter->ReserveSlot(); |
| @@ -391,7 +437,7 @@ VAddr Process::CreateTLSRegion() { | |||
| 391 | 437 | ||
| 392 | const VAddr start{page_table->GetKernelMapRegionStart()}; | 438 | const VAddr start{page_table->GetKernelMapRegionStart()}; |
| 393 | const VAddr size{page_table->GetKernelMapRegionEnd() - start}; | 439 | const VAddr size{page_table->GetKernelMapRegionEnd() - start}; |
| 394 | const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; | 440 | const PAddr tls_map_addr{kernel.System().DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; |
| 395 | const VAddr tls_page_addr{page_table | 441 | const VAddr tls_page_addr{page_table |
| 396 | ->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize, | 442 | ->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize, |
| 397 | KMemoryState::ThreadLocal, | 443 | KMemoryState::ThreadLocal, |
| @@ -410,8 +456,8 @@ VAddr Process::CreateTLSRegion() { | |||
| 410 | return *reserve_result; | 456 | return *reserve_result; |
| 411 | } | 457 | } |
| 412 | 458 | ||
| 413 | void Process::FreeTLSRegion(VAddr tls_address) { | 459 | void KProcess::FreeTLSRegion(VAddr tls_address) { |
| 414 | KScopedSchedulerLock lock(system.Kernel()); | 460 | KScopedSchedulerLock lock(kernel); |
| 415 | const VAddr aligned_address = Common::AlignDown(tls_address, Core::Memory::PAGE_SIZE); | 461 | const VAddr aligned_address = Common::AlignDown(tls_address, Core::Memory::PAGE_SIZE); |
| 416 | auto iter = | 462 | auto iter = |
| 417 | std::find_if(tls_pages.begin(), tls_pages.end(), [aligned_address](const auto& page) { | 463 | std::find_if(tls_pages.begin(), tls_pages.end(), [aligned_address](const auto& page) { |
| @@ -425,33 +471,34 @@ void Process::FreeTLSRegion(VAddr tls_address) { | |||
| 425 | iter->ReleaseSlot(tls_address); | 471 | iter->ReleaseSlot(tls_address); |
| 426 | } | 472 | } |
| 427 | 473 | ||
| 428 | void Process::LoadModule(CodeSet code_set, VAddr base_addr) { | 474 | void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { |
| 429 | std::lock_guard lock{HLE::g_hle_lock}; | 475 | std::lock_guard lock{HLE::g_hle_lock}; |
| 430 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, | 476 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, |
| 431 | KMemoryPermission permission) { | 477 | KMemoryPermission permission) { |
| 432 | page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); | 478 | page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); |
| 433 | }; | 479 | }; |
| 434 | 480 | ||
| 435 | system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size()); | 481 | kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), |
| 482 | code_set.memory.size()); | ||
| 436 | 483 | ||
| 437 | ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute); | 484 | ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute); |
| 438 | ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read); | 485 | ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read); |
| 439 | ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite); | 486 | ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite); |
| 440 | } | 487 | } |
| 441 | 488 | ||
| 442 | bool Process::IsSignaled() const { | 489 | bool KProcess::IsSignaled() const { |
| 443 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 490 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 444 | return is_signaled; | 491 | return is_signaled; |
| 445 | } | 492 | } |
| 446 | 493 | ||
| 447 | Process::Process(Core::System& system) | 494 | KProcess::KProcess(KernelCore& kernel_) |
| 448 | : KSynchronizationObject{system.Kernel()}, page_table{std::make_unique<KPageTable>(system)}, | 495 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, |
| 449 | handle_table{system.Kernel()}, address_arbiter{system}, condition_var{system}, | 496 | page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_}, |
| 450 | state_lock{system.Kernel()}, system{system} {} | 497 | address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {} |
| 451 | 498 | ||
| 452 | Process::~Process() = default; | 499 | KProcess::~KProcess() = default; |
| 453 | 500 | ||
| 454 | void Process::ChangeStatus(ProcessStatus new_status) { | 501 | void KProcess::ChangeStatus(ProcessStatus new_status) { |
| 455 | if (status == new_status) { | 502 | if (status == new_status) { |
| 456 | return; | 503 | return; |
| 457 | } | 504 | } |
| @@ -461,7 +508,7 @@ void Process::ChangeStatus(ProcessStatus new_status) { | |||
| 461 | NotifyAvailable(); | 508 | NotifyAvailable(); |
| 462 | } | 509 | } |
| 463 | 510 | ||
| 464 | ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) { | 511 | ResultCode KProcess::AllocateMainThreadStack(std::size_t stack_size) { |
| 465 | ASSERT(stack_size); | 512 | ASSERT(stack_size); |
| 466 | 513 | ||
| 467 | // The kernel always ensures that the given stack size is page aligned. | 514 | // The kernel always ensures that the given stack size is page aligned. |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/k_process.h index 45eefb90e..123d71cd3 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -11,11 +11,13 @@ | |||
| 11 | #include <unordered_map> | 11 | #include <unordered_map> |
| 12 | #include <vector> | 12 | #include <vector> |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/hle/kernel/handle_table.h" | ||
| 15 | #include "core/hle/kernel/k_address_arbiter.h" | 14 | #include "core/hle/kernel/k_address_arbiter.h" |
| 15 | #include "core/hle/kernel/k_auto_object.h" | ||
| 16 | #include "core/hle/kernel/k_condition_variable.h" | 16 | #include "core/hle/kernel/k_condition_variable.h" |
| 17 | #include "core/hle/kernel/k_handle_table.h" | ||
| 17 | #include "core/hle/kernel/k_synchronization_object.h" | 18 | #include "core/hle/kernel/k_synchronization_object.h" |
| 18 | #include "core/hle/kernel/process_capability.h" | 19 | #include "core/hle/kernel/process_capability.h" |
| 20 | #include "core/hle/kernel/slab_helpers.h" | ||
| 19 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| 20 | 22 | ||
| 21 | namespace Core { | 23 | namespace Core { |
| @@ -60,10 +62,13 @@ enum class ProcessStatus { | |||
| 60 | DebugBreak, | 62 | DebugBreak, |
| 61 | }; | 63 | }; |
| 62 | 64 | ||
| 63 | class Process final : public KSynchronizationObject { | 65 | class KProcess final |
| 66 | : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> { | ||
| 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | ||
| 68 | |||
| 64 | public: | 69 | public: |
| 65 | explicit Process(Core::System& system); | 70 | explicit KProcess(KernelCore& kernel_); |
| 66 | ~Process() override; | 71 | ~KProcess() override; |
| 67 | 72 | ||
| 68 | enum : u64 { | 73 | enum : u64 { |
| 69 | /// Lowest allowed process ID for a kernel initial process. | 74 | /// Lowest allowed process ID for a kernel initial process. |
| @@ -85,20 +90,8 @@ public: | |||
| 85 | 90 | ||
| 86 | static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; | 91 | static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; |
| 87 | 92 | ||
| 88 | static std::shared_ptr<Process> Create(Core::System& system, std::string name, | 93 | static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name, |
| 89 | ProcessType type); | 94 | ProcessType type); |
| 90 | |||
| 91 | std::string GetTypeName() const override { | ||
| 92 | return "Process"; | ||
| 93 | } | ||
| 94 | std::string GetName() const override { | ||
| 95 | return name; | ||
| 96 | } | ||
| 97 | |||
| 98 | static constexpr HandleType HANDLE_TYPE = HandleType::Process; | ||
| 99 | HandleType GetHandleType() const override { | ||
| 100 | return HANDLE_TYPE; | ||
| 101 | } | ||
| 102 | 95 | ||
| 103 | /// Gets a reference to the process' page table. | 96 | /// Gets a reference to the process' page table. |
| 104 | KPageTable& PageTable() { | 97 | KPageTable& PageTable() { |
| @@ -111,12 +104,12 @@ public: | |||
| 111 | } | 104 | } |
| 112 | 105 | ||
| 113 | /// Gets a reference to the process' handle table. | 106 | /// Gets a reference to the process' handle table. |
| 114 | HandleTable& GetHandleTable() { | 107 | KHandleTable& GetHandleTable() { |
| 115 | return handle_table; | 108 | return handle_table; |
| 116 | } | 109 | } |
| 117 | 110 | ||
| 118 | /// Gets a const reference to the process' handle table. | 111 | /// Gets a const reference to the process' handle table. |
| 119 | const HandleTable& GetHandleTable() const { | 112 | const KHandleTable& GetHandleTable() const { |
| 120 | return handle_table; | 113 | return handle_table; |
| 121 | } | 114 | } |
| 122 | 115 | ||
| @@ -167,7 +160,7 @@ public: | |||
| 167 | } | 160 | } |
| 168 | 161 | ||
| 169 | /// Gets the resource limit descriptor for this process | 162 | /// Gets the resource limit descriptor for this process |
| 170 | std::shared_ptr<KResourceLimit> GetResourceLimit() const; | 163 | KResourceLimit* GetResourceLimit() const; |
| 171 | 164 | ||
| 172 | /// Gets the ideal CPU core ID for this process | 165 | /// Gets the ideal CPU core ID for this process |
| 173 | u8 GetIdealCoreId() const { | 166 | u8 GetIdealCoreId() const { |
| @@ -338,9 +331,19 @@ public: | |||
| 338 | 331 | ||
| 339 | void LoadModule(CodeSet code_set, VAddr base_addr); | 332 | void LoadModule(CodeSet code_set, VAddr base_addr); |
| 340 | 333 | ||
| 341 | bool IsSignaled() const override; | 334 | virtual bool IsInitialized() const override { |
| 335 | return is_initialized; | ||
| 336 | } | ||
| 337 | |||
| 338 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||
| 339 | |||
| 340 | virtual void Finalize(); | ||
| 341 | |||
| 342 | virtual u64 GetId() const override final { | ||
| 343 | return GetProcessID(); | ||
| 344 | } | ||
| 342 | 345 | ||
| 343 | void Finalize() override {} | 346 | virtual bool IsSignaled() const override; |
| 344 | 347 | ||
| 345 | void PinCurrentThread(); | 348 | void PinCurrentThread(); |
| 346 | void UnpinCurrentThread(); | 349 | void UnpinCurrentThread(); |
| @@ -349,6 +352,9 @@ public: | |||
| 349 | return state_lock; | 352 | return state_lock; |
| 350 | } | 353 | } |
| 351 | 354 | ||
| 355 | ResultCode AddSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); | ||
| 356 | void RemoveSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); | ||
| 357 | |||
| 352 | /////////////////////////////////////////////////////////////////////////////////////////////// | 358 | /////////////////////////////////////////////////////////////////////////////////////////////// |
| 353 | // Thread-local storage management | 359 | // Thread-local storage management |
| 354 | 360 | ||
| @@ -399,7 +405,7 @@ private: | |||
| 399 | u32 system_resource_size = 0; | 405 | u32 system_resource_size = 0; |
| 400 | 406 | ||
| 401 | /// Resource limit descriptor for this process | 407 | /// Resource limit descriptor for this process |
| 402 | std::shared_ptr<KResourceLimit> resource_limit; | 408 | KResourceLimit* resource_limit{}; |
| 403 | 409 | ||
| 404 | /// The ideal CPU core for this process, threads are scheduled on this core by default. | 410 | /// The ideal CPU core for this process, threads are scheduled on this core by default. |
| 405 | u8 ideal_core = 0; | 411 | u8 ideal_core = 0; |
| @@ -423,7 +429,7 @@ private: | |||
| 423 | u64 total_process_running_time_ticks = 0; | 429 | u64 total_process_running_time_ticks = 0; |
| 424 | 430 | ||
| 425 | /// Per-process handle table for storing created object handles in. | 431 | /// Per-process handle table for storing created object handles in. |
| 426 | HandleTable handle_table; | 432 | KHandleTable handle_table; |
| 427 | 433 | ||
| 428 | /// Per-process address arbiter. | 434 | /// Per-process address arbiter. |
| 429 | KAddressArbiter address_arbiter; | 435 | KAddressArbiter address_arbiter; |
| @@ -454,14 +460,12 @@ private: | |||
| 454 | /// Process total image size | 460 | /// Process total image size |
| 455 | std::size_t image_size{}; | 461 | std::size_t image_size{}; |
| 456 | 462 | ||
| 457 | /// Name of this process | ||
| 458 | std::string name; | ||
| 459 | |||
| 460 | /// Schedule count of this process | 463 | /// Schedule count of this process |
| 461 | s64 schedule_count{}; | 464 | s64 schedule_count{}; |
| 462 | 465 | ||
| 463 | bool is_signaled{}; | 466 | bool is_signaled{}; |
| 464 | bool is_suspended{}; | 467 | bool is_suspended{}; |
| 468 | bool is_initialized{}; | ||
| 465 | 469 | ||
| 466 | std::atomic<s32> num_created_threads{}; | 470 | std::atomic<s32> num_created_threads{}; |
| 467 | std::atomic<u16> num_threads{}; | 471 | std::atomic<u16> num_threads{}; |
| @@ -474,9 +478,6 @@ private: | |||
| 474 | KThread* exception_thread{}; | 478 | KThread* exception_thread{}; |
| 475 | 479 | ||
| 476 | KLightLock state_lock; | 480 | KLightLock state_lock; |
| 477 | |||
| 478 | /// System context | ||
| 479 | Core::System& system; | ||
| 480 | }; | 481 | }; |
| 481 | 482 | ||
| 482 | } // namespace Kernel | 483 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index 4b4d34857..0ea2d0275 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp | |||
| @@ -2,21 +2,18 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 7 | #include "common/common_funcs.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "core/hle/kernel/k_readable_event.h" | 7 | #include "core/hle/kernel/k_readable_event.h" |
| 10 | #include "core/hle/kernel/k_scheduler.h" | 8 | #include "core/hle/kernel/k_scheduler.h" |
| 11 | #include "core/hle/kernel/k_thread.h" | 9 | #include "core/hle/kernel/k_thread.h" |
| 12 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/object.h" | ||
| 14 | #include "core/hle/kernel/svc_results.h" | 11 | #include "core/hle/kernel/svc_results.h" |
| 15 | 12 | ||
| 16 | namespace Kernel { | 13 | namespace Kernel { |
| 17 | 14 | ||
| 18 | KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name) | 15 | KReadableEvent::KReadableEvent(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 19 | : KSynchronizationObject{kernel, std::move(name)} {} | 16 | |
| 20 | KReadableEvent::~KReadableEvent() = default; | 17 | KReadableEvent::~KReadableEvent() = default; |
| 21 | 18 | ||
| 22 | bool KReadableEvent::IsSignaled() const { | 19 | bool KReadableEvent::IsSignaled() const { |
| @@ -25,6 +22,12 @@ bool KReadableEvent::IsSignaled() const { | |||
| 25 | return is_signaled; | 22 | return is_signaled; |
| 26 | } | 23 | } |
| 27 | 24 | ||
| 25 | void KReadableEvent::Destroy() { | ||
| 26 | if (parent) { | ||
| 27 | parent->Close(); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 28 | ResultCode KReadableEvent::Signal() { | 31 | ResultCode KReadableEvent::Signal() { |
| 29 | KScopedSchedulerLock lk{kernel}; | 32 | KScopedSchedulerLock lk{kernel}; |
| 30 | 33 | ||
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index e6f0fd900..33cd1dd3e 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_auto_object.h" | ||
| 7 | #include "core/hle/kernel/k_synchronization_object.h" | 8 | #include "core/hle/kernel/k_synchronization_object.h" |
| 8 | #include "core/hle/kernel/object.h" | 9 | #include "core/hle/kernel/slab_helpers.h" |
| 9 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 10 | 11 | ||
| 11 | namespace Kernel { | 12 | namespace Kernel { |
| @@ -13,31 +14,25 @@ namespace Kernel { | |||
| 13 | class KernelCore; | 14 | class KernelCore; |
| 14 | class KEvent; | 15 | class KEvent; |
| 15 | 16 | ||
| 16 | class KReadableEvent final : public KSynchronizationObject { | 17 | class KReadableEvent : public KSynchronizationObject { |
| 18 | KERNEL_AUTOOBJECT_TRAITS(KReadableEvent, KSynchronizationObject); | ||
| 19 | |||
| 17 | public: | 20 | public: |
| 18 | explicit KReadableEvent(KernelCore& kernel, std::string&& name); | 21 | explicit KReadableEvent(KernelCore& kernel_); |
| 19 | ~KReadableEvent() override; | 22 | ~KReadableEvent() override; |
| 20 | 23 | ||
| 21 | std::string GetTypeName() const override { | 24 | void Initialize(KEvent* parent_, std::string&& name_) { |
| 22 | return "KReadableEvent"; | 25 | is_signaled = false; |
| 23 | } | 26 | parent = parent_; |
| 24 | 27 | name = std::move(name_); | |
| 25 | static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent; | ||
| 26 | HandleType GetHandleType() const override { | ||
| 27 | return HANDLE_TYPE; | ||
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | KEvent* GetParent() const { | 30 | KEvent* GetParent() const { |
| 31 | return parent; | 31 | return parent; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | void Initialize(KEvent* parent_) { | 34 | virtual bool IsSignaled() const override; |
| 35 | is_signaled = false; | 35 | virtual void Destroy() override; |
| 36 | parent = parent_; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool IsSignaled() const override; | ||
| 40 | void Finalize() override {} | ||
| 41 | 36 | ||
| 42 | ResultCode Signal(); | 37 | ResultCode Signal(); |
| 43 | ResultCode Clear(); | 38 | ResultCode Clear(); |
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index d05b34ea3..bf20bf7d0 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp | |||
| @@ -10,10 +10,16 @@ | |||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds | 11 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds |
| 12 | 12 | ||
| 13 | KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_) | 13 | KResourceLimit::KResourceLimit(KernelCore& kernel_) |
| 14 | : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {} | 14 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, lock{kernel_}, cond_var{kernel_} {} |
| 15 | KResourceLimit::~KResourceLimit() = default; | 15 | KResourceLimit::~KResourceLimit() = default; |
| 16 | 16 | ||
| 17 | void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { | ||
| 18 | core_timing = core_timing_; | ||
| 19 | } | ||
| 20 | |||
| 21 | void KResourceLimit::Finalize() {} | ||
| 22 | |||
| 17 | s64 KResourceLimit::GetLimitValue(LimitableResource which) const { | 23 | s64 KResourceLimit::GetLimitValue(LimitableResource which) const { |
| 18 | const auto index = static_cast<std::size_t>(which); | 24 | const auto index = static_cast<std::size_t>(which); |
| 19 | s64 value{}; | 25 | s64 value{}; |
| @@ -78,7 +84,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { | |||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | bool KResourceLimit::Reserve(LimitableResource which, s64 value) { | 86 | bool KResourceLimit::Reserve(LimitableResource which, s64 value) { |
| 81 | return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout); | 87 | return Reserve(which, value, core_timing->GetGlobalTimeNs().count() + DefaultTimeout); |
| 82 | } | 88 | } |
| 83 | 89 | ||
| 84 | bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | 90 | bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { |
| @@ -109,7 +115,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | |||
| 109 | } | 115 | } |
| 110 | 116 | ||
| 111 | if (current_hints[index] + value <= limit_values[index] && | 117 | if (current_hints[index] + value <= limit_values[index] && |
| 112 | (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) { | 118 | (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { |
| 113 | waiter_count++; | 119 | waiter_count++; |
| 114 | cond_var.Wait(&lock, timeout); | 120 | cond_var.Wait(&lock, timeout); |
| 115 | waiter_count--; | 121 | waiter_count--; |
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 4542317d0..0debbbb51 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/hle/kernel/k_light_condition_variable.h" | 9 | #include "core/hle/kernel/k_light_condition_variable.h" |
| 10 | #include "core/hle/kernel/k_light_lock.h" | 10 | #include "core/hle/kernel/k_light_lock.h" |
| 11 | #include "core/hle/kernel/object.h" | ||
| 12 | 11 | ||
| 13 | union ResultCode; | 12 | union ResultCode; |
| 14 | 13 | ||
| @@ -32,10 +31,16 @@ constexpr bool IsValidResourceType(LimitableResource type) { | |||
| 32 | return type < LimitableResource::Count; | 31 | return type < LimitableResource::Count; |
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | class KResourceLimit final : public Object { | 34 | class KResourceLimit final |
| 35 | : public KAutoObjectWithSlabHeapAndContainer<KResourceLimit, KAutoObjectWithList> { | ||
| 36 | KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); | ||
| 37 | |||
| 36 | public: | 38 | public: |
| 37 | explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_); | 39 | explicit KResourceLimit(KernelCore& kernel_); |
| 38 | ~KResourceLimit(); | 40 | virtual ~KResourceLimit(); |
| 41 | |||
| 42 | void Initialize(const Core::Timing::CoreTiming* core_timing_); | ||
| 43 | virtual void Finalize() override; | ||
| 39 | 44 | ||
| 40 | s64 GetLimitValue(LimitableResource which) const; | 45 | s64 GetLimitValue(LimitableResource which) const; |
| 41 | s64 GetCurrentValue(LimitableResource which) const; | 46 | s64 GetCurrentValue(LimitableResource which) const; |
| @@ -49,19 +54,7 @@ public: | |||
| 49 | void Release(LimitableResource which, s64 value); | 54 | void Release(LimitableResource which, s64 value); |
| 50 | void Release(LimitableResource which, s64 value, s64 hint); | 55 | void Release(LimitableResource which, s64 value, s64 hint); |
| 51 | 56 | ||
| 52 | std::string GetTypeName() const override { | 57 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 53 | return "KResourceLimit"; | ||
| 54 | } | ||
| 55 | std::string GetName() const override { | ||
| 56 | return GetTypeName(); | ||
| 57 | } | ||
| 58 | |||
| 59 | static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit; | ||
| 60 | HandleType GetHandleType() const override { | ||
| 61 | return HANDLE_TYPE; | ||
| 62 | } | ||
| 63 | |||
| 64 | virtual void Finalize() override {} | ||
| 65 | 58 | ||
| 66 | private: | 59 | private: |
| 67 | using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; | 60 | using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; |
| @@ -72,6 +65,6 @@ private: | |||
| 72 | mutable KLightLock lock; | 65 | mutable KLightLock lock; |
| 73 | s32 waiter_count{}; | 66 | s32 waiter_count{}; |
| 74 | KLightConditionVariable cond_var; | 67 | KLightConditionVariable cond_var; |
| 75 | const Core::Timing::CoreTiming& core_timing; | 68 | const Core::Timing::CoreTiming* core_timing{}; |
| 76 | }; | 69 | }; |
| 77 | } // namespace Kernel | 70 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index d1df97305..2f82fbcd6 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -15,12 +15,12 @@ | |||
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 17 | #include "core/cpu_manager.h" | 17 | #include "core/cpu_manager.h" |
| 18 | #include "core/hle/kernel/k_process.h" | ||
| 18 | #include "core/hle/kernel/k_scheduler.h" | 19 | #include "core/hle/kernel/k_scheduler.h" |
| 19 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 20 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 20 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 22 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/physical_core.h" | 23 | #include "core/hle/kernel/physical_core.h" |
| 23 | #include "core/hle/kernel/process.h" | ||
| 24 | #include "core/hle/kernel/time_manager.h" | 24 | #include "core/hle/kernel/time_manager.h" |
| 25 | 25 | ||
| 26 | namespace Kernel { | 26 | namespace Kernel { |
| @@ -71,7 +71,7 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { | |||
| 71 | } | 71 | } |
| 72 | if (state.should_count_idle) { | 72 | if (state.should_count_idle) { |
| 73 | if (highest_thread != nullptr) { | 73 | if (highest_thread != nullptr) { |
| 74 | if (Process* process = highest_thread->GetOwnerProcess(); process != nullptr) { | 74 | if (KProcess* process = highest_thread->GetOwnerProcess(); process != nullptr) { |
| 75 | process->SetRunningThread(core_id, highest_thread, state.idle_count); | 75 | process->SetRunningThread(core_id, highest_thread, state.idle_count); |
| 76 | } | 76 | } |
| 77 | } else { | 77 | } else { |
| @@ -104,7 +104,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { | |||
| 104 | if (top_thread != nullptr) { | 104 | if (top_thread != nullptr) { |
| 105 | // If the thread has no waiters, we need to check if the process has a thread pinned. | 105 | // If the thread has no waiters, we need to check if the process has a thread pinned. |
| 106 | if (top_thread->GetNumKernelWaiters() == 0) { | 106 | if (top_thread->GetNumKernelWaiters() == 0) { |
| 107 | if (Process* parent = top_thread->GetOwnerProcess(); parent != nullptr) { | 107 | if (KProcess* parent = top_thread->GetOwnerProcess(); parent != nullptr) { |
| 108 | if (KThread* pinned = parent->GetPinnedThread(static_cast<s32>(core_id)); | 108 | if (KThread* pinned = parent->GetPinnedThread(static_cast<s32>(core_id)); |
| 109 | pinned != nullptr && pinned != top_thread) { | 109 | pinned != nullptr && pinned != top_thread) { |
| 110 | // We prefer our parent's pinned thread if possible. However, we also don't | 110 | // We prefer our parent's pinned thread if possible. However, we also don't |
| @@ -259,7 +259,7 @@ void KScheduler::OnThreadAffinityMaskChanged(KernelCore& kernel, KThread* thread | |||
| 259 | } | 259 | } |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | 262 | void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) { |
| 263 | ASSERT(system.GlobalSchedulerContext().IsLocked()); | 263 | ASSERT(system.GlobalSchedulerContext().IsLocked()); |
| 264 | 264 | ||
| 265 | // Get a reference to the priority queue. | 265 | // Get a reference to the priority queue. |
| @@ -267,7 +267,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 267 | auto& priority_queue = GetPriorityQueue(kernel); | 267 | auto& priority_queue = GetPriorityQueue(kernel); |
| 268 | 268 | ||
| 269 | // Rotate the front of the queue to the end. | 269 | // Rotate the front of the queue to the end. |
| 270 | KThread* top_thread = priority_queue.GetScheduledFront(core_id, priority); | 270 | KThread* top_thread = priority_queue.GetScheduledFront(cpu_core_id, priority); |
| 271 | KThread* next_thread = nullptr; | 271 | KThread* next_thread = nullptr; |
| 272 | if (top_thread != nullptr) { | 272 | if (top_thread != nullptr) { |
| 273 | next_thread = priority_queue.MoveToScheduledBack(top_thread); | 273 | next_thread = priority_queue.MoveToScheduledBack(top_thread); |
| @@ -279,7 +279,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 279 | 279 | ||
| 280 | // While we have a suggested thread, try to migrate it! | 280 | // While we have a suggested thread, try to migrate it! |
| 281 | { | 281 | { |
| 282 | KThread* suggested = priority_queue.GetSuggestedFront(core_id, priority); | 282 | KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id, priority); |
| 283 | while (suggested != nullptr) { | 283 | while (suggested != nullptr) { |
| 284 | // Check if the suggested thread is the top thread on its core. | 284 | // Check if the suggested thread is the top thread on its core. |
| 285 | const s32 suggested_core = suggested->GetActiveCore(); | 285 | const s32 suggested_core = suggested->GetActiveCore(); |
| @@ -300,7 +300,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 300 | // to the front of the queue. | 300 | // to the front of the queue. |
| 301 | if (top_on_suggested_core == nullptr || | 301 | if (top_on_suggested_core == nullptr || |
| 302 | top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { | 302 | top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { |
| 303 | suggested->SetActiveCore(core_id); | 303 | suggested->SetActiveCore(cpu_core_id); |
| 304 | priority_queue.ChangeCore(suggested_core, suggested, true); | 304 | priority_queue.ChangeCore(suggested_core, suggested, true); |
| 305 | IncrementScheduledCount(suggested); | 305 | IncrementScheduledCount(suggested); |
| 306 | break; | 306 | break; |
| @@ -308,22 +308,22 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | // Get the next suggestion. | 310 | // Get the next suggestion. |
| 311 | suggested = priority_queue.GetSamePriorityNext(core_id, suggested); | 311 | suggested = priority_queue.GetSamePriorityNext(cpu_core_id, suggested); |
| 312 | } | 312 | } |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | // Now that we might have migrated a thread with the same priority, check if we can do better. | 315 | // Now that we might have migrated a thread with the same priority, check if we can do better. |
| 316 | 316 | ||
| 317 | { | 317 | { |
| 318 | KThread* best_thread = priority_queue.GetScheduledFront(core_id); | 318 | KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id); |
| 319 | if (best_thread == GetCurrentThread()) { | 319 | if (best_thread == GetCurrentThread()) { |
| 320 | best_thread = priority_queue.GetScheduledNext(core_id, best_thread); | 320 | best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | // If the best thread we can choose has a priority the same or worse than ours, try to | 323 | // If the best thread we can choose has a priority the same or worse than ours, try to |
| 324 | // migrate a higher priority thread. | 324 | // migrate a higher priority thread. |
| 325 | if (best_thread != nullptr && best_thread->GetPriority() >= priority) { | 325 | if (best_thread != nullptr && best_thread->GetPriority() >= priority) { |
| 326 | KThread* suggested = priority_queue.GetSuggestedFront(core_id); | 326 | KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id); |
| 327 | while (suggested != nullptr) { | 327 | while (suggested != nullptr) { |
| 328 | // If the suggestion's priority is the same as ours, don't bother. | 328 | // If the suggestion's priority is the same as ours, don't bother. |
| 329 | if (suggested->GetPriority() >= best_thread->GetPriority()) { | 329 | if (suggested->GetPriority() >= best_thread->GetPriority()) { |
| @@ -342,7 +342,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 342 | if (top_on_suggested_core == nullptr || | 342 | if (top_on_suggested_core == nullptr || |
| 343 | top_on_suggested_core->GetPriority() >= | 343 | top_on_suggested_core->GetPriority() >= |
| 344 | HighestCoreMigrationAllowedPriority) { | 344 | HighestCoreMigrationAllowedPriority) { |
| 345 | suggested->SetActiveCore(core_id); | 345 | suggested->SetActiveCore(cpu_core_id); |
| 346 | priority_queue.ChangeCore(suggested_core, suggested, true); | 346 | priority_queue.ChangeCore(suggested_core, suggested, true); |
| 347 | IncrementScheduledCount(suggested); | 347 | IncrementScheduledCount(suggested); |
| 348 | break; | 348 | break; |
| @@ -350,7 +350,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | // Get the next suggestion. | 352 | // Get the next suggestion. |
| 353 | suggested = priority_queue.GetSuggestedNext(core_id, suggested); | 353 | suggested = priority_queue.GetSuggestedNext(cpu_core_id, suggested); |
| 354 | } | 354 | } |
| 355 | } | 355 | } |
| 356 | } | 356 | } |
| @@ -411,7 +411,7 @@ void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) { | |||
| 411 | 411 | ||
| 412 | // Get the current thread and process. | 412 | // Get the current thread and process. |
| 413 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); | 413 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); |
| 414 | Process& cur_process = *kernel.CurrentProcess(); | 414 | KProcess& cur_process = *kernel.CurrentProcess(); |
| 415 | 415 | ||
| 416 | // If the thread's yield count matches, there's nothing for us to do. | 416 | // If the thread's yield count matches, there's nothing for us to do. |
| 417 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { | 417 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { |
| @@ -450,7 +450,7 @@ void KScheduler::YieldWithCoreMigration(KernelCore& kernel) { | |||
| 450 | 450 | ||
| 451 | // Get the current thread and process. | 451 | // Get the current thread and process. |
| 452 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); | 452 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); |
| 453 | Process& cur_process = *kernel.CurrentProcess(); | 453 | KProcess& cur_process = *kernel.CurrentProcess(); |
| 454 | 454 | ||
| 455 | // If the thread's yield count matches, there's nothing for us to do. | 455 | // If the thread's yield count matches, there's nothing for us to do. |
| 456 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { | 456 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { |
| @@ -538,7 +538,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { | |||
| 538 | 538 | ||
| 539 | // Get the current thread and process. | 539 | // Get the current thread and process. |
| 540 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); | 540 | KThread& cur_thread = Kernel::GetCurrentThread(kernel); |
| 541 | Process& cur_process = *kernel.CurrentProcess(); | 541 | KProcess& cur_process = *kernel.CurrentProcess(); |
| 542 | 542 | ||
| 543 | // If the thread's yield count matches, there's nothing for us to do. | 543 | // If the thread's yield count matches, there's nothing for us to do. |
| 544 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { | 544 | if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) { |
| @@ -607,7 +607,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { | |||
| 607 | } | 607 | } |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { | 610 | KScheduler::KScheduler(Core::System& system_, s32 core_id_) : system{system_}, core_id{core_id_} { |
| 611 | switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); | 611 | switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); |
| 612 | state.needs_scheduling.store(true); | 612 | state.needs_scheduling.store(true); |
| 613 | state.interrupt_task_thread_runnable = false; | 613 | state.interrupt_task_thread_runnable = false; |
| @@ -617,7 +617,12 @@ KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core | |||
| 617 | state.highest_priority_thread = nullptr; | 617 | state.highest_priority_thread = nullptr; |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | KScheduler::~KScheduler() = default; | 620 | KScheduler::~KScheduler() { |
| 621 | if (idle_thread) { | ||
| 622 | idle_thread->Close(); | ||
| 623 | idle_thread = nullptr; | ||
| 624 | } | ||
| 625 | } | ||
| 621 | 626 | ||
| 622 | KThread* KScheduler::GetCurrentThread() const { | 627 | KThread* KScheduler::GetCurrentThread() const { |
| 623 | if (auto result = current_thread.load(); result) { | 628 | if (auto result = current_thread.load(); result) { |
| @@ -719,7 +724,7 @@ void KScheduler::ScheduleImpl() { | |||
| 719 | 724 | ||
| 720 | current_thread.store(next_thread); | 725 | current_thread.store(next_thread); |
| 721 | 726 | ||
| 722 | Process* const previous_process = system.Kernel().CurrentProcess(); | 727 | KProcess* const previous_process = system.Kernel().CurrentProcess(); |
| 723 | 728 | ||
| 724 | UpdateLastContextSwitchTime(previous_thread, previous_process); | 729 | UpdateLastContextSwitchTime(previous_thread, previous_process); |
| 725 | 730 | ||
| @@ -775,7 +780,7 @@ void KScheduler::SwitchToCurrent() { | |||
| 775 | } | 780 | } |
| 776 | } | 781 | } |
| 777 | 782 | ||
| 778 | void KScheduler::UpdateLastContextSwitchTime(KThread* thread, Process* process) { | 783 | void KScheduler::UpdateLastContextSwitchTime(KThread* thread, KProcess* process) { |
| 779 | const u64 prev_switch_ticks = last_context_switch_time; | 784 | const u64 prev_switch_ticks = last_context_switch_time; |
| 780 | const u64 most_recent_switch_ticks = system.CoreTiming().GetCPUTicks(); | 785 | const u64 most_recent_switch_ticks = system.CoreTiming().GetCPUTicks(); |
| 781 | const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks; | 786 | const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks; |
| @@ -792,13 +797,9 @@ void KScheduler::UpdateLastContextSwitchTime(KThread* thread, Process* process) | |||
| 792 | } | 797 | } |
| 793 | 798 | ||
| 794 | void KScheduler::Initialize() { | 799 | void KScheduler::Initialize() { |
| 795 | std::string name = "Idle Thread Id:" + std::to_string(core_id); | 800 | idle_thread = KThread::Create(system.Kernel()); |
| 796 | std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc(); | 801 | ASSERT(KThread::InitializeIdleThread(system, idle_thread, core_id).IsSuccess()); |
| 797 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); | 802 | idle_thread->SetName(fmt::format("IdleThread:{}", core_id)); |
| 798 | auto thread_res = KThread::CreateThread( | ||
| 799 | system, ThreadType::Main, name, 0, KThread::IdleThreadPriority, 0, | ||
| 800 | static_cast<u32>(core_id), 0, nullptr, std::move(init_func), init_func_parameter); | ||
| 801 | idle_thread = thread_res.Unwrap().get(); | ||
| 802 | } | 803 | } |
| 803 | 804 | ||
| 804 | KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel) | 805 | KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel) |
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index 8e32865aa..12cfae919 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -24,13 +24,13 @@ class System; | |||
| 24 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | 25 | ||
| 26 | class KernelCore; | 26 | class KernelCore; |
| 27 | class Process; | 27 | class KProcess; |
| 28 | class SchedulerLock; | 28 | class SchedulerLock; |
| 29 | class KThread; | 29 | class KThread; |
| 30 | 30 | ||
| 31 | class KScheduler final { | 31 | class KScheduler final { |
| 32 | public: | 32 | public: |
| 33 | explicit KScheduler(Core::System& system, s32 core_id); | 33 | explicit KScheduler(Core::System& system_, s32 core_id_); |
| 34 | ~KScheduler(); | 34 | ~KScheduler(); |
| 35 | 35 | ||
| 36 | /// Reschedules to the next available thread (call after current thread is suspended) | 36 | /// Reschedules to the next available thread (call after current thread is suspended) |
| @@ -141,7 +141,7 @@ private: | |||
| 141 | 141 | ||
| 142 | [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel); | 142 | [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel); |
| 143 | 143 | ||
| 144 | void RotateScheduledQueue(s32 core_id, s32 priority); | 144 | void RotateScheduledQueue(s32 cpu_core_id, s32 priority); |
| 145 | 145 | ||
| 146 | void Schedule() { | 146 | void Schedule() { |
| 147 | ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); | 147 | ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); |
| @@ -165,7 +165,7 @@ private: | |||
| 165 | * most recent tick count retrieved. No special arithmetic is | 165 | * most recent tick count retrieved. No special arithmetic is |
| 166 | * applied to it. | 166 | * applied to it. |
| 167 | */ | 167 | */ |
| 168 | void UpdateLastContextSwitchTime(KThread* thread, Process* process); | 168 | void UpdateLastContextSwitchTime(KThread* thread, KProcess* process); |
| 169 | 169 | ||
| 170 | static void OnSwitch(void* this_scheduler); | 170 | static void OnSwitch(void* this_scheduler); |
| 171 | void SwitchToCurrent(); | 171 | void SwitchToCurrent(); |
| @@ -173,12 +173,12 @@ private: | |||
| 173 | KThread* prev_thread{}; | 173 | KThread* prev_thread{}; |
| 174 | std::atomic<KThread*> current_thread{}; | 174 | std::atomic<KThread*> current_thread{}; |
| 175 | 175 | ||
| 176 | KThread* idle_thread; | 176 | KThread* idle_thread{}; |
| 177 | 177 | ||
| 178 | std::shared_ptr<Common::Fiber> switch_fiber{}; | 178 | std::shared_ptr<Common::Fiber> switch_fiber{}; |
| 179 | 179 | ||
| 180 | struct SchedulingState { | 180 | struct SchedulingState { |
| 181 | std::atomic<bool> needs_scheduling; | 181 | std::atomic<bool> needs_scheduling{}; |
| 182 | bool interrupt_task_thread_runnable{}; | 182 | bool interrupt_task_thread_runnable{}; |
| 183 | bool should_count_idle{}; | 183 | bool should_count_idle{}; |
| 184 | u64 idle_count{}; | 184 | u64 idle_count{}; |
diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h index c5deca00b..07272075d 100644 --- a/src/core/hle/kernel/k_scoped_resource_reservation.h +++ b/src/core/hle/kernel/k_scoped_resource_reservation.h | |||
| @@ -8,15 +8,14 @@ | |||
| 8 | #pragma once | 8 | #pragma once |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/k_process.h" | ||
| 11 | #include "core/hle/kernel/k_resource_limit.h" | 12 | #include "core/hle/kernel/k_resource_limit.h" |
| 12 | #include "core/hle/kernel/process.h" | ||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | class KScopedResourceReservation { | 16 | class KScopedResourceReservation { |
| 17 | public: | 17 | public: |
| 18 | explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, | 18 | explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) |
| 19 | s64 v, s64 timeout) | ||
| 20 | : resource_limit(std::move(l)), value(v), resource(r) { | 19 | : resource_limit(std::move(l)), value(v), resource(r) { |
| 21 | if (resource_limit && value) { | 20 | if (resource_limit && value) { |
| 22 | success = resource_limit->Reserve(resource, value, timeout); | 21 | success = resource_limit->Reserve(resource, value, timeout); |
| @@ -25,8 +24,7 @@ public: | |||
| 25 | } | 24 | } |
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, | 27 | explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) |
| 29 | s64 v = 1) | ||
| 30 | : resource_limit(std::move(l)), value(v), resource(r) { | 28 | : resource_limit(std::move(l)), value(v), resource(r) { |
| 31 | if (resource_limit && value) { | 29 | if (resource_limit && value) { |
| 32 | success = resource_limit->Reserve(resource, value); | 30 | success = resource_limit->Reserve(resource, value); |
| @@ -35,10 +33,10 @@ public: | |||
| 35 | } | 33 | } |
| 36 | } | 34 | } |
| 37 | 35 | ||
| 38 | explicit KScopedResourceReservation(const Process* p, LimitableResource r, s64 v, s64 t) | 36 | explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v, s64 t) |
| 39 | : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {} | 37 | : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {} |
| 40 | 38 | ||
| 41 | explicit KScopedResourceReservation(const Process* p, LimitableResource r, s64 v = 1) | 39 | explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v = 1) |
| 42 | : KScopedResourceReservation(p->GetResourceLimit(), r, v) {} | 40 | : KScopedResourceReservation(p->GetResourceLimit(), r, v) {} |
| 43 | 41 | ||
| 44 | ~KScopedResourceReservation() noexcept { | 42 | ~KScopedResourceReservation() noexcept { |
| @@ -58,7 +56,7 @@ public: | |||
| 58 | } | 56 | } |
| 59 | 57 | ||
| 60 | private: | 58 | private: |
| 61 | std::shared_ptr<KResourceLimit> resource_limit; | 59 | KResourceLimit* resource_limit{}; |
| 62 | s64 value; | 60 | s64 value; |
| 63 | LimitableResource resource; | 61 | LimitableResource resource; |
| 64 | bool success; | 62 | bool success; |
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index ebecf0c77..a86af56dd 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #pragma once | 8 | #pragma once |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/handle_table.h" | 11 | #include "core/hle/kernel/k_handle_table.h" |
| 12 | #include "core/hle/kernel/k_thread.h" | 12 | #include "core/hle/kernel/k_thread.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/kernel/time_manager.h" | 14 | #include "core/hle/kernel/time_manager.h" |
| @@ -17,8 +17,8 @@ namespace Kernel { | |||
| 17 | 17 | ||
| 18 | class [[nodiscard]] KScopedSchedulerLockAndSleep { | 18 | class [[nodiscard]] KScopedSchedulerLockAndSleep { |
| 19 | public: | 19 | public: |
| 20 | explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout) | 20 | explicit KScopedSchedulerLockAndSleep(KernelCore & kernel_, KThread * t, s64 timeout) |
| 21 | : kernel(kernel), thread(t), timeout_tick(timeout) { | 21 | : kernel(kernel_), thread(t), timeout_tick(timeout) { |
| 22 | // Lock the scheduler. | 22 | // Lock the scheduler. |
| 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); | 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); |
| 24 | } | 24 | } |
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp new file mode 100644 index 000000000..8cbde177a --- /dev/null +++ b/src/core/hle/kernel/k_server_port.cpp | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <tuple> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "core/hle/kernel/k_client_port.h" | ||
| 8 | #include "core/hle/kernel/k_port.h" | ||
| 9 | #include "core/hle/kernel/k_scheduler.h" | ||
| 10 | #include "core/hle/kernel/k_server_port.h" | ||
| 11 | #include "core/hle/kernel/k_server_session.h" | ||
| 12 | #include "core/hle/kernel/k_thread.h" | ||
| 13 | #include "core/hle/kernel/svc_results.h" | ||
| 14 | |||
| 15 | namespace Kernel { | ||
| 16 | |||
| 17 | KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||
| 18 | KServerPort::~KServerPort() = default; | ||
| 19 | |||
| 20 | void KServerPort::Initialize(KPort* parent_, std::string&& name_) { | ||
| 21 | // Set member variables. | ||
| 22 | parent = parent_; | ||
| 23 | name = std::move(name_); | ||
| 24 | } | ||
| 25 | |||
| 26 | bool KServerPort::IsLight() const { | ||
| 27 | return this->GetParent()->IsLight(); | ||
| 28 | } | ||
| 29 | |||
| 30 | void KServerPort::CleanupSessions() { | ||
| 31 | // Ensure our preconditions are met. | ||
| 32 | if (this->IsLight()) { | ||
| 33 | UNIMPLEMENTED(); | ||
| 34 | } | ||
| 35 | |||
| 36 | // Cleanup the session list. | ||
| 37 | while (true) { | ||
| 38 | // Get the last session in the list | ||
| 39 | KServerSession* session = nullptr; | ||
| 40 | { | ||
| 41 | KScopedSchedulerLock sl{kernel}; | ||
| 42 | if (!session_list.empty()) { | ||
| 43 | session = std::addressof(session_list.front()); | ||
| 44 | session_list.pop_front(); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | // Close the session. | ||
| 49 | if (session != nullptr) { | ||
| 50 | session->Close(); | ||
| 51 | } else { | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | void KServerPort::Destroy() { | ||
| 58 | // Note with our parent that we're closed. | ||
| 59 | parent->OnServerClosed(); | ||
| 60 | |||
| 61 | // Perform necessary cleanup of our session lists. | ||
| 62 | this->CleanupSessions(); | ||
| 63 | |||
| 64 | // Close our reference to our parent. | ||
| 65 | parent->Close(); | ||
| 66 | } | ||
| 67 | |||
| 68 | bool KServerPort::IsSignaled() const { | ||
| 69 | if (this->IsLight()) { | ||
| 70 | UNIMPLEMENTED(); | ||
| 71 | return false; | ||
| 72 | } else { | ||
| 73 | return !session_list.empty(); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | void KServerPort::EnqueueSession(KServerSession* session) { | ||
| 78 | ASSERT(!this->IsLight()); | ||
| 79 | |||
| 80 | KScopedSchedulerLock sl{kernel}; | ||
| 81 | |||
| 82 | // Add the session to our queue. | ||
| 83 | session_list.push_back(*session); | ||
| 84 | if (session_list.size() == 1) { | ||
| 85 | this->NotifyAvailable(); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | KServerSession* KServerPort::AcceptSession() { | ||
| 90 | ASSERT(!this->IsLight()); | ||
| 91 | |||
| 92 | KScopedSchedulerLock sl{kernel}; | ||
| 93 | |||
| 94 | // Return the first session in the list. | ||
| 95 | if (session_list.empty()) { | ||
| 96 | return nullptr; | ||
| 97 | } | ||
| 98 | |||
| 99 | KServerSession* session = std::addressof(session_list.front()); | ||
| 100 | session_list.pop_front(); | ||
| 101 | return session; | ||
| 102 | } | ||
| 103 | |||
| 104 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h new file mode 100644 index 000000000..e76792253 --- /dev/null +++ b/src/core/hle/kernel/k_server_port.h | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <utility> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include <boost/intrusive/list.hpp> | ||
| 13 | |||
| 14 | #include "common/common_types.h" | ||
| 15 | #include "core/hle/kernel/k_server_session.h" | ||
| 16 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 17 | #include "core/hle/result.h" | ||
| 18 | |||
| 19 | namespace Kernel { | ||
| 20 | |||
| 21 | class KernelCore; | ||
| 22 | class KPort; | ||
| 23 | class SessionRequestHandler; | ||
| 24 | |||
| 25 | class KServerPort final : public KSynchronizationObject { | ||
| 26 | KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); | ||
| 27 | |||
| 28 | private: | ||
| 29 | using SessionList = boost::intrusive::list<KServerSession>; | ||
| 30 | |||
| 31 | public: | ||
| 32 | explicit KServerPort(KernelCore& kernel_); | ||
| 33 | virtual ~KServerPort() override; | ||
| 34 | |||
| 35 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; | ||
| 36 | |||
| 37 | void Initialize(KPort* parent_, std::string&& name_); | ||
| 38 | |||
| 39 | /// Whether or not this server port has an HLE handler available. | ||
| 40 | bool HasHLEHandler() const { | ||
| 41 | return hle_handler != nullptr; | ||
| 42 | } | ||
| 43 | |||
| 44 | /// Gets the HLE handler for this port. | ||
| 45 | HLEHandler GetHLEHandler() const { | ||
| 46 | return hle_handler; | ||
| 47 | } | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port | ||
| 51 | * will inherit a reference to this handler. | ||
| 52 | */ | ||
| 53 | void SetHleHandler(HLEHandler hle_handler_) { | ||
| 54 | hle_handler = std::move(hle_handler_); | ||
| 55 | } | ||
| 56 | |||
| 57 | void EnqueueSession(KServerSession* pending_session); | ||
| 58 | |||
| 59 | KServerSession* AcceptSession(); | ||
| 60 | |||
| 61 | const KPort* GetParent() const { | ||
| 62 | return parent; | ||
| 63 | } | ||
| 64 | |||
| 65 | bool IsLight() const; | ||
| 66 | |||
| 67 | // Overridden virtual functions. | ||
| 68 | virtual void Destroy() override; | ||
| 69 | virtual bool IsSignaled() const override; | ||
| 70 | |||
| 71 | private: | ||
| 72 | void CleanupSessions(); | ||
| 73 | |||
| 74 | private: | ||
| 75 | SessionList session_list; | ||
| 76 | HLEHandler hle_handler; | ||
| 77 | KPort* parent{}; | ||
| 78 | }; | ||
| 79 | |||
| 80 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 790dbb998..8850d9af5 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -10,49 +10,39 @@ | |||
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "core/core_timing.h" | 11 | #include "core/core_timing.h" |
| 12 | #include "core/hle/ipc_helpers.h" | 12 | #include "core/hle/ipc_helpers.h" |
| 13 | #include "core/hle/kernel/client_port.h" | ||
| 14 | #include "core/hle/kernel/client_session.h" | ||
| 15 | #include "core/hle/kernel/handle_table.h" | ||
| 16 | #include "core/hle/kernel/hle_ipc.h" | 13 | #include "core/hle/kernel/hle_ipc.h" |
| 14 | #include "core/hle/kernel/k_client_port.h" | ||
| 15 | #include "core/hle/kernel/k_handle_table.h" | ||
| 16 | #include "core/hle/kernel/k_process.h" | ||
| 17 | #include "core/hle/kernel/k_scheduler.h" | 17 | #include "core/hle/kernel/k_scheduler.h" |
| 18 | #include "core/hle/kernel/k_server_session.h" | ||
| 19 | #include "core/hle/kernel/k_session.h" | ||
| 18 | #include "core/hle/kernel/k_thread.h" | 20 | #include "core/hle/kernel/k_thread.h" |
| 19 | #include "core/hle/kernel/kernel.h" | 21 | #include "core/hle/kernel/kernel.h" |
| 20 | #include "core/hle/kernel/process.h" | ||
| 21 | #include "core/hle/kernel/server_session.h" | ||
| 22 | #include "core/hle/kernel/session.h" | ||
| 23 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 24 | 23 | ||
| 25 | namespace Kernel { | 24 | namespace Kernel { |
| 26 | 25 | ||
| 27 | ServerSession::ServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 26 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 28 | 27 | ||
| 29 | ServerSession::~ServerSession() { | 28 | KServerSession::~KServerSession() { |
| 30 | kernel.ReleaseServiceThread(service_thread); | 29 | kernel.ReleaseServiceThread(service_thread); |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 33 | ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel, | 32 | void KServerSession::Initialize(KSession* parent_, std::string&& name_) { |
| 34 | std::shared_ptr<Session> parent, | 33 | // Set member variables. |
| 35 | std::string name) { | 34 | parent = parent_; |
| 36 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; | 35 | name = std::move(name_); |
| 37 | 36 | service_thread = kernel.CreateServiceThread(name); | |
| 38 | session->name = std::move(name); | ||
| 39 | session->parent = std::move(parent); | ||
| 40 | session->service_thread = kernel.CreateServiceThread(session->name); | ||
| 41 | |||
| 42 | return MakeResult(std::move(session)); | ||
| 43 | } | 37 | } |
| 44 | 38 | ||
| 45 | bool ServerSession::IsSignaled() const { | 39 | void KServerSession::Destroy() { |
| 46 | // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. | 40 | parent->OnServerClosed(); |
| 47 | if (!parent->Client()) { | ||
| 48 | return true; | ||
| 49 | } | ||
| 50 | 41 | ||
| 51 | // Wait if we have no pending requests, or if we're currently handling a request. | 42 | parent->Close(); |
| 52 | return !pending_requesting_threads.empty() && currently_handling == nullptr; | ||
| 53 | } | 43 | } |
| 54 | 44 | ||
| 55 | void ServerSession::ClientDisconnected() { | 45 | void KServerSession::OnClientClosed() { |
| 56 | // We keep a shared pointer to the hle handler to keep it alive throughout | 46 | // We keep a shared pointer to the hle handler to keep it alive throughout |
| 57 | // the call to ClientDisconnected, as ClientDisconnected invalidates the | 47 | // the call to ClientDisconnected, as ClientDisconnected invalidates the |
| 58 | // hle_handler member itself during the course of the function executing. | 48 | // hle_handler member itself during the course of the function executing. |
| @@ -60,24 +50,31 @@ void ServerSession::ClientDisconnected() { | |||
| 60 | if (handler) { | 50 | if (handler) { |
| 61 | // Note that after this returns, this server session's hle_handler is | 51 | // Note that after this returns, this server session's hle_handler is |
| 62 | // invalidated (set to null). | 52 | // invalidated (set to null). |
| 63 | handler->ClientDisconnected(SharedFrom(this)); | 53 | handler->ClientDisconnected(this); |
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | bool KServerSession::IsSignaled() const { | ||
| 58 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | ||
| 59 | |||
| 60 | // If the client is closed, we're always signaled. | ||
| 61 | if (parent->IsClientClosed()) { | ||
| 62 | return true; | ||
| 64 | } | 63 | } |
| 65 | 64 | ||
| 66 | // Clean up the list of client threads with pending requests, they are unneeded now that the | 65 | // Otherwise, we're signaled if we have a request and aren't handling one. |
| 67 | // client endpoint is closed. | 66 | return false; |
| 68 | pending_requesting_threads.clear(); | ||
| 69 | currently_handling = nullptr; | ||
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | void ServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) { | 69 | void KServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) { |
| 73 | domain_request_handlers.push_back(std::move(handler)); | 70 | domain_request_handlers.push_back(std::move(handler)); |
| 74 | } | 71 | } |
| 75 | 72 | ||
| 76 | std::size_t ServerSession::NumDomainRequestHandlers() const { | 73 | std::size_t KServerSession::NumDomainRequestHandlers() const { |
| 77 | return domain_request_handlers.size(); | 74 | return domain_request_handlers.size(); |
| 78 | } | 75 | } |
| 79 | 76 | ||
| 80 | ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { | 77 | ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { |
| 81 | if (!context.HasDomainMessageHeader()) { | 78 | if (!context.HasDomainMessageHeader()) { |
| 82 | return RESULT_SUCCESS; | 79 | return RESULT_SUCCESS; |
| 83 | } | 80 | } |
| @@ -98,7 +95,7 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con | |||
| 98 | UNREACHABLE(); | 95 | UNREACHABLE(); |
| 99 | return RESULT_SUCCESS; // Ignore error if asserts are off | 96 | return RESULT_SUCCESS; // Ignore error if asserts are off |
| 100 | } | 97 | } |
| 101 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); | 98 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(*this, context); |
| 102 | 99 | ||
| 103 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | 100 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { |
| 104 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | 101 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); |
| @@ -116,23 +113,21 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con | |||
| 116 | return RESULT_SUCCESS; | 113 | return RESULT_SUCCESS; |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 119 | ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<KThread> thread, | 116 | ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { |
| 120 | Core::Memory::Memory& memory) { | ||
| 121 | u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))}; | 117 | u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))}; |
| 122 | auto context = | 118 | auto context = std::make_shared<HLERequestContext>(kernel, memory, this, thread); |
| 123 | std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread)); | ||
| 124 | 119 | ||
| 125 | context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); | 120 | context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); |
| 126 | 121 | ||
| 127 | if (auto strong_ptr = service_thread.lock()) { | 122 | if (auto strong_ptr = service_thread.lock()) { |
| 128 | strong_ptr->QueueSyncRequest(*this, std::move(context)); | 123 | strong_ptr->QueueSyncRequest(*parent, std::move(context)); |
| 129 | return RESULT_SUCCESS; | 124 | return RESULT_SUCCESS; |
| 130 | } | 125 | } |
| 131 | 126 | ||
| 132 | return RESULT_SUCCESS; | 127 | return RESULT_SUCCESS; |
| 133 | } | 128 | } |
| 134 | 129 | ||
| 135 | ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) { | 130 | ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { |
| 136 | ResultCode result = RESULT_SUCCESS; | 131 | ResultCode result = RESULT_SUCCESS; |
| 137 | // If the session has been converted to a domain, handle the domain request | 132 | // If the session has been converted to a domain, handle the domain request |
| 138 | if (IsDomain() && context.HasDomainMessageHeader()) { | 133 | if (IsDomain() && context.HasDomainMessageHeader()) { |
| @@ -140,7 +135,7 @@ ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 140 | // If there is no domain header, the regular session handler is used | 135 | // If there is no domain header, the regular session handler is used |
| 141 | } else if (hle_handler != nullptr) { | 136 | } else if (hle_handler != nullptr) { |
| 142 | // If this ServerSession has an associated HLE handler, forward the request to it. | 137 | // If this ServerSession has an associated HLE handler, forward the request to it. |
| 143 | result = hle_handler->HandleSyncRequest(context); | 138 | result = hle_handler->HandleSyncRequest(*this, context); |
| 144 | } | 139 | } |
| 145 | 140 | ||
| 146 | if (convert_to_domain) { | 141 | if (convert_to_domain) { |
| @@ -161,10 +156,9 @@ ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 161 | return result; | 156 | return result; |
| 162 | } | 157 | } |
| 163 | 158 | ||
| 164 | ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<KThread> thread, | 159 | ResultCode KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, |
| 165 | Core::Memory::Memory& memory, | 160 | Core::Timing::CoreTiming& core_timing) { |
| 166 | Core::Timing::CoreTiming& core_timing) { | 161 | return QueueSyncRequest(thread, memory); |
| 167 | return QueueSyncRequest(std::move(thread), memory); | ||
| 168 | } | 162 | } |
| 169 | 163 | ||
| 170 | } // namespace Kernel | 164 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/k_server_session.h index c42d5ee59..597d76d38 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include <utility> | 9 | #include <utility> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | 11 | ||
| 12 | #include <boost/intrusive/list.hpp> | ||
| 13 | |||
| 12 | #include "common/threadsafe_queue.h" | 14 | #include "common/threadsafe_queue.h" |
| 13 | #include "core/hle/kernel/k_synchronization_object.h" | 15 | #include "core/hle/kernel/k_synchronization_object.h" |
| 14 | #include "core/hle/kernel/service_thread.h" | 16 | #include "core/hle/kernel/service_thread.h" |
| @@ -27,55 +29,35 @@ namespace Kernel { | |||
| 27 | 29 | ||
| 28 | class HLERequestContext; | 30 | class HLERequestContext; |
| 29 | class KernelCore; | 31 | class KernelCore; |
| 30 | class Session; | 32 | class KSession; |
| 31 | class SessionRequestHandler; | 33 | class SessionRequestHandler; |
| 32 | class KThread; | 34 | class KThread; |
| 33 | 35 | ||
| 34 | /** | 36 | class KServerSession final : public KSynchronizationObject, |
| 35 | * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS | 37 | public boost::intrusive::list_base_hook<> { |
| 36 | * primitive for communication between different processes, and are used to implement service calls | 38 | KERNEL_AUTOOBJECT_TRAITS(KServerSession, KSynchronizationObject); |
| 37 | * to the various system services. | 39 | |
| 38 | * | ||
| 39 | * To make a service call, the client must write the command header and parameters to the buffer | ||
| 40 | * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest | ||
| 41 | * SVC call with its ClientSession handle. The kernel will read the command header, using it to | ||
| 42 | * marshall the parameters to the process at the server endpoint of the session. | ||
| 43 | * After the server replies to the request, the response is marshalled back to the caller's | ||
| 44 | * TLS buffer and control is transferred back to it. | ||
| 45 | */ | ||
| 46 | class ServerSession final : public KSynchronizationObject { | ||
| 47 | friend class ServiceThread; | 40 | friend class ServiceThread; |
| 48 | 41 | ||
| 49 | public: | 42 | public: |
| 50 | explicit ServerSession(KernelCore& kernel); | 43 | explicit KServerSession(KernelCore& kernel_); |
| 51 | ~ServerSession() override; | 44 | virtual ~KServerSession() override; |
| 52 | 45 | ||
| 53 | friend class Session; | 46 | virtual void Destroy() override; |
| 54 | 47 | ||
| 55 | static ResultVal<std::shared_ptr<ServerSession>> Create(KernelCore& kernel, | 48 | void Initialize(KSession* parent_, std::string&& name_); |
| 56 | std::shared_ptr<Session> parent, | ||
| 57 | std::string name = "Unknown"); | ||
| 58 | 49 | ||
| 59 | std::string GetTypeName() const override { | 50 | KSession* GetParent() { |
| 60 | return "ServerSession"; | 51 | return parent; |
| 61 | } | 52 | } |
| 62 | 53 | ||
| 63 | std::string GetName() const override { | 54 | const KSession* GetParent() const { |
| 64 | return name; | 55 | return parent; |
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | static constexpr HandleType HANDLE_TYPE = HandleType::ServerSession; | 58 | virtual bool IsSignaled() const override; |
| 68 | HandleType GetHandleType() const override { | ||
| 69 | return HANDLE_TYPE; | ||
| 70 | } | ||
| 71 | 59 | ||
| 72 | Session* GetParent() { | 60 | void OnClientClosed(); |
| 73 | return parent.get(); | ||
| 74 | } | ||
| 75 | |||
| 76 | const Session* GetParent() const { | ||
| 77 | return parent.get(); | ||
| 78 | } | ||
| 79 | 61 | ||
| 80 | /** | 62 | /** |
| 81 | * Sets the HLE handler for the session. This handler will be called to service IPC requests | 63 | * Sets the HLE handler for the session. This handler will be called to service IPC requests |
| @@ -95,12 +77,9 @@ public: | |||
| 95 | * | 77 | * |
| 96 | * @returns ResultCode from the operation. | 78 | * @returns ResultCode from the operation. |
| 97 | */ | 79 | */ |
| 98 | ResultCode HandleSyncRequest(std::shared_ptr<KThread> thread, Core::Memory::Memory& memory, | 80 | ResultCode HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, |
| 99 | Core::Timing::CoreTiming& core_timing); | 81 | Core::Timing::CoreTiming& core_timing); |
| 100 | 82 | ||
| 101 | /// Called when a client disconnection occurs. | ||
| 102 | void ClientDisconnected(); | ||
| 103 | |||
| 104 | /// Adds a new domain request handler to the collection of request handlers within | 83 | /// Adds a new domain request handler to the collection of request handlers within |
| 105 | /// this ServerSession instance. | 84 | /// this ServerSession instance. |
| 106 | void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler); | 85 | void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler); |
| @@ -124,13 +103,9 @@ public: | |||
| 124 | convert_to_domain = true; | 103 | convert_to_domain = true; |
| 125 | } | 104 | } |
| 126 | 105 | ||
| 127 | bool IsSignaled() const override; | ||
| 128 | |||
| 129 | void Finalize() override {} | ||
| 130 | |||
| 131 | private: | 106 | private: |
| 132 | /// Queues a sync request from the emulated application. | 107 | /// Queues a sync request from the emulated application. |
| 133 | ResultCode QueueSyncRequest(std::shared_ptr<KThread> thread, Core::Memory::Memory& memory); | 108 | ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); |
| 134 | 109 | ||
| 135 | /// Completes a sync request from the emulated application. | 110 | /// Completes a sync request from the emulated application. |
| 136 | ResultCode CompleteSyncRequest(HLERequestContext& context); | 111 | ResultCode CompleteSyncRequest(HLERequestContext& context); |
| @@ -139,33 +114,20 @@ private: | |||
| 139 | /// object handle. | 114 | /// object handle. |
| 140 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); | 115 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); |
| 141 | 116 | ||
| 142 | /// The parent session, which links to the client endpoint. | ||
| 143 | std::shared_ptr<Session> parent; | ||
| 144 | |||
| 145 | /// This session's HLE request handler (applicable when not a domain) | 117 | /// This session's HLE request handler (applicable when not a domain) |
| 146 | std::shared_ptr<SessionRequestHandler> hle_handler; | 118 | std::shared_ptr<SessionRequestHandler> hle_handler; |
| 147 | 119 | ||
| 148 | /// This is the list of domain request handlers (after conversion to a domain) | 120 | /// This is the list of domain request handlers (after conversion to a domain) |
| 149 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | 121 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; |
| 150 | 122 | ||
| 151 | /// List of threads that are pending a response after a sync request. This list is processed in | ||
| 152 | /// a LIFO manner, thus, the last request will be dispatched first. | ||
| 153 | /// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test. | ||
| 154 | std::vector<std::shared_ptr<KThread>> pending_requesting_threads; | ||
| 155 | |||
| 156 | /// Thread whose request is currently being handled. A request is considered "handled" when a | ||
| 157 | /// response is sent via svcReplyAndReceive. | ||
| 158 | /// TODO(Subv): Find a better name for this. | ||
| 159 | std::shared_ptr<KThread> currently_handling; | ||
| 160 | |||
| 161 | /// When set to True, converts the session to a domain at the end of the command | 123 | /// When set to True, converts the session to a domain at the end of the command |
| 162 | bool convert_to_domain{}; | 124 | bool convert_to_domain{}; |
| 163 | 125 | ||
| 164 | /// The name of this session (optional) | ||
| 165 | std::string name; | ||
| 166 | |||
| 167 | /// Thread to dispatch service requests | 126 | /// Thread to dispatch service requests |
| 168 | std::weak_ptr<ServiceThread> service_thread; | 127 | std::weak_ptr<ServiceThread> service_thread; |
| 128 | |||
| 129 | /// KSession that owns this KServerSession | ||
| 130 | KSession* parent{}; | ||
| 169 | }; | 131 | }; |
| 170 | 132 | ||
| 171 | } // namespace Kernel | 133 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp new file mode 100644 index 000000000..b7ce27a0b --- /dev/null +++ b/src/core/hle/kernel/k_session.cpp | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "core/hle/kernel/k_client_port.h" | ||
| 7 | #include "core/hle/kernel/k_client_session.h" | ||
| 8 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 9 | #include "core/hle/kernel/k_server_session.h" | ||
| 10 | #include "core/hle/kernel/k_session.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | KSession::KSession(KernelCore& kernel_) | ||
| 15 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} | ||
| 16 | KSession::~KSession() = default; | ||
| 17 | |||
| 18 | void KSession::Initialize(KClientPort* port_, const std::string& name_) { | ||
| 19 | // Increment reference count. | ||
| 20 | // Because reference count is one on creation, this will result | ||
| 21 | // in a reference count of two. Thus, when both server and client are closed | ||
| 22 | // this object will be destroyed. | ||
| 23 | Open(); | ||
| 24 | |||
| 25 | // Create our sub sessions. | ||
| 26 | KAutoObject::Create(std::addressof(server)); | ||
| 27 | KAutoObject::Create(std::addressof(client)); | ||
| 28 | |||
| 29 | // Initialize our sub sessions. | ||
| 30 | server.Initialize(this, name_ + ":Server"); | ||
| 31 | client.Initialize(this, name_ + ":Client"); | ||
| 32 | |||
| 33 | // Set state and name. | ||
| 34 | SetState(State::Normal); | ||
| 35 | name = name_; | ||
| 36 | |||
| 37 | // Set our owner process. | ||
| 38 | process = kernel.CurrentProcess(); | ||
| 39 | process->Open(); | ||
| 40 | |||
| 41 | // Set our port. | ||
| 42 | port = port_; | ||
| 43 | if (port != nullptr) { | ||
| 44 | port->Open(); | ||
| 45 | } | ||
| 46 | |||
| 47 | // Mark initialized. | ||
| 48 | initialized = true; | ||
| 49 | } | ||
| 50 | |||
| 51 | void KSession::Finalize() { | ||
| 52 | if (port == nullptr) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | port->OnSessionFinalized(); | ||
| 57 | port->Close(); | ||
| 58 | } | ||
| 59 | |||
| 60 | void KSession::OnServerClosed() { | ||
| 61 | if (GetState() != State::Normal) { | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 65 | SetState(State::ServerClosed); | ||
| 66 | client.OnServerClosed(); | ||
| 67 | } | ||
| 68 | |||
| 69 | void KSession::OnClientClosed() { | ||
| 70 | if (GetState() != State::Normal) { | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | |||
| 74 | SetState(State::ClientClosed); | ||
| 75 | server.OnClientClosed(); | ||
| 76 | } | ||
| 77 | |||
| 78 | void KSession::PostDestroy(uintptr_t arg) { | ||
| 79 | // Release the session count resource the owner process holds. | ||
| 80 | KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||
| 81 | // owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); | ||
| 82 | owner->Close(); | ||
| 83 | } | ||
| 84 | |||
| 85 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h new file mode 100644 index 000000000..16901e19c --- /dev/null +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | #include <string> | ||
| 9 | |||
| 10 | #include "core/hle/kernel/k_client_session.h" | ||
| 11 | #include "core/hle/kernel/k_server_session.h" | ||
| 12 | #include "core/hle/kernel/slab_helpers.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> { | ||
| 17 | KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); | ||
| 18 | |||
| 19 | public: | ||
| 20 | explicit KSession(KernelCore& kernel_); | ||
| 21 | virtual ~KSession() override; | ||
| 22 | |||
| 23 | void Initialize(KClientPort* port_, const std::string& name_); | ||
| 24 | |||
| 25 | virtual void Finalize() override; | ||
| 26 | |||
| 27 | virtual bool IsInitialized() const override { | ||
| 28 | return initialized; | ||
| 29 | } | ||
| 30 | |||
| 31 | virtual uintptr_t GetPostDestroyArgument() const override { | ||
| 32 | return reinterpret_cast<uintptr_t>(process); | ||
| 33 | } | ||
| 34 | |||
| 35 | static void PostDestroy(uintptr_t arg); | ||
| 36 | |||
| 37 | void OnServerClosed(); | ||
| 38 | |||
| 39 | void OnClientClosed(); | ||
| 40 | |||
| 41 | bool IsServerClosed() const { | ||
| 42 | return this->GetState() != State::Normal; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool IsClientClosed() const { | ||
| 46 | return this->GetState() != State::Normal; | ||
| 47 | } | ||
| 48 | |||
| 49 | KClientSession& GetClientSession() { | ||
| 50 | return client; | ||
| 51 | } | ||
| 52 | |||
| 53 | KServerSession& GetServerSession() { | ||
| 54 | return server; | ||
| 55 | } | ||
| 56 | |||
| 57 | const KClientSession& GetClientSession() const { | ||
| 58 | return client; | ||
| 59 | } | ||
| 60 | |||
| 61 | const KServerSession& GetServerSession() const { | ||
| 62 | return server; | ||
| 63 | } | ||
| 64 | |||
| 65 | const KClientPort* GetParent() const { | ||
| 66 | return port; | ||
| 67 | } | ||
| 68 | |||
| 69 | private: | ||
| 70 | enum class State : u8 { | ||
| 71 | Invalid = 0, | ||
| 72 | Normal = 1, | ||
| 73 | ClientClosed = 2, | ||
| 74 | ServerClosed = 3, | ||
| 75 | }; | ||
| 76 | |||
| 77 | private: | ||
| 78 | void SetState(State state) { | ||
| 79 | atomic_state = static_cast<u8>(state); | ||
| 80 | } | ||
| 81 | |||
| 82 | State GetState() const { | ||
| 83 | return static_cast<State>(atomic_state.load(std::memory_order_relaxed)); | ||
| 84 | } | ||
| 85 | |||
| 86 | private: | ||
| 87 | KServerSession server; | ||
| 88 | KClientSession client; | ||
| 89 | std::atomic<std::underlying_type_t<State>> atomic_state{ | ||
| 90 | static_cast<std::underlying_type_t<State>>(State::Invalid)}; | ||
| 91 | KClientPort* port{}; | ||
| 92 | KProcess* process{}; | ||
| 93 | bool initialized{}; | ||
| 94 | }; | ||
| 95 | |||
| 96 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 9b14f42b5..7770b1868 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp | |||
| @@ -8,50 +8,74 @@ | |||
| 8 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 8 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 9 | #include "core/hle/kernel/k_shared_memory.h" | 9 | #include "core/hle/kernel/k_shared_memory.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/svc_results.h" | ||
| 11 | 12 | ||
| 12 | namespace Kernel { | 13 | namespace Kernel { |
| 13 | 14 | ||
| 14 | KSharedMemory::KSharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) | 15 | KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 15 | : Object{kernel}, device_memory{device_memory} {} | ||
| 16 | 16 | ||
| 17 | KSharedMemory::~KSharedMemory() { | 17 | KSharedMemory::~KSharedMemory() { |
| 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | std::shared_ptr<KSharedMemory> KSharedMemory::Create( | 21 | ResultCode KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, |
| 22 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, | 22 | KPageLinkedList&& page_list_, |
| 23 | KPageLinkedList&& page_list, KMemoryPermission owner_permission, | 23 | Svc::MemoryPermission owner_permission_, |
| 24 | KMemoryPermission user_permission, PAddr physical_address, std::size_t size, std::string name) { | 24 | Svc::MemoryPermission user_permission_, |
| 25 | PAddr physical_address_, std::size_t size_, | ||
| 26 | std::string name_) { | ||
| 27 | // Set members. | ||
| 28 | owner_process = owner_process_; | ||
| 29 | device_memory = &device_memory_; | ||
| 30 | page_list = std::move(page_list_); | ||
| 31 | owner_permission = owner_permission_; | ||
| 32 | user_permission = user_permission_; | ||
| 33 | physical_address = physical_address_; | ||
| 34 | size = size_; | ||
| 35 | name = std::move(name_); | ||
| 25 | 36 | ||
| 26 | const auto resource_limit = kernel.GetSystemResourceLimit(); | 37 | // Get the resource limit. |
| 27 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 38 | KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); |
| 28 | size); | ||
| 29 | ASSERT(memory_reservation.Succeeded()); | ||
| 30 | 39 | ||
| 31 | std::shared_ptr<KSharedMemory> shared_memory{ | 40 | // Reserve memory for ourselves. |
| 32 | std::make_shared<KSharedMemory>(kernel, device_memory)}; | 41 | KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, |
| 33 | 42 | size_); | |
| 34 | shared_memory->owner_process = owner_process; | 43 | R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); |
| 35 | shared_memory->page_list = std::move(page_list); | ||
| 36 | shared_memory->owner_permission = owner_permission; | ||
| 37 | shared_memory->user_permission = user_permission; | ||
| 38 | shared_memory->physical_address = physical_address; | ||
| 39 | shared_memory->size = size; | ||
| 40 | shared_memory->name = name; | ||
| 41 | 44 | ||
| 45 | // Commit our reservation. | ||
| 42 | memory_reservation.Commit(); | 46 | memory_reservation.Commit(); |
| 43 | return shared_memory; | 47 | |
| 48 | // Set our resource limit. | ||
| 49 | resource_limit = reslimit; | ||
| 50 | resource_limit->Open(); | ||
| 51 | |||
| 52 | // Mark initialized. | ||
| 53 | is_initialized = true; | ||
| 54 | |||
| 55 | // Clear all pages in the memory. | ||
| 56 | std::memset(device_memory_.GetPointer(physical_address_), 0, size_); | ||
| 57 | |||
| 58 | return RESULT_SUCCESS; | ||
| 59 | } | ||
| 60 | |||
| 61 | void KSharedMemory::Finalize() { | ||
| 62 | // Release the memory reservation. | ||
| 63 | resource_limit->Release(LimitableResource::PhysicalMemory, size); | ||
| 64 | resource_limit->Close(); | ||
| 65 | |||
| 66 | // Perform inherited finalization. | ||
| 67 | KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize(); | ||
| 44 | } | 68 | } |
| 45 | 69 | ||
| 46 | ResultCode KSharedMemory::Map(Process& target_process, VAddr address, std::size_t size, | 70 | ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, |
| 47 | KMemoryPermission permissions) { | 71 | Svc::MemoryPermission permissions) { |
| 48 | const u64 page_count{(size + PageSize - 1) / PageSize}; | 72 | const u64 page_count{(map_size + PageSize - 1) / PageSize}; |
| 49 | 73 | ||
| 50 | if (page_list.GetNumPages() != page_count) { | 74 | if (page_list.GetNumPages() != page_count) { |
| 51 | UNIMPLEMENTED_MSG("Page count does not match"); | 75 | UNIMPLEMENTED_MSG("Page count does not match"); |
| 52 | } | 76 | } |
| 53 | 77 | ||
| 54 | const KMemoryPermission expected = | 78 | const Svc::MemoryPermission expected = |
| 55 | &target_process == owner_process ? owner_permission : user_permission; | 79 | &target_process == owner_process ? owner_permission : user_permission; |
| 56 | 80 | ||
| 57 | if (permissions != expected) { | 81 | if (permissions != expected) { |
| @@ -59,7 +83,17 @@ ResultCode KSharedMemory::Map(Process& target_process, VAddr address, std::size_ | |||
| 59 | } | 83 | } |
| 60 | 84 | ||
| 61 | return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared, | 85 | return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared, |
| 62 | permissions); | 86 | ConvertToKMemoryPermission(permissions)); |
| 87 | } | ||
| 88 | |||
| 89 | ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { | ||
| 90 | const u64 page_count{(unmap_size + PageSize - 1) / PageSize}; | ||
| 91 | |||
| 92 | if (page_list.GetNumPages() != page_count) { | ||
| 93 | UNIMPLEMENTED_MSG("Page count does not match"); | ||
| 94 | } | ||
| 95 | |||
| 96 | return target_process.PageTable().UnmapPages(address, page_list, KMemoryState::Shared); | ||
| 63 | } | 97 | } |
| 64 | 98 | ||
| 65 | } // namespace Kernel | 99 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 016e34be5..553a56327 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h | |||
| @@ -11,47 +11,44 @@ | |||
| 11 | #include "core/device_memory.h" | 11 | #include "core/device_memory.h" |
| 12 | #include "core/hle/kernel/k_memory_block.h" | 12 | #include "core/hle/kernel/k_memory_block.h" |
| 13 | #include "core/hle/kernel/k_page_linked_list.h" | 13 | #include "core/hle/kernel/k_page_linked_list.h" |
| 14 | #include "core/hle/kernel/object.h" | 14 | #include "core/hle/kernel/k_process.h" |
| 15 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/slab_helpers.h" |
| 16 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| 17 | 17 | ||
| 18 | namespace Kernel { | 18 | namespace Kernel { |
| 19 | 19 | ||
| 20 | class KernelCore; | 20 | class KernelCore; |
| 21 | 21 | ||
| 22 | class KSharedMemory final : public Object { | 22 | class KSharedMemory final |
| 23 | : public KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList> { | ||
| 24 | KERNEL_AUTOOBJECT_TRAITS(KSharedMemory, KAutoObject); | ||
| 25 | |||
| 23 | public: | 26 | public: |
| 24 | explicit KSharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory); | 27 | explicit KSharedMemory(KernelCore& kernel_); |
| 25 | ~KSharedMemory() override; | 28 | ~KSharedMemory() override; |
| 26 | 29 | ||
| 27 | static std::shared_ptr<KSharedMemory> Create( | 30 | ResultCode Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, |
| 28 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, | 31 | KPageLinkedList&& page_list_, Svc::MemoryPermission owner_permission_, |
| 29 | KPageLinkedList&& page_list, KMemoryPermission owner_permission, | 32 | Svc::MemoryPermission user_permission_, PAddr physical_address_, |
| 30 | KMemoryPermission user_permission, PAddr physical_address, std::size_t size, | 33 | std::size_t size_, std::string name_); |
| 31 | std::string name); | ||
| 32 | |||
| 33 | std::string GetTypeName() const override { | ||
| 34 | return "SharedMemory"; | ||
| 35 | } | ||
| 36 | |||
| 37 | std::string GetName() const override { | ||
| 38 | return name; | ||
| 39 | } | ||
| 40 | |||
| 41 | static constexpr HandleType HANDLE_TYPE = HandleType::SharedMemory; | ||
| 42 | HandleType GetHandleType() const override { | ||
| 43 | return HANDLE_TYPE; | ||
| 44 | } | ||
| 45 | 34 | ||
| 46 | /** | 35 | /** |
| 47 | * Maps a shared memory block to an address in the target process' address space | 36 | * Maps a shared memory block to an address in the target process' address space |
| 48 | * @param target_process Process on which to map the memory block | 37 | * @param target_process Process on which to map the memory block |
| 49 | * @param address Address in system memory to map shared memory block to | 38 | * @param address Address in system memory to map shared memory block to |
| 50 | * @param size Size of the shared memory block to map | 39 | * @param map_size Size of the shared memory block to map |
| 51 | * @param permissions Memory block map permissions (specified by SVC field) | 40 | * @param permissions Memory block map permissions (specified by SVC field) |
| 52 | */ | 41 | */ |
| 53 | ResultCode Map(Process& target_process, VAddr address, std::size_t size, | 42 | ResultCode Map(KProcess& target_process, VAddr address, std::size_t map_size, |
| 54 | KMemoryPermission permissions); | 43 | Svc::MemoryPermission permissions); |
| 44 | |||
| 45 | /** | ||
| 46 | * Unmaps a shared memory block from an address in the target process' address space | ||
| 47 | * @param target_process Process on which to unmap the memory block | ||
| 48 | * @param address Address in system memory to unmap shared memory block | ||
| 49 | * @param unmap_size Size of the shared memory block to unmap | ||
| 50 | */ | ||
| 51 | ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size); | ||
| 55 | 52 | ||
| 56 | /** | 53 | /** |
| 57 | * Gets a pointer to the shared memory block | 54 | * Gets a pointer to the shared memory block |
| @@ -59,7 +56,7 @@ public: | |||
| 59 | * @return A pointer to the shared memory block from the specified offset | 56 | * @return A pointer to the shared memory block from the specified offset |
| 60 | */ | 57 | */ |
| 61 | u8* GetPointer(std::size_t offset = 0) { | 58 | u8* GetPointer(std::size_t offset = 0) { |
| 62 | return device_memory.GetPointer(physical_address + offset); | 59 | return device_memory->GetPointer(physical_address + offset); |
| 63 | } | 60 | } |
| 64 | 61 | ||
| 65 | /** | 62 | /** |
| @@ -68,20 +65,26 @@ public: | |||
| 68 | * @return A pointer to the shared memory block from the specified offset | 65 | * @return A pointer to the shared memory block from the specified offset |
| 69 | */ | 66 | */ |
| 70 | const u8* GetPointer(std::size_t offset = 0) const { | 67 | const u8* GetPointer(std::size_t offset = 0) const { |
| 71 | return device_memory.GetPointer(physical_address + offset); | 68 | return device_memory->GetPointer(physical_address + offset); |
| 72 | } | 69 | } |
| 73 | 70 | ||
| 74 | void Finalize() override {} | 71 | virtual void Finalize() override; |
| 72 | |||
| 73 | virtual bool IsInitialized() const override { | ||
| 74 | return is_initialized; | ||
| 75 | } | ||
| 76 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||
| 75 | 77 | ||
| 76 | private: | 78 | private: |
| 77 | Core::DeviceMemory& device_memory; | 79 | Core::DeviceMemory* device_memory; |
| 78 | Process* owner_process{}; | 80 | KProcess* owner_process{}; |
| 79 | KPageLinkedList page_list; | 81 | KPageLinkedList page_list; |
| 80 | KMemoryPermission owner_permission{}; | 82 | Svc::MemoryPermission owner_permission{}; |
| 81 | KMemoryPermission user_permission{}; | 83 | Svc::MemoryPermission user_permission{}; |
| 82 | PAddr physical_address{}; | 84 | PAddr physical_address{}; |
| 83 | std::size_t size{}; | 85 | std::size_t size{}; |
| 84 | std::string name; | 86 | KResourceLimit* resource_limit{}; |
| 87 | bool is_initialized{}; | ||
| 85 | }; | 88 | }; |
| 86 | 89 | ||
| 87 | } // namespace Kernel | 90 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index aa4471d2f..5ce9a1d7c 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h | |||
| @@ -97,6 +97,7 @@ public: | |||
| 97 | void FreeImpl(void* obj) { | 97 | void FreeImpl(void* obj) { |
| 98 | // Don't allow freeing an object that wasn't allocated from this heap | 98 | // Don't allow freeing an object that wasn't allocated from this heap |
| 99 | ASSERT(Contains(reinterpret_cast<uintptr_t>(obj))); | 99 | ASSERT(Contains(reinterpret_cast<uintptr_t>(obj))); |
| 100 | |||
| 100 | impl.Free(obj); | 101 | impl.Free(obj); |
| 101 | } | 102 | } |
| 102 | 103 | ||
| @@ -148,6 +149,14 @@ public: | |||
| 148 | return obj; | 149 | return obj; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 152 | T* AllocateWithKernel(KernelCore& kernel) { | ||
| 153 | T* obj = static_cast<T*>(AllocateImpl()); | ||
| 154 | if (obj != nullptr) { | ||
| 155 | new (obj) T(kernel); | ||
| 156 | } | ||
| 157 | return obj; | ||
| 158 | } | ||
| 159 | |||
| 151 | void Free(T* obj) { | 160 | void Free(T* obj) { |
| 152 | FreeImpl(obj); | 161 | FreeImpl(obj); |
| 153 | } | 162 | } |
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 82f72a0fe..45380dea0 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp | |||
| @@ -13,18 +13,23 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | 16 | void KSynchronizationObject::Finalize() { |
| 17 | this->OnFinalizeSynchronizationObject(); | ||
| 18 | KAutoObject::Finalize(); | ||
| 19 | } | ||
| 20 | |||
| 21 | ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, | ||
| 17 | KSynchronizationObject** objects, const s32 num_objects, | 22 | KSynchronizationObject** objects, const s32 num_objects, |
| 18 | s64 timeout) { | 23 | s64 timeout) { |
| 19 | // Allocate space on stack for thread nodes. | 24 | // Allocate space on stack for thread nodes. |
| 20 | std::vector<ThreadListNode> thread_nodes(num_objects); | 25 | std::vector<ThreadListNode> thread_nodes(num_objects); |
| 21 | 26 | ||
| 22 | // Prepare for wait. | 27 | // Prepare for wait. |
| 23 | KThread* thread = kernel.CurrentScheduler()->GetCurrentThread(); | 28 | KThread* thread = kernel_ctx.CurrentScheduler()->GetCurrentThread(); |
| 24 | 29 | ||
| 25 | { | 30 | { |
| 26 | // Setup the scheduling lock and sleep. | 31 | // Setup the scheduling lock and sleep. |
| 27 | KScopedSchedulerLockAndSleep slp{kernel, thread, timeout}; | 32 | KScopedSchedulerLockAndSleep slp{kernel_ctx, thread, timeout}; |
| 28 | 33 | ||
| 29 | // Check if any of the objects are already signaled. | 34 | // Check if any of the objects are already signaled. |
| 30 | for (auto i = 0; i < num_objects; ++i) { | 35 | for (auto i = 0; i < num_objects; ++i) { |
| @@ -89,13 +94,13 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | |||
| 89 | thread->SetWaitObjectsForDebugging({}); | 94 | thread->SetWaitObjectsForDebugging({}); |
| 90 | 95 | ||
| 91 | // Cancel the timer as needed. | 96 | // Cancel the timer as needed. |
| 92 | kernel.TimeManager().UnscheduleTimeEvent(thread); | 97 | kernel_ctx.TimeManager().UnscheduleTimeEvent(thread); |
| 93 | 98 | ||
| 94 | // Get the wait result. | 99 | // Get the wait result. |
| 95 | ResultCode wait_result{RESULT_SUCCESS}; | 100 | ResultCode wait_result{RESULT_SUCCESS}; |
| 96 | s32 sync_index = -1; | 101 | s32 sync_index = -1; |
| 97 | { | 102 | { |
| 98 | KScopedSchedulerLock lock(kernel); | 103 | KScopedSchedulerLock lock(kernel_ctx); |
| 99 | KSynchronizationObject* synced_obj; | 104 | KSynchronizationObject* synced_obj; |
| 100 | wait_result = thread->GetWaitResult(std::addressof(synced_obj)); | 105 | wait_result = thread->GetWaitResult(std::addressof(synced_obj)); |
| 101 | 106 | ||
| @@ -130,10 +135,8 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | |||
| 130 | return wait_result; | 135 | return wait_result; |
| 131 | } | 136 | } |
| 132 | 137 | ||
| 133 | KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {} | 138 | KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_) |
| 134 | 139 | : KAutoObjectWithList{kernel_} {} | |
| 135 | KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name) | ||
| 136 | : Object{kernel, std::move(name)} {} | ||
| 137 | 140 | ||
| 138 | KSynchronizationObject::~KSynchronizationObject() = default; | 141 | KSynchronizationObject::~KSynchronizationObject() = default; |
| 139 | 142 | ||
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index 5803718fd..a41dd1220 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "core/hle/kernel/object.h" | 9 | #include "core/hle/kernel/k_auto_object.h" |
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 11 | 11 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| @@ -16,7 +16,9 @@ class Synchronization; | |||
| 16 | class KThread; | 16 | class KThread; |
| 17 | 17 | ||
| 18 | /// Class that represents a Kernel object that a thread can be waiting on | 18 | /// Class that represents a Kernel object that a thread can be waiting on |
| 19 | class KSynchronizationObject : public Object { | 19 | class KSynchronizationObject : public KAutoObjectWithList { |
| 20 | KERNEL_AUTOOBJECT_TRAITS(KSynchronizationObject, KAutoObject); | ||
| 21 | |||
| 20 | public: | 22 | public: |
| 21 | struct ThreadListNode { | 23 | struct ThreadListNode { |
| 22 | ThreadListNode* next{}; | 24 | ThreadListNode* next{}; |
| @@ -27,15 +29,18 @@ public: | |||
| 27 | KSynchronizationObject** objects, const s32 num_objects, | 29 | KSynchronizationObject** objects, const s32 num_objects, |
| 28 | s64 timeout); | 30 | s64 timeout); |
| 29 | 31 | ||
| 32 | virtual void Finalize() override; | ||
| 33 | |||
| 30 | [[nodiscard]] virtual bool IsSignaled() const = 0; | 34 | [[nodiscard]] virtual bool IsSignaled() const = 0; |
| 31 | 35 | ||
| 32 | [[nodiscard]] std::vector<KThread*> GetWaitingThreadsForDebugging() const; | 36 | [[nodiscard]] std::vector<KThread*> GetWaitingThreadsForDebugging() const; |
| 33 | 37 | ||
| 34 | protected: | 38 | protected: |
| 35 | explicit KSynchronizationObject(KernelCore& kernel); | 39 | explicit KSynchronizationObject(KernelCore& kernel); |
| 36 | explicit KSynchronizationObject(KernelCore& kernel, std::string&& name); | ||
| 37 | virtual ~KSynchronizationObject(); | 40 | virtual ~KSynchronizationObject(); |
| 38 | 41 | ||
| 42 | virtual void OnFinalizeSynchronizationObject() {} | ||
| 43 | |||
| 39 | void NotifyAvailable(ResultCode result); | 44 | void NotifyAvailable(ResultCode result); |
| 40 | void NotifyAvailable() { | 45 | void NotifyAvailable() { |
| 41 | return this->NotifyAvailable(RESULT_SUCCESS); | 46 | return this->NotifyAvailable(RESULT_SUCCESS); |
| @@ -46,14 +51,4 @@ private: | |||
| 46 | ThreadListNode* thread_list_tail{}; | 51 | ThreadListNode* thread_list_tail{}; |
| 47 | }; | 52 | }; |
| 48 | 53 | ||
| 49 | // Specialization of DynamicObjectCast for KSynchronizationObjects | ||
| 50 | template <> | ||
| 51 | inline std::shared_ptr<KSynchronizationObject> DynamicObjectCast<KSynchronizationObject>( | ||
| 52 | std::shared_ptr<Object> object) { | ||
| 53 | if (object != nullptr && object->IsWaitable()) { | ||
| 54 | return std::static_pointer_cast<KSynchronizationObject>(object); | ||
| 55 | } | ||
| 56 | return nullptr; | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Kernel | 54 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e0f53287c..e3f08f256 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -18,17 +18,16 @@ | |||
| 18 | #include "core/core.h" | 18 | #include "core/core.h" |
| 19 | #include "core/cpu_manager.h" | 19 | #include "core/cpu_manager.h" |
| 20 | #include "core/hardware_properties.h" | 20 | #include "core/hardware_properties.h" |
| 21 | #include "core/hle/kernel/handle_table.h" | ||
| 22 | #include "core/hle/kernel/k_condition_variable.h" | 21 | #include "core/hle/kernel/k_condition_variable.h" |
| 22 | #include "core/hle/kernel/k_handle_table.h" | ||
| 23 | #include "core/hle/kernel/k_memory_layout.h" | 23 | #include "core/hle/kernel/k_memory_layout.h" |
| 24 | #include "core/hle/kernel/k_process.h" | ||
| 24 | #include "core/hle/kernel/k_resource_limit.h" | 25 | #include "core/hle/kernel/k_resource_limit.h" |
| 25 | #include "core/hle/kernel/k_scheduler.h" | 26 | #include "core/hle/kernel/k_scheduler.h" |
| 26 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 27 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 27 | #include "core/hle/kernel/k_thread.h" | 28 | #include "core/hle/kernel/k_thread.h" |
| 28 | #include "core/hle/kernel/k_thread_queue.h" | 29 | #include "core/hle/kernel/k_thread_queue.h" |
| 29 | #include "core/hle/kernel/kernel.h" | 30 | #include "core/hle/kernel/kernel.h" |
| 30 | #include "core/hle/kernel/object.h" | ||
| 31 | #include "core/hle/kernel/process.h" | ||
| 32 | #include "core/hle/kernel/svc_results.h" | 31 | #include "core/hle/kernel/svc_results.h" |
| 33 | #include "core/hle/kernel/time_manager.h" | 32 | #include "core/hle/kernel/time_manager.h" |
| 34 | #include "core/hle/result.h" | 33 | #include "core/hle/result.h" |
| @@ -61,12 +60,12 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, | |||
| 61 | 60 | ||
| 62 | namespace Kernel { | 61 | namespace Kernel { |
| 63 | 62 | ||
| 64 | KThread::KThread(KernelCore& kernel) | 63 | KThread::KThread(KernelCore& kernel_) |
| 65 | : KSynchronizationObject{kernel}, activity_pause_lock{kernel} {} | 64 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {} |
| 66 | KThread::~KThread() = default; | 65 | KThread::~KThread() = default; |
| 67 | 66 | ||
| 68 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, | 67 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, |
| 69 | s32 virt_core, Process* owner, ThreadType type) { | 68 | s32 virt_core, KProcess* owner, ThreadType type) { |
| 70 | // Assert parameters are valid. | 69 | // Assert parameters are valid. |
| 71 | ASSERT((type == ThreadType::Main) || | 70 | ASSERT((type == ThreadType::Main) || |
| 72 | (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); | 71 | (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); |
| @@ -177,6 +176,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s | |||
| 177 | // Set parent, if relevant. | 176 | // Set parent, if relevant. |
| 178 | if (owner != nullptr) { | 177 | if (owner != nullptr) { |
| 179 | parent = owner; | 178 | parent = owner; |
| 179 | parent->Open(); | ||
| 180 | parent->IncrementThreadCount(); | 180 | parent->IncrementThreadCount(); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| @@ -209,14 +209,56 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s | |||
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, | 211 | ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, |
| 212 | VAddr user_stack_top, s32 prio, s32 core, Process* owner, | 212 | VAddr user_stack_top, s32 prio, s32 core, KProcess* owner, |
| 213 | ThreadType type) { | 213 | ThreadType type, std::function<void(void*)>&& init_func, |
| 214 | void* init_func_parameter) { | ||
| 214 | // Initialize the thread. | 215 | // Initialize the thread. |
| 215 | R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); | 216 | R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); |
| 216 | 217 | ||
| 218 | // Initialize host context. | ||
| 219 | thread->host_context = | ||
| 220 | std::make_shared<Common::Fiber>(std::move(init_func), init_func_parameter); | ||
| 221 | |||
| 217 | return RESULT_SUCCESS; | 222 | return RESULT_SUCCESS; |
| 218 | } | 223 | } |
| 219 | 224 | ||
| 225 | ResultCode KThread::InitializeDummyThread(KThread* thread) { | ||
| 226 | return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Main); | ||
| 227 | } | ||
| 228 | |||
| 229 | ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { | ||
| 230 | return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, | ||
| 231 | Core::CpuManager::GetIdleThreadStartFunc(), | ||
| 232 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 233 | } | ||
| 234 | |||
| 235 | ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, | ||
| 236 | KThreadFunction func, uintptr_t arg, | ||
| 237 | s32 virt_core) { | ||
| 238 | return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, | ||
| 239 | Core::CpuManager::GetSuspendThreadStartFunc(), | ||
| 240 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 241 | } | ||
| 242 | |||
| 243 | ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, | ||
| 244 | KThreadFunction func, uintptr_t arg, VAddr user_stack_top, | ||
| 245 | s32 prio, s32 virt_core, KProcess* owner) { | ||
| 246 | system.Kernel().GlobalSchedulerContext().AddThread(thread); | ||
| 247 | return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, | ||
| 248 | ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), | ||
| 249 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 250 | } | ||
| 251 | |||
| 252 | void KThread::PostDestroy(uintptr_t arg) { | ||
| 253 | KProcess* owner = reinterpret_cast<KProcess*>(arg & ~1ULL); | ||
| 254 | const bool resource_limit_release_hint = (arg & 1); | ||
| 255 | const s64 hint_value = (resource_limit_release_hint ? 0 : 1); | ||
| 256 | if (owner != nullptr) { | ||
| 257 | owner->GetResourceLimit()->Release(LimitableResource::Threads, 1, hint_value); | ||
| 258 | owner->Close(); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 220 | void KThread::Finalize() { | 262 | void KThread::Finalize() { |
| 221 | // If the thread has an owner process, unregister it. | 263 | // If the thread has an owner process, unregister it. |
| 222 | if (parent != nullptr) { | 264 | if (parent != nullptr) { |
| @@ -246,8 +288,10 @@ void KThread::Finalize() { | |||
| 246 | // Decrement the parent process's thread count. | 288 | // Decrement the parent process's thread count. |
| 247 | if (parent != nullptr) { | 289 | if (parent != nullptr) { |
| 248 | parent->DecrementThreadCount(); | 290 | parent->DecrementThreadCount(); |
| 249 | parent->GetResourceLimit()->Release(LimitableResource::Threads, 1); | ||
| 250 | } | 291 | } |
| 292 | |||
| 293 | // Perform inherited finalization. | ||
| 294 | KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize(); | ||
| 251 | } | 295 | } |
| 252 | 296 | ||
| 253 | bool KThread::IsSignaled() const { | 297 | bool KThread::IsSignaled() const { |
| @@ -294,6 +338,9 @@ void KThread::StartTermination() { | |||
| 294 | 338 | ||
| 295 | // Register terminated dpc flag. | 339 | // Register terminated dpc flag. |
| 296 | RegisterDpc(DpcFlag::Terminated); | 340 | RegisterDpc(DpcFlag::Terminated); |
| 341 | |||
| 342 | // Close the thread. | ||
| 343 | this->Close(); | ||
| 297 | } | 344 | } |
| 298 | 345 | ||
| 299 | void KThread::Pin() { | 346 | void KThread::Pin() { |
| @@ -432,7 +479,7 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m | |||
| 432 | return RESULT_SUCCESS; | 479 | return RESULT_SUCCESS; |
| 433 | } | 480 | } |
| 434 | 481 | ||
| 435 | ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | 482 | ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { |
| 436 | ASSERT(parent != nullptr); | 483 | ASSERT(parent != nullptr); |
| 437 | ASSERT(v_affinity_mask != 0); | 484 | ASSERT(v_affinity_mask != 0); |
| 438 | KScopedLightLock lk{activity_pause_lock}; | 485 | KScopedLightLock lk{activity_pause_lock}; |
| @@ -444,18 +491,18 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 444 | ASSERT(num_core_migration_disables >= 0); | 491 | ASSERT(num_core_migration_disables >= 0); |
| 445 | 492 | ||
| 446 | // If the core id is no-update magic, preserve the ideal core id. | 493 | // If the core id is no-update magic, preserve the ideal core id. |
| 447 | if (core_id == Svc::IdealCoreNoUpdate) { | 494 | if (cpu_core_id == Svc::IdealCoreNoUpdate) { |
| 448 | core_id = virtual_ideal_core_id; | 495 | cpu_core_id = virtual_ideal_core_id; |
| 449 | R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, ResultInvalidCombination); | 496 | R_UNLESS(((1ULL << cpu_core_id) & v_affinity_mask) != 0, ResultInvalidCombination); |
| 450 | } | 497 | } |
| 451 | 498 | ||
| 452 | // Set the virtual core/affinity mask. | 499 | // Set the virtual core/affinity mask. |
| 453 | virtual_ideal_core_id = core_id; | 500 | virtual_ideal_core_id = cpu_core_id; |
| 454 | virtual_affinity_mask = v_affinity_mask; | 501 | virtual_affinity_mask = v_affinity_mask; |
| 455 | 502 | ||
| 456 | // Translate the virtual core to a physical core. | 503 | // Translate the virtual core to a physical core. |
| 457 | if (core_id >= 0) { | 504 | if (cpu_core_id >= 0) { |
| 458 | core_id = Core::Hardware::VirtualToPhysicalCoreMap[core_id]; | 505 | cpu_core_id = Core::Hardware::VirtualToPhysicalCoreMap[cpu_core_id]; |
| 459 | } | 506 | } |
| 460 | 507 | ||
| 461 | // Translate the virtual affinity mask to a physical one. | 508 | // Translate the virtual affinity mask to a physical one. |
| @@ -470,7 +517,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 470 | const KAffinityMask old_mask = physical_affinity_mask; | 517 | const KAffinityMask old_mask = physical_affinity_mask; |
| 471 | 518 | ||
| 472 | // Set our new ideals. | 519 | // Set our new ideals. |
| 473 | physical_ideal_core_id = core_id; | 520 | physical_ideal_core_id = cpu_core_id; |
| 474 | physical_affinity_mask.SetAffinityMask(p_affinity_mask); | 521 | physical_affinity_mask.SetAffinityMask(p_affinity_mask); |
| 475 | 522 | ||
| 476 | if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { | 523 | if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { |
| @@ -488,7 +535,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 488 | } | 535 | } |
| 489 | } else { | 536 | } else { |
| 490 | // Otherwise, we edit the original affinity for restoration later. | 537 | // Otherwise, we edit the original affinity for restoration later. |
| 491 | original_physical_ideal_core_id = core_id; | 538 | original_physical_ideal_core_id = cpu_core_id; |
| 492 | original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); | 539 | original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); |
| 493 | } | 540 | } |
| 494 | } | 541 | } |
| @@ -804,8 +851,8 @@ void KThread::RemoveWaiterImpl(KThread* thread) { | |||
| 804 | thread->SetLockOwner(nullptr); | 851 | thread->SetLockOwner(nullptr); |
| 805 | } | 852 | } |
| 806 | 853 | ||
| 807 | void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | 854 | void KThread::RestorePriority(KernelCore& kernel_ctx, KThread* thread) { |
| 808 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 855 | ASSERT(kernel_ctx.GlobalSchedulerContext().IsLocked()); |
| 809 | 856 | ||
| 810 | while (true) { | 857 | while (true) { |
| 811 | // We want to inherit priority where possible. | 858 | // We want to inherit priority where possible. |
| @@ -821,7 +868,7 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | |||
| 821 | 868 | ||
| 822 | // Ensure we don't violate condition variable red black tree invariants. | 869 | // Ensure we don't violate condition variable red black tree invariants. |
| 823 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { | 870 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { |
| 824 | BeforeUpdatePriority(kernel, cv_tree, thread); | 871 | BeforeUpdatePriority(kernel_ctx, cv_tree, thread); |
| 825 | } | 872 | } |
| 826 | 873 | ||
| 827 | // Change the priority. | 874 | // Change the priority. |
| @@ -830,11 +877,11 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | |||
| 830 | 877 | ||
| 831 | // Restore the condition variable, if relevant. | 878 | // Restore the condition variable, if relevant. |
| 832 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { | 879 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { |
| 833 | AfterUpdatePriority(kernel, cv_tree, thread); | 880 | AfterUpdatePriority(kernel_ctx, cv_tree, thread); |
| 834 | } | 881 | } |
| 835 | 882 | ||
| 836 | // Update the scheduler. | 883 | // Update the scheduler. |
| 837 | KScheduler::OnThreadPriorityChanged(kernel, thread, old_priority); | 884 | KScheduler::OnThreadPriorityChanged(kernel_ctx, thread, old_priority); |
| 838 | 885 | ||
| 839 | // Keep the lock owner up to date. | 886 | // Keep the lock owner up to date. |
| 840 | KThread* lock_owner = thread->GetLockOwner(); | 887 | KThread* lock_owner = thread->GetLockOwner(); |
| @@ -932,7 +979,7 @@ void KThread::Exit() { | |||
| 932 | 979 | ||
| 933 | // Release the thread resource hint from parent. | 980 | // Release the thread resource hint from parent. |
| 934 | if (parent != nullptr) { | 981 | if (parent != nullptr) { |
| 935 | // TODO(bunnei): Hint that the resource is about to be released. | 982 | parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1); |
| 936 | resource_limit_release_hint = true; | 983 | resource_limit_release_hint = true; |
| 937 | } | 984 | } |
| 938 | 985 | ||
| @@ -995,56 +1042,6 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() { | |||
| 995 | return host_context; | 1042 | return host_context; |
| 996 | } | 1043 | } |
| 997 | 1044 | ||
| 998 | ResultVal<std::shared_ptr<KThread>> KThread::CreateThread(Core::System& system, | ||
| 999 | ThreadType type_flags, std::string name, | ||
| 1000 | VAddr entry_point, u32 priority, u64 arg, | ||
| 1001 | s32 processor_id, VAddr stack_top, | ||
| 1002 | Process* owner_process) { | ||
| 1003 | auto& kernel = system.Kernel(); | ||
| 1004 | |||
| 1005 | std::shared_ptr<KThread> thread = std::make_shared<KThread>(kernel); | ||
| 1006 | |||
| 1007 | if (const auto result = | ||
| 1008 | thread->InitializeThread(thread.get(), entry_point, arg, stack_top, priority, | ||
| 1009 | processor_id, owner_process, type_flags); | ||
| 1010 | result.IsError()) { | ||
| 1011 | return result; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | thread->name = name; | ||
| 1015 | |||
| 1016 | auto& scheduler = kernel.GlobalSchedulerContext(); | ||
| 1017 | scheduler.AddThread(thread); | ||
| 1018 | |||
| 1019 | return MakeResult<std::shared_ptr<KThread>>(std::move(thread)); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | ResultVal<std::shared_ptr<KThread>> KThread::CreateThread( | ||
| 1023 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority, | ||
| 1024 | u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process, | ||
| 1025 | std::function<void(void*)>&& thread_start_func, void* thread_start_parameter) { | ||
| 1026 | auto thread_result = CreateThread(system, type_flags, name, entry_point, priority, arg, | ||
| 1027 | processor_id, stack_top, owner_process); | ||
| 1028 | |||
| 1029 | if (thread_result.Succeeded()) { | ||
| 1030 | (*thread_result)->host_context = | ||
| 1031 | std::make_shared<Common::Fiber>(std::move(thread_start_func), thread_start_parameter); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | return thread_result; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | ResultVal<std::shared_ptr<KThread>> KThread::CreateUserThread( | ||
| 1038 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority, | ||
| 1039 | u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process) { | ||
| 1040 | std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc(); | ||
| 1041 | |||
| 1042 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); | ||
| 1043 | |||
| 1044 | return CreateThread(system, type_flags, name, entry_point, priority, arg, processor_id, | ||
| 1045 | stack_top, owner_process, std::move(init_func), init_func_parameter); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | KThread* GetCurrentThreadPointer(KernelCore& kernel) { | 1045 | KThread* GetCurrentThreadPointer(KernelCore& kernel) { |
| 1049 | return kernel.GetCurrentEmuThread(); | 1046 | return kernel.GetCurrentEmuThread(); |
| 1050 | } | 1047 | } |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index b442dfe57..4abfc2b49 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include "core/hle/kernel/k_light_lock.h" | 19 | #include "core/hle/kernel/k_light_lock.h" |
| 20 | #include "core/hle/kernel/k_spin_lock.h" | 20 | #include "core/hle/kernel/k_spin_lock.h" |
| 21 | #include "core/hle/kernel/k_synchronization_object.h" | 21 | #include "core/hle/kernel/k_synchronization_object.h" |
| 22 | #include "core/hle/kernel/object.h" | 22 | #include "core/hle/kernel/slab_helpers.h" |
| 23 | #include "core/hle/kernel/svc_common.h" | 23 | #include "core/hle/kernel/svc_common.h" |
| 24 | #include "core/hle/kernel/svc_types.h" | 24 | #include "core/hle/kernel/svc_types.h" |
| 25 | #include "core/hle/result.h" | 25 | #include "core/hle/result.h" |
| @@ -37,7 +37,7 @@ namespace Kernel { | |||
| 37 | 37 | ||
| 38 | class GlobalSchedulerContext; | 38 | class GlobalSchedulerContext; |
| 39 | class KernelCore; | 39 | class KernelCore; |
| 40 | class Process; | 40 | class KProcess; |
| 41 | class KScheduler; | 41 | class KScheduler; |
| 42 | class KThreadQueue; | 42 | class KThreadQueue; |
| 43 | 43 | ||
| @@ -99,15 +99,19 @@ enum class ThreadWaitReasonForDebugging : u32 { | |||
| 99 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); | 99 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); |
| 100 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); | 100 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); |
| 101 | 101 | ||
| 102 | class KThread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { | 102 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, |
| 103 | public boost::intrusive::list_base_hook<> { | ||
| 104 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); | ||
| 105 | |||
| 106 | private: | ||
| 103 | friend class KScheduler; | 107 | friend class KScheduler; |
| 104 | friend class Process; | 108 | friend class KProcess; |
| 105 | 109 | ||
| 106 | public: | 110 | public: |
| 107 | static constexpr s32 DefaultThreadPriority = 44; | 111 | static constexpr s32 DefaultThreadPriority = 44; |
| 108 | static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; | 112 | static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; |
| 109 | 113 | ||
| 110 | explicit KThread(KernelCore& kernel); | 114 | explicit KThread(KernelCore& kernel_); |
| 111 | ~KThread() override; | 115 | ~KThread() override; |
| 112 | 116 | ||
| 113 | public: | 117 | public: |
| @@ -115,74 +119,10 @@ public: | |||
| 115 | using ThreadContext64 = Core::ARM_Interface::ThreadContext64; | 119 | using ThreadContext64 = Core::ARM_Interface::ThreadContext64; |
| 116 | using WaiterList = boost::intrusive::list<KThread>; | 120 | using WaiterList = boost::intrusive::list<KThread>; |
| 117 | 121 | ||
| 118 | /** | ||
| 119 | * Creates and returns a new thread. | ||
| 120 | * @param system The instance of the whole system | ||
| 121 | * @param name The friendly name desired for the thread | ||
| 122 | * @param entry_point The address at which the thread should start execution | ||
| 123 | * @param priority The thread's priority | ||
| 124 | * @param arg User data to pass to the thread | ||
| 125 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 126 | * @param stack_top The address of the thread's stack top | ||
| 127 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 128 | * @return A shared pointer to the newly created thread | ||
| 129 | */ | ||
| 130 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread( | ||
| 131 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 132 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Creates and returns a new thread, with a specified entry point. | ||
| 136 | * @param system The instance of the whole system | ||
| 137 | * @param name The friendly name desired for the thread | ||
| 138 | * @param entry_point The address at which the thread should start execution | ||
| 139 | * @param priority The thread's priority | ||
| 140 | * @param arg User data to pass to the thread | ||
| 141 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 142 | * @param stack_top The address of the thread's stack top | ||
| 143 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 144 | * @param thread_start_func The function where the host context will start. | ||
| 145 | * @param thread_start_parameter The parameter which will passed to host context on init | ||
| 146 | * @return A shared pointer to the newly created thread | ||
| 147 | */ | ||
| 148 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread( | ||
| 149 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 150 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process, | ||
| 151 | std::function<void(void*)>&& thread_start_func, void* thread_start_parameter); | ||
| 152 | |||
| 153 | /** | ||
| 154 | * Creates and returns a new thread for the emulated "user" process. | ||
| 155 | * @param system The instance of the whole system | ||
| 156 | * @param name The friendly name desired for the thread | ||
| 157 | * @param entry_point The address at which the thread should start execution | ||
| 158 | * @param priority The thread's priority | ||
| 159 | * @param arg User data to pass to the thread | ||
| 160 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 161 | * @param stack_top The address of the thread's stack top | ||
| 162 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 163 | * @return A shared pointer to the newly created thread | ||
| 164 | */ | ||
| 165 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateUserThread( | ||
| 166 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 167 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process); | ||
| 168 | |||
| 169 | [[nodiscard]] std::string GetName() const override { | ||
| 170 | return name; | ||
| 171 | } | ||
| 172 | |||
| 173 | void SetName(std::string new_name) { | 122 | void SetName(std::string new_name) { |
| 174 | name = std::move(new_name); | 123 | name = std::move(new_name); |
| 175 | } | 124 | } |
| 176 | 125 | ||
| 177 | [[nodiscard]] std::string GetTypeName() const override { | ||
| 178 | return "Thread"; | ||
| 179 | } | ||
| 180 | |||
| 181 | static constexpr HandleType HANDLE_TYPE = HandleType::Thread; | ||
| 182 | [[nodiscard]] HandleType GetHandleType() const override { | ||
| 183 | return HANDLE_TYPE; | ||
| 184 | } | ||
| 185 | |||
| 186 | /** | 126 | /** |
| 187 | * Gets the thread's current priority | 127 | * Gets the thread's current priority |
| 188 | * @return The current thread's priority | 128 | * @return The current thread's priority |
| @@ -257,10 +197,6 @@ public: | |||
| 257 | 197 | ||
| 258 | void Suspend(); | 198 | void Suspend(); |
| 259 | 199 | ||
| 260 | void Finalize() override; | ||
| 261 | |||
| 262 | bool IsSignaled() const override; | ||
| 263 | |||
| 264 | void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { | 200 | void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { |
| 265 | synced_object = obj; | 201 | synced_object = obj; |
| 266 | wait_result = wait_res; | 202 | wait_result = wait_res; |
| @@ -354,11 +290,11 @@ public: | |||
| 354 | current_core_id = core; | 290 | current_core_id = core; |
| 355 | } | 291 | } |
| 356 | 292 | ||
| 357 | [[nodiscard]] Process* GetOwnerProcess() { | 293 | [[nodiscard]] KProcess* GetOwnerProcess() { |
| 358 | return parent; | 294 | return parent; |
| 359 | } | 295 | } |
| 360 | 296 | ||
| 361 | [[nodiscard]] const Process* GetOwnerProcess() const { | 297 | [[nodiscard]] const KProcess* GetOwnerProcess() const { |
| 362 | return parent; | 298 | return parent; |
| 363 | } | 299 | } |
| 364 | 300 | ||
| @@ -382,7 +318,7 @@ public: | |||
| 382 | 318 | ||
| 383 | [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); | 319 | [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); |
| 384 | 320 | ||
| 385 | [[nodiscard]] ResultCode SetCoreMask(s32 core_id, u64 v_affinity_mask); | 321 | [[nodiscard]] ResultCode SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); |
| 386 | 322 | ||
| 387 | [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); | 323 | [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); |
| 388 | 324 | ||
| @@ -422,6 +358,40 @@ public: | |||
| 422 | return termination_requested || GetRawState() == ThreadState::Terminated; | 358 | return termination_requested || GetRawState() == ThreadState::Terminated; |
| 423 | } | 359 | } |
| 424 | 360 | ||
| 361 | [[nodiscard]] virtual u64 GetId() const override final { | ||
| 362 | return this->GetThreadID(); | ||
| 363 | } | ||
| 364 | |||
| 365 | [[nodiscard]] virtual bool IsInitialized() const override { | ||
| 366 | return initialized; | ||
| 367 | } | ||
| 368 | |||
| 369 | [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { | ||
| 370 | return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); | ||
| 371 | } | ||
| 372 | |||
| 373 | virtual void Finalize() override; | ||
| 374 | |||
| 375 | [[nodiscard]] virtual bool IsSignaled() const override; | ||
| 376 | |||
| 377 | static void PostDestroy(uintptr_t arg); | ||
| 378 | |||
| 379 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); | ||
| 380 | |||
| 381 | [[nodiscard]] static ResultCode InitializeIdleThread(Core::System& system, KThread* thread, | ||
| 382 | s32 virt_core); | ||
| 383 | |||
| 384 | [[nodiscard]] static ResultCode InitializeHighPriorityThread(Core::System& system, | ||
| 385 | KThread* thread, | ||
| 386 | KThreadFunction func, | ||
| 387 | uintptr_t arg, s32 virt_core); | ||
| 388 | |||
| 389 | [[nodiscard]] static ResultCode InitializeUserThread(Core::System& system, KThread* thread, | ||
| 390 | KThreadFunction func, uintptr_t arg, | ||
| 391 | VAddr user_stack_top, s32 prio, | ||
| 392 | s32 virt_core, KProcess* owner); | ||
| 393 | |||
| 394 | public: | ||
| 425 | struct StackParameters { | 395 | struct StackParameters { |
| 426 | u8 svc_permission[0x10]; | 396 | u8 svc_permission[0x10]; |
| 427 | std::atomic<u8> dpc_flags; | 397 | std::atomic<u8> dpc_flags; |
| @@ -671,13 +641,15 @@ private: | |||
| 671 | void StartTermination(); | 641 | void StartTermination(); |
| 672 | 642 | ||
| 673 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, | 643 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, |
| 674 | s32 prio, s32 virt_core, Process* owner, ThreadType type); | 644 | s32 prio, s32 virt_core, KProcess* owner, ThreadType type); |
| 675 | 645 | ||
| 676 | [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, | 646 | [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, |
| 677 | uintptr_t arg, VAddr user_stack_top, s32 prio, | 647 | uintptr_t arg, VAddr user_stack_top, s32 prio, |
| 678 | s32 core, Process* owner, ThreadType type); | 648 | s32 core, KProcess* owner, ThreadType type, |
| 649 | std::function<void(void*)>&& init_func, | ||
| 650 | void* init_func_parameter); | ||
| 679 | 651 | ||
| 680 | static void RestorePriority(KernelCore& kernel, KThread* thread); | 652 | static void RestorePriority(KernelCore& kernel_ctx, KThread* thread); |
| 681 | 653 | ||
| 682 | // For core KThread implementation | 654 | // For core KThread implementation |
| 683 | ThreadContext32 thread_context_32{}; | 655 | ThreadContext32 thread_context_32{}; |
| @@ -697,7 +669,7 @@ private: | |||
| 697 | std::atomic<s64> cpu_time{}; | 669 | std::atomic<s64> cpu_time{}; |
| 698 | KSynchronizationObject* synced_object{}; | 670 | KSynchronizationObject* synced_object{}; |
| 699 | VAddr address_key{}; | 671 | VAddr address_key{}; |
| 700 | Process* parent{}; | 672 | KProcess* parent{}; |
| 701 | VAddr kernel_stack_top{}; | 673 | VAddr kernel_stack_top{}; |
| 702 | u32* light_ipc_data{}; | 674 | u32* light_ipc_data{}; |
| 703 | VAddr tls_address{}; | 675 | VAddr tls_address{}; |
| @@ -742,7 +714,6 @@ private: | |||
| 742 | VAddr mutex_wait_address_for_debugging{}; | 714 | VAddr mutex_wait_address_for_debugging{}; |
| 743 | ThreadWaitReasonForDebugging wait_reason_for_debugging{}; | 715 | ThreadWaitReasonForDebugging wait_reason_for_debugging{}; |
| 744 | ThreadType thread_type_for_debugging{}; | 716 | ThreadType thread_type_for_debugging{}; |
| 745 | std::string name; | ||
| 746 | 717 | ||
| 747 | public: | 718 | public: |
| 748 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; | 719 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; |
diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index c52eba249..35d471dc5 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h | |||
| @@ -10,7 +10,7 @@ namespace Kernel { | |||
| 10 | 10 | ||
| 11 | class KThreadQueue { | 11 | class KThreadQueue { |
| 12 | public: | 12 | public: |
| 13 | explicit KThreadQueue(KernelCore& kernel) : kernel{kernel} {} | 13 | explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} |
| 14 | 14 | ||
| 15 | bool IsEmpty() const { | 15 | bool IsEmpty() const { |
| 16 | return wait_list.empty(); | 16 | return wait_list.empty(); |
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp new file mode 100644 index 000000000..5bc33706d --- /dev/null +++ b/src/core/hle/kernel/k_transfer_memory.cpp | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_process.h" | ||
| 6 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 7 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 8 | #include "core/hle/kernel/kernel.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | KTransferMemory::KTransferMemory(KernelCore& kernel_) | ||
| 13 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||
| 14 | |||
| 15 | KTransferMemory::~KTransferMemory() = default; | ||
| 16 | |||
| 17 | ResultCode KTransferMemory::Initialize(VAddr address_, std::size_t size_, | ||
| 18 | Svc::MemoryPermission owner_perm_) { | ||
| 19 | // Set members. | ||
| 20 | owner = kernel.CurrentProcess(); | ||
| 21 | |||
| 22 | // TODO(bunnei): Lock for transfer memory | ||
| 23 | |||
| 24 | // Set remaining tracking members. | ||
| 25 | owner->Open(); | ||
| 26 | owner_perm = owner_perm_; | ||
| 27 | address = address_; | ||
| 28 | size = size_; | ||
| 29 | is_initialized = true; | ||
| 30 | |||
| 31 | return RESULT_SUCCESS; | ||
| 32 | } | ||
| 33 | |||
| 34 | void KTransferMemory::Finalize() { | ||
| 35 | // Perform inherited finalization. | ||
| 36 | KAutoObjectWithSlabHeapAndContainer<KTransferMemory, KAutoObjectWithList>::Finalize(); | ||
| 37 | } | ||
| 38 | |||
| 39 | void KTransferMemory::PostDestroy(uintptr_t arg) { | ||
| 40 | KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||
| 41 | owner->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); | ||
| 42 | owner->Close(); | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h new file mode 100644 index 000000000..c2d0f1eaf --- /dev/null +++ b/src/core/hle/kernel/k_transfer_memory.h | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "core/hle/kernel/slab_helpers.h" | ||
| 10 | #include "core/hle/kernel/svc_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | union ResultCode; | ||
| 14 | |||
| 15 | namespace Core::Memory { | ||
| 16 | class Memory; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Kernel { | ||
| 20 | |||
| 21 | class KernelCore; | ||
| 22 | class KProcess; | ||
| 23 | |||
| 24 | class KTransferMemory final | ||
| 25 | : public KAutoObjectWithSlabHeapAndContainer<KTransferMemory, KAutoObjectWithList> { | ||
| 26 | KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject); | ||
| 27 | |||
| 28 | public: | ||
| 29 | explicit KTransferMemory(KernelCore& kernel_); | ||
| 30 | virtual ~KTransferMemory() override; | ||
| 31 | |||
| 32 | ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); | ||
| 33 | |||
| 34 | virtual void Finalize() override; | ||
| 35 | |||
| 36 | virtual bool IsInitialized() const override { | ||
| 37 | return is_initialized; | ||
| 38 | } | ||
| 39 | |||
| 40 | virtual uintptr_t GetPostDestroyArgument() const override { | ||
| 41 | return reinterpret_cast<uintptr_t>(owner); | ||
| 42 | } | ||
| 43 | |||
| 44 | static void PostDestroy(uintptr_t arg); | ||
| 45 | |||
| 46 | KProcess* GetOwner() const { | ||
| 47 | return owner; | ||
| 48 | } | ||
| 49 | |||
| 50 | VAddr GetSourceAddress() const { | ||
| 51 | return address; | ||
| 52 | } | ||
| 53 | |||
| 54 | size_t GetSize() const { | ||
| 55 | return is_initialized ? size : 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | KProcess* owner{}; | ||
| 60 | VAddr address{}; | ||
| 61 | Svc::MemoryPermission owner_perm{}; | ||
| 62 | size_t size{}; | ||
| 63 | bool is_initialized{}; | ||
| 64 | }; | ||
| 65 | |||
| 66 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp index 25c52edb2..b7b83c151 100644 --- a/src/core/hle/kernel/k_writable_event.cpp +++ b/src/core/hle/kernel/k_writable_event.cpp | |||
| @@ -8,20 +8,29 @@ | |||
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name) | 11 | KWritableEvent::KWritableEvent(KernelCore& kernel_) |
| 12 | : Object{kernel, std::move(name)} {} | 12 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 13 | |||
| 13 | KWritableEvent::~KWritableEvent() = default; | 14 | KWritableEvent::~KWritableEvent() = default; |
| 14 | 15 | ||
| 15 | void KWritableEvent::Initialize(KEvent* parent_) { | 16 | void KWritableEvent::Initialize(KEvent* parent_, std::string&& name_) { |
| 16 | parent = parent_; | 17 | parent = parent_; |
| 18 | name = std::move(name_); | ||
| 19 | parent->GetReadableEvent().Open(); | ||
| 17 | } | 20 | } |
| 18 | 21 | ||
| 19 | ResultCode KWritableEvent::Signal() { | 22 | ResultCode KWritableEvent::Signal() { |
| 20 | return parent->GetReadableEvent()->Signal(); | 23 | return parent->GetReadableEvent().Signal(); |
| 21 | } | 24 | } |
| 22 | 25 | ||
| 23 | ResultCode KWritableEvent::Clear() { | 26 | ResultCode KWritableEvent::Clear() { |
| 24 | return parent->GetReadableEvent()->Clear(); | 27 | return parent->GetReadableEvent().Clear(); |
| 28 | } | ||
| 29 | |||
| 30 | void KWritableEvent::Destroy() { | ||
| 31 | // Close our references. | ||
| 32 | parent->GetReadableEvent().Close(); | ||
| 33 | parent->Close(); | ||
| 25 | } | 34 | } |
| 26 | 35 | ||
| 27 | } // namespace Kernel | 36 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h index 518f5448d..607b0eadb 100644 --- a/src/core/hle/kernel/k_writable_event.h +++ b/src/core/hle/kernel/k_writable_event.h | |||
| @@ -4,7 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/object.h" | 7 | #include "core/hle/kernel/k_auto_object.h" |
| 8 | #include "core/hle/kernel/slab_helpers.h" | ||
| 8 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 9 | 10 | ||
| 10 | namespace Kernel { | 11 | namespace Kernel { |
| @@ -12,24 +13,19 @@ namespace Kernel { | |||
| 12 | class KernelCore; | 13 | class KernelCore; |
| 13 | class KEvent; | 14 | class KEvent; |
| 14 | 15 | ||
| 15 | class KWritableEvent final : public Object { | 16 | class KWritableEvent final |
| 17 | : public KAutoObjectWithSlabHeapAndContainer<KWritableEvent, KAutoObjectWithList> { | ||
| 18 | KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); | ||
| 19 | |||
| 16 | public: | 20 | public: |
| 17 | explicit KWritableEvent(KernelCore& kernel, std::string&& name); | 21 | explicit KWritableEvent(KernelCore& kernel_); |
| 18 | ~KWritableEvent() override; | 22 | ~KWritableEvent() override; |
| 19 | 23 | ||
| 20 | std::string GetTypeName() const override { | 24 | virtual void Destroy() override; |
| 21 | return "KWritableEvent"; | ||
| 22 | } | ||
| 23 | |||
| 24 | static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent; | ||
| 25 | HandleType GetHandleType() const override { | ||
| 26 | return HANDLE_TYPE; | ||
| 27 | } | ||
| 28 | |||
| 29 | void Initialize(KEvent* parent_); | ||
| 30 | 25 | ||
| 31 | void Finalize() override {} | 26 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 32 | 27 | ||
| 28 | void Initialize(KEvent* parent_, std::string&& name_); | ||
| 33 | ResultCode Signal(); | 29 | ResultCode Signal(); |
| 34 | ResultCode Clear(); | 30 | ResultCode Clear(); |
| 35 | 31 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 5c4f45ab4..8b55df82e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -26,10 +26,12 @@ | |||
| 26 | #include "core/cpu_manager.h" | 26 | #include "core/cpu_manager.h" |
| 27 | #include "core/device_memory.h" | 27 | #include "core/device_memory.h" |
| 28 | #include "core/hardware_properties.h" | 28 | #include "core/hardware_properties.h" |
| 29 | #include "core/hle/kernel/client_port.h" | 29 | #include "core/hle/kernel/init/init_slab_setup.h" |
| 30 | #include "core/hle/kernel/handle_table.h" | 30 | #include "core/hle/kernel/k_client_port.h" |
| 31 | #include "core/hle/kernel/k_handle_table.h" | ||
| 31 | #include "core/hle/kernel/k_memory_layout.h" | 32 | #include "core/hle/kernel/k_memory_layout.h" |
| 32 | #include "core/hle/kernel/k_memory_manager.h" | 33 | #include "core/hle/kernel/k_memory_manager.h" |
| 34 | #include "core/hle/kernel/k_process.h" | ||
| 33 | #include "core/hle/kernel/k_resource_limit.h" | 35 | #include "core/hle/kernel/k_resource_limit.h" |
| 34 | #include "core/hle/kernel/k_scheduler.h" | 36 | #include "core/hle/kernel/k_scheduler.h" |
| 35 | #include "core/hle/kernel/k_shared_memory.h" | 37 | #include "core/hle/kernel/k_shared_memory.h" |
| @@ -37,12 +39,12 @@ | |||
| 37 | #include "core/hle/kernel/k_thread.h" | 39 | #include "core/hle/kernel/k_thread.h" |
| 38 | #include "core/hle/kernel/kernel.h" | 40 | #include "core/hle/kernel/kernel.h" |
| 39 | #include "core/hle/kernel/physical_core.h" | 41 | #include "core/hle/kernel/physical_core.h" |
| 40 | #include "core/hle/kernel/process.h" | ||
| 41 | #include "core/hle/kernel/service_thread.h" | 42 | #include "core/hle/kernel/service_thread.h" |
| 42 | #include "core/hle/kernel/svc_results.h" | 43 | #include "core/hle/kernel/svc_results.h" |
| 43 | #include "core/hle/kernel/time_manager.h" | 44 | #include "core/hle/kernel/time_manager.h" |
| 44 | #include "core/hle/lock.h" | 45 | #include "core/hle/lock.h" |
| 45 | #include "core/hle/result.h" | 46 | #include "core/hle/result.h" |
| 47 | #include "core/hle/service/sm/sm.h" | ||
| 46 | #include "core/memory.h" | 48 | #include "core/memory.h" |
| 47 | 49 | ||
| 48 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | 50 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); |
| @@ -50,17 +52,16 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | |||
| 50 | namespace Kernel { | 52 | namespace Kernel { |
| 51 | 53 | ||
| 52 | struct KernelCore::Impl { | 54 | struct KernelCore::Impl { |
| 53 | explicit Impl(Core::System& system, KernelCore& kernel) | 55 | explicit Impl(Core::System& system_, KernelCore& kernel_) |
| 54 | : time_manager{system}, global_handle_table{kernel}, system{system} {} | 56 | : time_manager{system_}, object_list_container{kernel_}, system{system_} {} |
| 55 | 57 | ||
| 56 | void SetMulticore(bool is_multicore) { | 58 | void SetMulticore(bool is_multi) { |
| 57 | this->is_multicore = is_multicore; | 59 | is_multicore = is_multi; |
| 58 | } | 60 | } |
| 59 | 61 | ||
| 60 | void Initialize(KernelCore& kernel) { | 62 | void Initialize(KernelCore& kernel) { |
| 61 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); | 63 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); |
| 62 | 64 | global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); | |
| 63 | RegisterHostThread(); | ||
| 64 | 65 | ||
| 65 | service_thread_manager = | 66 | service_thread_manager = |
| 66 | std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); | 67 | std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); |
| @@ -69,14 +70,20 @@ struct KernelCore::Impl { | |||
| 69 | InitializePhysicalCores(); | 70 | InitializePhysicalCores(); |
| 70 | 71 | ||
| 71 | // Derive the initial memory layout from the emulated board | 72 | // Derive the initial memory layout from the emulated board |
| 73 | Init::InitializeSlabResourceCounts(kernel); | ||
| 72 | KMemoryLayout memory_layout; | 74 | KMemoryLayout memory_layout; |
| 73 | DeriveInitialMemoryLayout(memory_layout); | 75 | DeriveInitialMemoryLayout(memory_layout); |
| 74 | InitializeMemoryLayout(memory_layout); | 76 | Init::InitializeSlabHeaps(system, memory_layout); |
| 77 | |||
| 78 | // Initialize kernel memory and resources. | ||
| 75 | InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); | 79 | InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); |
| 76 | InitializeSlabHeaps(); | 80 | InitializeMemoryLayout(memory_layout); |
| 81 | InitializePageSlab(); | ||
| 77 | InitializeSchedulers(); | 82 | InitializeSchedulers(); |
| 78 | InitializeSuspendThreads(); | 83 | InitializeSuspendThreads(); |
| 79 | InitializePreemption(kernel); | 84 | InitializePreemption(kernel); |
| 85 | |||
| 86 | RegisterHostThread(); | ||
| 80 | } | 87 | } |
| 81 | 88 | ||
| 82 | void InitializeCores() { | 89 | void InitializeCores() { |
| @@ -93,34 +100,49 @@ struct KernelCore::Impl { | |||
| 93 | service_threads.clear(); | 100 | service_threads.clear(); |
| 94 | 101 | ||
| 95 | next_object_id = 0; | 102 | next_object_id = 0; |
| 96 | next_kernel_process_id = Process::InitialKIPIDMin; | 103 | next_kernel_process_id = KProcess::InitialKIPIDMin; |
| 97 | next_user_process_id = Process::ProcessIDMin; | 104 | next_user_process_id = KProcess::ProcessIDMin; |
| 98 | next_thread_id = 1; | 105 | next_thread_id = 1; |
| 99 | 106 | ||
| 100 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | 107 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 101 | if (suspend_threads[i]) { | 108 | if (suspend_threads[core_id]) { |
| 102 | suspend_threads[i].reset(); | 109 | suspend_threads[core_id]->Close(); |
| 110 | suspend_threads[core_id] = nullptr; | ||
| 103 | } | 111 | } |
| 112 | |||
| 113 | schedulers[core_id].reset(); | ||
| 104 | } | 114 | } |
| 105 | 115 | ||
| 106 | cores.clear(); | 116 | cores.clear(); |
| 107 | 117 | ||
| 108 | current_process = nullptr; | 118 | if (current_process) { |
| 119 | current_process->Close(); | ||
| 120 | current_process = nullptr; | ||
| 121 | } | ||
| 109 | 122 | ||
| 110 | global_handle_table.Clear(); | 123 | global_handle_table.reset(); |
| 111 | 124 | ||
| 112 | preemption_event = nullptr; | 125 | preemption_event = nullptr; |
| 113 | 126 | ||
| 127 | for (auto& iter : named_ports) { | ||
| 128 | iter.second->Close(); | ||
| 129 | } | ||
| 114 | named_ports.clear(); | 130 | named_ports.clear(); |
| 115 | 131 | ||
| 116 | exclusive_monitor.reset(); | 132 | exclusive_monitor.reset(); |
| 117 | 133 | ||
| 118 | hid_shared_mem = nullptr; | 134 | // Cleanup persistent kernel objects |
| 119 | font_shared_mem = nullptr; | 135 | auto CleanupObject = [](KAutoObject* obj) { |
| 120 | irs_shared_mem = nullptr; | 136 | if (obj) { |
| 121 | time_shared_mem = nullptr; | 137 | obj->Close(); |
| 122 | 138 | obj = nullptr; | |
| 123 | system_resource_limit = nullptr; | 139 | } |
| 140 | }; | ||
| 141 | CleanupObject(hid_shared_mem); | ||
| 142 | CleanupObject(font_shared_mem); | ||
| 143 | CleanupObject(irs_shared_mem); | ||
| 144 | CleanupObject(time_shared_mem); | ||
| 145 | CleanupObject(system_resource_limit); | ||
| 124 | 146 | ||
| 125 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | 147 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others |
| 126 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; | 148 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; |
| @@ -145,7 +167,9 @@ struct KernelCore::Impl { | |||
| 145 | void InitializeSystemResourceLimit(KernelCore& kernel, | 167 | void InitializeSystemResourceLimit(KernelCore& kernel, |
| 146 | const Core::Timing::CoreTiming& core_timing, | 168 | const Core::Timing::CoreTiming& core_timing, |
| 147 | const KMemoryLayout& memory_layout) { | 169 | const KMemoryLayout& memory_layout) { |
| 148 | system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing); | 170 | system_resource_limit = KResourceLimit::Create(system.Kernel()); |
| 171 | system_resource_limit->Initialize(&core_timing); | ||
| 172 | |||
| 149 | const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); | 173 | const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); |
| 150 | 174 | ||
| 151 | // If setting the default system values fails, then something seriously wrong has occurred. | 175 | // If setting the default system values fails, then something seriously wrong has occurred. |
| @@ -189,19 +213,16 @@ struct KernelCore::Impl { | |||
| 189 | } | 213 | } |
| 190 | 214 | ||
| 191 | void InitializeSuspendThreads() { | 215 | void InitializeSuspendThreads() { |
| 192 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | 216 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 193 | std::string name = "Suspend Thread Id:" + std::to_string(i); | 217 | suspend_threads[core_id] = KThread::Create(system.Kernel()); |
| 194 | std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc(); | 218 | ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {}, |
| 195 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); | 219 | core_id) |
| 196 | auto thread_res = KThread::CreateThread( | 220 | .IsSuccess()); |
| 197 | system, ThreadType::HighPriority, std::move(name), 0, 0, 0, static_cast<u32>(i), 0, | 221 | suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id)); |
| 198 | nullptr, std::move(init_func), init_func_parameter); | ||
| 199 | |||
| 200 | suspend_threads[i] = std::move(thread_res).Unwrap(); | ||
| 201 | } | 222 | } |
| 202 | } | 223 | } |
| 203 | 224 | ||
| 204 | void MakeCurrentProcess(Process* process) { | 225 | void MakeCurrentProcess(KProcess* process) { |
| 205 | current_process = process; | 226 | current_process = process; |
| 206 | if (process == nullptr) { | 227 | if (process == nullptr) { |
| 207 | return; | 228 | return; |
| @@ -232,11 +253,15 @@ struct KernelCore::Impl { | |||
| 232 | 253 | ||
| 233 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time | 254 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time |
| 234 | KThread* GetHostDummyThread() { | 255 | KThread* GetHostDummyThread() { |
| 235 | const thread_local auto thread = | 256 | auto make_thread = [this]() { |
| 236 | KThread::CreateThread( | 257 | std::unique_ptr<KThread> thread = std::make_unique<KThread>(system.Kernel()); |
| 237 | system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0, | 258 | KAutoObject::Create(thread.get()); |
| 238 | KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr) | 259 | ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); |
| 239 | .Unwrap(); | 260 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); |
| 261 | return std::move(thread); | ||
| 262 | }; | ||
| 263 | |||
| 264 | thread_local auto thread = make_thread(); | ||
| 240 | return thread.get(); | 265 | return thread.get(); |
| 241 | } | 266 | } |
| 242 | 267 | ||
| @@ -371,7 +396,8 @@ struct KernelCore::Impl { | |||
| 371 | const size_t resource_region_size = memory_layout.GetResourceRegionSizeForInit(); | 396 | const size_t resource_region_size = memory_layout.GetResourceRegionSizeForInit(); |
| 372 | 397 | ||
| 373 | // Determine the size of the slab region. | 398 | // Determine the size of the slab region. |
| 374 | const size_t slab_region_size = Common::AlignUp(KernelSlabHeapSize, PageSize); | 399 | const size_t slab_region_size = |
| 400 | Common::AlignUp(Init::CalculateTotalSlabHeapSize(system.Kernel()), PageSize); | ||
| 375 | ASSERT(slab_region_size <= resource_region_size); | 401 | ASSERT(slab_region_size <= resource_region_size); |
| 376 | 402 | ||
| 377 | // Setup the slab region. | 403 | // Setup the slab region. |
| @@ -569,25 +595,30 @@ struct KernelCore::Impl { | |||
| 569 | const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size}; | 595 | const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size}; |
| 570 | const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size}; | 596 | const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size}; |
| 571 | 597 | ||
| 572 | hid_shared_mem = Kernel::KSharedMemory::Create( | 598 | hid_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 573 | system.Kernel(), system.DeviceMemory(), nullptr, {hid_phys_addr, hid_size / PageSize}, | 599 | font_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 574 | KMemoryPermission::None, KMemoryPermission::Read, hid_phys_addr, hid_size, | 600 | irs_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 575 | "HID:SharedMemory"); | 601 | time_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 576 | font_shared_mem = Kernel::KSharedMemory::Create( | 602 | |
| 577 | system.Kernel(), system.DeviceMemory(), nullptr, {font_phys_addr, font_size / PageSize}, | 603 | hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 578 | KMemoryPermission::None, KMemoryPermission::Read, font_phys_addr, font_size, | 604 | {hid_phys_addr, hid_size / PageSize}, |
| 579 | "Font:SharedMemory"); | 605 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 580 | irs_shared_mem = Kernel::KSharedMemory::Create( | 606 | hid_phys_addr, hid_size, "HID:SharedMemory"); |
| 581 | system.Kernel(), system.DeviceMemory(), nullptr, {irs_phys_addr, irs_size / PageSize}, | 607 | font_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 582 | KMemoryPermission::None, KMemoryPermission::Read, irs_phys_addr, irs_size, | 608 | {font_phys_addr, font_size / PageSize}, |
| 583 | "IRS:SharedMemory"); | 609 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 584 | time_shared_mem = Kernel::KSharedMemory::Create( | 610 | font_phys_addr, font_size, "Font:SharedMemory"); |
| 585 | system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, | 611 | irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 586 | KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, | 612 | {irs_phys_addr, irs_size / PageSize}, |
| 587 | "Time:SharedMemory"); | 613 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 614 | irs_phys_addr, irs_size, "IRS:SharedMemory"); | ||
| 615 | time_shared_mem->Initialize(system.DeviceMemory(), nullptr, | ||
| 616 | {time_phys_addr, time_size / PageSize}, | ||
| 617 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, | ||
| 618 | time_phys_addr, time_size, "Time:SharedMemory"); | ||
| 588 | } | 619 | } |
| 589 | 620 | ||
| 590 | void InitializeSlabHeaps() { | 621 | void InitializePageSlab() { |
| 591 | // Allocate slab heaps | 622 | // Allocate slab heaps |
| 592 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); | 623 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); |
| 593 | 624 | ||
| @@ -596,33 +627,37 @@ struct KernelCore::Impl { | |||
| 596 | // Reserve slab heaps | 627 | // Reserve slab heaps |
| 597 | ASSERT( | 628 | ASSERT( |
| 598 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); | 629 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); |
| 599 | // Initialize slab heaps | 630 | // Initialize slab heap |
| 600 | user_slab_heap_pages->Initialize( | 631 | user_slab_heap_pages->Initialize( |
| 601 | system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase), | 632 | system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase), |
| 602 | user_slab_heap_size); | 633 | user_slab_heap_size); |
| 603 | } | 634 | } |
| 604 | 635 | ||
| 605 | std::atomic<u32> next_object_id{0}; | 636 | std::atomic<u32> next_object_id{0}; |
| 606 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; | 637 | std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; |
| 607 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; | 638 | std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin}; |
| 608 | std::atomic<u64> next_thread_id{1}; | 639 | std::atomic<u64> next_thread_id{1}; |
| 609 | 640 | ||
| 610 | // Lists all processes that exist in the current session. | 641 | // Lists all processes that exist in the current session. |
| 611 | std::vector<std::shared_ptr<Process>> process_list; | 642 | std::vector<KProcess*> process_list; |
| 612 | Process* current_process = nullptr; | 643 | KProcess* current_process{}; |
| 613 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; | 644 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; |
| 614 | Kernel::TimeManager time_manager; | 645 | Kernel::TimeManager time_manager; |
| 615 | 646 | ||
| 616 | std::shared_ptr<KResourceLimit> system_resource_limit; | 647 | Init::KSlabResourceCounts slab_resource_counts{}; |
| 648 | KResourceLimit* system_resource_limit{}; | ||
| 617 | 649 | ||
| 618 | std::shared_ptr<Core::Timing::EventType> preemption_event; | 650 | std::shared_ptr<Core::Timing::EventType> preemption_event; |
| 619 | 651 | ||
| 620 | // This is the kernel's handle table or supervisor handle table which | 652 | // This is the kernel's handle table or supervisor handle table which |
| 621 | // stores all the objects in place. | 653 | // stores all the objects in place. |
| 622 | HandleTable global_handle_table; | 654 | std::unique_ptr<KHandleTable> global_handle_table; |
| 655 | |||
| 656 | KAutoObjectWithListContainer object_list_container; | ||
| 623 | 657 | ||
| 624 | /// Map of named ports managed by the kernel, which can be retrieved using | 658 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 625 | /// the ConnectToPort SVC. | 659 | /// the ConnectToPort SVC. |
| 660 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; | ||
| 626 | NamedPortTable named_ports; | 661 | NamedPortTable named_ports; |
| 627 | 662 | ||
| 628 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 663 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| @@ -636,10 +671,10 @@ struct KernelCore::Impl { | |||
| 636 | std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages; | 671 | std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages; |
| 637 | 672 | ||
| 638 | // Shared memory for services | 673 | // Shared memory for services |
| 639 | std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem; | 674 | Kernel::KSharedMemory* hid_shared_mem{}; |
| 640 | std::shared_ptr<Kernel::KSharedMemory> font_shared_mem; | 675 | Kernel::KSharedMemory* font_shared_mem{}; |
| 641 | std::shared_ptr<Kernel::KSharedMemory> irs_shared_mem; | 676 | Kernel::KSharedMemory* irs_shared_mem{}; |
| 642 | std::shared_ptr<Kernel::KSharedMemory> time_shared_mem; | 677 | Kernel::KSharedMemory* time_shared_mem{}; |
| 643 | 678 | ||
| 644 | // Threads used for services | 679 | // Threads used for services |
| 645 | std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; | 680 | std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; |
| @@ -648,7 +683,7 @@ struct KernelCore::Impl { | |||
| 648 | // the release of itself | 683 | // the release of itself |
| 649 | std::unique_ptr<Common::ThreadWorker> service_thread_manager; | 684 | std::unique_ptr<Common::ThreadWorker> service_thread_manager; |
| 650 | 685 | ||
| 651 | std::array<std::shared_ptr<KThread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{}; | 686 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; |
| 652 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; | 687 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; |
| 653 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; | 688 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; |
| 654 | 689 | ||
| @@ -663,15 +698,14 @@ struct KernelCore::Impl { | |||
| 663 | }; | 698 | }; |
| 664 | 699 | ||
| 665 | KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {} | 700 | KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {} |
| 666 | KernelCore::~KernelCore() { | 701 | KernelCore::~KernelCore() = default; |
| 667 | Shutdown(); | ||
| 668 | } | ||
| 669 | 702 | ||
| 670 | void KernelCore::SetMulticore(bool is_multicore) { | 703 | void KernelCore::SetMulticore(bool is_multicore) { |
| 671 | impl->SetMulticore(is_multicore); | 704 | impl->SetMulticore(is_multicore); |
| 672 | } | 705 | } |
| 673 | 706 | ||
| 674 | void KernelCore::Initialize() { | 707 | void KernelCore::Initialize() { |
| 708 | slab_heap_container = std::make_unique<SlabHeapContainer>(); | ||
| 675 | impl->Initialize(*this); | 709 | impl->Initialize(*this); |
| 676 | } | 710 | } |
| 677 | 711 | ||
| @@ -683,31 +717,35 @@ void KernelCore::Shutdown() { | |||
| 683 | impl->Shutdown(); | 717 | impl->Shutdown(); |
| 684 | } | 718 | } |
| 685 | 719 | ||
| 686 | std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const { | 720 | const KResourceLimit* KernelCore::GetSystemResourceLimit() const { |
| 721 | return impl->system_resource_limit; | ||
| 722 | } | ||
| 723 | |||
| 724 | KResourceLimit* KernelCore::GetSystemResourceLimit() { | ||
| 687 | return impl->system_resource_limit; | 725 | return impl->system_resource_limit; |
| 688 | } | 726 | } |
| 689 | 727 | ||
| 690 | std::shared_ptr<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { | 728 | KScopedAutoObject<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { |
| 691 | return impl->global_handle_table.Get<KThread>(handle); | 729 | return impl->global_handle_table->GetObject<KThread>(handle); |
| 692 | } | 730 | } |
| 693 | 731 | ||
| 694 | void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { | 732 | void KernelCore::AppendNewProcess(KProcess* process) { |
| 695 | impl->process_list.push_back(std::move(process)); | 733 | impl->process_list.push_back(process); |
| 696 | } | 734 | } |
| 697 | 735 | ||
| 698 | void KernelCore::MakeCurrentProcess(Process* process) { | 736 | void KernelCore::MakeCurrentProcess(KProcess* process) { |
| 699 | impl->MakeCurrentProcess(process); | 737 | impl->MakeCurrentProcess(process); |
| 700 | } | 738 | } |
| 701 | 739 | ||
| 702 | Process* KernelCore::CurrentProcess() { | 740 | KProcess* KernelCore::CurrentProcess() { |
| 703 | return impl->current_process; | 741 | return impl->current_process; |
| 704 | } | 742 | } |
| 705 | 743 | ||
| 706 | const Process* KernelCore::CurrentProcess() const { | 744 | const KProcess* KernelCore::CurrentProcess() const { |
| 707 | return impl->current_process; | 745 | return impl->current_process; |
| 708 | } | 746 | } |
| 709 | 747 | ||
| 710 | const std::vector<std::shared_ptr<Process>>& KernelCore::GetProcessList() const { | 748 | const std::vector<KProcess*>& KernelCore::GetProcessList() const { |
| 711 | return impl->process_list; | 749 | return impl->process_list; |
| 712 | } | 750 | } |
| 713 | 751 | ||
| @@ -781,6 +819,14 @@ const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { | |||
| 781 | return *impl->exclusive_monitor; | 819 | return *impl->exclusive_monitor; |
| 782 | } | 820 | } |
| 783 | 821 | ||
| 822 | KAutoObjectWithListContainer& KernelCore::ObjectListContainer() { | ||
| 823 | return impl->object_list_container; | ||
| 824 | } | ||
| 825 | |||
| 826 | const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { | ||
| 827 | return impl->object_list_container; | ||
| 828 | } | ||
| 829 | |||
| 784 | void KernelCore::InvalidateAllInstructionCaches() { | 830 | void KernelCore::InvalidateAllInstructionCaches() { |
| 785 | for (auto& physical_core : impl->cores) { | 831 | for (auto& physical_core : impl->cores) { |
| 786 | physical_core.ArmInterface().ClearInstructionCache(); | 832 | physical_core.ArmInterface().ClearInstructionCache(); |
| @@ -800,17 +846,17 @@ void KernelCore::PrepareReschedule(std::size_t id) { | |||
| 800 | // TODO: Reimplement, this | 846 | // TODO: Reimplement, this |
| 801 | } | 847 | } |
| 802 | 848 | ||
| 803 | void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) { | 849 | void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) { |
| 804 | impl->named_ports.emplace(std::move(name), std::move(port)); | 850 | impl->service_interface_factory.emplace(std::move(name), factory); |
| 805 | } | 851 | } |
| 806 | 852 | ||
| 807 | KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) { | 853 | KClientPort* KernelCore::CreateNamedServicePort(std::string name) { |
| 808 | return impl->named_ports.find(name); | 854 | auto search = impl->service_interface_factory.find(name); |
| 809 | } | 855 | if (search == impl->service_interface_factory.end()) { |
| 810 | 856 | UNIMPLEMENTED(); | |
| 811 | KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort( | 857 | return {}; |
| 812 | const std::string& name) const { | 858 | } |
| 813 | return impl->named_ports.find(name); | 859 | return &search->second(impl->system.ServiceManager(), impl->system); |
| 814 | } | 860 | } |
| 815 | 861 | ||
| 816 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 862 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
| @@ -833,12 +879,12 @@ u64 KernelCore::CreateNewUserProcessID() { | |||
| 833 | return impl->next_user_process_id++; | 879 | return impl->next_user_process_id++; |
| 834 | } | 880 | } |
| 835 | 881 | ||
| 836 | Kernel::HandleTable& KernelCore::GlobalHandleTable() { | 882 | KHandleTable& KernelCore::GlobalHandleTable() { |
| 837 | return impl->global_handle_table; | 883 | return *impl->global_handle_table; |
| 838 | } | 884 | } |
| 839 | 885 | ||
| 840 | const Kernel::HandleTable& KernelCore::GlobalHandleTable() const { | 886 | const KHandleTable& KernelCore::GlobalHandleTable() const { |
| 841 | return impl->global_handle_table; | 887 | return *impl->global_handle_table; |
| 842 | } | 888 | } |
| 843 | 889 | ||
| 844 | void KernelCore::RegisterCoreThread(std::size_t core_id) { | 890 | void KernelCore::RegisterCoreThread(std::size_t core_id) { |
| @@ -910,9 +956,9 @@ void KernelCore::Suspend(bool in_suspention) { | |||
| 910 | { | 956 | { |
| 911 | KScopedSchedulerLock lock(*this); | 957 | KScopedSchedulerLock lock(*this); |
| 912 | const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; | 958 | const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; |
| 913 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | 959 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 914 | impl->suspend_threads[i]->SetState(state); | 960 | impl->suspend_threads[core_id]->SetState(state); |
| 915 | impl->suspend_threads[i]->SetWaitReasonForDebugging( | 961 | impl->suspend_threads[core_id]->SetWaitReasonForDebugging( |
| 916 | ThreadWaitReasonForDebugging::Suspended); | 962 | ThreadWaitReasonForDebugging::Suspended); |
| 917 | } | 963 | } |
| 918 | } | 964 | } |
| @@ -952,6 +998,14 @@ void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> servi | |||
| 952 | }); | 998 | }); |
| 953 | } | 999 | } |
| 954 | 1000 | ||
| 1001 | Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() { | ||
| 1002 | return impl->slab_resource_counts; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | const Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() const { | ||
| 1006 | return impl->slab_resource_counts; | ||
| 1007 | } | ||
| 1008 | |||
| 955 | bool KernelCore::IsPhantomModeForSingleCore() const { | 1009 | bool KernelCore::IsPhantomModeForSingleCore() const { |
| 956 | return impl->IsPhantomModeForSingleCore(); | 1010 | return impl->IsPhantomModeForSingleCore(); |
| 957 | } | 1011 | } |
| @@ -960,4 +1014,12 @@ void KernelCore::SetIsPhantomModeForSingleCore(bool value) { | |||
| 960 | impl->SetIsPhantomModeForSingleCore(value); | 1014 | impl->SetIsPhantomModeForSingleCore(value); |
| 961 | } | 1015 | } |
| 962 | 1016 | ||
| 1017 | Core::System& KernelCore::System() { | ||
| 1018 | return impl->system; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | const Core::System& KernelCore::System() const { | ||
| 1022 | return impl->system; | ||
| 1023 | } | ||
| 1024 | |||
| 963 | } // namespace Kernel | 1025 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index a500e63bc..2d01e1ae0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | #include "core/arm/cpu_interrupt_handler.h" | 12 | #include "core/arm/cpu_interrupt_handler.h" |
| 13 | #include "core/hardware_properties.h" | 13 | #include "core/hardware_properties.h" |
| 14 | #include "core/hle/kernel/k_auto_object.h" | ||
| 15 | #include "core/hle/kernel/k_slab_heap.h" | ||
| 14 | #include "core/hle/kernel/memory_types.h" | 16 | #include "core/hle/kernel/memory_types.h" |
| 15 | #include "core/hle/kernel/object.h" | 17 | #include "core/hle/kernel/svc_common.h" |
| 16 | 18 | ||
| 17 | namespace Core { | 19 | namespace Core { |
| 18 | class CPUInterruptHandler; | 20 | class CPUInterruptHandler; |
| @@ -25,22 +27,41 @@ class CoreTiming; | |||
| 25 | struct EventType; | 27 | struct EventType; |
| 26 | } // namespace Core::Timing | 28 | } // namespace Core::Timing |
| 27 | 29 | ||
| 30 | namespace Service::SM { | ||
| 31 | class ServiceManager; | ||
| 32 | } | ||
| 33 | |||
| 28 | namespace Kernel { | 34 | namespace Kernel { |
| 29 | 35 | ||
| 30 | class ClientPort; | 36 | class KClientPort; |
| 31 | class GlobalSchedulerContext; | 37 | class GlobalSchedulerContext; |
| 32 | class HandleTable; | 38 | class KAutoObjectWithListContainer; |
| 39 | class KClientSession; | ||
| 40 | class KEvent; | ||
| 41 | class KHandleTable; | ||
| 42 | class KLinkedListNode; | ||
| 33 | class KMemoryManager; | 43 | class KMemoryManager; |
| 44 | class KPort; | ||
| 45 | class KProcess; | ||
| 34 | class KResourceLimit; | 46 | class KResourceLimit; |
| 35 | class KScheduler; | 47 | class KScheduler; |
| 48 | class KSession; | ||
| 36 | class KSharedMemory; | 49 | class KSharedMemory; |
| 37 | class KThread; | 50 | class KThread; |
| 51 | class KTransferMemory; | ||
| 52 | class KWritableEvent; | ||
| 38 | class PhysicalCore; | 53 | class PhysicalCore; |
| 39 | class Process; | ||
| 40 | class ServiceThread; | 54 | class ServiceThread; |
| 41 | class Synchronization; | 55 | class Synchronization; |
| 42 | class TimeManager; | 56 | class TimeManager; |
| 43 | 57 | ||
| 58 | using ServiceInterfaceFactory = | ||
| 59 | std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; | ||
| 60 | |||
| 61 | namespace Init { | ||
| 62 | struct KSlabResourceCounts; | ||
| 63 | } | ||
| 64 | |||
| 44 | template <typename T> | 65 | template <typename T> |
| 45 | class KSlabHeap; | 66 | class KSlabHeap; |
| 46 | 67 | ||
| @@ -51,7 +72,7 @@ constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63}; | |||
| 51 | /// Represents a single instance of the kernel. | 72 | /// Represents a single instance of the kernel. |
| 52 | class KernelCore { | 73 | class KernelCore { |
| 53 | private: | 74 | private: |
| 54 | using NamedPortTable = std::unordered_map<std::string, std::shared_ptr<ClientPort>>; | 75 | using NamedPortTable = std::unordered_map<std::string, KClientPort*>; |
| 55 | 76 | ||
| 56 | public: | 77 | public: |
| 57 | /// Constructs an instance of the kernel using the given System | 78 | /// Constructs an instance of the kernel using the given System |
| @@ -83,25 +104,28 @@ public: | |||
| 83 | void Shutdown(); | 104 | void Shutdown(); |
| 84 | 105 | ||
| 85 | /// Retrieves a shared pointer to the system resource limit instance. | 106 | /// Retrieves a shared pointer to the system resource limit instance. |
| 86 | std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const; | 107 | const KResourceLimit* GetSystemResourceLimit() const; |
| 108 | |||
| 109 | /// Retrieves a shared pointer to the system resource limit instance. | ||
| 110 | KResourceLimit* GetSystemResourceLimit(); | ||
| 87 | 111 | ||
| 88 | /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. | 112 | /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. |
| 89 | std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; | 113 | KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; |
| 90 | 114 | ||
| 91 | /// Adds the given shared pointer to an internal list of active processes. | 115 | /// Adds the given shared pointer to an internal list of active processes. |
| 92 | void AppendNewProcess(std::shared_ptr<Process> process); | 116 | void AppendNewProcess(KProcess* process); |
| 93 | 117 | ||
| 94 | /// Makes the given process the new current process. | 118 | /// Makes the given process the new current process. |
| 95 | void MakeCurrentProcess(Process* process); | 119 | void MakeCurrentProcess(KProcess* process); |
| 96 | 120 | ||
| 97 | /// Retrieves a pointer to the current process. | 121 | /// Retrieves a pointer to the current process. |
| 98 | Process* CurrentProcess(); | 122 | KProcess* CurrentProcess(); |
| 99 | 123 | ||
| 100 | /// Retrieves a const pointer to the current process. | 124 | /// Retrieves a const pointer to the current process. |
| 101 | const Process* CurrentProcess() const; | 125 | const KProcess* CurrentProcess() const; |
| 102 | 126 | ||
| 103 | /// Retrieves the list of processes. | 127 | /// Retrieves the list of processes. |
| 104 | const std::vector<std::shared_ptr<Process>>& GetProcessList() const; | 128 | const std::vector<KProcess*>& GetProcessList() const; |
| 105 | 129 | ||
| 106 | /// Gets the sole instance of the global scheduler | 130 | /// Gets the sole instance of the global scheduler |
| 107 | Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); | 131 | Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); |
| @@ -143,6 +167,10 @@ public: | |||
| 143 | 167 | ||
| 144 | const Core::ExclusiveMonitor& GetExclusiveMonitor() const; | 168 | const Core::ExclusiveMonitor& GetExclusiveMonitor() const; |
| 145 | 169 | ||
| 170 | KAutoObjectWithListContainer& ObjectListContainer(); | ||
| 171 | |||
| 172 | const KAutoObjectWithListContainer& ObjectListContainer() const; | ||
| 173 | |||
| 146 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts(); | 174 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts(); |
| 147 | 175 | ||
| 148 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; | 176 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; |
| @@ -151,14 +179,11 @@ public: | |||
| 151 | 179 | ||
| 152 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | 180 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); |
| 153 | 181 | ||
| 154 | /// Adds a port to the named port table | 182 | /// Registers a named HLE service, passing a factory used to open a port to that service. |
| 155 | void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); | 183 | void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory); |
| 156 | |||
| 157 | /// Finds a port within the named port table with the given name. | ||
| 158 | NamedPortTable::iterator FindNamedPort(const std::string& name); | ||
| 159 | 184 | ||
| 160 | /// Finds a port within the named port table with the given name. | 185 | /// Opens a port to a service previously registered with RegisterNamedService. |
| 161 | NamedPortTable::const_iterator FindNamedPort(const std::string& name) const; | 186 | KClientPort* CreateNamedServicePort(std::string name); |
| 162 | 187 | ||
| 163 | /// Determines whether or not the given port is a valid named port. | 188 | /// Determines whether or not the given port is a valid named port. |
| 164 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 189 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
| @@ -225,9 +250,10 @@ public: | |||
| 225 | 250 | ||
| 226 | /** | 251 | /** |
| 227 | * Creates an HLE service thread, which are used to execute service routines asynchronously. | 252 | * Creates an HLE service thread, which are used to execute service routines asynchronously. |
| 228 | * While these are allocated per ServerSession, these need to be owned and managed outside of | 253 | * While these are allocated per ServerSession, these need to be owned and managed outside |
| 229 | * ServerSession to avoid a circular dependency. | 254 | * of ServerSession to avoid a circular dependency. |
| 230 | * @param name String name for the ServerSession creating this thread, used for debug purposes. | 255 | * @param name String name for the ServerSession creating this thread, used for debug |
| 256 | * purposes. | ||
| 231 | * @returns The a weak pointer newly created service thread. | 257 | * @returns The a weak pointer newly created service thread. |
| 232 | */ | 258 | */ |
| 233 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); | 259 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); |
| @@ -243,9 +269,45 @@ public: | |||
| 243 | bool IsPhantomModeForSingleCore() const; | 269 | bool IsPhantomModeForSingleCore() const; |
| 244 | void SetIsPhantomModeForSingleCore(bool value); | 270 | void SetIsPhantomModeForSingleCore(bool value); |
| 245 | 271 | ||
| 272 | Core::System& System(); | ||
| 273 | const Core::System& System() const; | ||
| 274 | |||
| 275 | /// Gets the slab heap for the specified kernel object type. | ||
| 276 | template <typename T> | ||
| 277 | KSlabHeap<T>& SlabHeap() { | ||
| 278 | if constexpr (std::is_same_v<T, KClientSession>) { | ||
| 279 | return slab_heap_container->client_session; | ||
| 280 | } else if constexpr (std::is_same_v<T, KEvent>) { | ||
| 281 | return slab_heap_container->event; | ||
| 282 | } else if constexpr (std::is_same_v<T, KLinkedListNode>) { | ||
| 283 | return slab_heap_container->linked_list_node; | ||
| 284 | } else if constexpr (std::is_same_v<T, KPort>) { | ||
| 285 | return slab_heap_container->port; | ||
| 286 | } else if constexpr (std::is_same_v<T, KProcess>) { | ||
| 287 | return slab_heap_container->process; | ||
| 288 | } else if constexpr (std::is_same_v<T, KResourceLimit>) { | ||
| 289 | return slab_heap_container->resource_limit; | ||
| 290 | } else if constexpr (std::is_same_v<T, KSession>) { | ||
| 291 | return slab_heap_container->session; | ||
| 292 | } else if constexpr (std::is_same_v<T, KSharedMemory>) { | ||
| 293 | return slab_heap_container->shared_memory; | ||
| 294 | } else if constexpr (std::is_same_v<T, KThread>) { | ||
| 295 | return slab_heap_container->thread; | ||
| 296 | } else if constexpr (std::is_same_v<T, KTransferMemory>) { | ||
| 297 | return slab_heap_container->transfer_memory; | ||
| 298 | } else if constexpr (std::is_same_v<T, KWritableEvent>) { | ||
| 299 | return slab_heap_container->writeable_event; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | /// Gets the current slab resource counts. | ||
| 304 | Init::KSlabResourceCounts& SlabResourceCounts(); | ||
| 305 | |||
| 306 | /// Gets the current slab resource counts. | ||
| 307 | const Init::KSlabResourceCounts& SlabResourceCounts() const; | ||
| 308 | |||
| 246 | private: | 309 | private: |
| 247 | friend class Object; | 310 | friend class KProcess; |
| 248 | friend class Process; | ||
| 249 | friend class KThread; | 311 | friend class KThread; |
| 250 | 312 | ||
| 251 | /// Creates a new object ID, incrementing the internal object ID counter. | 313 | /// Creates a new object ID, incrementing the internal object ID counter. |
| @@ -261,14 +323,33 @@ private: | |||
| 261 | u64 CreateNewThreadID(); | 323 | u64 CreateNewThreadID(); |
| 262 | 324 | ||
| 263 | /// Provides a reference to the global handle table. | 325 | /// Provides a reference to the global handle table. |
| 264 | Kernel::HandleTable& GlobalHandleTable(); | 326 | KHandleTable& GlobalHandleTable(); |
| 265 | 327 | ||
| 266 | /// Provides a const reference to the global handle table. | 328 | /// Provides a const reference to the global handle table. |
| 267 | const Kernel::HandleTable& GlobalHandleTable() const; | 329 | const KHandleTable& GlobalHandleTable() const; |
| 268 | 330 | ||
| 269 | struct Impl; | 331 | struct Impl; |
| 270 | std::unique_ptr<Impl> impl; | 332 | std::unique_ptr<Impl> impl; |
| 333 | |||
| 271 | bool exception_exited{}; | 334 | bool exception_exited{}; |
| 335 | |||
| 336 | private: | ||
| 337 | /// Helper to encapsulate all slab heaps in a single heap allocated container | ||
| 338 | struct SlabHeapContainer { | ||
| 339 | KSlabHeap<KClientSession> client_session; | ||
| 340 | KSlabHeap<KEvent> event; | ||
| 341 | KSlabHeap<KLinkedListNode> linked_list_node; | ||
| 342 | KSlabHeap<KPort> port; | ||
| 343 | KSlabHeap<KProcess> process; | ||
| 344 | KSlabHeap<KResourceLimit> resource_limit; | ||
| 345 | KSlabHeap<KSession> session; | ||
| 346 | KSlabHeap<KSharedMemory> shared_memory; | ||
| 347 | KSlabHeap<KThread> thread; | ||
| 348 | KSlabHeap<KTransferMemory> transfer_memory; | ||
| 349 | KSlabHeap<KWritableEvent> writeable_event; | ||
| 350 | }; | ||
| 351 | |||
| 352 | std::unique_ptr<SlabHeapContainer> slab_heap_container; | ||
| 272 | }; | 353 | }; |
| 273 | 354 | ||
| 274 | } // namespace Kernel | 355 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp deleted file mode 100644 index d7f40c403..000000000 --- a/src/core/hle/kernel/object.cpp +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "core/hle/kernel/kernel.h" | ||
| 7 | #include "core/hle/kernel/object.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | Object::Object(KernelCore& kernel_) | ||
| 12 | : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {} | ||
| 13 | Object::Object(KernelCore& kernel_, std::string&& name_) | ||
| 14 | : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {} | ||
| 15 | Object::~Object() = default; | ||
| 16 | |||
| 17 | bool Object::IsWaitable() const { | ||
| 18 | switch (GetHandleType()) { | ||
| 19 | case HandleType::ReadableEvent: | ||
| 20 | case HandleType::Thread: | ||
| 21 | case HandleType::Process: | ||
| 22 | case HandleType::ServerPort: | ||
| 23 | case HandleType::ServerSession: | ||
| 24 | return true; | ||
| 25 | |||
| 26 | case HandleType::Unknown: | ||
| 27 | case HandleType::Event: | ||
| 28 | case HandleType::WritableEvent: | ||
| 29 | case HandleType::SharedMemory: | ||
| 30 | case HandleType::TransferMemory: | ||
| 31 | case HandleType::ResourceLimit: | ||
| 32 | case HandleType::ClientPort: | ||
| 33 | case HandleType::ClientSession: | ||
| 34 | case HandleType::Session: | ||
| 35 | return false; | ||
| 36 | } | ||
| 37 | |||
| 38 | UNREACHABLE(); | ||
| 39 | return false; | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h deleted file mode 100644 index 501e58b33..000000000 --- a/src/core/hle/kernel/object.h +++ /dev/null | |||
| @@ -1,96 +0,0 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | #include <memory> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class KernelCore; | ||
| 16 | |||
| 17 | using Handle = u32; | ||
| 18 | |||
| 19 | enum class HandleType : u32 { | ||
| 20 | Unknown, | ||
| 21 | Event, | ||
| 22 | WritableEvent, | ||
| 23 | ReadableEvent, | ||
| 24 | SharedMemory, | ||
| 25 | TransferMemory, | ||
| 26 | Thread, | ||
| 27 | Process, | ||
| 28 | ResourceLimit, | ||
| 29 | ClientPort, | ||
| 30 | ServerPort, | ||
| 31 | ClientSession, | ||
| 32 | ServerSession, | ||
| 33 | Session, | ||
| 34 | }; | ||
| 35 | |||
| 36 | class Object : NonCopyable, public std::enable_shared_from_this<Object> { | ||
| 37 | public: | ||
| 38 | explicit Object(KernelCore& kernel_); | ||
| 39 | explicit Object(KernelCore& kernel_, std::string&& name_); | ||
| 40 | virtual ~Object(); | ||
| 41 | |||
| 42 | /// Returns a unique identifier for the object. For debugging purposes only. | ||
| 43 | u32 GetObjectId() const { | ||
| 44 | return object_id.load(std::memory_order_relaxed); | ||
| 45 | } | ||
| 46 | |||
| 47 | virtual std::string GetTypeName() const { | ||
| 48 | return "[BAD KERNEL OBJECT TYPE]"; | ||
| 49 | } | ||
| 50 | virtual std::string GetName() const { | ||
| 51 | return name; | ||
| 52 | } | ||
| 53 | virtual HandleType GetHandleType() const = 0; | ||
| 54 | |||
| 55 | void Close() { | ||
| 56 | // TODO(bunnei): This is a placeholder to decrement the reference count, which we will use | ||
| 57 | // when we implement KAutoObject instead of using shared_ptr. | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Check if a thread can wait on the object | ||
| 62 | * @return True if a thread can wait on the object, otherwise false | ||
| 63 | */ | ||
| 64 | bool IsWaitable() const; | ||
| 65 | |||
| 66 | virtual void Finalize() = 0; | ||
| 67 | |||
| 68 | protected: | ||
| 69 | /// The kernel instance this object was created under. | ||
| 70 | KernelCore& kernel; | ||
| 71 | |||
| 72 | private: | ||
| 73 | std::atomic<u32> object_id{0}; | ||
| 74 | std::string name; | ||
| 75 | }; | ||
| 76 | |||
| 77 | template <typename T> | ||
| 78 | std::shared_ptr<T> SharedFrom(T* raw) { | ||
| 79 | if (raw == nullptr) | ||
| 80 | return nullptr; | ||
| 81 | return std::static_pointer_cast<T>(raw->shared_from_this()); | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Attempts to downcast the given Object pointer to a pointer to T. | ||
| 86 | * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T. | ||
| 87 | */ | ||
| 88 | template <typename T> | ||
| 89 | inline std::shared_ptr<T> DynamicObjectCast(std::shared_ptr<Object> object) { | ||
| 90 | if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) { | ||
| 91 | return std::static_pointer_cast<T>(object); | ||
| 92 | } | ||
| 93 | return nullptr; | ||
| 94 | } | ||
| 95 | |||
| 96 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 7fea45f96..7f02d9471 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp | |||
| @@ -13,10 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, | 16 | PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, |
| 17 | Kernel::KScheduler& scheduler, Core::CPUInterrupts& interrupts) | 17 | Core::CPUInterrupts& interrupts_) |
| 18 | : core_index{core_index}, system{system}, scheduler{scheduler}, | 18 | : core_index{core_index_}, system{system_}, scheduler{scheduler_}, |
| 19 | interrupts{interrupts}, guard{std::make_unique<Common::SpinLock>()} {} | 19 | interrupts{interrupts_}, guard{std::make_unique<Common::SpinLock>()} {} |
| 20 | 20 | ||
| 21 | PhysicalCore::~PhysicalCore() = default; | 21 | PhysicalCore::~PhysicalCore() = default; |
| 22 | 22 | ||
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index f2b0911aa..901f7e3b0 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h | |||
| @@ -28,8 +28,8 @@ namespace Kernel { | |||
| 28 | 28 | ||
| 29 | class PhysicalCore { | 29 | class PhysicalCore { |
| 30 | public: | 30 | public: |
| 31 | PhysicalCore(std::size_t core_index, Core::System& system, Kernel::KScheduler& scheduler, | 31 | PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, |
| 32 | Core::CPUInterrupts& interrupts); | 32 | Core::CPUInterrupts& interrupts_); |
| 33 | ~PhysicalCore(); | 33 | ~PhysicalCore(); |
| 34 | 34 | ||
| 35 | PhysicalCore(const PhysicalCore&) = delete; | 35 | PhysicalCore(const PhysicalCore&) = delete; |
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 1006ee50c..fcb8b1ea5 100644 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/bit_util.h" | 7 | #include "common/bit_util.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/hle/kernel/handle_table.h" | 9 | #include "core/hle/kernel/k_handle_table.h" |
| 10 | #include "core/hle/kernel/k_page_table.h" | 10 | #include "core/hle/kernel/k_page_table.h" |
| 11 | #include "core/hle/kernel/process_capability.h" | 11 | #include "core/hle/kernel/process_capability.h" |
| 12 | #include "core/hle/kernel/svc_results.h" | 12 | #include "core/hle/kernel/svc_results.h" |
| @@ -99,7 +99,7 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() { | |||
| 99 | interrupt_capabilities.set(); | 99 | interrupt_capabilities.set(); |
| 100 | 100 | ||
| 101 | // Allow using the maximum possible amount of handles | 101 | // Allow using the maximum possible amount of handles |
| 102 | handle_table_size = static_cast<s32>(HandleTable::MAX_COUNT); | 102 | handle_table_size = static_cast<s32>(KHandleTable::MaxTableSize); |
| 103 | 103 | ||
| 104 | // Allow all debugging capabilities. | 104 | // Allow all debugging capabilities. |
| 105 | is_debuggable = true; | 105 | is_debuggable = true; |
| @@ -159,7 +159,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s | |||
| 159 | const auto type = GetCapabilityType(flag); | 159 | const auto type = GetCapabilityType(flag); |
| 160 | 160 | ||
| 161 | if (type == CapabilityType::Unset) { | 161 | if (type == CapabilityType::Unset) { |
| 162 | return ResultInvalidCapabilityDescriptor; | 162 | return ResultInvalidArgument; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | // Bail early on ignorable entries, as one would expect, | 165 | // Bail early on ignorable entries, as one would expect, |
| @@ -202,7 +202,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | LOG_ERROR(Kernel, "Invalid capability type! type={}", type); | 204 | LOG_ERROR(Kernel, "Invalid capability type! type={}", type); |
| 205 | return ResultInvalidCapabilityDescriptor; | 205 | return ResultInvalidArgument; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | void ProcessCapabilities::Clear() { | 208 | void ProcessCapabilities::Clear() { |
| @@ -225,7 +225,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { | |||
| 225 | if (priority_mask != 0 || core_mask != 0) { | 225 | if (priority_mask != 0 || core_mask != 0) { |
| 226 | LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}", | 226 | LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}", |
| 227 | priority_mask, core_mask); | 227 | priority_mask, core_mask); |
| 228 | return ResultInvalidCapabilityDescriptor; | 228 | return ResultInvalidArgument; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | const u32 core_num_min = (flags >> 16) & 0xFF; | 231 | const u32 core_num_min = (flags >> 16) & 0xFF; |
| @@ -329,7 +329,7 @@ ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) { | |||
| 329 | const u32 reserved = flags >> 17; | 329 | const u32 reserved = flags >> 17; |
| 330 | if (reserved != 0) { | 330 | if (reserved != 0) { |
| 331 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); | 331 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); |
| 332 | return ResultReservedValue; | 332 | return ResultReservedUsed; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | program_type = static_cast<ProgramType>((flags >> 14) & 0b111); | 335 | program_type = static_cast<ProgramType>((flags >> 14) & 0b111); |
| @@ -349,7 +349,7 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { | |||
| 349 | LOG_ERROR(Kernel, | 349 | LOG_ERROR(Kernel, |
| 350 | "Kernel version is non zero or flags are too small! major_version={}, flags={}", | 350 | "Kernel version is non zero or flags are too small! major_version={}, flags={}", |
| 351 | major_version, flags); | 351 | major_version, flags); |
| 352 | return ResultInvalidCapabilityDescriptor; | 352 | return ResultInvalidArgument; |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | kernel_version = flags; | 355 | kernel_version = flags; |
| @@ -360,7 +360,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { | |||
| 360 | const u32 reserved = flags >> 26; | 360 | const u32 reserved = flags >> 26; |
| 361 | if (reserved != 0) { | 361 | if (reserved != 0) { |
| 362 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); | 362 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); |
| 363 | return ResultReservedValue; | 363 | return ResultReservedUsed; |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF); | 366 | handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF); |
| @@ -371,7 +371,7 @@ ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) { | |||
| 371 | const u32 reserved = flags >> 19; | 371 | const u32 reserved = flags >> 19; |
| 372 | if (reserved != 0) { | 372 | if (reserved != 0) { |
| 373 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); | 373 | LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); |
| 374 | return ResultReservedValue; | 374 | return ResultReservedUsed; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | is_debuggable = (flags & 0x20000) != 0; | 377 | is_debuggable = (flags & 0x20000) != 0; |
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp deleted file mode 100644 index 5d17346ad..000000000 --- a/src/core/hle/kernel/server_port.cpp +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <tuple> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "core/hle/kernel/client_port.h" | ||
| 8 | #include "core/hle/kernel/k_thread.h" | ||
| 9 | #include "core/hle/kernel/object.h" | ||
| 10 | #include "core/hle/kernel/server_port.h" | ||
| 11 | #include "core/hle/kernel/server_session.h" | ||
| 12 | #include "core/hle/kernel/svc_results.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | ServerPort::ServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} | ||
| 17 | ServerPort::~ServerPort() = default; | ||
| 18 | |||
| 19 | ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() { | ||
| 20 | if (pending_sessions.empty()) { | ||
| 21 | return ResultNotFound; | ||
| 22 | } | ||
| 23 | |||
| 24 | auto session = std::move(pending_sessions.back()); | ||
| 25 | pending_sessions.pop_back(); | ||
| 26 | return MakeResult(std::move(session)); | ||
| 27 | } | ||
| 28 | |||
| 29 | void ServerPort::AppendPendingSession(std::shared_ptr<ServerSession> pending_session) { | ||
| 30 | pending_sessions.push_back(std::move(pending_session)); | ||
| 31 | if (pending_sessions.size() == 1) { | ||
| 32 | NotifyAvailable(); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | bool ServerPort::IsSignaled() const { | ||
| 37 | return !pending_sessions.empty(); | ||
| 38 | } | ||
| 39 | |||
| 40 | ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, | ||
| 41 | std::string name) { | ||
| 42 | std::shared_ptr<ServerPort> server_port = std::make_shared<ServerPort>(kernel); | ||
| 43 | std::shared_ptr<ClientPort> client_port = std::make_shared<ClientPort>(kernel); | ||
| 44 | |||
| 45 | server_port->name = name + "_Server"; | ||
| 46 | client_port->name = name + "_Client"; | ||
| 47 | client_port->server_port = server_port; | ||
| 48 | client_port->max_sessions = max_sessions; | ||
| 49 | client_port->active_sessions = 0; | ||
| 50 | |||
| 51 | return std::make_pair(std::move(server_port), std::move(client_port)); | ||
| 52 | } | ||
| 53 | |||
| 54 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h deleted file mode 100644 index 29b4f2509..000000000 --- a/src/core/hle/kernel/server_port.h +++ /dev/null | |||
| @@ -1,98 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <utility> | ||
| 10 | #include <vector> | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 13 | #include "core/hle/kernel/object.h" | ||
| 14 | #include "core/hle/result.h" | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | class ClientPort; | ||
| 19 | class KernelCore; | ||
| 20 | class ServerSession; | ||
| 21 | class SessionRequestHandler; | ||
| 22 | |||
| 23 | class ServerPort final : public KSynchronizationObject { | ||
| 24 | public: | ||
| 25 | explicit ServerPort(KernelCore& kernel); | ||
| 26 | ~ServerPort() override; | ||
| 27 | |||
| 28 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; | ||
| 29 | using PortPair = std::pair<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>>; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Creates a pair of ServerPort and an associated ClientPort. | ||
| 33 | * | ||
| 34 | * @param kernel The kernel instance to create the port pair under. | ||
| 35 | * @param max_sessions Maximum number of sessions to the port | ||
| 36 | * @param name Optional name of the ports | ||
| 37 | * @return The created port tuple | ||
| 38 | */ | ||
| 39 | static PortPair CreatePortPair(KernelCore& kernel, u32 max_sessions, | ||
| 40 | std::string name = "UnknownPort"); | ||
| 41 | |||
| 42 | std::string GetTypeName() const override { | ||
| 43 | return "ServerPort"; | ||
| 44 | } | ||
| 45 | std::string GetName() const override { | ||
| 46 | return name; | ||
| 47 | } | ||
| 48 | |||
| 49 | static constexpr HandleType HANDLE_TYPE = HandleType::ServerPort; | ||
| 50 | HandleType GetHandleType() const override { | ||
| 51 | return HANDLE_TYPE; | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Accepts a pending incoming connection on this port. If there are no pending sessions, will | ||
| 56 | * return ERR_NO_PENDING_SESSIONS. | ||
| 57 | */ | ||
| 58 | ResultVal<std::shared_ptr<ServerSession>> Accept(); | ||
| 59 | |||
| 60 | /// Whether or not this server port has an HLE handler available. | ||
| 61 | bool HasHLEHandler() const { | ||
| 62 | return hle_handler != nullptr; | ||
| 63 | } | ||
| 64 | |||
| 65 | /// Gets the HLE handler for this port. | ||
| 66 | HLEHandler GetHLEHandler() const { | ||
| 67 | return hle_handler; | ||
| 68 | } | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port | ||
| 72 | * will inherit a reference to this handler. | ||
| 73 | */ | ||
| 74 | void SetHleHandler(HLEHandler hle_handler_) { | ||
| 75 | hle_handler = std::move(hle_handler_); | ||
| 76 | } | ||
| 77 | |||
| 78 | /// Appends a ServerSession to the collection of ServerSessions | ||
| 79 | /// waiting to be accepted by this port. | ||
| 80 | void AppendPendingSession(std::shared_ptr<ServerSession> pending_session); | ||
| 81 | |||
| 82 | bool IsSignaled() const override; | ||
| 83 | |||
| 84 | void Finalize() override {} | ||
| 85 | |||
| 86 | private: | ||
| 87 | /// ServerSessions waiting to be accepted by the port | ||
| 88 | std::vector<std::shared_ptr<ServerSession>> pending_sessions; | ||
| 89 | |||
| 90 | /// This session's HLE request handler template (optional) | ||
| 91 | /// ServerSessions created from this port inherit a reference to this handler. | ||
| 92 | HLEHandler hle_handler; | ||
| 93 | |||
| 94 | /// Name of the port (optional) | ||
| 95 | std::string name; | ||
| 96 | }; | ||
| 97 | |||
| 98 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index ee46f3e21..04be8a502 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include "common/scope_exit.h" | 13 | #include "common/scope_exit.h" |
| 14 | #include "common/thread.h" | 14 | #include "common/thread.h" |
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/hle/kernel/k_session.h" | ||
| 16 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/server_session.h" | ||
| 18 | #include "core/hle/kernel/service_thread.h" | 18 | #include "core/hle/kernel/service_thread.h" |
| 19 | #include "core/hle/lock.h" | 19 | #include "core/hle/lock.h" |
| 20 | #include "video_core/renderer_base.h" | 20 | #include "video_core/renderer_base.h" |
| @@ -26,7 +26,7 @@ public: | |||
| 26 | explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name); | 26 | explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name); |
| 27 | ~Impl(); | 27 | ~Impl(); |
| 28 | 28 | ||
| 29 | void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context); | 29 | void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); |
| 30 | 30 | ||
| 31 | private: | 31 | private: |
| 32 | std::vector<std::thread> threads; | 32 | std::vector<std::thread> threads; |
| @@ -69,18 +69,27 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std | |||
| 69 | }); | 69 | }); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void ServiceThread::Impl::QueueSyncRequest(ServerSession& session, | 72 | void ServiceThread::Impl::QueueSyncRequest(KSession& session, |
| 73 | std::shared_ptr<HLERequestContext>&& context) { | 73 | std::shared_ptr<HLERequestContext>&& context) { |
| 74 | { | 74 | { |
| 75 | std::unique_lock lock{queue_mutex}; | 75 | std::unique_lock lock{queue_mutex}; |
| 76 | 76 | ||
| 77 | // ServerSession owns the service thread, so we cannot caption a strong pointer here in the | 77 | // Open a reference to the session to ensure it is not closes while the service request |
| 78 | // event that the ServerSession is terminated. | 78 | // completes asynchronously. |
| 79 | std::weak_ptr<ServerSession> weak_ptr{SharedFrom(&session)}; | 79 | session.Open(); |
| 80 | requests.emplace([weak_ptr, context{std::move(context)}]() { | 80 | |
| 81 | if (auto strong_ptr = weak_ptr.lock()) { | 81 | requests.emplace([session_ptr{&session}, context{std::move(context)}]() { |
| 82 | strong_ptr->CompleteSyncRequest(*context); | 82 | // Close the reference. |
| 83 | SCOPE_EXIT({ session_ptr->Close(); }); | ||
| 84 | |||
| 85 | // If the session has been closed, we are done. | ||
| 86 | if (session_ptr->IsServerClosed()) { | ||
| 87 | return; | ||
| 83 | } | 88 | } |
| 89 | |||
| 90 | // Complete the service request. | ||
| 91 | KScopedAutoObject server_session{&session_ptr->GetServerSession()}; | ||
| 92 | server_session->CompleteSyncRequest(*context); | ||
| 84 | }); | 93 | }); |
| 85 | } | 94 | } |
| 86 | condition.notify_one(); | 95 | condition.notify_one(); |
| @@ -102,7 +111,7 @@ ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const | |||
| 102 | 111 | ||
| 103 | ServiceThread::~ServiceThread() = default; | 112 | ServiceThread::~ServiceThread() = default; |
| 104 | 113 | ||
| 105 | void ServiceThread::QueueSyncRequest(ServerSession& session, | 114 | void ServiceThread::QueueSyncRequest(KSession& session, |
| 106 | std::shared_ptr<HLERequestContext>&& context) { | 115 | std::shared_ptr<HLERequestContext>&& context) { |
| 107 | impl->QueueSyncRequest(session, std::move(context)); | 116 | impl->QueueSyncRequest(session, std::move(context)); |
| 108 | } | 117 | } |
diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h index 025ab8fb5..6a7fd7c56 100644 --- a/src/core/hle/kernel/service_thread.h +++ b/src/core/hle/kernel/service_thread.h | |||
| @@ -11,14 +11,14 @@ namespace Kernel { | |||
| 11 | 11 | ||
| 12 | class HLERequestContext; | 12 | class HLERequestContext; |
| 13 | class KernelCore; | 13 | class KernelCore; |
| 14 | class ServerSession; | 14 | class KSession; |
| 15 | 15 | ||
| 16 | class ServiceThread final { | 16 | class ServiceThread final { |
| 17 | public: | 17 | public: |
| 18 | explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name); | 18 | explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name); |
| 19 | ~ServiceThread(); | 19 | ~ServiceThread(); |
| 20 | 20 | ||
| 21 | void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context); | 21 | void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); |
| 22 | 22 | ||
| 23 | private: | 23 | private: |
| 24 | class Impl; | 24 | class Impl; |
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp deleted file mode 100644 index 8830d4e91..000000000 --- a/src/core/hle/kernel/session.cpp +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "core/hle/kernel/client_session.h" | ||
| 7 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 8 | #include "core/hle/kernel/server_session.h" | ||
| 9 | #include "core/hle/kernel/session.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {} | ||
| 14 | Session::~Session() { | ||
| 15 | // Release reserved resource when the Session pair was created. | ||
| 16 | kernel.GetSystemResourceLimit()->Release(LimitableResource::Sessions, 1); | ||
| 17 | } | ||
| 18 | |||
| 19 | Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { | ||
| 20 | // Reserve a new session from the resource limit. | ||
| 21 | KScopedResourceReservation session_reservation(kernel.GetSystemResourceLimit(), | ||
| 22 | LimitableResource::Sessions); | ||
| 23 | ASSERT(session_reservation.Succeeded()); | ||
| 24 | auto session{std::make_shared<Session>(kernel)}; | ||
| 25 | auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()}; | ||
| 26 | auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()}; | ||
| 27 | |||
| 28 | session->name = std::move(name); | ||
| 29 | session->client = client_session; | ||
| 30 | session->server = server_session; | ||
| 31 | |||
| 32 | session_reservation.Commit(); | ||
| 33 | return std::make_pair(std::move(client_session), std::move(server_session)); | ||
| 34 | } | ||
| 35 | |||
| 36 | bool Session::IsSignaled() const { | ||
| 37 | UNIMPLEMENTED(); | ||
| 38 | return true; | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h deleted file mode 100644 index fa3c5651a..000000000 --- a/src/core/hle/kernel/session.h +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <utility> | ||
| 10 | |||
| 11 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class ClientSession; | ||
| 16 | class ServerSession; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Parent structure to link the client and server endpoints of a session with their associated | ||
| 20 | * client port. | ||
| 21 | */ | ||
| 22 | class Session final : public KSynchronizationObject { | ||
| 23 | public: | ||
| 24 | explicit Session(KernelCore& kernel); | ||
| 25 | ~Session() override; | ||
| 26 | |||
| 27 | using SessionPair = std::pair<std::shared_ptr<ClientSession>, std::shared_ptr<ServerSession>>; | ||
| 28 | |||
| 29 | static SessionPair Create(KernelCore& kernel, std::string name = "Unknown"); | ||
| 30 | |||
| 31 | std::string GetName() const override { | ||
| 32 | return name; | ||
| 33 | } | ||
| 34 | |||
| 35 | static constexpr HandleType HANDLE_TYPE = HandleType::Session; | ||
| 36 | HandleType GetHandleType() const override { | ||
| 37 | return HANDLE_TYPE; | ||
| 38 | } | ||
| 39 | |||
| 40 | bool IsSignaled() const override; | ||
| 41 | |||
| 42 | void Finalize() override {} | ||
| 43 | |||
| 44 | std::shared_ptr<ClientSession> Client() { | ||
| 45 | if (auto result{client.lock()}) { | ||
| 46 | return result; | ||
| 47 | } | ||
| 48 | return {}; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::shared_ptr<ServerSession> Server() { | ||
| 52 | if (auto result{server.lock()}) { | ||
| 53 | return result; | ||
| 54 | } | ||
| 55 | return {}; | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::string name; | ||
| 60 | std::weak_ptr<ClientSession> client; | ||
| 61 | std::weak_ptr<ServerSession> server; | ||
| 62 | }; | ||
| 63 | |||
| 64 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h new file mode 100644 index 000000000..d0f7f084b --- /dev/null +++ b/src/core/hle/kernel/slab_helpers.h | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/intrusive_red_black_tree.h" | ||
| 13 | #include "core/hle/kernel/k_auto_object.h" | ||
| 14 | #include "core/hle/kernel/k_auto_object_container.h" | ||
| 15 | #include "core/hle/kernel/k_light_lock.h" | ||
| 16 | #include "core/hle/kernel/k_slab_heap.h" | ||
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | |||
| 19 | namespace Kernel { | ||
| 20 | |||
| 21 | template <class Derived> | ||
| 22 | class KSlabAllocated { | ||
| 23 | public: | ||
| 24 | constexpr KSlabAllocated() = default; | ||
| 25 | |||
| 26 | size_t GetSlabIndex(KernelCore& kernel) const { | ||
| 27 | return kernel.SlabHeap<Derived>().GetIndex(static_cast<const Derived*>(this)); | ||
| 28 | } | ||
| 29 | |||
| 30 | public: | ||
| 31 | static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) { | ||
| 32 | kernel.SlabHeap<Derived>().Initialize(memory, memory_size); | ||
| 33 | } | ||
| 34 | |||
| 35 | static Derived* Allocate(KernelCore& kernel) { | ||
| 36 | return kernel.SlabHeap<Derived>().Allocate(); | ||
| 37 | } | ||
| 38 | |||
| 39 | static void Free(KernelCore& kernel, Derived* obj) { | ||
| 40 | kernel.SlabHeap<Derived>().Free(obj); | ||
| 41 | } | ||
| 42 | |||
| 43 | static size_t GetObjectSize(KernelCore& kernel) { | ||
| 44 | return kernel.SlabHeap<Derived>().GetObjectSize(); | ||
| 45 | } | ||
| 46 | |||
| 47 | static size_t GetSlabHeapSize(KernelCore& kernel) { | ||
| 48 | return kernel.SlabHeap<Derived>().GetSlabHeapSize(); | ||
| 49 | } | ||
| 50 | |||
| 51 | static size_t GetPeakIndex(KernelCore& kernel) { | ||
| 52 | return kernel.SlabHeap<Derived>().GetPeakIndex(); | ||
| 53 | } | ||
| 54 | |||
| 55 | static uintptr_t GetSlabHeapAddress(KernelCore& kernel) { | ||
| 56 | return kernel.SlabHeap<Derived>().GetSlabHeapAddress(); | ||
| 57 | } | ||
| 58 | |||
| 59 | static size_t GetNumRemaining(KernelCore& kernel) { | ||
| 60 | return kernel.SlabHeap<Derived>().GetNumRemaining(); | ||
| 61 | } | ||
| 62 | }; | ||
| 63 | |||
| 64 | template <typename Derived, typename Base> | ||
| 65 | class KAutoObjectWithSlabHeapAndContainer : public Base { | ||
| 66 | static_assert(std::is_base_of<KAutoObjectWithList, Base>::value); | ||
| 67 | |||
| 68 | private: | ||
| 69 | static Derived* Allocate(KernelCore& kernel) { | ||
| 70 | return new Derived(kernel); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void Free(KernelCore& kernel, Derived* obj) { | ||
| 74 | delete obj; | ||
| 75 | } | ||
| 76 | |||
| 77 | public: | ||
| 78 | KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel_) : Base(kernel_), kernel(kernel_) {} | ||
| 79 | virtual ~KAutoObjectWithSlabHeapAndContainer() {} | ||
| 80 | |||
| 81 | virtual void Destroy() override { | ||
| 82 | const bool is_initialized = this->IsInitialized(); | ||
| 83 | uintptr_t arg = 0; | ||
| 84 | if (is_initialized) { | ||
| 85 | kernel.ObjectListContainer().Unregister(this); | ||
| 86 | arg = this->GetPostDestroyArgument(); | ||
| 87 | this->Finalize(); | ||
| 88 | } | ||
| 89 | Free(kernel, static_cast<Derived*>(this)); | ||
| 90 | if (is_initialized) { | ||
| 91 | Derived::PostDestroy(arg); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | virtual bool IsInitialized() const { | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | virtual uintptr_t GetPostDestroyArgument() const { | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | size_t GetSlabIndex() const { | ||
| 103 | return SlabHeap<Derived>(kernel).GetObjectIndex(static_cast<const Derived*>(this)); | ||
| 104 | } | ||
| 105 | |||
| 106 | public: | ||
| 107 | static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) { | ||
| 108 | kernel.SlabHeap<Derived>().Initialize(memory, memory_size); | ||
| 109 | kernel.ObjectListContainer().Initialize(); | ||
| 110 | } | ||
| 111 | |||
| 112 | static Derived* Create(KernelCore& kernel) { | ||
| 113 | Derived* obj = Allocate(kernel); | ||
| 114 | if (obj != nullptr) { | ||
| 115 | KAutoObject::Create(obj); | ||
| 116 | } | ||
| 117 | return obj; | ||
| 118 | } | ||
| 119 | |||
| 120 | static void Register(KernelCore& kernel, Derived* obj) { | ||
| 121 | return kernel.ObjectListContainer().Register(obj); | ||
| 122 | } | ||
| 123 | |||
| 124 | static size_t GetObjectSize(KernelCore& kernel) { | ||
| 125 | return kernel.SlabHeap<Derived>().GetObjectSize(); | ||
| 126 | } | ||
| 127 | |||
| 128 | static size_t GetSlabHeapSize(KernelCore& kernel) { | ||
| 129 | return kernel.SlabHeap<Derived>().GetSlabHeapSize(); | ||
| 130 | } | ||
| 131 | |||
| 132 | static size_t GetPeakIndex(KernelCore& kernel) { | ||
| 133 | return kernel.SlabHeap<Derived>().GetPeakIndex(); | ||
| 134 | } | ||
| 135 | |||
| 136 | static uintptr_t GetSlabHeapAddress(KernelCore& kernel) { | ||
| 137 | return kernel.SlabHeap<Derived>().GetSlabHeapAddress(); | ||
| 138 | } | ||
| 139 | |||
| 140 | static size_t GetNumRemaining(KernelCore& kernel) { | ||
| 141 | return kernel.SlabHeap<Derived>().GetNumRemaining(); | ||
| 142 | } | ||
| 143 | |||
| 144 | protected: | ||
| 145 | KernelCore& kernel; | ||
| 146 | }; | ||
| 147 | |||
| 148 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bebb86154..81e23f700 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -21,15 +21,16 @@ | |||
| 21 | #include "core/core_timing.h" | 21 | #include "core/core_timing.h" |
| 22 | #include "core/core_timing_util.h" | 22 | #include "core/core_timing_util.h" |
| 23 | #include "core/cpu_manager.h" | 23 | #include "core/cpu_manager.h" |
| 24 | #include "core/hle/kernel/client_port.h" | ||
| 25 | #include "core/hle/kernel/client_session.h" | ||
| 26 | #include "core/hle/kernel/handle_table.h" | ||
| 27 | #include "core/hle/kernel/k_address_arbiter.h" | 24 | #include "core/hle/kernel/k_address_arbiter.h" |
| 25 | #include "core/hle/kernel/k_client_port.h" | ||
| 26 | #include "core/hle/kernel/k_client_session.h" | ||
| 28 | #include "core/hle/kernel/k_condition_variable.h" | 27 | #include "core/hle/kernel/k_condition_variable.h" |
| 29 | #include "core/hle/kernel/k_event.h" | 28 | #include "core/hle/kernel/k_event.h" |
| 29 | #include "core/hle/kernel/k_handle_table.h" | ||
| 30 | #include "core/hle/kernel/k_memory_block.h" | 30 | #include "core/hle/kernel/k_memory_block.h" |
| 31 | #include "core/hle/kernel/k_memory_layout.h" | 31 | #include "core/hle/kernel/k_memory_layout.h" |
| 32 | #include "core/hle/kernel/k_page_table.h" | 32 | #include "core/hle/kernel/k_page_table.h" |
| 33 | #include "core/hle/kernel/k_process.h" | ||
| 33 | #include "core/hle/kernel/k_readable_event.h" | 34 | #include "core/hle/kernel/k_readable_event.h" |
| 34 | #include "core/hle/kernel/k_resource_limit.h" | 35 | #include "core/hle/kernel/k_resource_limit.h" |
| 35 | #include "core/hle/kernel/k_scheduler.h" | 36 | #include "core/hle/kernel/k_scheduler.h" |
| @@ -38,16 +39,15 @@ | |||
| 38 | #include "core/hle/kernel/k_shared_memory.h" | 39 | #include "core/hle/kernel/k_shared_memory.h" |
| 39 | #include "core/hle/kernel/k_synchronization_object.h" | 40 | #include "core/hle/kernel/k_synchronization_object.h" |
| 40 | #include "core/hle/kernel/k_thread.h" | 41 | #include "core/hle/kernel/k_thread.h" |
| 42 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 41 | #include "core/hle/kernel/k_writable_event.h" | 43 | #include "core/hle/kernel/k_writable_event.h" |
| 42 | #include "core/hle/kernel/kernel.h" | 44 | #include "core/hle/kernel/kernel.h" |
| 43 | #include "core/hle/kernel/physical_core.h" | 45 | #include "core/hle/kernel/physical_core.h" |
| 44 | #include "core/hle/kernel/process.h" | ||
| 45 | #include "core/hle/kernel/svc.h" | 46 | #include "core/hle/kernel/svc.h" |
| 46 | #include "core/hle/kernel/svc_results.h" | 47 | #include "core/hle/kernel/svc_results.h" |
| 47 | #include "core/hle/kernel/svc_types.h" | 48 | #include "core/hle/kernel/svc_types.h" |
| 48 | #include "core/hle/kernel/svc_wrap.h" | 49 | #include "core/hle/kernel/svc_wrap.h" |
| 49 | #include "core/hle/kernel/time_manager.h" | 50 | #include "core/hle/kernel/time_manager.h" |
| 50 | #include "core/hle/kernel/transfer_memory.h" | ||
| 51 | #include "core/hle/lock.h" | 51 | #include "core/hle/lock.h" |
| 52 | #include "core/hle/result.h" | 52 | #include "core/hle/result.h" |
| 53 | #include "core/hle/service/service.h" | 53 | #include "core/hle/service/service.h" |
| @@ -113,7 +113,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, | |||
| 113 | LOG_ERROR(Kernel_SVC, | 113 | LOG_ERROR(Kernel_SVC, |
| 114 | "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", | 114 | "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", |
| 115 | dst_addr, size); | 115 | dst_addr, size); |
| 116 | return ResultInvalidMemoryRange; | 116 | return ResultInvalidMemoryRegion; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | if (manager.IsInsideHeapRegion(dst_addr, size)) { | 119 | if (manager.IsInsideHeapRegion(dst_addr, size)) { |
| @@ -121,7 +121,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, | |||
| 121 | "Destination does not fit within the heap region, addr=0x{:016X}, " | 121 | "Destination does not fit within the heap region, addr=0x{:016X}, " |
| 122 | "size=0x{:016X}", | 122 | "size=0x{:016X}", |
| 123 | dst_addr, size); | 123 | dst_addr, size); |
| 124 | return ResultInvalidMemoryRange; | 124 | return ResultInvalidMemoryRegion; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | if (manager.IsInsideAliasRegion(dst_addr, size)) { | 127 | if (manager.IsInsideAliasRegion(dst_addr, size)) { |
| @@ -129,7 +129,7 @@ ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, | |||
| 129 | "Destination does not fit within the map region, addr=0x{:016X}, " | 129 | "Destination does not fit within the map region, addr=0x{:016X}, " |
| 130 | "size=0x{:016X}", | 130 | "size=0x{:016X}", |
| 131 | dst_addr, size); | 131 | dst_addr, size); |
| 132 | return ResultInvalidMemoryRange; | 132 | return ResultInvalidMemoryRegion; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | return RESULT_SUCCESS; | 135 | return RESULT_SUCCESS; |
| @@ -141,38 +141,6 @@ enum class ResourceLimitValueType { | |||
| 141 | PeakValue, | 141 | PeakValue, |
| 142 | }; | 142 | }; |
| 143 | 143 | ||
| 144 | ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, | ||
| 145 | u32 resource_type, ResourceLimitValueType value_type) { | ||
| 146 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 147 | const auto type = static_cast<LimitableResource>(resource_type); | ||
| 148 | if (!IsValidResourceType(type)) { | ||
| 149 | LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); | ||
| 150 | return ResultInvalidEnumValue; | ||
| 151 | } | ||
| 152 | |||
| 153 | const auto* const current_process = system.Kernel().CurrentProcess(); | ||
| 154 | ASSERT(current_process != nullptr); | ||
| 155 | |||
| 156 | const auto resource_limit_object = | ||
| 157 | current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); | ||
| 158 | if (!resource_limit_object) { | ||
| 159 | LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", | ||
| 160 | resource_limit); | ||
| 161 | return ResultInvalidHandle; | ||
| 162 | } | ||
| 163 | |||
| 164 | switch (value_type) { | ||
| 165 | case ResourceLimitValueType::CurrentValue: | ||
| 166 | return MakeResult(resource_limit_object->GetCurrentValue(type)); | ||
| 167 | case ResourceLimitValueType::LimitValue: | ||
| 168 | return MakeResult(resource_limit_object->GetLimitValue(type)); | ||
| 169 | case ResourceLimitValueType::PeakValue: | ||
| 170 | return MakeResult(resource_limit_object->GetPeakValue(type)); | ||
| 171 | default: | ||
| 172 | LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type); | ||
| 173 | return ResultInvalidEnumValue; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } // Anonymous namespace | 144 | } // Anonymous namespace |
| 177 | 145 | ||
| 178 | /// Set the process heap to a given Size. It can both extend and shrink the heap. | 146 | /// Set the process heap to a given Size. It can both extend and shrink the heap. |
| @@ -291,11 +259,8 @@ static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr | |||
| 291 | } | 259 | } |
| 292 | 260 | ||
| 293 | /// Connect to an OS service given the port name, returns the handle to the port to out | 261 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 294 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | 262 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) { |
| 295 | VAddr port_name_address) { | ||
| 296 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 297 | auto& memory = system.Memory(); | 263 | auto& memory = system.Memory(); |
| 298 | |||
| 299 | if (!memory.IsValidVirtualAddress(port_name_address)) { | 264 | if (!memory.IsValidVirtualAddress(port_name_address)) { |
| 300 | LOG_ERROR(Kernel_SVC, | 265 | LOG_ERROR(Kernel_SVC, |
| 301 | "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", | 266 | "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", |
| @@ -314,21 +279,32 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | |||
| 314 | 279 | ||
| 315 | LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); | 280 | LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); |
| 316 | 281 | ||
| 282 | // Get the current handle table. | ||
| 317 | auto& kernel = system.Kernel(); | 283 | auto& kernel = system.Kernel(); |
| 318 | const auto it = kernel.FindNamedPort(port_name); | 284 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 319 | if (!kernel.IsValidNamedPort(it)) { | 285 | |
| 320 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); | 286 | // Find the client port. |
| 287 | auto port = kernel.CreateNamedServicePort(port_name); | ||
| 288 | if (!port) { | ||
| 289 | LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name); | ||
| 321 | return ResultNotFound; | 290 | return ResultNotFound; |
| 322 | } | 291 | } |
| 323 | 292 | ||
| 324 | auto client_port = it->second; | 293 | // Reserve a handle for the port. |
| 294 | // NOTE: Nintendo really does write directly to the output handle here. | ||
| 295 | R_TRY(handle_table.Reserve(out)); | ||
| 296 | auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); }); | ||
| 325 | 297 | ||
| 326 | std::shared_ptr<ClientSession> client_session; | 298 | // Create a session. |
| 327 | CASCADE_RESULT(client_session, client_port->Connect()); | 299 | KClientSession* session{}; |
| 300 | R_TRY(port->CreateSession(std::addressof(session))); | ||
| 328 | 301 | ||
| 329 | // Return the client session | 302 | // Register the session in the table, close the extra reference. |
| 330 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 303 | handle_table.Register(*out, session); |
| 331 | CASCADE_RESULT(*out_handle, handle_table.Create(client_session)); | 304 | session->Close(); |
| 305 | |||
| 306 | // We succeeded. | ||
| 307 | handle_guard.Cancel(); | ||
| 332 | return RESULT_SUCCESS; | 308 | return RESULT_SUCCESS; |
| 333 | } | 309 | } |
| 334 | 310 | ||
| @@ -340,14 +316,12 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, | |||
| 340 | 316 | ||
| 341 | /// Makes a blocking IPC call to an OS service. | 317 | /// Makes a blocking IPC call to an OS service. |
| 342 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 318 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { |
| 319 | |||
| 343 | auto& kernel = system.Kernel(); | 320 | auto& kernel = system.Kernel(); |
| 344 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | ||
| 345 | std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle); | ||
| 346 | if (!session) { | ||
| 347 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); | ||
| 348 | return ResultInvalidHandle; | ||
| 349 | } | ||
| 350 | 321 | ||
| 322 | KScopedAutoObject session = | ||
| 323 | kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); | ||
| 324 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 351 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | 325 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); |
| 352 | 326 | ||
| 353 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); | 327 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| @@ -355,7 +329,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 355 | KScopedSchedulerLock lock(kernel); | 329 | KScopedSchedulerLock lock(kernel); |
| 356 | thread->SetState(ThreadState::Waiting); | 330 | thread->SetState(ThreadState::Waiting); |
| 357 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); | 331 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); |
| 358 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); | 332 | session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); |
| 359 | } | 333 | } |
| 360 | 334 | ||
| 361 | KSynchronizationObject* dummy{}; | 335 | KSynchronizationObject* dummy{}; |
| @@ -368,18 +342,13 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { | |||
| 368 | 342 | ||
| 369 | /// Get the ID for the specified thread. | 343 | /// Get the ID for the specified thread. |
| 370 | static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { | 344 | static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { |
| 371 | LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); | ||
| 372 | |||
| 373 | // Get the thread from its handle. | 345 | // Get the thread from its handle. |
| 374 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 346 | KScopedAutoObject thread = |
| 375 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 347 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 376 | if (!thread) { | 348 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 377 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 378 | return ResultInvalidHandle; | ||
| 379 | } | ||
| 380 | 349 | ||
| 381 | // Get the thread's id. | 350 | // Get the thread's id. |
| 382 | *out_thread_id = thread->GetThreadID(); | 351 | *out_thread_id = thread->GetId(); |
| 383 | return RESULT_SUCCESS; | 352 | return RESULT_SUCCESS; |
| 384 | } | 353 | } |
| 385 | 354 | ||
| @@ -395,110 +364,101 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low, | |||
| 395 | } | 364 | } |
| 396 | 365 | ||
| 397 | /// Gets the ID of the specified process or a specified thread's owning process. | 366 | /// Gets the ID of the specified process or a specified thread's owning process. |
| 398 | static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { | 367 | static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { |
| 399 | LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); | 368 | LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); |
| 400 | 369 | ||
| 401 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 370 | // Get the object from the handle table. |
| 402 | const std::shared_ptr<Process> process = handle_table.Get<Process>(handle); | 371 | KScopedAutoObject obj = |
| 403 | if (process) { | 372 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KAutoObject>( |
| 404 | *process_id = process->GetProcessID(); | 373 | static_cast<Handle>(handle)); |
| 405 | return RESULT_SUCCESS; | 374 | R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); |
| 375 | |||
| 376 | // Get the process from the object. | ||
| 377 | KProcess* process = nullptr; | ||
| 378 | if (KProcess* p = obj->DynamicCast<KProcess*>(); p != nullptr) { | ||
| 379 | // The object is a process, so we can use it directly. | ||
| 380 | process = p; | ||
| 381 | } else if (KThread* t = obj->DynamicCast<KThread*>(); t != nullptr) { | ||
| 382 | // The object is a thread, so we want to use its parent. | ||
| 383 | process = reinterpret_cast<KThread*>(obj.GetPointerUnsafe())->GetOwnerProcess(); | ||
| 384 | } else { | ||
| 385 | // TODO(bunnei): This should also handle debug objects before returning. | ||
| 386 | UNIMPLEMENTED_MSG("Debug objects not implemented"); | ||
| 406 | } | 387 | } |
| 407 | 388 | ||
| 408 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 389 | // Make sure the target process exists. |
| 409 | if (thread) { | 390 | R_UNLESS(process != nullptr, ResultInvalidHandle); |
| 410 | const Process* const owner_process = thread->GetOwnerProcess(); | ||
| 411 | if (!owner_process) { | ||
| 412 | LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered."); | ||
| 413 | return ResultInvalidHandle; | ||
| 414 | } | ||
| 415 | |||
| 416 | *process_id = owner_process->GetProcessID(); | ||
| 417 | return RESULT_SUCCESS; | ||
| 418 | } | ||
| 419 | 391 | ||
| 420 | // NOTE: This should also handle debug objects before returning. | 392 | // Get the process id. |
| 393 | *out_process_id = process->GetId(); | ||
| 421 | 394 | ||
| 422 | LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle); | ||
| 423 | return ResultInvalidHandle; | 395 | return ResultInvalidHandle; |
| 424 | } | 396 | } |
| 425 | 397 | ||
| 426 | static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high, | 398 | static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, |
| 427 | Handle handle) { | 399 | u32* out_process_id_high, Handle handle) { |
| 428 | u64 process_id{}; | 400 | u64 out_process_id{}; |
| 429 | const auto result = GetProcessId(system, &process_id, handle); | 401 | const auto result = GetProcessId(system, &out_process_id, handle); |
| 430 | *process_id_low = static_cast<u32>(process_id); | 402 | *out_process_id_low = static_cast<u32>(out_process_id); |
| 431 | *process_id_high = static_cast<u32>(process_id >> 32); | 403 | *out_process_id_high = static_cast<u32>(out_process_id >> 32); |
| 432 | return result; | 404 | return result; |
| 433 | } | 405 | } |
| 434 | 406 | ||
| 435 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 407 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 436 | static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, | 408 | static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, |
| 437 | u64 handle_count, s64 nano_seconds) { | 409 | u64 num_handles, s64 nano_seconds) { |
| 438 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", | 410 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", |
| 439 | handles_address, handle_count, nano_seconds); | 411 | handles_address, num_handles, nano_seconds); |
| 440 | 412 | ||
| 441 | auto& memory = system.Memory(); | 413 | // Ensure number of handles is valid. |
| 442 | if (!memory.IsValidVirtualAddress(handles_address)) { | 414 | R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); |
| 443 | LOG_ERROR(Kernel_SVC, | ||
| 444 | "Handle address is not a valid virtual address, handle_address=0x{:016X}", | ||
| 445 | handles_address); | ||
| 446 | return ResultInvalidPointer; | ||
| 447 | } | ||
| 448 | |||
| 449 | static constexpr u64 MaxHandles = 0x40; | ||
| 450 | |||
| 451 | if (handle_count > MaxHandles) { | ||
| 452 | LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}", | ||
| 453 | MaxHandles, handle_count); | ||
| 454 | return ResultOutOfRange; | ||
| 455 | } | ||
| 456 | 415 | ||
| 457 | auto& kernel = system.Kernel(); | 416 | auto& kernel = system.Kernel(); |
| 458 | std::vector<KSynchronizationObject*> objects(handle_count); | 417 | std::vector<KSynchronizationObject*> objs(num_handles); |
| 459 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 418 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 419 | Handle* handles = system.Memory().GetPointer<Handle>(handles_address); | ||
| 460 | 420 | ||
| 461 | for (u64 i = 0; i < handle_count; ++i) { | 421 | // Copy user handles. |
| 462 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 422 | if (num_handles > 0) { |
| 463 | const auto object = handle_table.Get<KSynchronizationObject>(handle); | 423 | // Convert the handles to objects. |
| 424 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | ||
| 425 | num_handles), | ||
| 426 | ResultInvalidHandle); | ||
| 427 | } | ||
| 464 | 428 | ||
| 465 | if (object == nullptr) { | 429 | // Ensure handles are closed when we're done. |
| 466 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | 430 | SCOPE_EXIT({ |
| 467 | return ResultInvalidHandle; | 431 | for (u64 i = 0; i < num_handles; ++i) { |
| 432 | objs[i]->Close(); | ||
| 468 | } | 433 | } |
| 434 | }); | ||
| 469 | 435 | ||
| 470 | objects[i] = object.get(); | 436 | return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()), |
| 471 | } | 437 | nano_seconds); |
| 472 | return KSynchronizationObject::Wait(kernel, index, objects.data(), | ||
| 473 | static_cast<s32>(objects.size()), nano_seconds); | ||
| 474 | } | 438 | } |
| 475 | 439 | ||
| 476 | static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, | 440 | static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, |
| 477 | s32 handle_count, u32 timeout_high, s32* index) { | 441 | s32 num_handles, u32 timeout_high, s32* index) { |
| 478 | const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; | 442 | const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; |
| 479 | return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds); | 443 | return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds); |
| 480 | } | 444 | } |
| 481 | 445 | ||
| 482 | /// Resumes a thread waiting on WaitSynchronization | 446 | /// Resumes a thread waiting on WaitSynchronization |
| 483 | static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { | 447 | static ResultCode CancelSynchronization(Core::System& system, Handle handle) { |
| 484 | LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); | 448 | LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); |
| 485 | 449 | ||
| 486 | // Get the thread from its handle. | 450 | // Get the thread from its handle. |
| 487 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 451 | KScopedAutoObject thread = |
| 488 | std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 452 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>( |
| 489 | 453 | static_cast<Handle>(handle)); | |
| 490 | if (!thread) { | ||
| 491 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 492 | return ResultInvalidHandle; | ||
| 493 | } | ||
| 494 | 454 | ||
| 495 | // Cancel the thread's wait. | 455 | // Cancel the thread's wait. |
| 496 | thread->WaitCancel(); | 456 | thread->WaitCancel(); |
| 497 | return RESULT_SUCCESS; | 457 | return RESULT_SUCCESS; |
| 498 | } | 458 | } |
| 499 | 459 | ||
| 500 | static ResultCode CancelSynchronization32(Core::System& system, Handle thread_handle) { | 460 | static ResultCode CancelSynchronization32(Core::System& system, Handle handle) { |
| 501 | return CancelSynchronization(system, thread_handle); | 461 | return CancelSynchronization(system, handle); |
| 502 | } | 462 | } |
| 503 | 463 | ||
| 504 | /// Attempts to locks a mutex | 464 | /// Attempts to locks a mutex |
| @@ -678,7 +638,7 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) { | |||
| 678 | } | 638 | } |
| 679 | 639 | ||
| 680 | /// Gets system/memory information for the current process | 640 | /// Gets system/memory information for the current process |
| 681 | static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 handle, | 641 | static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, |
| 682 | u64 info_sub_id) { | 642 | u64 info_sub_id) { |
| 683 | std::lock_guard lock{HLE::g_hle_lock}; | 643 | std::lock_guard lock{HLE::g_hle_lock}; |
| 684 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, | 644 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, |
| @@ -744,10 +704,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 744 | return ResultInvalidEnumValue; | 704 | return ResultInvalidEnumValue; |
| 745 | } | 705 | } |
| 746 | 706 | ||
| 747 | const auto& current_process_handle_table = | 707 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 748 | system.Kernel().CurrentProcess()->GetHandleTable(); | 708 | KScopedAutoObject process = handle_table.GetObject<KProcess>(handle); |
| 749 | const auto process = current_process_handle_table.Get<Process>(static_cast<Handle>(handle)); | 709 | if (process.IsNull()) { |
| 750 | if (!process) { | ||
| 751 | LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", | 710 | LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", |
| 752 | info_id, info_sub_id, handle); | 711 | info_id, info_sub_id, handle); |
| 753 | return ResultInvalidHandle; | 712 | return ResultInvalidHandle; |
| @@ -851,21 +810,19 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 851 | return ResultInvalidCombination; | 810 | return ResultInvalidCombination; |
| 852 | } | 811 | } |
| 853 | 812 | ||
| 854 | Process* const current_process = system.Kernel().CurrentProcess(); | 813 | KProcess* const current_process = system.Kernel().CurrentProcess(); |
| 855 | HandleTable& handle_table = current_process->GetHandleTable(); | 814 | KHandleTable& handle_table = current_process->GetHandleTable(); |
| 856 | const auto resource_limit = current_process->GetResourceLimit(); | 815 | const auto resource_limit = current_process->GetResourceLimit(); |
| 857 | if (!resource_limit) { | 816 | if (!resource_limit) { |
| 858 | *result = KernelHandle::InvalidHandle; | 817 | *result = Svc::InvalidHandle; |
| 859 | // Yes, the kernel considers this a successful operation. | 818 | // Yes, the kernel considers this a successful operation. |
| 860 | return RESULT_SUCCESS; | 819 | return RESULT_SUCCESS; |
| 861 | } | 820 | } |
| 862 | 821 | ||
| 863 | const auto table_result = handle_table.Create(resource_limit); | 822 | Handle resource_handle{}; |
| 864 | if (table_result.Failed()) { | 823 | R_TRY(handle_table.Add(&resource_handle, resource_limit)); |
| 865 | return table_result.Code(); | ||
| 866 | } | ||
| 867 | 824 | ||
| 868 | *result = *table_result; | 825 | *result = resource_handle; |
| 869 | return RESULT_SUCCESS; | 826 | return RESULT_SUCCESS; |
| 870 | } | 827 | } |
| 871 | 828 | ||
| @@ -876,9 +833,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 876 | return ResultInvalidHandle; | 833 | return ResultInvalidHandle; |
| 877 | } | 834 | } |
| 878 | 835 | ||
| 879 | if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) { | 836 | if (info_sub_id >= KProcess::RANDOM_ENTROPY_SIZE) { |
| 880 | LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}", | 837 | LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}", |
| 881 | Process::RANDOM_ENTROPY_SIZE, info_sub_id); | 838 | KProcess::RANDOM_ENTROPY_SIZE, info_sub_id); |
| 882 | return ResultInvalidCombination; | 839 | return ResultInvalidCombination; |
| 883 | } | 840 | } |
| 884 | 841 | ||
| @@ -899,9 +856,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 899 | return ResultInvalidCombination; | 856 | return ResultInvalidCombination; |
| 900 | } | 857 | } |
| 901 | 858 | ||
| 902 | const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>( | 859 | KScopedAutoObject thread = |
| 903 | static_cast<Handle>(handle)); | 860 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>( |
| 904 | if (!thread) { | 861 | static_cast<Handle>(handle)); |
| 862 | if (thread.IsNull()) { | ||
| 905 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", | 863 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", |
| 906 | static_cast<Handle>(handle)); | 864 | static_cast<Handle>(handle)); |
| 907 | return ResultInvalidHandle; | 865 | return ResultInvalidHandle; |
| @@ -910,7 +868,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 910 | const auto& core_timing = system.CoreTiming(); | 868 | const auto& core_timing = system.CoreTiming(); |
| 911 | const auto& scheduler = *system.Kernel().CurrentScheduler(); | 869 | const auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 912 | const auto* const current_thread = scheduler.GetCurrentThread(); | 870 | const auto* const current_thread = scheduler.GetCurrentThread(); |
| 913 | const bool same_thread = current_thread == thread.get(); | 871 | const bool same_thread = current_thread == thread.GetPointerUnsafe(); |
| 914 | 872 | ||
| 915 | const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); | 873 | const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); |
| 916 | u64 out_ticks = 0; | 874 | u64 out_ticks = 0; |
| @@ -966,10 +924,10 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) | |||
| 966 | 924 | ||
| 967 | if (!(addr < addr + size)) { | 925 | if (!(addr < addr + size)) { |
| 968 | LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); | 926 | LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); |
| 969 | return ResultInvalidMemoryRange; | 927 | return ResultInvalidMemoryRegion; |
| 970 | } | 928 | } |
| 971 | 929 | ||
| 972 | Process* const current_process{system.Kernel().CurrentProcess()}; | 930 | KProcess* const current_process{system.Kernel().CurrentProcess()}; |
| 973 | auto& page_table{current_process->PageTable()}; | 931 | auto& page_table{current_process->PageTable()}; |
| 974 | 932 | ||
| 975 | if (current_process->GetSystemResourceSize() == 0) { | 933 | if (current_process->GetSystemResourceSize() == 0) { |
| @@ -981,14 +939,14 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) | |||
| 981 | LOG_ERROR(Kernel_SVC, | 939 | LOG_ERROR(Kernel_SVC, |
| 982 | "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, | 940 | "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, |
| 983 | size); | 941 | size); |
| 984 | return ResultInvalidMemoryRange; | 942 | return ResultInvalidMemoryRegion; |
| 985 | } | 943 | } |
| 986 | 944 | ||
| 987 | if (page_table.IsOutsideAliasRegion(addr, size)) { | 945 | if (page_table.IsOutsideAliasRegion(addr, size)) { |
| 988 | LOG_ERROR(Kernel_SVC, | 946 | LOG_ERROR(Kernel_SVC, |
| 989 | "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, | 947 | "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, |
| 990 | size); | 948 | size); |
| 991 | return ResultInvalidMemoryRange; | 949 | return ResultInvalidMemoryRegion; |
| 992 | } | 950 | } |
| 993 | 951 | ||
| 994 | return page_table.MapPhysicalMemory(addr, size); | 952 | return page_table.MapPhysicalMemory(addr, size); |
| @@ -1020,10 +978,10 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size | |||
| 1020 | 978 | ||
| 1021 | if (!(addr < addr + size)) { | 979 | if (!(addr < addr + size)) { |
| 1022 | LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); | 980 | LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address"); |
| 1023 | return ResultInvalidMemoryRange; | 981 | return ResultInvalidMemoryRegion; |
| 1024 | } | 982 | } |
| 1025 | 983 | ||
| 1026 | Process* const current_process{system.Kernel().CurrentProcess()}; | 984 | KProcess* const current_process{system.Kernel().CurrentProcess()}; |
| 1027 | auto& page_table{current_process->PageTable()}; | 985 | auto& page_table{current_process->PageTable()}; |
| 1028 | 986 | ||
| 1029 | if (current_process->GetSystemResourceSize() == 0) { | 987 | if (current_process->GetSystemResourceSize() == 0) { |
| @@ -1035,14 +993,14 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size | |||
| 1035 | LOG_ERROR(Kernel_SVC, | 993 | LOG_ERROR(Kernel_SVC, |
| 1036 | "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, | 994 | "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, |
| 1037 | size); | 995 | size); |
| 1038 | return ResultInvalidMemoryRange; | 996 | return ResultInvalidMemoryRegion; |
| 1039 | } | 997 | } |
| 1040 | 998 | ||
| 1041 | if (page_table.IsOutsideAliasRegion(addr, size)) { | 999 | if (page_table.IsOutsideAliasRegion(addr, size)) { |
| 1042 | LOG_ERROR(Kernel_SVC, | 1000 | LOG_ERROR(Kernel_SVC, |
| 1043 | "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, | 1001 | "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, |
| 1044 | size); | 1002 | size); |
| 1045 | return ResultInvalidMemoryRange; | 1003 | return ResultInvalidMemoryRegion; |
| 1046 | } | 1004 | } |
| 1047 | 1005 | ||
| 1048 | return page_table.UnmapPhysicalMemory(addr, size); | 1006 | return page_table.UnmapPhysicalMemory(addr, size); |
| @@ -1062,37 +1020,19 @@ static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, | |||
| 1062 | constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { | 1020 | constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { |
| 1063 | return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; | 1021 | return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; |
| 1064 | }; | 1022 | }; |
| 1065 | if (!IsValidThreadActivity(thread_activity)) { | 1023 | R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue); |
| 1066 | LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})", | ||
| 1067 | thread_activity); | ||
| 1068 | return ResultInvalidEnumValue; | ||
| 1069 | } | ||
| 1070 | 1024 | ||
| 1071 | // Get the thread from its handle. | 1025 | // Get the thread from its handle. |
| 1072 | auto& kernel = system.Kernel(); | 1026 | KScopedAutoObject thread = |
| 1073 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1027 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 1074 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1028 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1075 | if (!thread) { | ||
| 1076 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 1077 | return ResultInvalidHandle; | ||
| 1078 | } | ||
| 1079 | 1029 | ||
| 1080 | // Check that the activity is being set on a non-current thread for the current process. | 1030 | // Check that the activity is being set on a non-current thread for the current process. |
| 1081 | if (thread->GetOwnerProcess() != kernel.CurrentProcess()) { | 1031 | R_UNLESS(thread->GetOwnerProcess() == system.Kernel().CurrentProcess(), ResultInvalidHandle); |
| 1082 | LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread."); | 1032 | R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); |
| 1083 | return ResultInvalidHandle; | ||
| 1084 | } | ||
| 1085 | if (thread.get() == GetCurrentThreadPointer(kernel)) { | ||
| 1086 | LOG_ERROR(Kernel_SVC, "Thread is busy"); | ||
| 1087 | return ResultBusy; | ||
| 1088 | } | ||
| 1089 | 1033 | ||
| 1090 | // Set the activity. | 1034 | // Set the activity. |
| 1091 | const auto set_result = thread->SetActivity(thread_activity); | 1035 | R_TRY(thread->SetActivity(thread_activity)); |
| 1092 | if (set_result.IsError()) { | ||
| 1093 | LOG_ERROR(Kernel_SVC, "Failed to set thread activity."); | ||
| 1094 | return set_result; | ||
| 1095 | } | ||
| 1096 | 1036 | ||
| 1097 | return RESULT_SUCCESS; | 1037 | return RESULT_SUCCESS; |
| 1098 | } | 1038 | } |
| @@ -1107,36 +1047,55 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand | |||
| 1107 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, | 1047 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, |
| 1108 | thread_handle); | 1048 | thread_handle); |
| 1109 | 1049 | ||
| 1050 | auto& kernel = system.Kernel(); | ||
| 1051 | |||
| 1110 | // Get the thread from its handle. | 1052 | // Get the thread from its handle. |
| 1111 | const auto* current_process = system.Kernel().CurrentProcess(); | 1053 | KScopedAutoObject thread = |
| 1112 | const std::shared_ptr<KThread> thread = | 1054 | kernel.CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 1113 | current_process->GetHandleTable().Get<KThread>(thread_handle); | 1055 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1114 | if (!thread) { | ||
| 1115 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle); | ||
| 1116 | return ResultInvalidHandle; | ||
| 1117 | } | ||
| 1118 | 1056 | ||
| 1119 | // Require the handle be to a non-current thread in the current process. | 1057 | // Require the handle be to a non-current thread in the current process. |
| 1120 | if (thread->GetOwnerProcess() != current_process) { | 1058 | const auto* current_process = kernel.CurrentProcess(); |
| 1121 | LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process."); | 1059 | R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId); |
| 1122 | return ResultInvalidHandle; | ||
| 1123 | } | ||
| 1124 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { | ||
| 1125 | LOG_ERROR(Kernel_SVC, "Current thread is busy."); | ||
| 1126 | return ResultBusy; | ||
| 1127 | } | ||
| 1128 | 1060 | ||
| 1129 | // Get the thread context. | 1061 | // Verify that the thread isn't terminated. |
| 1130 | std::vector<u8> context; | 1062 | R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested); |
| 1131 | const auto context_result = thread->GetThreadContext3(context); | 1063 | |
| 1132 | if (context_result.IsError()) { | 1064 | /// Check that the thread is not the current one. |
| 1133 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})", | 1065 | /// NOTE: Nintendo does not check this, and thus the following loop will deadlock. |
| 1134 | context_result.raw); | 1066 | R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId); |
| 1135 | return context_result; | 1067 | |
| 1136 | } | 1068 | // Try to get the thread context until the thread isn't current on any core. |
| 1069 | while (true) { | ||
| 1070 | KScopedSchedulerLock sl{kernel}; | ||
| 1137 | 1071 | ||
| 1138 | // Copy the thread context to user space. | 1072 | // TODO(bunnei): Enforce that thread is suspended for debug here. |
| 1139 | system.Memory().WriteBlock(out_context, context.data(), context.size()); | 1073 | |
| 1074 | // If the thread's raw state isn't runnable, check if it's current on some core. | ||
| 1075 | if (thread->GetRawState() != ThreadState::Runnable) { | ||
| 1076 | bool current = false; | ||
| 1077 | for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { | ||
| 1078 | if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) { | ||
| 1079 | current = true; | ||
| 1080 | } | ||
| 1081 | break; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | // If the thread is current, retry until it isn't. | ||
| 1085 | if (current) { | ||
| 1086 | continue; | ||
| 1087 | } | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | // Get the thread context. | ||
| 1091 | std::vector<u8> context; | ||
| 1092 | R_TRY(thread->GetThreadContext3(context)); | ||
| 1093 | |||
| 1094 | // Copy the thread context to user space. | ||
| 1095 | system.Memory().WriteBlock(out_context, context.data(), context.size()); | ||
| 1096 | |||
| 1097 | return RESULT_SUCCESS; | ||
| 1098 | } | ||
| 1140 | 1099 | ||
| 1141 | return RESULT_SUCCESS; | 1100 | return RESULT_SUCCESS; |
| 1142 | } | 1101 | } |
| @@ -1150,12 +1109,9 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han | |||
| 1150 | LOG_TRACE(Kernel_SVC, "called"); | 1109 | LOG_TRACE(Kernel_SVC, "called"); |
| 1151 | 1110 | ||
| 1152 | // Get the thread from its handle. | 1111 | // Get the thread from its handle. |
| 1153 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1112 | KScopedAutoObject thread = |
| 1154 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 1113 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle); |
| 1155 | if (!thread) { | 1114 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1156 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle); | ||
| 1157 | return ResultInvalidHandle; | ||
| 1158 | } | ||
| 1159 | 1115 | ||
| 1160 | // Get the thread's priority. | 1116 | // Get the thread's priority. |
| 1161 | *out_priority = thread->GetPriority(); | 1117 | *out_priority = thread->GetPriority(); |
| @@ -1167,30 +1123,26 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H | |||
| 1167 | } | 1123 | } |
| 1168 | 1124 | ||
| 1169 | /// Sets the priority for the specified thread | 1125 | /// Sets the priority for the specified thread |
| 1170 | static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { | 1126 | static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) { |
| 1171 | LOG_TRACE(Kernel_SVC, "called"); | 1127 | // Get the current process. |
| 1128 | KProcess& process = *system.Kernel().CurrentProcess(); | ||
| 1172 | 1129 | ||
| 1173 | // Validate the priority. | 1130 | // Validate the priority. |
| 1174 | if (HighestThreadPriority > priority || priority > LowestThreadPriority) { | 1131 | R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority, |
| 1175 | LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); | 1132 | ResultInvalidPriority); |
| 1176 | return ResultInvalidPriority; | 1133 | R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); |
| 1177 | } | ||
| 1178 | 1134 | ||
| 1179 | // Get the thread from its handle. | 1135 | // Get the thread from its handle. |
| 1180 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1136 | KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(thread_handle); |
| 1181 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 1137 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1182 | if (!thread) { | ||
| 1183 | LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle); | ||
| 1184 | return ResultInvalidHandle; | ||
| 1185 | } | ||
| 1186 | 1138 | ||
| 1187 | // Set the thread priority. | 1139 | // Set the thread priority. |
| 1188 | thread->SetBasePriority(priority); | 1140 | thread->SetBasePriority(priority); |
| 1189 | return RESULT_SUCCESS; | 1141 | return RESULT_SUCCESS; |
| 1190 | } | 1142 | } |
| 1191 | 1143 | ||
| 1192 | static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) { | 1144 | static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) { |
| 1193 | return SetThreadPriority(system, handle, priority); | 1145 | return SetThreadPriority(system, thread_handle, priority); |
| 1194 | } | 1146 | } |
| 1195 | 1147 | ||
| 1196 | /// Get which CPU core is executing the current thread | 1148 | /// Get which CPU core is executing the current thread |
| @@ -1203,82 +1155,97 @@ static u32 GetCurrentProcessorNumber32(Core::System& system) { | |||
| 1203 | return GetCurrentProcessorNumber(system); | 1155 | return GetCurrentProcessorNumber(system); |
| 1204 | } | 1156 | } |
| 1205 | 1157 | ||
| 1206 | static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, | 1158 | constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { |
| 1207 | u64 size, u32 permissions) { | 1159 | switch (perm) { |
| 1208 | std::lock_guard lock{HLE::g_hle_lock}; | 1160 | case Svc::MemoryPermission::Read: |
| 1161 | case Svc::MemoryPermission::ReadWrite: | ||
| 1162 | return true; | ||
| 1163 | default: | ||
| 1164 | return false; | ||
| 1165 | } | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1169 | return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, | ||
| 1173 | u64 size, Svc::MemoryPermission map_perm) { | ||
| 1209 | LOG_TRACE(Kernel_SVC, | 1174 | LOG_TRACE(Kernel_SVC, |
| 1210 | "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", | 1175 | "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", |
| 1211 | shared_memory_handle, addr, size, permissions); | 1176 | shmem_handle, address, size, map_perm); |
| 1212 | 1177 | ||
| 1213 | if (!Common::Is4KBAligned(addr)) { | 1178 | // Validate the address/size. |
| 1214 | LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr); | 1179 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); |
| 1215 | return ResultInvalidAddress; | 1180 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); |
| 1216 | } | 1181 | R_UNLESS(size > 0, ResultInvalidSize); |
| 1182 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 1217 | 1183 | ||
| 1218 | if (size == 0) { | 1184 | // Validate the permission. |
| 1219 | LOG_ERROR(Kernel_SVC, "Size is 0"); | 1185 | R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); |
| 1220 | return ResultInvalidSize; | ||
| 1221 | } | ||
| 1222 | 1186 | ||
| 1223 | if (!Common::Is4KBAligned(size)) { | 1187 | // Get the current process. |
| 1224 | LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size); | 1188 | auto& process = *system.Kernel().CurrentProcess(); |
| 1225 | return ResultInvalidSize; | 1189 | auto& page_table = process.PageTable(); |
| 1226 | } | ||
| 1227 | 1190 | ||
| 1228 | if (!IsValidAddressRange(addr, size)) { | 1191 | // Get the shared memory. |
| 1229 | LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}", | 1192 | KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); |
| 1230 | addr, size); | 1193 | R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); |
| 1231 | return ResultInvalidCurrentMemory; | ||
| 1232 | } | ||
| 1233 | 1194 | ||
| 1234 | const auto permission_type = static_cast<MemoryPermission>(permissions); | 1195 | // Verify that the mapping is in range. |
| 1235 | if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) { | 1196 | R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); |
| 1236 | LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", | ||
| 1237 | permissions); | ||
| 1238 | return ResultInvalidMemoryPermissions; | ||
| 1239 | } | ||
| 1240 | 1197 | ||
| 1241 | auto* const current_process{system.Kernel().CurrentProcess()}; | 1198 | // Add the shared memory to the process. |
| 1242 | auto& page_table{current_process->PageTable()}; | 1199 | R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); |
| 1243 | 1200 | ||
| 1244 | if (page_table.IsInvalidRegion(addr, size)) { | 1201 | // Ensure that we clean up the shared memory if we fail to map it. |
| 1245 | LOG_ERROR(Kernel_SVC, | 1202 | auto guard = |
| 1246 | "Addr does not fit within the valid region, addr=0x{:016X}, " | 1203 | SCOPE_GUARD({ process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); }); |
| 1247 | "size=0x{:016X}", | ||
| 1248 | addr, size); | ||
| 1249 | return ResultInvalidMemoryRange; | ||
| 1250 | } | ||
| 1251 | 1204 | ||
| 1252 | if (page_table.IsInsideHeapRegion(addr, size)) { | 1205 | // Map the shared memory. |
| 1253 | LOG_ERROR(Kernel_SVC, | 1206 | R_TRY(shmem->Map(process, address, size, map_perm)); |
| 1254 | "Addr does not fit within the heap region, addr=0x{:016X}, " | ||
| 1255 | "size=0x{:016X}", | ||
| 1256 | addr, size); | ||
| 1257 | return ResultInvalidMemoryRange; | ||
| 1258 | } | ||
| 1259 | 1207 | ||
| 1260 | if (page_table.IsInsideAliasRegion(addr, size)) { | 1208 | // We succeeded. |
| 1261 | LOG_ERROR(Kernel_SVC, | 1209 | guard.Cancel(); |
| 1262 | "Address does not fit within the map region, addr=0x{:016X}, " | 1210 | return RESULT_SUCCESS; |
| 1263 | "size=0x{:016X}", | 1211 | } |
| 1264 | addr, size); | ||
| 1265 | return ResultInvalidMemoryRange; | ||
| 1266 | } | ||
| 1267 | 1212 | ||
| 1268 | auto shared_memory{current_process->GetHandleTable().Get<KSharedMemory>(shared_memory_handle)}; | 1213 | static ResultCode MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, |
| 1269 | if (!shared_memory) { | 1214 | u32 size, Svc::MemoryPermission map_perm) { |
| 1270 | LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", | 1215 | return MapSharedMemory(system, shmem_handle, address, size, map_perm); |
| 1271 | shared_memory_handle); | 1216 | } |
| 1272 | return ResultInvalidHandle; | 1217 | |
| 1273 | } | 1218 | static ResultCode UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, |
| 1219 | u64 size) { | ||
| 1220 | // Validate the address/size. | ||
| 1221 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | ||
| 1222 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1223 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1224 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 1225 | |||
| 1226 | // Get the current process. | ||
| 1227 | auto& process = *system.Kernel().CurrentProcess(); | ||
| 1228 | auto& page_table = process.PageTable(); | ||
| 1229 | |||
| 1230 | // Get the shared memory. | ||
| 1231 | KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); | ||
| 1232 | R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); | ||
| 1274 | 1233 | ||
| 1275 | return shared_memory->Map(*current_process, addr, size, | 1234 | // Verify that the mapping is in range. |
| 1276 | static_cast<KMemoryPermission>(permission_type)); | 1235 | R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); |
| 1236 | |||
| 1237 | // Unmap the shared memory. | ||
| 1238 | R_TRY(shmem->Unmap(process, address, size)); | ||
| 1239 | |||
| 1240 | // Remove the shared memory from the process. | ||
| 1241 | process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); | ||
| 1242 | |||
| 1243 | return RESULT_SUCCESS; | ||
| 1277 | } | 1244 | } |
| 1278 | 1245 | ||
| 1279 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, | 1246 | static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, |
| 1280 | u32 size, u32 permissions) { | 1247 | u32 size) { |
| 1281 | return MapSharedMemory(system, shared_memory_handle, addr, size, permissions); | 1248 | return UnmapSharedMemory(system, shmem_handle, address, size); |
| 1282 | } | 1249 | } |
| 1283 | 1250 | ||
| 1284 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, | 1251 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, |
| @@ -1287,8 +1254,8 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add | |||
| 1287 | std::lock_guard lock{HLE::g_hle_lock}; | 1254 | std::lock_guard lock{HLE::g_hle_lock}; |
| 1288 | LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); | 1255 | LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); |
| 1289 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1256 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1290 | std::shared_ptr<Process> process = handle_table.Get<Process>(process_handle); | 1257 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |
| 1291 | if (!process) { | 1258 | if (process.IsNull()) { |
| 1292 | LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", | 1259 | LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", |
| 1293 | process_handle); | 1260 | process_handle); |
| 1294 | return ResultInvalidHandle; | 1261 | return ResultInvalidHandle; |
| @@ -1369,8 +1336,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand | |||
| 1369 | } | 1336 | } |
| 1370 | 1337 | ||
| 1371 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1338 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1372 | auto process = handle_table.Get<Process>(process_handle); | 1339 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |
| 1373 | if (!process) { | 1340 | if (process.IsNull()) { |
| 1374 | LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", | 1341 | LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", |
| 1375 | process_handle); | 1342 | process_handle); |
| 1376 | return ResultInvalidHandle; | 1343 | return ResultInvalidHandle; |
| @@ -1390,7 +1357,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand | |||
| 1390 | "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " | 1357 | "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " |
| 1391 | "size=0x{:016X}).", | 1358 | "size=0x{:016X}).", |
| 1392 | dst_address, size); | 1359 | dst_address, size); |
| 1393 | return ResultInvalidMemoryRange; | 1360 | return ResultInvalidMemoryRegion; |
| 1394 | } | 1361 | } |
| 1395 | 1362 | ||
| 1396 | return page_table.MapProcessCodeMemory(dst_address, src_address, size); | 1363 | return page_table.MapProcessCodeMemory(dst_address, src_address, size); |
| @@ -1437,8 +1404,8 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha | |||
| 1437 | } | 1404 | } |
| 1438 | 1405 | ||
| 1439 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1406 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1440 | auto process = handle_table.Get<Process>(process_handle); | 1407 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |
| 1441 | if (!process) { | 1408 | if (process.IsNull()) { |
| 1442 | LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", | 1409 | LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", |
| 1443 | process_handle); | 1410 | process_handle); |
| 1444 | return ResultInvalidHandle; | 1411 | return ResultInvalidHandle; |
| @@ -1458,7 +1425,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha | |||
| 1458 | "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " | 1425 | "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " |
| 1459 | "size=0x{:016X}).", | 1426 | "size=0x{:016X}).", |
| 1460 | dst_address, size); | 1427 | dst_address, size); |
| 1461 | return ResultInvalidMemoryRange; | 1428 | return ResultInvalidMemoryRegion; |
| 1462 | } | 1429 | } |
| 1463 | 1430 | ||
| 1464 | return page_table.UnmapProcessCodeMemory(dst_address, src_address, size); | 1431 | return page_table.UnmapProcessCodeMemory(dst_address, src_address, size); |
| @@ -1483,7 +1450,7 @@ static void ExitProcess32(Core::System& system) { | |||
| 1483 | ExitProcess(system); | 1450 | ExitProcess(system); |
| 1484 | } | 1451 | } |
| 1485 | 1452 | ||
| 1486 | static constexpr bool IsValidCoreId(int32_t core_id) { | 1453 | static constexpr bool IsValidVirtualCoreId(int32_t core_id) { |
| 1487 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); | 1454 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); |
| 1488 | } | 1455 | } |
| 1489 | 1456 | ||
| @@ -1503,7 +1470,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1503 | } | 1470 | } |
| 1504 | 1471 | ||
| 1505 | // Validate arguments. | 1472 | // Validate arguments. |
| 1506 | if (!IsValidCoreId(core_id)) { | 1473 | if (!IsValidVirtualCoreId(core_id)) { |
| 1507 | LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); | 1474 | LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); |
| 1508 | return ResultInvalidCoreId; | 1475 | return ResultInvalidCoreId; |
| 1509 | } | 1476 | } |
| @@ -1521,35 +1488,42 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1521 | return ResultInvalidPriority; | 1488 | return ResultInvalidPriority; |
| 1522 | } | 1489 | } |
| 1523 | 1490 | ||
| 1491 | // Reserve a new thread from the process resource limit (waiting up to 100ms). | ||
| 1524 | KScopedResourceReservation thread_reservation( | 1492 | KScopedResourceReservation thread_reservation( |
| 1525 | kernel.CurrentProcess(), LimitableResource::Threads, 1, | 1493 | kernel.CurrentProcess(), LimitableResource::Threads, 1, |
| 1526 | system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | 1494 | system.CoreTiming().GetGlobalTimeNs().count() + 100000000); |
| 1527 | if (!thread_reservation.Succeeded()) { | 1495 | if (!thread_reservation.Succeeded()) { |
| 1528 | LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); | 1496 | LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); |
| 1529 | return ResultResourceLimitedExceeded; | 1497 | return ResultLimitReached; |
| 1530 | } | 1498 | } |
| 1531 | 1499 | ||
| 1532 | std::shared_ptr<KThread> thread; | 1500 | // Create the thread. |
| 1533 | { | 1501 | KThread* thread = KThread::Create(kernel); |
| 1534 | KScopedLightLock lk{process.GetStateLock()}; | 1502 | if (!thread) { |
| 1535 | CASCADE_RESULT(thread, | 1503 | LOG_ERROR(Kernel_SVC, "Unable to create new threads. Thread creation limit reached."); |
| 1536 | KThread::CreateUserThread(system, ThreadType::User, "", entry_point, | 1504 | return ResultOutOfResource; |
| 1537 | priority, arg, core_id, stack_bottom, &process)); | ||
| 1538 | } | 1505 | } |
| 1506 | SCOPE_EXIT({ thread->Close(); }); | ||
| 1539 | 1507 | ||
| 1540 | const auto new_thread_handle = process.GetHandleTable().Create(thread); | 1508 | // Initialize the thread. |
| 1541 | if (new_thread_handle.Failed()) { | 1509 | { |
| 1542 | LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", | 1510 | KScopedLightLock lk{process.GetStateLock()}; |
| 1543 | new_thread_handle.Code().raw); | 1511 | R_TRY(KThread::InitializeUserThread(system, thread, entry_point, arg, stack_bottom, |
| 1544 | return new_thread_handle.Code(); | 1512 | priority, core_id, &process)); |
| 1545 | } | 1513 | } |
| 1546 | *out_handle = *new_thread_handle; | ||
| 1547 | 1514 | ||
| 1548 | // Set the thread name for debugging purposes. | 1515 | // Set the thread name for debugging purposes. |
| 1549 | thread->SetName( | 1516 | thread->SetName(fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *out_handle)); |
| 1550 | fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); | 1517 | |
| 1518 | // Commit the thread reservation. | ||
| 1551 | thread_reservation.Commit(); | 1519 | thread_reservation.Commit(); |
| 1552 | 1520 | ||
| 1521 | // Register the new thread. | ||
| 1522 | KThread::Register(kernel, thread); | ||
| 1523 | |||
| 1524 | // Add the thread to the handle table. | ||
| 1525 | R_TRY(process.GetHandleTable().Add(out_handle, thread)); | ||
| 1526 | |||
| 1553 | return RESULT_SUCCESS; | 1527 | return RESULT_SUCCESS; |
| 1554 | } | 1528 | } |
| 1555 | 1529 | ||
| @@ -1563,21 +1537,15 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
| 1563 | LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); | 1537 | LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); |
| 1564 | 1538 | ||
| 1565 | // Get the thread from its handle. | 1539 | // Get the thread from its handle. |
| 1566 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1540 | KScopedAutoObject thread = |
| 1567 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1541 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 1568 | if (!thread) { | 1542 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1569 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 1570 | return ResultInvalidHandle; | ||
| 1571 | } | ||
| 1572 | 1543 | ||
| 1573 | // Try to start the thread. | 1544 | // Try to start the thread. |
| 1574 | const auto run_result = thread->Run(); | 1545 | R_TRY(thread->Run()); |
| 1575 | if (run_result.IsError()) { | 1546 | |
| 1576 | LOG_ERROR(Kernel_SVC, | 1547 | // If we succeeded, persist a reference to the thread. |
| 1577 | "Unable to successfuly start thread (thread handle={:08X}, result={})", | 1548 | thread->Open(); |
| 1578 | thread_handle, run_result.raw); | ||
| 1579 | return run_result; | ||
| 1580 | } | ||
| 1581 | 1549 | ||
| 1582 | return RESULT_SUCCESS; | 1550 | return RESULT_SUCCESS; |
| 1583 | } | 1551 | } |
| @@ -1591,7 +1559,7 @@ static void ExitThread(Core::System& system) { | |||
| 1591 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); | 1559 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); |
| 1592 | 1560 | ||
| 1593 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); | 1561 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 1594 | system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); | 1562 | system.GlobalSchedulerContext().RemoveThread(current_thread); |
| 1595 | current_thread->Exit(); | 1563 | current_thread->Exit(); |
| 1596 | } | 1564 | } |
| 1597 | 1565 | ||
| @@ -1824,8 +1792,11 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) | |||
| 1824 | static ResultCode CloseHandle(Core::System& system, Handle handle) { | 1792 | static ResultCode CloseHandle(Core::System& system, Handle handle) { |
| 1825 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); | 1793 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); |
| 1826 | 1794 | ||
| 1827 | auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1795 | // Remove the handle. |
| 1828 | return handle_table.Close(handle); | 1796 | R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle), |
| 1797 | ResultInvalidHandle); | ||
| 1798 | |||
| 1799 | return RESULT_SUCCESS; | ||
| 1829 | } | 1800 | } |
| 1830 | 1801 | ||
| 1831 | static ResultCode CloseHandle32(Core::System& system, Handle handle) { | 1802 | static ResultCode CloseHandle32(Core::System& system, Handle handle) { |
| @@ -1841,16 +1812,16 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) { | |||
| 1841 | 1812 | ||
| 1842 | // Try to reset as readable event. | 1813 | // Try to reset as readable event. |
| 1843 | { | 1814 | { |
| 1844 | auto readable_event = handle_table.Get<KReadableEvent>(handle); | 1815 | KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(handle); |
| 1845 | if (readable_event) { | 1816 | if (readable_event.IsNotNull()) { |
| 1846 | return readable_event->Reset(); | 1817 | return readable_event->Reset(); |
| 1847 | } | 1818 | } |
| 1848 | } | 1819 | } |
| 1849 | 1820 | ||
| 1850 | // Try to reset as process. | 1821 | // Try to reset as process. |
| 1851 | { | 1822 | { |
| 1852 | auto process = handle_table.Get<Process>(handle); | 1823 | KScopedAutoObject process = handle_table.GetObject<KProcess>(handle); |
| 1853 | if (process) { | 1824 | if (process.IsNotNull()) { |
| 1854 | return process->Reset(); | 1825 | return process->Reset(); |
| 1855 | } | 1826 | } |
| 1856 | } | 1827 | } |
| @@ -1864,65 +1835,68 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) { | |||
| 1864 | return ResetSignal(system, handle); | 1835 | return ResetSignal(system, handle); |
| 1865 | } | 1836 | } |
| 1866 | 1837 | ||
| 1867 | /// Creates a TransferMemory object | 1838 | static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { |
| 1868 | static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size, | 1839 | switch (perm) { |
| 1869 | u32 permissions) { | 1840 | case MemoryPermission::None: |
| 1870 | std::lock_guard lock{HLE::g_hle_lock}; | 1841 | case MemoryPermission::Read: |
| 1871 | LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size, | 1842 | case MemoryPermission::ReadWrite: |
| 1872 | permissions); | 1843 | return true; |
| 1873 | 1844 | default: | |
| 1874 | if (!Common::Is4KBAligned(addr)) { | 1845 | return false; |
| 1875 | LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr); | ||
| 1876 | return ResultInvalidAddress; | ||
| 1877 | } | 1846 | } |
| 1847 | } | ||
| 1878 | 1848 | ||
| 1879 | if (!Common::Is4KBAligned(size) || size == 0) { | 1849 | /// Creates a TransferMemory object |
| 1880 | LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size); | 1850 | static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, |
| 1881 | return ResultInvalidAddress; | 1851 | MemoryPermission map_perm) { |
| 1882 | } | 1852 | auto& kernel = system.Kernel(); |
| 1883 | 1853 | ||
| 1884 | if (!IsValidAddressRange(addr, size)) { | 1854 | // Validate the size. |
| 1885 | LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})", | 1855 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); |
| 1886 | addr, size); | 1856 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); |
| 1887 | return ResultInvalidCurrentMemory; | 1857 | R_UNLESS(size > 0, ResultInvalidSize); |
| 1888 | } | 1858 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); |
| 1889 | 1859 | ||
| 1890 | const auto perms{static_cast<MemoryPermission>(permissions)}; | 1860 | // Validate the permissions. |
| 1891 | if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) { | 1861 | R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); |
| 1892 | LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", | 1862 | |
| 1893 | permissions); | 1863 | // Get the current process and handle table. |
| 1894 | return ResultInvalidMemoryPermissions; | 1864 | auto& process = *kernel.CurrentProcess(); |
| 1895 | } | 1865 | auto& handle_table = process.GetHandleTable(); |
| 1896 | 1866 | ||
| 1897 | auto& kernel = system.Kernel(); | ||
| 1898 | // Reserve a new transfer memory from the process resource limit. | 1867 | // Reserve a new transfer memory from the process resource limit. |
| 1899 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | 1868 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), |
| 1900 | LimitableResource::TransferMemory); | 1869 | LimitableResource::TransferMemory); |
| 1901 | if (!trmem_reservation.Succeeded()) { | 1870 | R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); |
| 1902 | LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); | ||
| 1903 | return ResultResourceLimitedExceeded; | ||
| 1904 | } | ||
| 1905 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, | ||
| 1906 | static_cast<KMemoryPermission>(perms)); | ||
| 1907 | 1871 | ||
| 1908 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { | 1872 | // Create the transfer memory. |
| 1909 | return reserve_result; | 1873 | KTransferMemory* trmem = KTransferMemory::Create(kernel); |
| 1910 | } | 1874 | R_UNLESS(trmem != nullptr, ResultOutOfResource); |
| 1911 | 1875 | ||
| 1912 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1876 | // Ensure the only reference is in the handle table when we're done. |
| 1913 | const auto result{handle_table.Create(std::move(transfer_mem_handle))}; | 1877 | SCOPE_EXIT({ trmem->Close(); }); |
| 1914 | if (result.Failed()) { | 1878 | |
| 1915 | return result.Code(); | 1879 | // Ensure that the region is in range. |
| 1916 | } | 1880 | R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); |
| 1881 | |||
| 1882 | // Initialize the transfer memory. | ||
| 1883 | R_TRY(trmem->Initialize(address, size, map_perm)); | ||
| 1884 | |||
| 1885 | // Commit the reservation. | ||
| 1917 | trmem_reservation.Commit(); | 1886 | trmem_reservation.Commit(); |
| 1918 | 1887 | ||
| 1919 | *handle = *result; | 1888 | // Register the transfer memory. |
| 1889 | KTransferMemory::Register(kernel, trmem); | ||
| 1890 | |||
| 1891 | // Add the transfer memory to the handle table. | ||
| 1892 | R_TRY(handle_table.Add(out, trmem)); | ||
| 1893 | |||
| 1920 | return RESULT_SUCCESS; | 1894 | return RESULT_SUCCESS; |
| 1921 | } | 1895 | } |
| 1922 | 1896 | ||
| 1923 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, | 1897 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size, |
| 1924 | u32 permissions) { | 1898 | MemoryPermission map_perm) { |
| 1925 | return CreateTransferMemory(system, handle, addr, size, permissions); | 1899 | return CreateTransferMemory(system, out, address, size, map_perm); |
| 1926 | } | 1900 | } |
| 1927 | 1901 | ||
| 1928 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, | 1902 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, |
| @@ -1930,19 +1904,12 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1930 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); | 1904 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); |
| 1931 | 1905 | ||
| 1932 | // Get the thread from its handle. | 1906 | // Get the thread from its handle. |
| 1933 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1907 | KScopedAutoObject thread = |
| 1934 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1908 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 1935 | if (!thread) { | 1909 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1936 | LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle); | ||
| 1937 | return ResultInvalidHandle; | ||
| 1938 | } | ||
| 1939 | 1910 | ||
| 1940 | // Get the core mask. | 1911 | // Get the core mask. |
| 1941 | const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask); | 1912 | R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); |
| 1942 | if (result.IsError()) { | ||
| 1943 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw); | ||
| 1944 | return result; | ||
| 1945 | } | ||
| 1946 | 1913 | ||
| 1947 | return RESULT_SUCCESS; | 1914 | return RESULT_SUCCESS; |
| 1948 | } | 1915 | } |
| @@ -1958,58 +1925,33 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle | |||
| 1958 | 1925 | ||
| 1959 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, | 1926 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, |
| 1960 | u64 affinity_mask) { | 1927 | u64 affinity_mask) { |
| 1961 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}", | ||
| 1962 | thread_handle, core_id, affinity_mask); | ||
| 1963 | |||
| 1964 | const auto& current_process = *system.Kernel().CurrentProcess(); | ||
| 1965 | |||
| 1966 | // Determine the core id/affinity mask. | 1928 | // Determine the core id/affinity mask. |
| 1967 | if (core_id == Svc::IdealCoreUseProcessValue) { | 1929 | if (core_id == IdealCoreUseProcessValue) { |
| 1968 | core_id = current_process.GetIdealCoreId(); | 1930 | core_id = system.Kernel().CurrentProcess()->GetIdealCoreId(); |
| 1969 | affinity_mask = (1ULL << core_id); | 1931 | affinity_mask = (1ULL << core_id); |
| 1970 | } else { | 1932 | } else { |
| 1971 | // Validate the affinity mask. | 1933 | // Validate the affinity mask. |
| 1972 | const u64 process_core_mask = current_process.GetCoreMask(); | 1934 | const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask(); |
| 1973 | if ((affinity_mask | process_core_mask) != process_core_mask) { | 1935 | R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId); |
| 1974 | LOG_ERROR(Kernel_SVC, | 1936 | R_UNLESS(affinity_mask != 0, ResultInvalidCombination); |
| 1975 | "Affinity mask does match the process core mask (affinity mask={:016X}, core " | ||
| 1976 | "mask={:016X})", | ||
| 1977 | affinity_mask, process_core_mask); | ||
| 1978 | return ResultInvalidCoreId; | ||
| 1979 | } | ||
| 1980 | if (affinity_mask == 0) { | ||
| 1981 | LOG_ERROR(Kernel_SVC, "Affinity mask is zero."); | ||
| 1982 | return ResultInvalidCombination; | ||
| 1983 | } | ||
| 1984 | 1937 | ||
| 1985 | // Validate the core id. | 1938 | // Validate the core id. |
| 1986 | if (IsValidCoreId(core_id)) { | 1939 | if (IsValidVirtualCoreId(core_id)) { |
| 1987 | if (((1ULL << core_id) & affinity_mask) == 0) { | 1940 | R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination); |
| 1988 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); | ||
| 1989 | return ResultInvalidCombination; | ||
| 1990 | } | ||
| 1991 | } else { | 1941 | } else { |
| 1992 | if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { | 1942 | R_UNLESS(core_id == IdealCoreNoUpdate || core_id == IdealCoreDontCare, |
| 1993 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); | 1943 | ResultInvalidCoreId); |
| 1994 | return ResultInvalidCoreId; | ||
| 1995 | } | ||
| 1996 | } | 1944 | } |
| 1997 | } | 1945 | } |
| 1998 | 1946 | ||
| 1999 | // Get the thread from its handle. | 1947 | // Get the thread from its handle. |
| 2000 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1948 | KScopedAutoObject thread = |
| 2001 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1949 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 2002 | if (!thread) { | 1950 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 2003 | LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle); | ||
| 2004 | return ResultInvalidHandle; | ||
| 2005 | } | ||
| 2006 | 1951 | ||
| 2007 | // Set the core mask. | 1952 | // Set the core mask. |
| 2008 | const auto set_result = thread->SetCoreMask(core_id, affinity_mask); | 1953 | R_TRY(thread->SetCoreMask(core_id, affinity_mask)); |
| 2009 | if (set_result.IsError()) { | 1954 | |
| 2010 | LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); | ||
| 2011 | return set_result; | ||
| 2012 | } | ||
| 2013 | return RESULT_SUCCESS; | 1955 | return RESULT_SUCCESS; |
| 2014 | } | 1956 | } |
| 2015 | 1957 | ||
| @@ -2022,27 +1964,12 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle | |||
| 2022 | static ResultCode SignalEvent(Core::System& system, Handle event_handle) { | 1964 | static ResultCode SignalEvent(Core::System& system, Handle event_handle) { |
| 2023 | LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); | 1965 | LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); |
| 2024 | 1966 | ||
| 2025 | auto& kernel = system.Kernel(); | ||
| 2026 | // Get the current handle table. | 1967 | // Get the current handle table. |
| 2027 | const HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1968 | const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 2028 | |||
| 2029 | // Reserve a new event from the process resource limit. | ||
| 2030 | KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | ||
| 2031 | LimitableResource::Events); | ||
| 2032 | if (!event_reservation.Succeeded()) { | ||
| 2033 | LOG_ERROR(Kernel, "Could not reserve a new event"); | ||
| 2034 | return ResultResourceLimitedExceeded; | ||
| 2035 | } | ||
| 2036 | 1969 | ||
| 2037 | // Get the writable event. | 1970 | // Get the writable event. |
| 2038 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); | 1971 | KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle); |
| 2039 | if (!writable_event) { | 1972 | R_UNLESS(writable_event.IsNotNull(), ResultInvalidHandle); |
| 2040 | LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle); | ||
| 2041 | return ResultInvalidHandle; | ||
| 2042 | } | ||
| 2043 | |||
| 2044 | // Commit the successfuly reservation. | ||
| 2045 | event_reservation.Commit(); | ||
| 2046 | 1973 | ||
| 2047 | return writable_event->Signal(); | 1974 | return writable_event->Signal(); |
| 2048 | } | 1975 | } |
| @@ -2059,16 +1986,16 @@ static ResultCode ClearEvent(Core::System& system, Handle event_handle) { | |||
| 2059 | 1986 | ||
| 2060 | // Try to clear the writable event. | 1987 | // Try to clear the writable event. |
| 2061 | { | 1988 | { |
| 2062 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); | 1989 | KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle); |
| 2063 | if (writable_event) { | 1990 | if (writable_event.IsNotNull()) { |
| 2064 | return writable_event->Clear(); | 1991 | return writable_event->Clear(); |
| 2065 | } | 1992 | } |
| 2066 | } | 1993 | } |
| 2067 | 1994 | ||
| 2068 | // Try to clear the readable event. | 1995 | // Try to clear the readable event. |
| 2069 | { | 1996 | { |
| 2070 | auto readable_event = handle_table.Get<KReadableEvent>(event_handle); | 1997 | KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(event_handle); |
| 2071 | if (readable_event) { | 1998 | if (readable_event.IsNotNull()) { |
| 2072 | return readable_event->Clear(); | 1999 | return readable_event->Clear(); |
| 2073 | } | 2000 | } |
| 2074 | } | 2001 | } |
| @@ -2087,34 +2014,40 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o | |||
| 2087 | 2014 | ||
| 2088 | // Get the kernel reference and handle table. | 2015 | // Get the kernel reference and handle table. |
| 2089 | auto& kernel = system.Kernel(); | 2016 | auto& kernel = system.Kernel(); |
| 2090 | HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 2017 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 2018 | |||
| 2019 | // Reserve a new event from the process resource limit | ||
| 2020 | KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | ||
| 2021 | LimitableResource::Events); | ||
| 2022 | R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); | ||
| 2091 | 2023 | ||
| 2092 | // Create a new event. | 2024 | // Create a new event. |
| 2093 | const auto event = KEvent::Create(kernel, "CreateEvent"); | 2025 | KEvent* event = KEvent::Create(kernel); |
| 2094 | if (!event) { | 2026 | R_UNLESS(event != nullptr, ResultOutOfResource); |
| 2095 | LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached."); | ||
| 2096 | return ResultOutOfResource; | ||
| 2097 | } | ||
| 2098 | 2027 | ||
| 2099 | // Initialize the event. | 2028 | // Initialize the event. |
| 2100 | event->Initialize(); | 2029 | event->Initialize("CreateEvent"); |
| 2030 | |||
| 2031 | // Commit the thread reservation. | ||
| 2032 | event_reservation.Commit(); | ||
| 2033 | |||
| 2034 | // Ensure that we clean up the event (and its only references are handle table) on function end. | ||
| 2035 | SCOPE_EXIT({ | ||
| 2036 | event->GetWritableEvent().Close(); | ||
| 2037 | event->GetReadableEvent().Close(); | ||
| 2038 | }); | ||
| 2039 | |||
| 2040 | // Register the event. | ||
| 2041 | KEvent::Register(kernel, event); | ||
| 2101 | 2042 | ||
| 2102 | // Add the writable event to the handle table. | 2043 | // Add the writable event to the handle table. |
| 2103 | const auto write_create_result = handle_table.Create(event->GetWritableEvent()); | 2044 | R_TRY(handle_table.Add(out_write, std::addressof(event->GetWritableEvent()))); |
| 2104 | if (write_create_result.Failed()) { | ||
| 2105 | return write_create_result.Code(); | ||
| 2106 | } | ||
| 2107 | *out_write = *write_create_result; | ||
| 2108 | 2045 | ||
| 2109 | // Add the writable event to the handle table. | 2046 | // Add the writable event to the handle table. |
| 2110 | auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); }); | 2047 | auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*out_write); }); |
| 2111 | 2048 | ||
| 2112 | // Add the readable event to the handle table. | 2049 | // Add the readable event to the handle table. |
| 2113 | const auto read_create_result = handle_table.Create(event->GetReadableEvent()); | 2050 | R_TRY(handle_table.Add(out_read, std::addressof(event->GetReadableEvent()))); |
| 2114 | if (read_create_result.Failed()) { | ||
| 2115 | return read_create_result.Code(); | ||
| 2116 | } | ||
| 2117 | *out_read = *read_create_result; | ||
| 2118 | 2051 | ||
| 2119 | // We succeeded. | 2052 | // We succeeded. |
| 2120 | handle_guard.Cancel(); | 2053 | handle_guard.Cancel(); |
| @@ -2134,8 +2067,8 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ | |||
| 2134 | }; | 2067 | }; |
| 2135 | 2068 | ||
| 2136 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 2069 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 2137 | const auto process = handle_table.Get<Process>(process_handle); | 2070 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |
| 2138 | if (!process) { | 2071 | if (process.IsNull()) { |
| 2139 | LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", | 2072 | LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", |
| 2140 | process_handle); | 2073 | process_handle); |
| 2141 | return ResultInvalidHandle; | 2074 | return ResultInvalidHandle; |
| @@ -2152,83 +2085,86 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ | |||
| 2152 | } | 2085 | } |
| 2153 | 2086 | ||
| 2154 | static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { | 2087 | static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { |
| 2155 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 2156 | LOG_DEBUG(Kernel_SVC, "called"); | 2088 | LOG_DEBUG(Kernel_SVC, "called"); |
| 2157 | 2089 | ||
| 2090 | // Create a new resource limit. | ||
| 2158 | auto& kernel = system.Kernel(); | 2091 | auto& kernel = system.Kernel(); |
| 2159 | auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming()); | 2092 | KResourceLimit* resource_limit = KResourceLimit::Create(kernel); |
| 2093 | R_UNLESS(resource_limit != nullptr, ResultOutOfResource); | ||
| 2160 | 2094 | ||
| 2161 | auto* const current_process = kernel.CurrentProcess(); | 2095 | // Ensure we don't leak a reference to the limit. |
| 2162 | ASSERT(current_process != nullptr); | 2096 | SCOPE_EXIT({ resource_limit->Close(); }); |
| 2163 | 2097 | ||
| 2164 | const auto handle = current_process->GetHandleTable().Create(std::move(resource_limit)); | 2098 | // Initialize the resource limit. |
| 2165 | if (handle.Failed()) { | 2099 | resource_limit->Initialize(&system.CoreTiming()); |
| 2166 | return handle.Code(); | 2100 | |
| 2167 | } | 2101 | // Register the limit. |
| 2102 | KResourceLimit::Register(kernel, resource_limit); | ||
| 2103 | |||
| 2104 | // Add the limit to the handle table. | ||
| 2105 | R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit)); | ||
| 2168 | 2106 | ||
| 2169 | *out_handle = *handle; | ||
| 2170 | return RESULT_SUCCESS; | 2107 | return RESULT_SUCCESS; |
| 2171 | } | 2108 | } |
| 2172 | 2109 | ||
| 2173 | static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value, | 2110 | static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value, |
| 2174 | Handle resource_limit, u32 resource_type) { | 2111 | Handle resource_limit_handle, |
| 2175 | LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); | 2112 | LimitableResource which) { |
| 2113 | LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, | ||
| 2114 | which); | ||
| 2176 | 2115 | ||
| 2177 | const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, | 2116 | // Validate the resource. |
| 2178 | ResourceLimitValueType::LimitValue); | 2117 | R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); |
| 2179 | if (limit_value.Failed()) { | 2118 | |
| 2180 | return limit_value.Code(); | 2119 | // Get the resource limit. |
| 2181 | } | 2120 | auto& kernel = system.Kernel(); |
| 2121 | KScopedAutoObject resource_limit = | ||
| 2122 | kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); | ||
| 2123 | R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); | ||
| 2124 | |||
| 2125 | // Get the limit value. | ||
| 2126 | *out_limit_value = resource_limit->GetLimitValue(which); | ||
| 2182 | 2127 | ||
| 2183 | *out_value = static_cast<u64>(*limit_value); | ||
| 2184 | return RESULT_SUCCESS; | 2128 | return RESULT_SUCCESS; |
| 2185 | } | 2129 | } |
| 2186 | 2130 | ||
| 2187 | static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value, | 2131 | static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value, |
| 2188 | Handle resource_limit, u32 resource_type) { | 2132 | Handle resource_limit_handle, |
| 2189 | LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); | 2133 | LimitableResource which) { |
| 2134 | LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, | ||
| 2135 | which); | ||
| 2190 | 2136 | ||
| 2191 | const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, | 2137 | // Validate the resource. |
| 2192 | ResourceLimitValueType::CurrentValue); | 2138 | R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); |
| 2193 | if (current_value.Failed()) { | 2139 | |
| 2194 | return current_value.Code(); | 2140 | // Get the resource limit. |
| 2195 | } | 2141 | auto& kernel = system.Kernel(); |
| 2142 | KScopedAutoObject resource_limit = | ||
| 2143 | kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); | ||
| 2144 | R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); | ||
| 2145 | |||
| 2146 | // Get the current value. | ||
| 2147 | *out_current_value = resource_limit->GetCurrentValue(which); | ||
| 2196 | 2148 | ||
| 2197 | *out_value = static_cast<u64>(*current_value); | ||
| 2198 | return RESULT_SUCCESS; | 2149 | return RESULT_SUCCESS; |
| 2199 | } | 2150 | } |
| 2200 | 2151 | ||
| 2201 | static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit, | 2152 | static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, |
| 2202 | u32 resource_type, u64 value) { | 2153 | LimitableResource which, u64 limit_value) { |
| 2203 | LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, | 2154 | LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}", |
| 2204 | resource_type, value); | 2155 | resource_limit_handle, which, limit_value); |
| 2205 | 2156 | ||
| 2206 | const auto type = static_cast<LimitableResource>(resource_type); | 2157 | // Validate the resource. |
| 2207 | if (!IsValidResourceType(type)) { | 2158 | R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); |
| 2208 | LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); | ||
| 2209 | return ResultInvalidEnumValue; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | auto* const current_process = system.Kernel().CurrentProcess(); | ||
| 2213 | ASSERT(current_process != nullptr); | ||
| 2214 | 2159 | ||
| 2215 | auto resource_limit_object = | 2160 | // Get the resource limit. |
| 2216 | current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); | 2161 | auto& kernel = system.Kernel(); |
| 2217 | if (!resource_limit_object) { | 2162 | KScopedAutoObject resource_limit = |
| 2218 | LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", | 2163 | kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); |
| 2219 | resource_limit); | 2164 | R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); |
| 2220 | return ResultInvalidHandle; | ||
| 2221 | } | ||
| 2222 | 2165 | ||
| 2223 | const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value)); | 2166 | // Set the limit value. |
| 2224 | if (set_result.IsError()) { | 2167 | R_TRY(resource_limit->SetLimitValue(which, limit_value)); |
| 2225 | LOG_ERROR(Kernel_SVC, | ||
| 2226 | "Attempted to lower resource limit ({}) for category '{}' below its current " | ||
| 2227 | "value ({})", | ||
| 2228 | resource_limit_object->GetLimitValue(type), resource_type, | ||
| 2229 | resource_limit_object->GetCurrentValue(type)); | ||
| 2230 | return set_result; | ||
| 2231 | } | ||
| 2232 | 2168 | ||
| 2233 | return RESULT_SUCCESS; | 2169 | return RESULT_SUCCESS; |
| 2234 | } | 2170 | } |
| @@ -2351,7 +2287,7 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2351 | {0x11, SvcWrap32<SignalEvent32>, "SignalEvent32"}, | 2287 | {0x11, SvcWrap32<SignalEvent32>, "SignalEvent32"}, |
| 2352 | {0x12, SvcWrap32<ClearEvent32>, "ClearEvent32"}, | 2288 | {0x12, SvcWrap32<ClearEvent32>, "ClearEvent32"}, |
| 2353 | {0x13, SvcWrap32<MapSharedMemory32>, "MapSharedMemory32"}, | 2289 | {0x13, SvcWrap32<MapSharedMemory32>, "MapSharedMemory32"}, |
| 2354 | {0x14, nullptr, "UnmapSharedMemory32"}, | 2290 | {0x14, SvcWrap32<UnmapSharedMemory32>, "UnmapSharedMemory32"}, |
| 2355 | {0x15, SvcWrap32<CreateTransferMemory32>, "CreateTransferMemory32"}, | 2291 | {0x15, SvcWrap32<CreateTransferMemory32>, "CreateTransferMemory32"}, |
| 2356 | {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, | 2292 | {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, |
| 2357 | {0x17, SvcWrap32<ResetSignal32>, "ResetSignal32"}, | 2293 | {0x17, SvcWrap32<ResetSignal32>, "ResetSignal32"}, |
| @@ -2546,7 +2482,7 @@ static const FunctionDef SVC_Table_64[] = { | |||
| 2546 | {0x11, SvcWrap64<SignalEvent>, "SignalEvent"}, | 2482 | {0x11, SvcWrap64<SignalEvent>, "SignalEvent"}, |
| 2547 | {0x12, SvcWrap64<ClearEvent>, "ClearEvent"}, | 2483 | {0x12, SvcWrap64<ClearEvent>, "ClearEvent"}, |
| 2548 | {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"}, | 2484 | {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"}, |
| 2549 | {0x14, nullptr, "UnmapSharedMemory"}, | 2485 | {0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"}, |
| 2550 | {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"}, | 2486 | {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"}, |
| 2551 | {0x16, SvcWrap64<CloseHandle>, "CloseHandle"}, | 2487 | {0x16, SvcWrap64<CloseHandle>, "CloseHandle"}, |
| 2552 | {0x17, SvcWrap64<ResetSignal>, "ResetSignal"}, | 2488 | {0x17, SvcWrap64<ResetSignal>, "ResetSignal"}, |
diff --git a/src/core/hle/kernel/svc_common.h b/src/core/hle/kernel/svc_common.h index 4af049551..60ea2c405 100644 --- a/src/core/hle/kernel/svc_common.h +++ b/src/core/hle/kernel/svc_common.h | |||
| @@ -6,9 +6,24 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | namespace Kernel { | ||
| 10 | using Handle = u32; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Kernel::Svc { | 13 | namespace Kernel::Svc { |
| 10 | 14 | ||
| 11 | constexpr s32 ArgumentHandleCountMax = 0x40; | 15 | constexpr s32 ArgumentHandleCountMax = 0x40; |
| 12 | constexpr u32 HandleWaitMask{1u << 30}; | 16 | constexpr u32 HandleWaitMask{1u << 30}; |
| 13 | 17 | ||
| 18 | constexpr inline Handle InvalidHandle = Handle(0); | ||
| 19 | |||
| 20 | enum PseudoHandle : Handle { | ||
| 21 | CurrentThread = 0xFFFF8000, | ||
| 22 | CurrentProcess = 0xFFFF8001, | ||
| 23 | }; | ||
| 24 | |||
| 25 | constexpr bool IsPseudoHandle(Handle handle) { | ||
| 26 | return handle == PseudoHandle::CurrentProcess || handle == PseudoHandle::CurrentThread; | ||
| 27 | } | ||
| 28 | |||
| 14 | } // namespace Kernel::Svc | 29 | } // namespace Kernel::Svc |
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h index a26d9f2c9..53a940723 100644 --- a/src/core/hle/kernel/svc_results.h +++ b/src/core/hle/kernel/svc_results.h | |||
| @@ -10,18 +10,18 @@ namespace Kernel { | |||
| 10 | 10 | ||
| 11 | // Confirmed Switch kernel error codes | 11 | // Confirmed Switch kernel error codes |
| 12 | 12 | ||
| 13 | constexpr ResultCode ResultMaxConnectionsReached{ErrorModule::Kernel, 7}; | 13 | constexpr ResultCode ResultOutOfSessions{ErrorModule::Kernel, 7}; |
| 14 | constexpr ResultCode ResultInvalidCapabilityDescriptor{ErrorModule::Kernel, 14}; | 14 | constexpr ResultCode ResultInvalidArgument{ErrorModule::Kernel, 14}; |
| 15 | constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; | 15 | constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; |
| 16 | constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; | 16 | constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; |
| 17 | constexpr ResultCode ResultInvalidSize{ErrorModule::Kernel, 101}; | 17 | constexpr ResultCode ResultInvalidSize{ErrorModule::Kernel, 101}; |
| 18 | constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; | 18 | constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; |
| 19 | constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103}; | 19 | constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103}; |
| 20 | constexpr ResultCode ResultOutOfMemory{ErrorModule::Kernel, 104}; | 20 | constexpr ResultCode ResultOutOfMemory{ErrorModule::Kernel, 104}; |
| 21 | constexpr ResultCode ResultHandleTableFull{ErrorModule::Kernel, 105}; | 21 | constexpr ResultCode ResultOutOfHandles{ErrorModule::Kernel, 105}; |
| 22 | constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; | 22 | constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; |
| 23 | constexpr ResultCode ResultInvalidMemoryPermissions{ErrorModule::Kernel, 108}; | 23 | constexpr ResultCode ResultInvalidNewMemoryPermission{ErrorModule::Kernel, 108}; |
| 24 | constexpr ResultCode ResultInvalidMemoryRange{ErrorModule::Kernel, 110}; | 24 | constexpr ResultCode ResultInvalidMemoryRegion{ErrorModule::Kernel, 110}; |
| 25 | constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; | 25 | constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; |
| 26 | constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; | 26 | constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; |
| 27 | constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; | 27 | constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; |
| @@ -33,9 +33,11 @@ constexpr ResultCode ResultOutOfRange{ErrorModule::Kernel, 119}; | |||
| 33 | constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120}; | 33 | constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120}; |
| 34 | constexpr ResultCode ResultNotFound{ErrorModule::Kernel, 121}; | 34 | constexpr ResultCode ResultNotFound{ErrorModule::Kernel, 121}; |
| 35 | constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122}; | 35 | constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122}; |
| 36 | constexpr ResultCode ResultSessionClosedByRemote{ErrorModule::Kernel, 123}; | 36 | constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123}; |
| 37 | constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; | 37 | constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; |
| 38 | constexpr ResultCode ResultReservedValue{ErrorModule::Kernel, 126}; | 38 | constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126}; |
| 39 | constexpr ResultCode ResultResourceLimitedExceeded{ErrorModule::Kernel, 132}; | 39 | constexpr ResultCode ResultPortClosed{ErrorModule::Kernel, 131}; |
| 40 | constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132}; | ||
| 41 | constexpr ResultCode ResultInvalidId{ErrorModule::Kernel, 519}; | ||
| 40 | 42 | ||
| 41 | } // namespace Kernel | 43 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 96afd544b..913b16494 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -154,15 +154,28 @@ void SvcWrap64(Core::System& system) { | |||
| 154 | FuncReturn(system, retval); | 154 | FuncReturn(system, retval); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | // Used by GetResourceLimitLimitValue. | ||
| 158 | template <ResultCode func(Core::System&, u64*, Handle, LimitableResource)> | ||
| 159 | void SvcWrap64(Core::System& system) { | ||
| 160 | u64 param_1 = 0; | ||
| 161 | const u32 retval = func(system, ¶m_1, static_cast<Handle>(Param(system, 1)), | ||
| 162 | static_cast<LimitableResource>(Param(system, 2))) | ||
| 163 | .raw; | ||
| 164 | |||
| 165 | system.CurrentArmInterface().SetReg(1, param_1); | ||
| 166 | FuncReturn(system, retval); | ||
| 167 | } | ||
| 168 | |||
| 157 | template <ResultCode func(Core::System&, u32, u64)> | 169 | template <ResultCode func(Core::System&, u32, u64)> |
| 158 | void SvcWrap64(Core::System& system) { | 170 | void SvcWrap64(Core::System& system) { |
| 159 | FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); | 171 | FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); |
| 160 | } | 172 | } |
| 161 | 173 | ||
| 162 | template <ResultCode func(Core::System&, u32, u32, u64)> | 174 | // Used by SetResourceLimitLimitValue |
| 175 | template <ResultCode func(Core::System&, Handle, LimitableResource, u64)> | ||
| 163 | void SvcWrap64(Core::System& system) { | 176 | void SvcWrap64(Core::System& system) { |
| 164 | FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), | 177 | FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), |
| 165 | static_cast<u32>(Param(system, 1)), Param(system, 2)) | 178 | static_cast<LimitableResource>(Param(system, 1)), Param(system, 2)) |
| 166 | .raw); | 179 | .raw); |
| 167 | } | 180 | } |
| 168 | 181 | ||
| @@ -219,10 +232,11 @@ void SvcWrap64(Core::System& system) { | |||
| 219 | func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); | 232 | func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); |
| 220 | } | 233 | } |
| 221 | 234 | ||
| 222 | template <ResultCode func(Core::System&, u32, u64, u64, u32)> | 235 | // Used by MapSharedMemory |
| 236 | template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)> | ||
| 223 | void SvcWrap64(Core::System& system) { | 237 | void SvcWrap64(Core::System& system) { |
| 224 | FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), | 238 | FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1), |
| 225 | Param(system, 2), static_cast<u32>(Param(system, 3))) | 239 | Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3))) |
| 226 | .raw); | 240 | .raw); |
| 227 | } | 241 | } |
| 228 | 242 | ||
| @@ -252,11 +266,13 @@ void SvcWrap64(Core::System& system) { | |||
| 252 | .raw); | 266 | .raw); |
| 253 | } | 267 | } |
| 254 | 268 | ||
| 255 | template <ResultCode func(Core::System&, u64*, u64, u64, u64)> | 269 | // Used by GetInfo |
| 270 | template <ResultCode func(Core::System&, u64*, u64, Handle, u64)> | ||
| 256 | void SvcWrap64(Core::System& system) { | 271 | void SvcWrap64(Core::System& system) { |
| 257 | u64 param_1 = 0; | 272 | u64 param_1 = 0; |
| 258 | const u32 retval = | 273 | const u32 retval = func(system, ¶m_1, Param(system, 1), |
| 259 | func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw; | 274 | static_cast<Handle>(Param(system, 2)), Param(system, 3)) |
| 275 | .raw; | ||
| 260 | 276 | ||
| 261 | system.CurrentArmInterface().SetReg(1, param_1); | 277 | system.CurrentArmInterface().SetReg(1, param_1); |
| 262 | FuncReturn(system, retval); | 278 | FuncReturn(system, retval); |
| @@ -273,11 +289,12 @@ void SvcWrap64(Core::System& system) { | |||
| 273 | FuncReturn(system, retval); | 289 | FuncReturn(system, retval); |
| 274 | } | 290 | } |
| 275 | 291 | ||
| 276 | template <ResultCode func(Core::System&, u32*, u64, u64, u32)> | 292 | // Used by CreateTransferMemory |
| 293 | template <ResultCode func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)> | ||
| 277 | void SvcWrap64(Core::System& system) { | 294 | void SvcWrap64(Core::System& system) { |
| 278 | u32 param_1 = 0; | 295 | u32 param_1 = 0; |
| 279 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), | 296 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), |
| 280 | static_cast<u32>(Param(system, 3))) | 297 | static_cast<Svc::MemoryPermission>(Param(system, 3))) |
| 281 | .raw; | 298 | .raw; |
| 282 | 299 | ||
| 283 | system.CurrentArmInterface().SetReg(1, param_1); | 300 | system.CurrentArmInterface().SetReg(1, param_1); |
| @@ -537,6 +554,16 @@ void SvcWrap32(Core::System& system) { | |||
| 537 | FuncReturn(system, retval); | 554 | FuncReturn(system, retval); |
| 538 | } | 555 | } |
| 539 | 556 | ||
| 557 | // Used by MapSharedMemory32 | ||
| 558 | template <ResultCode func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)> | ||
| 559 | void SvcWrap32(Core::System& system) { | ||
| 560 | const u32 retval = func(system, static_cast<Handle>(Param(system, 0)), | ||
| 561 | static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)), | ||
| 562 | static_cast<Svc::MemoryPermission>(Param(system, 3))) | ||
| 563 | .raw; | ||
| 564 | FuncReturn(system, retval); | ||
| 565 | } | ||
| 566 | |||
| 540 | // Used by SetThreadCoreMask32 | 567 | // Used by SetThreadCoreMask32 |
| 541 | template <ResultCode func(Core::System&, Handle, s32, u32, u32)> | 568 | template <ResultCode func(Core::System&, Handle, s32, u32, u32)> |
| 542 | void SvcWrap32(Core::System& system) { | 569 | void SvcWrap32(Core::System& system) { |
| @@ -586,11 +613,12 @@ void SvcWrap32(Core::System& system) { | |||
| 586 | } | 613 | } |
| 587 | 614 | ||
| 588 | // Used by CreateTransferMemory32 | 615 | // Used by CreateTransferMemory32 |
| 589 | template <ResultCode func(Core::System&, Handle*, u32, u32, u32)> | 616 | template <ResultCode func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)> |
| 590 | void SvcWrap32(Core::System& system) { | 617 | void SvcWrap32(Core::System& system) { |
| 591 | Handle handle = 0; | 618 | Handle handle = 0; |
| 592 | const u32 retval = | 619 | const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2), |
| 593 | func(system, &handle, Param32(system, 1), Param32(system, 2), Param32(system, 3)).raw; | 620 | static_cast<Svc::MemoryPermission>(Param32(system, 3))) |
| 621 | .raw; | ||
| 594 | system.CurrentArmInterface().SetReg(1, handle); | 622 | system.CurrentArmInterface().SetReg(1, handle); |
| 595 | FuncReturn(system, retval); | 623 | FuncReturn(system, retval); |
| 596 | } | 624 | } |
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index fd0630019..ae9b4be2f 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/core_timing_util.h" | 8 | #include "core/core_timing_util.h" |
| 9 | #include "core/hle/kernel/handle_table.h" | ||
| 10 | #include "core/hle/kernel/k_scheduler.h" | 9 | #include "core/hle/kernel/k_scheduler.h" |
| 11 | #include "core/hle/kernel/k_thread.h" | 10 | #include "core/hle/kernel/k_thread.h" |
| 12 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| @@ -15,16 +14,12 @@ | |||
| 15 | namespace Kernel { | 14 | namespace Kernel { |
| 16 | 15 | ||
| 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { | 16 | TimeManager::TimeManager(Core::System& system_) : system{system_} { |
| 18 | time_manager_event_type = Core::Timing::CreateEvent( | 17 | time_manager_event_type = |
| 19 | "Kernel::TimeManagerCallback", | 18 | Core::Timing::CreateEvent("Kernel::TimeManagerCallback", |
| 20 | [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { | 19 | [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { |
| 21 | std::shared_ptr<KThread> thread; | 20 | KThread* thread = reinterpret_cast<KThread*>(thread_handle); |
| 22 | { | 21 | thread->Wakeup(); |
| 23 | std::lock_guard lock{mutex}; | 22 | }); |
| 24 | thread = SharedFrom<KThread>(reinterpret_cast<KThread*>(thread_handle)); | ||
| 25 | } | ||
| 26 | thread->Wakeup(); | ||
| 27 | }); | ||
| 28 | } | 23 | } |
| 29 | 24 | ||
| 30 | void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { | 25 | void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { |
diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h index 0d7f05f30..2d175a9c4 100644 --- a/src/core/hle/kernel/time_manager.h +++ b/src/core/hle/kernel/time_manager.h | |||
| @@ -8,8 +8,6 @@ | |||
| 8 | #include <mutex> | 8 | #include <mutex> |
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | 10 | ||
| 11 | #include "core/hle/kernel/object.h" | ||
| 12 | |||
| 13 | namespace Core { | 11 | namespace Core { |
| 14 | class System; | 12 | class System; |
| 15 | } // namespace Core | 13 | } // namespace Core |
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp deleted file mode 100644 index cad063e4d..000000000 --- a/src/core/hle/kernel/transfer_memory.cpp +++ /dev/null | |||
| @@ -1,51 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_page_table.h" | ||
| 6 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | ||
| 8 | #include "core/hle/kernel/process.h" | ||
| 9 | #include "core/hle/kernel/transfer_memory.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "core/memory.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | TransferMemory::TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory) | ||
| 16 | : Object{kernel}, memory{memory} {} | ||
| 17 | |||
| 18 | TransferMemory::~TransferMemory() { | ||
| 19 | // Release memory region when transfer memory is destroyed | ||
| 20 | Reset(); | ||
| 21 | owner_process->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); | ||
| 22 | } | ||
| 23 | |||
| 24 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, | ||
| 25 | Core::Memory::Memory& memory, | ||
| 26 | VAddr base_address, std::size_t size, | ||
| 27 | KMemoryPermission permissions) { | ||
| 28 | std::shared_ptr<TransferMemory> transfer_memory{ | ||
| 29 | std::make_shared<TransferMemory>(kernel, memory)}; | ||
| 30 | |||
| 31 | transfer_memory->base_address = base_address; | ||
| 32 | transfer_memory->size = size; | ||
| 33 | transfer_memory->owner_permissions = permissions; | ||
| 34 | transfer_memory->owner_process = kernel.CurrentProcess(); | ||
| 35 | |||
| 36 | return transfer_memory; | ||
| 37 | } | ||
| 38 | |||
| 39 | const u8* TransferMemory::GetPointer() const { | ||
| 40 | return memory.GetPointer(base_address); | ||
| 41 | } | ||
| 42 | |||
| 43 | ResultCode TransferMemory::Reserve() { | ||
| 44 | return owner_process->PageTable().ReserveTransferMemory(base_address, size, owner_permissions); | ||
| 45 | } | ||
| 46 | |||
| 47 | ResultCode TransferMemory::Reset() { | ||
| 48 | return owner_process->PageTable().ResetTransferMemory(base_address, size); | ||
| 49 | } | ||
| 50 | |||
| 51 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h deleted file mode 100644 index 521951424..000000000 --- a/src/core/hle/kernel/transfer_memory.h +++ /dev/null | |||
| @@ -1,93 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "core/hle/kernel/k_memory_block.h" | ||
| 10 | #include "core/hle/kernel/object.h" | ||
| 11 | #include "core/hle/kernel/physical_memory.h" | ||
| 12 | |||
| 13 | union ResultCode; | ||
| 14 | |||
| 15 | namespace Core::Memory { | ||
| 16 | class Memory; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Kernel { | ||
| 20 | |||
| 21 | class KernelCore; | ||
| 22 | class Process; | ||
| 23 | |||
| 24 | /// Defines the interface for transfer memory objects. | ||
| 25 | /// | ||
| 26 | /// Transfer memory is typically used for the purpose of | ||
| 27 | /// transferring memory between separate process instances, | ||
| 28 | /// thus the name. | ||
| 29 | /// | ||
| 30 | class TransferMemory final : public Object { | ||
| 31 | public: | ||
| 32 | explicit TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory); | ||
| 33 | ~TransferMemory() override; | ||
| 34 | |||
| 35 | static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; | ||
| 36 | |||
| 37 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory, | ||
| 38 | VAddr base_address, std::size_t size, | ||
| 39 | KMemoryPermission permissions); | ||
| 40 | |||
| 41 | TransferMemory(const TransferMemory&) = delete; | ||
| 42 | TransferMemory& operator=(const TransferMemory&) = delete; | ||
| 43 | |||
| 44 | TransferMemory(TransferMemory&&) = delete; | ||
| 45 | TransferMemory& operator=(TransferMemory&&) = delete; | ||
| 46 | |||
| 47 | std::string GetTypeName() const override { | ||
| 48 | return "TransferMemory"; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::string GetName() const override { | ||
| 52 | return GetTypeName(); | ||
| 53 | } | ||
| 54 | |||
| 55 | HandleType GetHandleType() const override { | ||
| 56 | return HANDLE_TYPE; | ||
| 57 | } | ||
| 58 | |||
| 59 | /// Gets a pointer to the backing block of this instance. | ||
| 60 | const u8* GetPointer() const; | ||
| 61 | |||
| 62 | /// Gets the size of the memory backing this instance in bytes. | ||
| 63 | constexpr std::size_t GetSize() const { | ||
| 64 | return size; | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Reserves the region to be used for the transfer memory, called after the transfer memory is | ||
| 68 | /// created. | ||
| 69 | ResultCode Reserve(); | ||
| 70 | |||
| 71 | /// Resets the region previously used for the transfer memory, called after the transfer memory | ||
| 72 | /// is closed. | ||
| 73 | ResultCode Reset(); | ||
| 74 | |||
| 75 | void Finalize() override {} | ||
| 76 | |||
| 77 | private: | ||
| 78 | /// The base address for the memory managed by this instance. | ||
| 79 | VAddr base_address{}; | ||
| 80 | |||
| 81 | /// Size of the memory, in bytes, that this instance manages. | ||
| 82 | std::size_t size{}; | ||
| 83 | |||
| 84 | /// The memory permissions that are applied to this instance. | ||
| 85 | KMemoryPermission owner_permissions{}; | ||
| 86 | |||
| 87 | /// The process that this transfer memory instance was created under. | ||
| 88 | Process* owner_process{}; | ||
| 89 | |||
| 90 | Core::Memory::Memory& memory; | ||
| 91 | }; | ||
| 92 | |||
| 93 | } // namespace Kernel | ||
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 8feda7ad7..43968386f 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -56,7 +56,7 @@ enum class ErrorModule : u32 { | |||
| 56 | PCIe = 120, | 56 | PCIe = 120, |
| 57 | Friends = 121, | 57 | Friends = 121, |
| 58 | BCAT = 122, | 58 | BCAT = 122, |
| 59 | SSL = 123, | 59 | SSLSrv = 123, |
| 60 | Account = 124, | 60 | Account = 124, |
| 61 | News = 125, | 61 | News = 125, |
| 62 | Mii = 126, | 62 | Mii = 126, |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 5450dcf0f..49c09a570 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -16,8 +16,8 @@ | |||
| 16 | #include "core/file_sys/control_metadata.h" | 16 | #include "core/file_sys/control_metadata.h" |
| 17 | #include "core/file_sys/patch_manager.h" | 17 | #include "core/file_sys/patch_manager.h" |
| 18 | #include "core/hle/ipc_helpers.h" | 18 | #include "core/hle/ipc_helpers.h" |
| 19 | #include "core/hle/kernel/k_process.h" | ||
| 19 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 20 | #include "core/hle/kernel/process.h" | ||
| 21 | #include "core/hle/service/acc/acc.h" | 21 | #include "core/hle/service/acc/acc.h" |
| 22 | #include "core/hle/service/acc/acc_aa.h" | 22 | #include "core/hle/service/acc/acc_aa.h" |
| 23 | #include "core/hle/service/acc/acc_su.h" | 23 | #include "core/hle/service/acc/acc_su.h" |
diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp index 51f119b12..e498fb64d 100644 --- a/src/core/hle/service/acc/acc_aa.cpp +++ b/src/core/hle/service/acc/acc_aa.cpp | |||
| @@ -6,9 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Account { | 7 | namespace Service::Account { |
| 8 | 8 | ||
| 9 | ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 9 | ACC_AA::ACC_AA(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, |
| 10 | Core::System& system) | 10 | Core::System& system_) |
| 11 | : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:aa") { | 11 | : Interface(std::move(module_), std::move(profile_manager_), system_, "acc:aa") { |
| 12 | // clang-format off | ||
| 12 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 13 | {0, nullptr, "EnsureCacheAsync"}, | 14 | {0, nullptr, "EnsureCacheAsync"}, |
| 14 | {1, nullptr, "LoadCache"}, | 15 | {1, nullptr, "LoadCache"}, |
| @@ -16,6 +17,7 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 16 | {50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 | 17 | {50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 |
| 17 | {51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 | 18 | {51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 |
| 18 | }; | 19 | }; |
| 20 | // clang-format on | ||
| 19 | RegisterHandlers(functions); | 21 | RegisterHandlers(functions); |
| 20 | } | 22 | } |
| 21 | 23 | ||
diff --git a/src/core/hle/service/acc/acc_aa.h b/src/core/hle/service/acc/acc_aa.h index 932c04890..d1be20ff3 100644 --- a/src/core/hle/service/acc/acc_aa.h +++ b/src/core/hle/service/acc/acc_aa.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Account { | |||
| 10 | 10 | ||
| 11 | class ACC_AA final : public Module::Interface { | 11 | class ACC_AA final : public Module::Interface { |
| 12 | public: | 12 | public: |
| 13 | explicit ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 13 | explicit ACC_AA(std::shared_ptr<Module> module_, |
| 14 | Core::System& system); | 14 | std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_); |
| 15 | ~ACC_AA() override; | 15 | ~ACC_AA() override; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index bb6118abf..94a1b8814 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Account { | 7 | namespace Service::Account { |
| 8 | 8 | ||
| 9 | ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 9 | ACC_SU::ACC_SU(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, |
| 10 | Core::System& system) | 10 | Core::System& system_) |
| 11 | : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:su") { | 11 | : Interface(std::move(module_), std::move(profile_manager_), system_, "acc:su") { |
| 12 | // clang-format off | 12 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 14 | {0, &ACC_SU::GetUserCount, "GetUserCount"}, | 14 | {0, &ACC_SU::GetUserCount, "GetUserCount"}, |
diff --git a/src/core/hle/service/acc/acc_su.h b/src/core/hle/service/acc/acc_su.h index 0a700d9bf..132a126b4 100644 --- a/src/core/hle/service/acc/acc_su.h +++ b/src/core/hle/service/acc/acc_su.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Account { | |||
| 10 | 10 | ||
| 11 | class ACC_SU final : public Module::Interface { | 11 | class ACC_SU final : public Module::Interface { |
| 12 | public: | 12 | public: |
| 13 | explicit ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 13 | explicit ACC_SU(std::shared_ptr<Module> module_, |
| 14 | Core::System& system); | 14 | std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_); |
| 15 | ~ACC_SU() override; | 15 | ~ACC_SU() override; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 8d66d180d..ed241647c 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Account { | 7 | namespace Service::Account { |
| 8 | 8 | ||
| 9 | ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 9 | ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, |
| 10 | Core::System& system) | 10 | Core::System& system_) |
| 11 | : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:u0") { | 11 | : Interface(std::move(module_), std::move(profile_manager_), system_, "acc:u0") { |
| 12 | // clang-format off | 12 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 14 | {0, &ACC_U0::GetUserCount, "GetUserCount"}, | 14 | {0, &ACC_U0::GetUserCount, "GetUserCount"}, |
diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h index 3bd9c3164..4c2600b67 100644 --- a/src/core/hle/service/acc/acc_u0.h +++ b/src/core/hle/service/acc/acc_u0.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Account { | |||
| 10 | 10 | ||
| 11 | class ACC_U0 final : public Module::Interface { | 11 | class ACC_U0 final : public Module::Interface { |
| 12 | public: | 12 | public: |
| 13 | explicit ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 13 | explicit ACC_U0(std::shared_ptr<Module> module_, |
| 14 | Core::System& system); | 14 | std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_); |
| 15 | ~ACC_U0() override; | 15 | ~ACC_U0() override; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 71982ad5a..6ce7fe8e6 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Account { | 7 | namespace Service::Account { |
| 8 | 8 | ||
| 9 | ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 9 | ACC_U1::ACC_U1(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, |
| 10 | Core::System& system) | 10 | Core::System& system_) |
| 11 | : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:u1") { | 11 | : Interface(std::move(module_), std::move(profile_manager_), system_, "acc:u1") { |
| 12 | // clang-format off | 12 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 14 | {0, &ACC_U1::GetUserCount, "GetUserCount"}, | 14 | {0, &ACC_U1::GetUserCount, "GetUserCount"}, |
diff --git a/src/core/hle/service/acc/acc_u1.h b/src/core/hle/service/acc/acc_u1.h index 829f8a744..2d478324a 100644 --- a/src/core/hle/service/acc/acc_u1.h +++ b/src/core/hle/service/acc/acc_u1.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Account { | |||
| 10 | 10 | ||
| 11 | class ACC_U1 final : public Module::Interface { | 11 | class ACC_U1 final : public Module::Interface { |
| 12 | public: | 12 | public: |
| 13 | explicit ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, | 13 | explicit ACC_U1(std::shared_ptr<Module> module_, |
| 14 | Core::System& system); | 14 | std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_); |
| 15 | ~ACC_U1() override; | 15 | ~ACC_U1() override; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 58c7f2930..234173297 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -15,11 +15,11 @@ | |||
| 15 | #include "core/file_sys/savedata_factory.h" | 15 | #include "core/file_sys/savedata_factory.h" |
| 16 | #include "core/hle/ipc_helpers.h" | 16 | #include "core/hle/ipc_helpers.h" |
| 17 | #include "core/hle/kernel/k_event.h" | 17 | #include "core/hle/kernel/k_event.h" |
| 18 | #include "core/hle/kernel/k_process.h" | ||
| 18 | #include "core/hle/kernel/k_readable_event.h" | 19 | #include "core/hle/kernel/k_readable_event.h" |
| 20 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 19 | #include "core/hle/kernel/k_writable_event.h" | 21 | #include "core/hle/kernel/k_writable_event.h" |
| 20 | #include "core/hle/kernel/kernel.h" | 22 | #include "core/hle/kernel/kernel.h" |
| 21 | #include "core/hle/kernel/process.h" | ||
| 22 | #include "core/hle/kernel/transfer_memory.h" | ||
| 23 | #include "core/hle/service/acc/profile_manager.h" | 23 | #include "core/hle/service/acc/profile_manager.h" |
| 24 | #include "core/hle/service/am/am.h" | 24 | #include "core/hle/service/am/am.h" |
| 25 | #include "core/hle/service/am/applet_ae.h" | 25 | #include "core/hle/service/am/applet_ae.h" |
| @@ -42,6 +42,7 @@ | |||
| 42 | #include "core/hle/service/set/set.h" | 42 | #include "core/hle/service/set/set.h" |
| 43 | #include "core/hle/service/sm/sm.h" | 43 | #include "core/hle/service/sm/sm.h" |
| 44 | #include "core/hle/service/vi/vi.h" | 44 | #include "core/hle/service/vi/vi.h" |
| 45 | #include "core/memory.h" | ||
| 45 | 46 | ||
| 46 | namespace Service::AM { | 47 | namespace Service::AM { |
| 47 | 48 | ||
| @@ -253,7 +254,8 @@ IDebugFunctions::IDebugFunctions(Core::System& system_) | |||
| 253 | IDebugFunctions::~IDebugFunctions() = default; | 254 | IDebugFunctions::~IDebugFunctions() = default; |
| 254 | 255 | ||
| 255 | ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_) | 256 | ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_) |
| 256 | : ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_} { | 257 | : ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_}, |
| 258 | launchable_event{system.Kernel()}, accumulated_suspended_tick_changed_event{system.Kernel()} { | ||
| 257 | // clang-format off | 259 | // clang-format off |
| 258 | static const FunctionInfo functions[] = { | 260 | static const FunctionInfo functions[] = { |
| 259 | {0, &ISelfController::Exit, "Exit"}, | 261 | {0, &ISelfController::Exit, "Exit"}, |
| @@ -306,19 +308,20 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv | |||
| 306 | 308 | ||
| 307 | RegisterHandlers(functions); | 309 | RegisterHandlers(functions); |
| 308 | 310 | ||
| 309 | auto& kernel = system.Kernel(); | 311 | Kernel::KAutoObject::Create(std::addressof(launchable_event)); |
| 310 | launchable_event = Kernel::KEvent::Create(kernel, "ISelfController:LaunchableEvent"); | 312 | |
| 311 | launchable_event->Initialize(); | 313 | launchable_event.Initialize("ISelfController:LaunchableEvent"); |
| 312 | 314 | ||
| 313 | // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is | 315 | // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is |
| 314 | // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple | 316 | // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple |
| 315 | // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not | 317 | // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not |
| 316 | // suspended if the event has previously been created by a call to | 318 | // suspended if the event has previously been created by a call to |
| 317 | // GetAccumulatedSuspendedTickChangedEvent. | 319 | // GetAccumulatedSuspendedTickChangedEvent. |
| 318 | accumulated_suspended_tick_changed_event = | 320 | |
| 319 | Kernel::KEvent::Create(kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent"); | 321 | Kernel::KAutoObject::Create(std::addressof(accumulated_suspended_tick_changed_event)); |
| 320 | accumulated_suspended_tick_changed_event->Initialize(); | 322 | accumulated_suspended_tick_changed_event.Initialize( |
| 321 | accumulated_suspended_tick_changed_event->GetWritableEvent()->Signal(); | 323 | "ISelfController:AccumulatedSuspendedTickChangedEvent"); |
| 324 | accumulated_suspended_tick_changed_event.GetWritableEvent().Signal(); | ||
| 322 | } | 325 | } |
| 323 | 326 | ||
| 324 | ISelfController::~ISelfController() = default; | 327 | ISelfController::~ISelfController() = default; |
| @@ -377,11 +380,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { | |||
| 377 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | 380 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { |
| 378 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 381 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 379 | 382 | ||
| 380 | launchable_event->GetWritableEvent()->Signal(); | 383 | launchable_event.GetWritableEvent().Signal(); |
| 381 | 384 | ||
| 382 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 385 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 383 | rb.Push(RESULT_SUCCESS); | 386 | rb.Push(RESULT_SUCCESS); |
| 384 | rb.PushCopyObjects(launchable_event->GetReadableEvent()); | 387 | rb.PushCopyObjects(launchable_event.GetReadableEvent()); |
| 385 | } | 388 | } |
| 386 | 389 | ||
| 387 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { | 390 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { |
| @@ -560,7 +563,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest | |||
| 560 | 563 | ||
| 561 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 564 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 562 | rb.Push(RESULT_SUCCESS); | 565 | rb.Push(RESULT_SUCCESS); |
| 563 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); | 566 | rb.PushCopyObjects(accumulated_suspended_tick_changed_event.GetReadableEvent()); |
| 564 | } | 567 | } |
| 565 | 568 | ||
| 566 | void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) { | 569 | void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) { |
| @@ -578,39 +581,40 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestCo | |||
| 578 | rb.Push(RESULT_SUCCESS); | 581 | rb.Push(RESULT_SUCCESS); |
| 579 | } | 582 | } |
| 580 | 583 | ||
| 581 | AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { | 584 | AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) |
| 582 | on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived"); | 585 | : on_new_message{kernel}, on_operation_mode_changed{kernel} { |
| 583 | on_new_message->Initialize(); | 586 | |
| 584 | on_operation_mode_changed = | 587 | Kernel::KAutoObject::Create(std::addressof(on_new_message)); |
| 585 | Kernel::KEvent::Create(kernel, "AMMessageQueue:OperationModeChanged"); | 588 | Kernel::KAutoObject::Create(std::addressof(on_operation_mode_changed)); |
| 586 | on_operation_mode_changed->Initialize(); | 589 | |
| 590 | on_new_message.Initialize("AMMessageQueue:OnMessageReceived"); | ||
| 591 | on_operation_mode_changed.Initialize("AMMessageQueue:OperationModeChanged"); | ||
| 587 | } | 592 | } |
| 588 | 593 | ||
| 589 | AppletMessageQueue::~AppletMessageQueue() = default; | 594 | AppletMessageQueue::~AppletMessageQueue() = default; |
| 590 | 595 | ||
| 591 | const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const { | 596 | Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() { |
| 592 | return on_new_message->GetReadableEvent(); | 597 | return on_new_message.GetReadableEvent(); |
| 593 | } | 598 | } |
| 594 | 599 | ||
| 595 | const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent() | 600 | Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { |
| 596 | const { | 601 | return on_operation_mode_changed.GetReadableEvent(); |
| 597 | return on_operation_mode_changed->GetReadableEvent(); | ||
| 598 | } | 602 | } |
| 599 | 603 | ||
| 600 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | 604 | void AppletMessageQueue::PushMessage(AppletMessage msg) { |
| 601 | messages.push(msg); | 605 | messages.push(msg); |
| 602 | on_new_message->GetWritableEvent()->Signal(); | 606 | on_new_message.GetWritableEvent().Signal(); |
| 603 | } | 607 | } |
| 604 | 608 | ||
| 605 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | 609 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { |
| 606 | if (messages.empty()) { | 610 | if (messages.empty()) { |
| 607 | on_new_message->GetWritableEvent()->Clear(); | 611 | on_new_message.GetWritableEvent().Clear(); |
| 608 | return AppletMessage::NoMessage; | 612 | return AppletMessage::NoMessage; |
| 609 | } | 613 | } |
| 610 | auto msg = messages.front(); | 614 | auto msg = messages.front(); |
| 611 | messages.pop(); | 615 | messages.pop(); |
| 612 | if (messages.empty()) { | 616 | if (messages.empty()) { |
| 613 | on_new_message->GetWritableEvent()->Clear(); | 617 | on_new_message.GetWritableEvent().Clear(); |
| 614 | } | 618 | } |
| 615 | return msg; | 619 | return msg; |
| 616 | } | 620 | } |
| @@ -630,7 +634,7 @@ void AppletMessageQueue::FocusStateChanged() { | |||
| 630 | void AppletMessageQueue::OperationModeChanged() { | 634 | void AppletMessageQueue::OperationModeChanged() { |
| 631 | PushMessage(AppletMessage::OperationModeChanged); | 635 | PushMessage(AppletMessage::OperationModeChanged); |
| 632 | PushMessage(AppletMessage::PerformanceModeChanged); | 636 | PushMessage(AppletMessage::PerformanceModeChanged); |
| 633 | on_operation_mode_changed->GetWritableEvent()->Signal(); | 637 | on_operation_mode_changed.GetWritableEvent().Signal(); |
| 634 | } | 638 | } |
| 635 | 639 | ||
| 636 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, | 640 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, |
| @@ -829,7 +833,7 @@ IStorageImpl::~IStorageImpl() = default; | |||
| 829 | 833 | ||
| 830 | class StorageDataImpl final : public IStorageImpl { | 834 | class StorageDataImpl final : public IStorageImpl { |
| 831 | public: | 835 | public: |
| 832 | explicit StorageDataImpl(std::vector<u8>&& buffer) : buffer{std::move(buffer)} {} | 836 | explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {} |
| 833 | 837 | ||
| 834 | std::vector<u8>& GetData() override { | 838 | std::vector<u8>& GetData() override { |
| 835 | return buffer; | 839 | return buffer; |
| @@ -927,11 +931,9 @@ private: | |||
| 927 | void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { | 931 | void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { |
| 928 | LOG_DEBUG(Service_AM, "called"); | 932 | LOG_DEBUG(Service_AM, "called"); |
| 929 | 933 | ||
| 930 | const auto event = applet->GetBroker().GetStateChangedEvent(); | ||
| 931 | |||
| 932 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 934 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 933 | rb.Push(RESULT_SUCCESS); | 935 | rb.Push(RESULT_SUCCESS); |
| 934 | rb.PushCopyObjects(event); | 936 | rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent()); |
| 935 | } | 937 | } |
| 936 | 938 | ||
| 937 | void IsCompleted(Kernel::HLERequestContext& ctx) { | 939 | void IsCompleted(Kernel::HLERequestContext& ctx) { |
| @@ -1213,16 +1215,16 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex | |||
| 1213 | } | 1215 | } |
| 1214 | 1216 | ||
| 1215 | auto transfer_mem = | 1217 | auto transfer_mem = |
| 1216 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); | 1218 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); |
| 1217 | 1219 | ||
| 1218 | if (transfer_mem == nullptr) { | 1220 | if (transfer_mem.IsNull()) { |
| 1219 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | 1221 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); |
| 1220 | IPC::ResponseBuilder rb{ctx, 2}; | 1222 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1221 | rb.Push(RESULT_UNKNOWN); | 1223 | rb.Push(RESULT_UNKNOWN); |
| 1222 | return; | 1224 | return; |
| 1223 | } | 1225 | } |
| 1224 | 1226 | ||
| 1225 | const u8* const mem_begin = transfer_mem->GetPointer(); | 1227 | const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress()); |
| 1226 | const u8* const mem_end = mem_begin + transfer_mem->GetSize(); | 1228 | const u8* const mem_end = mem_begin + transfer_mem->GetSize(); |
| 1227 | std::vector<u8> memory{mem_begin, mem_end}; | 1229 | std::vector<u8> memory{mem_begin, mem_end}; |
| 1228 | 1230 | ||
| @@ -1247,16 +1249,16 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) | |||
| 1247 | } | 1249 | } |
| 1248 | 1250 | ||
| 1249 | auto transfer_mem = | 1251 | auto transfer_mem = |
| 1250 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); | 1252 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); |
| 1251 | 1253 | ||
| 1252 | if (transfer_mem == nullptr) { | 1254 | if (transfer_mem.IsNull()) { |
| 1253 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | 1255 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); |
| 1254 | IPC::ResponseBuilder rb{ctx, 2}; | 1256 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1255 | rb.Push(RESULT_UNKNOWN); | 1257 | rb.Push(RESULT_UNKNOWN); |
| 1256 | return; | 1258 | return; |
| 1257 | } | 1259 | } |
| 1258 | 1260 | ||
| 1259 | const u8* const mem_begin = transfer_mem->GetPointer(); | 1261 | const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress()); |
| 1260 | const u8* const mem_end = mem_begin + transfer_mem->GetSize(); | 1262 | const u8* const mem_end = mem_begin + transfer_mem->GetSize(); |
| 1261 | std::vector<u8> memory{mem_begin, mem_end}; | 1263 | std::vector<u8> memory{mem_begin, mem_end}; |
| 1262 | 1264 | ||
| @@ -1266,7 +1268,9 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) | |||
| 1266 | } | 1268 | } |
| 1267 | 1269 | ||
| 1268 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | 1270 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) |
| 1269 | : ServiceFramework{system_, "IApplicationFunctions"} { | 1271 | : ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()}, |
| 1272 | friend_invitation_storage_channel_event{system.Kernel()}, | ||
| 1273 | health_warning_disappeared_system_event{system.Kernel()} { | ||
| 1270 | // clang-format off | 1274 | // clang-format off |
| 1271 | static const FunctionInfo functions[] = { | 1275 | static const FunctionInfo functions[] = { |
| 1272 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | 1276 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, |
| @@ -1334,16 +1338,15 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1334 | 1338 | ||
| 1335 | RegisterHandlers(functions); | 1339 | RegisterHandlers(functions); |
| 1336 | 1340 | ||
| 1337 | auto& kernel = system.Kernel(); | 1341 | Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event)); |
| 1338 | gpu_error_detected_event = | 1342 | Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event)); |
| 1339 | Kernel::KEvent::Create(kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); | 1343 | Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event)); |
| 1340 | gpu_error_detected_event->Initialize(); | 1344 | |
| 1341 | friend_invitation_storage_channel_event = | 1345 | gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent"); |
| 1342 | Kernel::KEvent::Create(kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent"); | 1346 | friend_invitation_storage_channel_event.Initialize( |
| 1343 | friend_invitation_storage_channel_event->Initialize(); | 1347 | "IApplicationFunctions:FriendInvitationStorageChannelEvent"); |
| 1344 | health_warning_disappeared_system_event = | 1348 | health_warning_disappeared_system_event.Initialize( |
| 1345 | Kernel::KEvent::Create(kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent"); | 1349 | "IApplicationFunctions:HealthWarningDisappearedSystemEvent"); |
| 1346 | health_warning_disappeared_system_event->Initialize(); | ||
| 1347 | } | 1350 | } |
| 1348 | 1351 | ||
| 1349 | IApplicationFunctions::~IApplicationFunctions() = default; | 1352 | IApplicationFunctions::~IApplicationFunctions() = default; |
| @@ -1510,9 +1513,9 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { | |||
| 1510 | 1513 | ||
| 1511 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | 1514 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1512 | system.GetContentProvider()}; | 1515 | system.GetContentProvider()}; |
| 1513 | auto res = pm.GetControlMetadata(); | 1516 | auto metadata = pm.GetControlMetadata(); |
| 1514 | if (res.first != nullptr) { | 1517 | if (metadata.first != nullptr) { |
| 1515 | return res; | 1518 | return metadata; |
| 1516 | } | 1519 | } |
| 1517 | 1520 | ||
| 1518 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | 1521 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
| @@ -1547,9 +1550,9 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { | |||
| 1547 | 1550 | ||
| 1548 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | 1551 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1549 | system.GetContentProvider()}; | 1552 | system.GetContentProvider()}; |
| 1550 | auto res = pm.GetControlMetadata(); | 1553 | auto metadata = pm.GetControlMetadata(); |
| 1551 | if (res.first != nullptr) { | 1554 | if (metadata.first != nullptr) { |
| 1552 | return res; | 1555 | return metadata; |
| 1553 | } | 1556 | } |
| 1554 | 1557 | ||
| 1555 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | 1558 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
| @@ -1740,7 +1743,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon | |||
| 1740 | 1743 | ||
| 1741 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 1744 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 1742 | rb.Push(RESULT_SUCCESS); | 1745 | rb.Push(RESULT_SUCCESS); |
| 1743 | rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent()); | 1746 | rb.PushCopyObjects(gpu_error_detected_event.GetReadableEvent()); |
| 1744 | } | 1747 | } |
| 1745 | 1748 | ||
| 1746 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { | 1749 | void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { |
| @@ -1748,7 +1751,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe | |||
| 1748 | 1751 | ||
| 1749 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 1752 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 1750 | rb.Push(RESULT_SUCCESS); | 1753 | rb.Push(RESULT_SUCCESS); |
| 1751 | rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent()); | 1754 | rb.PushCopyObjects(friend_invitation_storage_channel_event.GetReadableEvent()); |
| 1752 | } | 1755 | } |
| 1753 | 1756 | ||
| 1754 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( | 1757 | void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( |
| @@ -1764,7 +1767,7 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERe | |||
| 1764 | 1767 | ||
| 1765 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 1768 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 1766 | rb.Push(RESULT_SUCCESS); | 1769 | rb.Push(RESULT_SUCCESS); |
| 1767 | rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent()); | 1770 | rb.PushCopyObjects(health_warning_disappeared_system_event.GetReadableEvent()); |
| 1768 | } | 1771 | } |
| 1769 | 1772 | ||
| 1770 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, | 1773 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, |
| @@ -1782,7 +1785,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger | |||
| 1782 | } | 1785 | } |
| 1783 | 1786 | ||
| 1784 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | 1787 | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) |
| 1785 | : ServiceFramework{system_, "IHomeMenuFunctions"} { | 1788 | : ServiceFramework{system_, "IHomeMenuFunctions"}, pop_from_general_channel_event{ |
| 1789 | system.Kernel()} { | ||
| 1786 | // clang-format off | 1790 | // clang-format off |
| 1787 | static const FunctionInfo functions[] = { | 1791 | static const FunctionInfo functions[] = { |
| 1788 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, | 1792 | {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, |
| @@ -1803,9 +1807,8 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) | |||
| 1803 | 1807 | ||
| 1804 | RegisterHandlers(functions); | 1808 | RegisterHandlers(functions); |
| 1805 | 1809 | ||
| 1806 | pop_from_general_channel_event = | 1810 | Kernel::KAutoObject::Create(std::addressof(pop_from_general_channel_event)); |
| 1807 | Kernel::KEvent::Create(system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent"); | 1811 | pop_from_general_channel_event.Initialize("IHomeMenuFunctions:PopFromGeneralChannelEvent"); |
| 1808 | pop_from_general_channel_event->Initialize(); | ||
| 1809 | } | 1812 | } |
| 1810 | 1813 | ||
| 1811 | IHomeMenuFunctions::~IHomeMenuFunctions() = default; | 1814 | IHomeMenuFunctions::~IHomeMenuFunctions() = default; |
| @@ -1822,7 +1825,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext | |||
| 1822 | 1825 | ||
| 1823 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 1826 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 1824 | rb.Push(RESULT_SUCCESS); | 1827 | rb.Push(RESULT_SUCCESS); |
| 1825 | rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); | 1828 | rb.PushCopyObjects(pop_from_general_channel_event.GetReadableEvent()); |
| 1826 | } | 1829 | } |
| 1827 | 1830 | ||
| 1828 | IGlobalStateController::IGlobalStateController(Core::System& system_) | 1831 | IGlobalStateController::IGlobalStateController(Core::System& system_) |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 5d302e155..184030a8e 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -8,12 +8,12 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <queue> | 9 | #include <queue> |
| 10 | 10 | ||
| 11 | #include "core/hle/kernel/k_event.h" | ||
| 11 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 12 | 13 | ||
| 13 | namespace Kernel { | 14 | namespace Kernel { |
| 14 | class KernelCore; | 15 | class KernelCore; |
| 15 | class KEvent; | 16 | class KTransferMemory; |
| 16 | class TransferMemory; | ||
| 17 | } // namespace Kernel | 17 | } // namespace Kernel |
| 18 | 18 | ||
| 19 | namespace Service::NVFlinger { | 19 | namespace Service::NVFlinger { |
| @@ -56,8 +56,8 @@ public: | |||
| 56 | explicit AppletMessageQueue(Kernel::KernelCore& kernel); | 56 | explicit AppletMessageQueue(Kernel::KernelCore& kernel); |
| 57 | ~AppletMessageQueue(); | 57 | ~AppletMessageQueue(); |
| 58 | 58 | ||
| 59 | const std::shared_ptr<Kernel::KReadableEvent>& GetMessageReceiveEvent() const; | 59 | Kernel::KReadableEvent& GetMessageReceiveEvent(); |
| 60 | const std::shared_ptr<Kernel::KReadableEvent>& GetOperationModeChangedEvent() const; | 60 | Kernel::KReadableEvent& GetOperationModeChangedEvent(); |
| 61 | void PushMessage(AppletMessage msg); | 61 | void PushMessage(AppletMessage msg); |
| 62 | AppletMessage PopMessage(); | 62 | AppletMessage PopMessage(); |
| 63 | std::size_t GetMessageCount() const; | 63 | std::size_t GetMessageCount() const; |
| @@ -67,8 +67,8 @@ public: | |||
| 67 | 67 | ||
| 68 | private: | 68 | private: |
| 69 | std::queue<AppletMessage> messages; | 69 | std::queue<AppletMessage> messages; |
| 70 | std::shared_ptr<Kernel::KEvent> on_new_message; | 70 | Kernel::KEvent on_new_message; |
| 71 | std::shared_ptr<Kernel::KEvent> on_operation_mode_changed; | 71 | Kernel::KEvent on_operation_mode_changed; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | class IWindowController final : public ServiceFramework<IWindowController> { | 74 | class IWindowController final : public ServiceFramework<IWindowController> { |
| @@ -156,8 +156,8 @@ private: | |||
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | NVFlinger::NVFlinger& nvflinger; | 158 | NVFlinger::NVFlinger& nvflinger; |
| 159 | std::shared_ptr<Kernel::KEvent> launchable_event; | 159 | Kernel::KEvent launchable_event; |
| 160 | std::shared_ptr<Kernel::KEvent> accumulated_suspended_tick_changed_event; | 160 | Kernel::KEvent accumulated_suspended_tick_changed_event; |
| 161 | 161 | ||
| 162 | u32 idle_time_detection_extension = 0; | 162 | u32 idle_time_detection_extension = 0; |
| 163 | u64 num_fatal_sections_entered = 0; | 163 | u64 num_fatal_sections_entered = 0; |
| @@ -300,9 +300,9 @@ private: | |||
| 300 | bool launch_popped_application_specific = false; | 300 | bool launch_popped_application_specific = false; |
| 301 | bool launch_popped_account_preselect = false; | 301 | bool launch_popped_account_preselect = false; |
| 302 | s32 previous_program_index{-1}; | 302 | s32 previous_program_index{-1}; |
| 303 | std::shared_ptr<Kernel::KEvent> gpu_error_detected_event; | 303 | Kernel::KEvent gpu_error_detected_event; |
| 304 | std::shared_ptr<Kernel::KEvent> friend_invitation_storage_channel_event; | 304 | Kernel::KEvent friend_invitation_storage_channel_event; |
| 305 | std::shared_ptr<Kernel::KEvent> health_warning_disappeared_system_event; | 305 | Kernel::KEvent health_warning_disappeared_system_event; |
| 306 | }; | 306 | }; |
| 307 | 307 | ||
| 308 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | 308 | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { |
| @@ -314,7 +314,7 @@ private: | |||
| 314 | void RequestToGetForeground(Kernel::HLERequestContext& ctx); | 314 | void RequestToGetForeground(Kernel::HLERequestContext& ctx); |
| 315 | void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); | 315 | void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); |
| 316 | 316 | ||
| 317 | std::shared_ptr<Kernel::KEvent> pop_from_general_channel_event; | 317 | Kernel::KEvent pop_from_general_channel_event; |
| 318 | }; | 318 | }; |
| 319 | 319 | ||
| 320 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { | 320 | class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index a56df6a7e..ae995df6b 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -12,10 +12,8 @@ | |||
| 12 | #include "core/frontend/applets/profile_select.h" | 12 | #include "core/frontend/applets/profile_select.h" |
| 13 | #include "core/frontend/applets/software_keyboard.h" | 13 | #include "core/frontend/applets/software_keyboard.h" |
| 14 | #include "core/frontend/applets/web_browser.h" | 14 | #include "core/frontend/applets/web_browser.h" |
| 15 | #include "core/hle/kernel/k_event.h" | ||
| 16 | #include "core/hle/kernel/k_readable_event.h" | 15 | #include "core/hle/kernel/k_readable_event.h" |
| 17 | #include "core/hle/kernel/k_writable_event.h" | 16 | #include "core/hle/kernel/k_writable_event.h" |
| 18 | #include "core/hle/kernel/server_session.h" | ||
| 19 | #include "core/hle/service/am/am.h" | 17 | #include "core/hle/service/am/am.h" |
| 20 | #include "core/hle/service/am/applet_ae.h" | 18 | #include "core/hle/service/am/applet_ae.h" |
| 21 | #include "core/hle/service/am/applet_oe.h" | 19 | #include "core/hle/service/am/applet_oe.h" |
| @@ -31,16 +29,16 @@ | |||
| 31 | namespace Service::AM::Applets { | 29 | namespace Service::AM::Applets { |
| 32 | 30 | ||
| 33 | AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) | 31 | AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_) |
| 34 | : system{system_}, applet_mode{applet_mode_} { | 32 | : system{system_}, applet_mode{applet_mode_}, state_changed_event{system.Kernel()}, |
| 35 | state_changed_event = | 33 | pop_out_data_event{system.Kernel()}, pop_interactive_out_data_event{system.Kernel()} { |
| 36 | Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:StateChangedEvent"); | 34 | |
| 37 | state_changed_event->Initialize(); | 35 | Kernel::KAutoObject::Create(std::addressof(state_changed_event)); |
| 38 | pop_out_data_event = | 36 | Kernel::KAutoObject::Create(std::addressof(pop_out_data_event)); |
| 39 | Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:PopDataOutEvent"); | 37 | Kernel::KAutoObject::Create(std::addressof(pop_interactive_out_data_event)); |
| 40 | pop_out_data_event->Initialize(); | 38 | |
| 41 | pop_interactive_out_data_event = Kernel::KEvent::Create( | 39 | state_changed_event.Initialize("ILibraryAppletAccessor:StateChangedEvent"); |
| 42 | system.Kernel(), "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); | 40 | pop_out_data_event.Initialize("ILibraryAppletAccessor:PopDataOutEvent"); |
| 43 | pop_interactive_out_data_event->Initialize(); | 41 | pop_interactive_out_data_event.Initialize("ILibraryAppletAccessor:PopInteractiveDataOutEvent"); |
| 44 | } | 42 | } |
| 45 | 43 | ||
| 46 | AppletDataBroker::~AppletDataBroker() = default; | 44 | AppletDataBroker::~AppletDataBroker() = default; |
| @@ -67,7 +65,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { | |||
| 67 | 65 | ||
| 68 | auto out = std::move(out_channel.front()); | 66 | auto out = std::move(out_channel.front()); |
| 69 | out_channel.pop_front(); | 67 | out_channel.pop_front(); |
| 70 | pop_out_data_event->GetWritableEvent()->Clear(); | 68 | pop_out_data_event.GetWritableEvent().Clear(); |
| 71 | return out; | 69 | return out; |
| 72 | } | 70 | } |
| 73 | 71 | ||
| @@ -86,7 +84,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { | |||
| 86 | 84 | ||
| 87 | auto out = std::move(out_interactive_channel.front()); | 85 | auto out = std::move(out_interactive_channel.front()); |
| 88 | out_interactive_channel.pop_front(); | 86 | out_interactive_channel.pop_front(); |
| 89 | pop_interactive_out_data_event->GetWritableEvent()->Clear(); | 87 | pop_interactive_out_data_event.GetWritableEvent().Clear(); |
| 90 | return out; | 88 | return out; |
| 91 | } | 89 | } |
| 92 | 90 | ||
| @@ -105,7 +103,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag | |||
| 105 | 103 | ||
| 106 | void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { | 104 | void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { |
| 107 | out_channel.emplace_back(std::move(storage)); | 105 | out_channel.emplace_back(std::move(storage)); |
| 108 | pop_out_data_event->GetWritableEvent()->Signal(); | 106 | pop_out_data_event.GetWritableEvent().Signal(); |
| 109 | } | 107 | } |
| 110 | 108 | ||
| 111 | void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { | 109 | void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { |
| @@ -114,11 +112,11 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s | |||
| 114 | 112 | ||
| 115 | void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { | 113 | void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { |
| 116 | out_interactive_channel.emplace_back(std::move(storage)); | 114 | out_interactive_channel.emplace_back(std::move(storage)); |
| 117 | pop_interactive_out_data_event->GetWritableEvent()->Signal(); | 115 | pop_interactive_out_data_event.GetWritableEvent().Signal(); |
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | void AppletDataBroker::SignalStateChanged() const { | 118 | void AppletDataBroker::SignalStateChanged() { |
| 121 | state_changed_event->GetWritableEvent()->Signal(); | 119 | state_changed_event.GetWritableEvent().Signal(); |
| 122 | 120 | ||
| 123 | switch (applet_mode) { | 121 | switch (applet_mode) { |
| 124 | case LibraryAppletMode::AllForeground: | 122 | case LibraryAppletMode::AllForeground: |
| @@ -142,16 +140,16 @@ void AppletDataBroker::SignalStateChanged() const { | |||
| 142 | } | 140 | } |
| 143 | } | 141 | } |
| 144 | 142 | ||
| 145 | std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const { | 143 | Kernel::KReadableEvent& AppletDataBroker::GetNormalDataEvent() { |
| 146 | return pop_out_data_event->GetReadableEvent(); | 144 | return pop_out_data_event.GetReadableEvent(); |
| 147 | } | 145 | } |
| 148 | 146 | ||
| 149 | std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const { | 147 | Kernel::KReadableEvent& AppletDataBroker::GetInteractiveDataEvent() { |
| 150 | return pop_interactive_out_data_event->GetReadableEvent(); | 148 | return pop_interactive_out_data_event.GetReadableEvent(); |
| 151 | } | 149 | } |
| 152 | 150 | ||
| 153 | std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent() const { | 151 | Kernel::KReadableEvent& AppletDataBroker::GetStateChangedEvent() { |
| 154 | return state_changed_event->GetReadableEvent(); | 152 | return state_changed_event.GetReadableEvent(); |
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_) | 155 | Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_) |
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 4215d2232..5c0b4b459 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <queue> | 8 | #include <queue> |
| 9 | 9 | ||
| 10 | #include "common/swap.h" | 10 | #include "common/swap.h" |
| 11 | #include "core/hle/kernel/object.h" | 11 | #include "core/hle/kernel/k_event.h" |
| 12 | 12 | ||
| 13 | union ResultCode; | 13 | union ResultCode; |
| 14 | 14 | ||
| @@ -95,11 +95,11 @@ public: | |||
| 95 | void PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage); | 95 | void PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage); |
| 96 | void PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage); | 96 | void PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage); |
| 97 | 97 | ||
| 98 | void SignalStateChanged() const; | 98 | void SignalStateChanged(); |
| 99 | 99 | ||
| 100 | std::shared_ptr<Kernel::KReadableEvent> GetNormalDataEvent() const; | 100 | Kernel::KReadableEvent& GetNormalDataEvent(); |
| 101 | std::shared_ptr<Kernel::KReadableEvent> GetInteractiveDataEvent() const; | 101 | Kernel::KReadableEvent& GetInteractiveDataEvent(); |
| 102 | std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const; | 102 | Kernel::KReadableEvent& GetStateChangedEvent(); |
| 103 | 103 | ||
| 104 | private: | 104 | private: |
| 105 | Core::System& system; | 105 | Core::System& system; |
| @@ -119,13 +119,13 @@ private: | |||
| 119 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet | 119 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet |
| 120 | std::deque<std::shared_ptr<IStorage>> out_interactive_channel; | 120 | std::deque<std::shared_ptr<IStorage>> out_interactive_channel; |
| 121 | 121 | ||
| 122 | std::shared_ptr<Kernel::KEvent> state_changed_event; | 122 | Kernel::KEvent state_changed_event; |
| 123 | 123 | ||
| 124 | // Signaled on PushNormalDataFromApplet | 124 | // Signaled on PushNormalDataFromApplet |
| 125 | std::shared_ptr<Kernel::KEvent> pop_out_data_event; | 125 | Kernel::KEvent pop_out_data_event; |
| 126 | 126 | ||
| 127 | // Signaled on PushInteractiveDataFromApplet | 127 | // Signaled on PushInteractiveDataFromApplet |
| 128 | std::shared_ptr<Kernel::KEvent> pop_interactive_out_data_event; | 128 | Kernel::KEvent pop_interactive_out_data_event; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | class Applet { | 131 | class Applet { |
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index 23e30aa45..08348b180 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/frontend/applets/error.h" | 11 | #include "core/frontend/applets/error.h" |
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/k_process.h" |
| 13 | #include "core/hle/service/am/am.h" | 13 | #include "core/hle/service/am/am.h" |
| 14 | #include "core/hle/service/am/applets/error.h" | 14 | #include "core/hle/service/am/applets/error.h" |
| 15 | #include "core/reporter.h" | 15 | #include "core/reporter.h" |
| @@ -158,11 +158,11 @@ void Error::Execute() { | |||
| 158 | break; | 158 | break; |
| 159 | case ErrorAppletMode::ShowSystemError: | 159 | case ErrorAppletMode::ShowSystemError: |
| 160 | case ErrorAppletMode::ShowApplicationError: { | 160 | case ErrorAppletMode::ShowApplicationError: { |
| 161 | const auto system = mode == ErrorAppletMode::ShowSystemError; | 161 | const auto is_system = mode == ErrorAppletMode::ShowSystemError; |
| 162 | const auto& main_text = | 162 | const auto& main_text = |
| 163 | system ? args->system_error.main_text : args->application_error.main_text; | 163 | is_system ? args->system_error.main_text : args->application_error.main_text; |
| 164 | const auto& detail_text = | 164 | const auto& detail_text = |
| 165 | system ? args->system_error.detail_text : args->application_error.detail_text; | 165 | is_system ? args->system_error.detail_text : args->application_error.detail_text; |
| 166 | 166 | ||
| 167 | const auto main_text_string = | 167 | const auto main_text_string = |
| 168 | Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()); | 168 | Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()); |
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index b26abad36..e95499edd 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/frontend/applets/general_frontend.h" | 11 | #include "core/frontend/applets/general_frontend.h" |
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/k_process.h" |
| 13 | #include "core/hle/result.h" | 13 | #include "core/hle/result.h" |
| 14 | #include "core/hle/service/am/am.h" | 14 | #include "core/hle/service/am/am.h" |
| 15 | #include "core/hle/service/am/applets/general_backend.h" | 15 | #include "core/hle/service/am/applets/general_backend.h" |
| @@ -96,7 +96,7 @@ void Auth::Execute() { | |||
| 96 | 96 | ||
| 97 | switch (type) { | 97 | switch (type) { |
| 98 | case AuthAppletType::ShowParentalAuthentication: { | 98 | case AuthAppletType::ShowParentalAuthentication: { |
| 99 | const auto callback = [this](bool successful) { AuthFinished(successful); }; | 99 | const auto callback = [this](bool is_successful) { AuthFinished(is_successful); }; |
| 100 | 100 | ||
| 101 | if (arg0 == 1 && arg1 == 0 && arg2 == 1) { | 101 | if (arg0 == 1 && arg1 == 0 && arg2 == 1) { |
| 102 | // ShowAuthenticatorForConfiguration | 102 | // ShowAuthenticatorForConfiguration |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 73a06def1..b05a5da04 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -241,7 +241,7 @@ void SoftwareKeyboard::InitializeForeground() { | |||
| 241 | InitializeFrontendKeyboard(); | 241 | InitializeFrontendKeyboard(); |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) { | 244 | void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) { |
| 245 | LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet."); | 245 | LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet."); |
| 246 | 246 | ||
| 247 | is_background = true; | 247 | is_background = true; |
| @@ -256,9 +256,9 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) { | |||
| 256 | swkbd_inline_initialize_arg.size()); | 256 | swkbd_inline_initialize_arg.size()); |
| 257 | 257 | ||
| 258 | if (swkbd_initialize_arg.library_applet_mode_flag) { | 258 | if (swkbd_initialize_arg.library_applet_mode_flag) { |
| 259 | ASSERT(applet_mode == LibraryAppletMode::Background); | 259 | ASSERT(library_applet_mode == LibraryAppletMode::Background); |
| 260 | } else { | 260 | } else { |
| 261 | ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); | 261 | ASSERT(library_applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); |
| 262 | } | 262 | } |
| 263 | } | 263 | } |
| 264 | 264 | ||
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 7c67b7574..7bdef78a7 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h | |||
| @@ -57,7 +57,7 @@ private: | |||
| 57 | void InitializeForeground(); | 57 | void InitializeForeground(); |
| 58 | 58 | ||
| 59 | /// Initializes the inline software keyboard. | 59 | /// Initializes the inline software keyboard. |
| 60 | void InitializeBackground(LibraryAppletMode applet_mode); | 60 | void InitializeBackground(LibraryAppletMode library_applet_mode); |
| 61 | 61 | ||
| 62 | /// Processes the text check sent by the application. | 62 | /// Processes the text check sent by the application. |
| 63 | void ProcessTextCheck(); | 63 | void ProcessTextCheck(); |
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 2404921fd..e5f4a4485 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include "core/file_sys/system_archive/system_archive.h" | 17 | #include "core/file_sys/system_archive/system_archive.h" |
| 18 | #include "core/file_sys/vfs_vector.h" | 18 | #include "core/file_sys/vfs_vector.h" |
| 19 | #include "core/frontend/applets/web_browser.h" | 19 | #include "core/frontend/applets/web_browser.h" |
| 20 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/k_process.h" |
| 21 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| 22 | #include "core/hle/service/am/am.h" | 22 | #include "core/hle/service/am/am.h" |
| 23 | #include "core/hle/service/am/applets/web_browser.h" | 23 | #include "core/hle/service/am/applets/web_browser.h" |
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index 21fd910c2..1e1812f36 100644 --- a/src/core/hle/service/am/applets/web_browser.h +++ b/src/core/hle/service/am/applets/web_browser.h | |||
| @@ -69,13 +69,12 @@ private: | |||
| 69 | bool complete{false}; | 69 | bool complete{false}; |
| 70 | ResultCode status{RESULT_SUCCESS}; | 70 | ResultCode status{RESULT_SUCCESS}; |
| 71 | 71 | ||
| 72 | WebAppletVersion web_applet_version; | 72 | WebAppletVersion web_applet_version{}; |
| 73 | WebExitReason web_exit_reason; | 73 | WebArgHeader web_arg_header{}; |
| 74 | WebArgHeader web_arg_header; | ||
| 75 | WebArgInputTLVMap web_arg_input_tlv_map; | 74 | WebArgInputTLVMap web_arg_input_tlv_map; |
| 76 | 75 | ||
| 77 | u64 title_id; | 76 | u64 title_id{}; |
| 78 | FileSys::ContentRecordType nca_type; | 77 | FileSys::ContentRecordType nca_type{}; |
| 79 | std::string offline_cache_dir; | 78 | std::string offline_cache_dir; |
| 80 | std::string offline_document; | 79 | std::string offline_document; |
| 81 | FileSys::VirtualFile offline_romfs; | 80 | FileSys::VirtualFile offline_romfs; |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 75867e349..1863260f1 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -16,10 +16,9 @@ | |||
| 16 | #include "core/file_sys/patch_manager.h" | 16 | #include "core/file_sys/patch_manager.h" |
| 17 | #include "core/file_sys/registered_cache.h" | 17 | #include "core/file_sys/registered_cache.h" |
| 18 | #include "core/hle/ipc_helpers.h" | 18 | #include "core/hle/ipc_helpers.h" |
| 19 | #include "core/hle/kernel/k_event.h" | 19 | #include "core/hle/kernel/k_process.h" |
| 20 | #include "core/hle/kernel/k_readable_event.h" | 20 | #include "core/hle/kernel/k_readable_event.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 21 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/process.h" | ||
| 23 | #include "core/hle/service/aoc/aoc_u.h" | 22 | #include "core/hle/service/aoc/aoc_u.h" |
| 24 | #include "core/loader/loader.h" | 23 | #include "core/loader/loader.h" |
| 25 | 24 | ||
| @@ -50,7 +49,7 @@ static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { | |||
| 50 | class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> { | 49 | class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> { |
| 51 | public: | 50 | public: |
| 52 | explicit IPurchaseEventManager(Core::System& system_) | 51 | explicit IPurchaseEventManager(Core::System& system_) |
| 53 | : ServiceFramework{system_, "IPurchaseEventManager"} { | 52 | : ServiceFramework{system_, "IPurchaseEventManager"}, purchased_event{system.Kernel()} { |
| 54 | // clang-format off | 53 | // clang-format off |
| 55 | static const FunctionInfo functions[] = { | 54 | static const FunctionInfo functions[] = { |
| 56 | {0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"}, | 55 | {0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"}, |
| @@ -63,9 +62,8 @@ public: | |||
| 63 | 62 | ||
| 64 | RegisterHandlers(functions); | 63 | RegisterHandlers(functions); |
| 65 | 64 | ||
| 66 | purchased_event = | 65 | Kernel::KAutoObject::Create(std::addressof(purchased_event)); |
| 67 | Kernel::KEvent::Create(system.Kernel(), "IPurchaseEventManager:PurchasedEvent"); | 66 | purchased_event.Initialize("IPurchaseEventManager:PurchasedEvent"); |
| 68 | purchased_event->Initialize(); | ||
| 69 | } | 67 | } |
| 70 | 68 | ||
| 71 | private: | 69 | private: |
| @@ -98,14 +96,15 @@ private: | |||
| 98 | 96 | ||
| 99 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 97 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 100 | rb.Push(RESULT_SUCCESS); | 98 | rb.Push(RESULT_SUCCESS); |
| 101 | rb.PushCopyObjects(purchased_event->GetReadableEvent()); | 99 | rb.PushCopyObjects(purchased_event.GetReadableEvent()); |
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | std::shared_ptr<Kernel::KEvent> purchased_event; | 102 | Kernel::KEvent purchased_event; |
| 105 | }; | 103 | }; |
| 106 | 104 | ||
| 107 | AOC_U::AOC_U(Core::System& system_) | 105 | AOC_U::AOC_U(Core::System& system_) |
| 108 | : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)} { | 106 | : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)}, |
| 107 | aoc_change_event{system.Kernel()} { | ||
| 109 | // clang-format off | 108 | // clang-format off |
| 110 | static const FunctionInfo functions[] = { | 109 | static const FunctionInfo functions[] = { |
| 111 | {0, nullptr, "CountAddOnContentByApplicationId"}, | 110 | {0, nullptr, "CountAddOnContentByApplicationId"}, |
| @@ -127,9 +126,8 @@ AOC_U::AOC_U(Core::System& system_) | |||
| 127 | 126 | ||
| 128 | RegisterHandlers(functions); | 127 | RegisterHandlers(functions); |
| 129 | 128 | ||
| 130 | auto& kernel = system.Kernel(); | 129 | Kernel::KAutoObject::Create(std::addressof(aoc_change_event)); |
| 131 | aoc_change_event = Kernel::KEvent::Create(kernel, "GetAddOnContentListChanged:Event"); | 130 | aoc_change_event.Initialize("GetAddOnContentListChanged:Event"); |
| 132 | aoc_change_event->Initialize(); | ||
| 133 | } | 131 | } |
| 134 | 132 | ||
| 135 | AOC_U::~AOC_U() = default; | 133 | AOC_U::~AOC_U() = default; |
| @@ -256,7 +254,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) { | |||
| 256 | 254 | ||
| 257 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 255 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 258 | rb.Push(RESULT_SUCCESS); | 256 | rb.Push(RESULT_SUCCESS); |
| 259 | rb.PushCopyObjects(aoc_change_event->GetReadableEvent()); | 257 | rb.PushCopyObjects(aoc_change_event.GetReadableEvent()); |
| 260 | } | 258 | } |
| 261 | 259 | ||
| 262 | void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { | 260 | void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h index 1aa23529e..65095baa2 100644 --- a/src/core/hle/service/aoc/aoc_u.h +++ b/src/core/hle/service/aoc/aoc_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -31,7 +32,7 @@ private: | |||
| 31 | void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx); | 32 | void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx); |
| 32 | 33 | ||
| 33 | std::vector<u64> add_on_content; | 34 | std::vector<u64> add_on_content; |
| 34 | std::shared_ptr<Kernel::KEvent> aoc_change_event; | 35 | Kernel::KEvent aoc_change_event; |
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 37 | /// Registers all AOC services with the specified service manager. | 38 | /// Registers all AOC services with the specified service manager. |
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp index 00c174bb0..8bfa7c0e4 100644 --- a/src/core/hle/service/apm/controller.cpp +++ b/src/core/hle/service/apm/controller.cpp | |||
| @@ -15,11 +15,11 @@ namespace Service::APM { | |||
| 15 | 15 | ||
| 16 | constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7; | 16 | constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7; |
| 17 | 17 | ||
| 18 | Controller::Controller(Core::Timing::CoreTiming& core_timing) | 18 | Controller::Controller(Core::Timing::CoreTiming& core_timing_) |
| 19 | : core_timing{core_timing}, configs{ | 19 | : core_timing{core_timing_}, configs{ |
| 20 | {PerformanceMode::Handheld, DEFAULT_PERFORMANCE_CONFIGURATION}, | 20 | {PerformanceMode::Handheld, DEFAULT_PERFORMANCE_CONFIGURATION}, |
| 21 | {PerformanceMode::Docked, DEFAULT_PERFORMANCE_CONFIGURATION}, | 21 | {PerformanceMode::Docked, DEFAULT_PERFORMANCE_CONFIGURATION}, |
| 22 | } {} | 22 | } {} |
| 23 | 23 | ||
| 24 | Controller::~Controller() = default; | 24 | Controller::~Controller() = default; |
| 25 | 25 | ||
diff --git a/src/core/hle/service/apm/controller.h b/src/core/hle/service/apm/controller.h index af0c4cd34..8d48e0104 100644 --- a/src/core/hle/service/apm/controller.h +++ b/src/core/hle/service/apm/controller.h | |||
| @@ -50,7 +50,7 @@ enum class PerformanceMode : u8 { | |||
| 50 | // system during times of high load -- this simply maps to different PerformanceConfigs to use. | 50 | // system during times of high load -- this simply maps to different PerformanceConfigs to use. |
| 51 | class Controller { | 51 | class Controller { |
| 52 | public: | 52 | public: |
| 53 | explicit Controller(Core::Timing::CoreTiming& core_timing); | 53 | explicit Controller(Core::Timing::CoreTiming& core_timing_); |
| 54 | ~Controller(); | 54 | ~Controller(); |
| 55 | 55 | ||
| 56 | void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config); | 56 | void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config); |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 5f51fca9a..e1ae726f5 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -43,9 +43,9 @@ class IAudioOut final : public ServiceFramework<IAudioOut> { | |||
| 43 | public: | 43 | public: |
| 44 | IAudioOut(Core::System& system_, AudoutParams audio_params_, AudioCore::AudioOut& audio_core_, | 44 | IAudioOut(Core::System& system_, AudoutParams audio_params_, AudioCore::AudioOut& audio_core_, |
| 45 | std::string&& device_name_, std::string&& unique_name) | 45 | std::string&& device_name_, std::string&& unique_name) |
| 46 | : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, | 46 | : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, device_name{std::move( |
| 47 | device_name{std::move(device_name_)}, audio_params{audio_params_}, main_memory{ | 47 | device_name_)}, |
| 48 | system.Memory()} { | 48 | audio_params{audio_params_}, buffer_event{system.Kernel()}, main_memory{system.Memory()} { |
| 49 | // clang-format off | 49 | // clang-format off |
| 50 | static const FunctionInfo functions[] = { | 50 | static const FunctionInfo functions[] = { |
| 51 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 51 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
| @@ -67,13 +67,13 @@ public: | |||
| 67 | RegisterHandlers(functions); | 67 | RegisterHandlers(functions); |
| 68 | 68 | ||
| 69 | // This is the event handle used to check if the audio buffer was released | 69 | // This is the event handle used to check if the audio buffer was released |
| 70 | buffer_event = Kernel::KEvent::Create(system.Kernel(), "IAudioOutBufferReleased"); | 70 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); |
| 71 | buffer_event->Initialize(); | 71 | buffer_event.Initialize("IAudioOutBufferReleased"); |
| 72 | 72 | ||
| 73 | stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, | 73 | stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, |
| 74 | audio_params.channel_count, std::move(unique_name), [this] { | 74 | audio_params.channel_count, std::move(unique_name), [this] { |
| 75 | const auto guard = LockService(); | 75 | const auto guard = LockService(); |
| 76 | buffer_event->GetWritableEvent()->Signal(); | 76 | buffer_event.GetWritableEvent().Signal(); |
| 77 | }); | 77 | }); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| @@ -126,7 +126,7 @@ private: | |||
| 126 | 126 | ||
| 127 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 127 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 128 | rb.Push(RESULT_SUCCESS); | 128 | rb.Push(RESULT_SUCCESS); |
| 129 | rb.PushCopyObjects(buffer_event->GetReadableEvent()); | 129 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { | 132 | void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { |
| @@ -220,7 +220,7 @@ private: | |||
| 220 | [[maybe_unused]] AudoutParams audio_params{}; | 220 | [[maybe_unused]] AudoutParams audio_params{}; |
| 221 | 221 | ||
| 222 | /// This is the event handle used to check if the audio buffer was released | 222 | /// This is the event handle used to check if the audio buffer was released |
| 223 | std::shared_ptr<Kernel::KEvent> buffer_event; | 223 | Kernel::KEvent buffer_event; |
| 224 | Core::Memory::Memory& main_memory; | 224 | Core::Memory::Memory& main_memory; |
| 225 | }; | 225 | }; |
| 226 | 226 | ||
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 572be8e00..ae4284adf 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -27,9 +27,10 @@ namespace Service::Audio { | |||
| 27 | 27 | ||
| 28 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { | 28 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { |
| 29 | public: | 29 | public: |
| 30 | explicit IAudioRenderer(Core::System& system, AudioCommon::AudioRendererParameter audren_params, | 30 | explicit IAudioRenderer(Core::System& system_, |
| 31 | const AudioCommon::AudioRendererParameter& audren_params, | ||
| 31 | const std::size_t instance_number) | 32 | const std::size_t instance_number) |
| 32 | : ServiceFramework{system, "IAudioRenderer"} { | 33 | : ServiceFramework{system_, "IAudioRenderer"}, system_event{system.Kernel()} { |
| 33 | // clang-format off | 34 | // clang-format off |
| 34 | static const FunctionInfo functions[] = { | 35 | static const FunctionInfo functions[] = { |
| 35 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, | 36 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, |
| @@ -48,13 +49,13 @@ public: | |||
| 48 | // clang-format on | 49 | // clang-format on |
| 49 | RegisterHandlers(functions); | 50 | RegisterHandlers(functions); |
| 50 | 51 | ||
| 51 | system_event = Kernel::KEvent::Create(system.Kernel(), "IAudioRenderer:SystemEvent"); | 52 | Kernel::KAutoObject::Create(std::addressof(system_event)); |
| 52 | system_event->Initialize(); | 53 | system_event.Initialize("IAudioRenderer:SystemEvent"); |
| 53 | renderer = std::make_unique<AudioCore::AudioRenderer>( | 54 | renderer = std::make_unique<AudioCore::AudioRenderer>( |
| 54 | system.CoreTiming(), system.Memory(), audren_params, | 55 | system.CoreTiming(), system.Memory(), audren_params, |
| 55 | [this]() { | 56 | [this]() { |
| 56 | const auto guard = LockService(); | 57 | const auto guard = LockService(); |
| 57 | system_event->GetWritableEvent()->Signal(); | 58 | system_event.GetWritableEvent().Signal(); |
| 58 | }, | 59 | }, |
| 59 | instance_number); | 60 | instance_number); |
| 60 | } | 61 | } |
| @@ -127,7 +128,7 @@ private: | |||
| 127 | 128 | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 129 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 129 | rb.Push(RESULT_SUCCESS); | 130 | rb.Push(RESULT_SUCCESS); |
| 130 | rb.PushCopyObjects(system_event->GetReadableEvent()); | 131 | rb.PushCopyObjects(system_event.GetReadableEvent()); |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { | 134 | void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { |
| @@ -161,15 +162,16 @@ private: | |||
| 161 | rb.Push(ERR_NOT_SUPPORTED); | 162 | rb.Push(ERR_NOT_SUPPORTED); |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | std::shared_ptr<Kernel::KEvent> system_event; | 165 | Kernel::KEvent system_event; |
| 165 | std::unique_ptr<AudioCore::AudioRenderer> renderer; | 166 | std::unique_ptr<AudioCore::AudioRenderer> renderer; |
| 166 | u32 rendering_time_limit_percent = 100; | 167 | u32 rendering_time_limit_percent = 100; |
| 167 | }; | 168 | }; |
| 168 | 169 | ||
| 169 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 170 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
| 170 | public: | 171 | public: |
| 171 | explicit IAudioDevice(Core::System& system_, u32_le revision_num) | 172 | explicit IAudioDevice(Core::System& system_, Kernel::KEvent& buffer_event_, u32_le revision_) |
| 172 | : ServiceFramework{system_, "IAudioDevice"}, revision{revision_num} { | 173 | : ServiceFramework{system_, "IAudioDevice"}, buffer_event{buffer_event_}, revision{ |
| 174 | revision_} { | ||
| 173 | static const FunctionInfo functions[] = { | 175 | static const FunctionInfo functions[] = { |
| 174 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, | 176 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, |
| 175 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, | 177 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, |
| @@ -186,21 +188,6 @@ public: | |||
| 186 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, | 188 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, |
| 187 | }; | 189 | }; |
| 188 | RegisterHandlers(functions); | 190 | RegisterHandlers(functions); |
| 189 | |||
| 190 | auto& kernel = system.Kernel(); | ||
| 191 | buffer_event = Kernel::KEvent::Create(kernel, "IAudioOutBufferReleasedEvent"); | ||
| 192 | buffer_event->Initialize(); | ||
| 193 | |||
| 194 | // Should be similar to audio_output_device_switch_event | ||
| 195 | audio_input_device_switch_event = | ||
| 196 | Kernel::KEvent::Create(kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent"); | ||
| 197 | audio_input_device_switch_event->Initialize(); | ||
| 198 | |||
| 199 | // Should only be signalled when an audio output device has been changed, example: speaker | ||
| 200 | // to headset | ||
| 201 | audio_output_device_switch_event = | ||
| 202 | Kernel::KEvent::Create(kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); | ||
| 203 | audio_output_device_switch_event->Initialize(); | ||
| 204 | } | 191 | } |
| 205 | 192 | ||
| 206 | private: | 193 | private: |
| @@ -289,11 +276,11 @@ private: | |||
| 289 | void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { | 276 | void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { |
| 290 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 277 | LOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 291 | 278 | ||
| 292 | buffer_event->GetWritableEvent()->Signal(); | 279 | buffer_event.GetWritableEvent().Signal(); |
| 293 | 280 | ||
| 294 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 281 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 295 | rb.Push(RESULT_SUCCESS); | 282 | rb.Push(RESULT_SUCCESS); |
| 296 | rb.PushCopyObjects(buffer_event->GetReadableEvent()); | 283 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 297 | } | 284 | } |
| 298 | 285 | ||
| 299 | void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { | 286 | void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { |
| @@ -310,7 +297,7 @@ private: | |||
| 310 | 297 | ||
| 311 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 298 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 312 | rb.Push(RESULT_SUCCESS); | 299 | rb.Push(RESULT_SUCCESS); |
| 313 | rb.PushCopyObjects(audio_input_device_switch_event->GetReadableEvent()); | 300 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 314 | } | 301 | } |
| 315 | 302 | ||
| 316 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { | 303 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { |
| @@ -318,17 +305,16 @@ private: | |||
| 318 | 305 | ||
| 319 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 306 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 320 | rb.Push(RESULT_SUCCESS); | 307 | rb.Push(RESULT_SUCCESS); |
| 321 | rb.PushCopyObjects(audio_output_device_switch_event->GetReadableEvent()); | 308 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 322 | } | 309 | } |
| 323 | 310 | ||
| 311 | Kernel::KEvent& buffer_event; | ||
| 324 | u32_le revision = 0; | 312 | u32_le revision = 0; |
| 325 | std::shared_ptr<Kernel::KEvent> buffer_event; | 313 | }; |
| 326 | std::shared_ptr<Kernel::KEvent> audio_input_device_switch_event; | ||
| 327 | std::shared_ptr<Kernel::KEvent> audio_output_device_switch_event; | ||
| 328 | 314 | ||
| 329 | }; // namespace Audio | 315 | AudRenU::AudRenU(Core::System& system_) |
| 316 | : ServiceFramework{system_, "audren:u"}, buffer_event{system.Kernel()} { | ||
| 330 | 317 | ||
| 331 | AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} { | ||
| 332 | // clang-format off | 318 | // clang-format off |
| 333 | static const FunctionInfo functions[] = { | 319 | static const FunctionInfo functions[] = { |
| 334 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, | 320 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, |
| @@ -340,6 +326,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} | |||
| 340 | // clang-format on | 326 | // clang-format on |
| 341 | 327 | ||
| 342 | RegisterHandlers(functions); | 328 | RegisterHandlers(functions); |
| 329 | |||
| 330 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); | ||
| 331 | buffer_event.Initialize("IAudioOutBufferReleasedEvent"); | ||
| 343 | } | 332 | } |
| 344 | 333 | ||
| 345 | AudRenU::~AudRenU() = default; | 334 | AudRenU::~AudRenU() = default; |
| @@ -373,7 +362,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 373 | static constexpr u64 max_perf_detail_entries = 100; | 362 | static constexpr u64 max_perf_detail_entries = 100; |
| 374 | 363 | ||
| 375 | // Size of the data structure representing the bulk of the voice-related state. | 364 | // Size of the data structure representing the bulk of the voice-related state. |
| 376 | static constexpr u64 voice_state_size = 0x100; | 365 | static constexpr u64 voice_state_size_bytes = 0x100; |
| 377 | 366 | ||
| 378 | // Size of the upsampler manager data structure | 367 | // Size of the upsampler manager data structure |
| 379 | constexpr u64 upsampler_manager_size = 0x48; | 368 | constexpr u64 upsampler_manager_size = 0x48; |
| @@ -460,7 +449,8 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 460 | size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size); | 449 | size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size); |
| 461 | size += | 450 | size += |
| 462 | Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size); | 451 | Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size); |
| 463 | size += Common::AlignUp(voice_state_size * params.voice_count, info_field_alignment_size); | 452 | size += |
| 453 | Common::AlignUp(voice_state_size_bytes * params.voice_count, info_field_alignment_size); | ||
| 464 | return size; | 454 | return size; |
| 465 | }; | 455 | }; |
| 466 | 456 | ||
| @@ -662,7 +652,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { | |||
| 662 | // always assumes the initial release revision (REV1). | 652 | // always assumes the initial release revision (REV1). |
| 663 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 653 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 664 | rb.Push(RESULT_SUCCESS); | 654 | rb.Push(RESULT_SUCCESS); |
| 665 | rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); | 655 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, Common::MakeMagic('R', 'E', 'V', '1')); |
| 666 | } | 656 | } |
| 667 | 657 | ||
| 668 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { | 658 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { |
| @@ -684,7 +674,7 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c | |||
| 684 | 674 | ||
| 685 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 675 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 686 | rb.Push(RESULT_SUCCESS); | 676 | rb.Push(RESULT_SUCCESS); |
| 687 | rb.PushIpcInterface<IAudioDevice>(system, revision); | 677 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, revision); |
| 688 | } | 678 | } |
| 689 | 679 | ||
| 690 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { | 680 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 37e8b4716..0ee6f9542 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -31,6 +32,7 @@ private: | |||
| 31 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); | 32 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); |
| 32 | 33 | ||
| 33 | std::size_t audren_instance_count = 0; | 34 | std::size_t audren_instance_count = 0; |
| 35 | Kernel::KEvent buffer_event; | ||
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | // Describes a particular audio feature that may be supported in a particular revision. | 38 | // Describes a particular audio feature that may be supported in a particular revision. |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 19c578b3a..ee5ec8cd6 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -50,8 +50,8 @@ public: | |||
| 50 | Enabled, | 50 | Enabled, |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | explicit OpusDecoderState(OpusDecoderPtr decoder, u32 sample_rate, u32 channel_count) | 53 | explicit OpusDecoderState(OpusDecoderPtr decoder_, u32 sample_rate_, u32 channel_count_) |
| 54 | : decoder{std::move(decoder)}, sample_rate{sample_rate}, channel_count{channel_count} {} | 54 | : decoder{std::move(decoder_)}, sample_rate{sample_rate_}, channel_count{channel_count_} {} |
| 55 | 55 | ||
| 56 | // Decodes interleaved Opus packets. Optionally allows reporting time taken to | 56 | // Decodes interleaved Opus packets. Optionally allows reporting time taken to |
| 57 | // perform the decoding, as well as any relevant extra behavior. | 57 | // perform the decoding, as well as any relevant extra behavior. |
| @@ -160,9 +160,9 @@ private: | |||
| 160 | 160 | ||
| 161 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { | 161 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { |
| 162 | public: | 162 | public: |
| 163 | explicit IHardwareOpusDecoderManager(Core::System& system_, OpusDecoderState decoder_state) | 163 | explicit IHardwareOpusDecoderManager(Core::System& system_, OpusDecoderState decoder_state_) |
| 164 | : ServiceFramework{system_, "IHardwareOpusDecoderManager"}, decoder_state{ | 164 | : ServiceFramework{system_, "IHardwareOpusDecoderManager"}, decoder_state{ |
| 165 | std::move(decoder_state)} { | 165 | std::move(decoder_state_)} { |
| 166 | // clang-format off | 166 | // clang-format off |
| 167 | static const FunctionInfo functions[] = { | 167 | static const FunctionInfo functions[] = { |
| 168 | {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"}, | 168 | {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"}, |
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index 92d25dbe4..0e935bfa6 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp | |||
| @@ -5,7 +5,6 @@ | |||
| 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/hle/kernel/k_event.h" | ||
| 9 | #include "core/hle/kernel/k_readable_event.h" | 8 | #include "core/hle/kernel/k_readable_event.h" |
| 10 | #include "core/hle/kernel/k_writable_event.h" | 9 | #include "core/hle/kernel/k_writable_event.h" |
| 11 | #include "core/hle/lock.h" | 10 | #include "core/hle/lock.h" |
| @@ -14,14 +13,14 @@ | |||
| 14 | namespace Service::BCAT { | 13 | namespace Service::BCAT { |
| 15 | 14 | ||
| 16 | ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, | 15 | ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, |
| 17 | std::string_view event_name) { | 16 | std::string_view event_name) |
| 18 | event = Kernel::KEvent::Create(kernel, | 17 | : update_event{kernel} { |
| 19 | "ProgressServiceBackend:UpdateEvent:" + std::string(event_name)); | 18 | Kernel::KAutoObject::Create(std::addressof(update_event)); |
| 20 | event->Initialize(); | 19 | update_event.Initialize("ProgressServiceBackend:UpdateEvent:" + std::string(event_name)); |
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | std::shared_ptr<Kernel::KReadableEvent> ProgressServiceBackend::GetEvent() const { | 22 | Kernel::KReadableEvent& ProgressServiceBackend::GetEvent() { |
| 24 | return event->GetReadableEvent(); | 23 | return update_event.GetReadableEvent(); |
| 25 | } | 24 | } |
| 26 | 25 | ||
| 27 | DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { | 26 | DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { |
| @@ -86,12 +85,12 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) { | |||
| 86 | SignalUpdate(); | 85 | SignalUpdate(); |
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | void ProgressServiceBackend::SignalUpdate() const { | 88 | void ProgressServiceBackend::SignalUpdate() { |
| 90 | if (need_hle_lock) { | 89 | if (need_hle_lock) { |
| 91 | std::lock_guard lock(HLE::g_hle_lock); | 90 | std::lock_guard lock(HLE::g_hle_lock); |
| 92 | event->GetWritableEvent()->Signal(); | 91 | update_event.GetWritableEvent().Signal(); |
| 93 | } else { | 92 | } else { |
| 94 | event->GetWritableEvent()->Signal(); | 93 | update_event.GetWritableEvent().Signal(); |
| 95 | } | 94 | } |
| 96 | } | 95 | } |
| 97 | 96 | ||
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index db585b069..f591a362a 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/file_sys/vfs_types.h" | 13 | #include "core/file_sys/vfs_types.h" |
| 14 | #include "core/hle/kernel/k_event.h" | ||
| 14 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 15 | 16 | ||
| 16 | namespace Core { | 17 | namespace Core { |
| @@ -98,13 +99,13 @@ public: | |||
| 98 | private: | 99 | private: |
| 99 | explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name); | 100 | explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name); |
| 100 | 101 | ||
| 101 | std::shared_ptr<Kernel::KReadableEvent> GetEvent() const; | 102 | Kernel::KReadableEvent& GetEvent(); |
| 102 | DeliveryCacheProgressImpl& GetImpl(); | 103 | DeliveryCacheProgressImpl& GetImpl(); |
| 103 | 104 | ||
| 104 | void SignalUpdate() const; | 105 | void SignalUpdate(); |
| 105 | 106 | ||
| 106 | DeliveryCacheProgressImpl impl{}; | 107 | DeliveryCacheProgressImpl impl{}; |
| 107 | std::shared_ptr<Kernel::KEvent> event; | 108 | Kernel::KEvent update_event; |
| 108 | bool need_hle_lock = false; | 109 | bool need_hle_lock = false; |
| 109 | }; | 110 | }; |
| 110 | 111 | ||
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index 78c047bd2..d6d2f52e5 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp | |||
| @@ -3,9 +3,18 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <fmt/ostream.h> | 5 | #include <fmt/ostream.h> |
| 6 | |||
| 7 | #ifdef __GNUC__ | ||
| 8 | #pragma GCC diagnostic push | ||
| 9 | #pragma GCC diagnostic ignored "-Wshadow" | ||
| 10 | #endif | ||
| 6 | #include <httplib.h> | 11 | #include <httplib.h> |
| 7 | #include <mbedtls/sha256.h> | 12 | #include <mbedtls/sha256.h> |
| 8 | #include <nlohmann/json.hpp> | 13 | #include <nlohmann/json.hpp> |
| 14 | #ifdef __GNUC__ | ||
| 15 | #pragma GCC diagnostic pop | ||
| 16 | #endif | ||
| 17 | |||
| 9 | #include "common/hex_util.h" | 18 | #include "common/hex_util.h" |
| 10 | #include "common/logging/backend.h" | 19 | #include "common/logging/backend.h" |
| 11 | #include "common/logging/log.h" | 20 | #include "common/logging/log.h" |
| @@ -178,8 +187,8 @@ bool VfsRawCopyDProgress(FileSys::VirtualDir src, FileSys::VirtualDir dest, | |||
| 178 | 187 | ||
| 179 | class Boxcat::Client { | 188 | class Boxcat::Client { |
| 180 | public: | 189 | public: |
| 181 | Client(std::string path, u64 title_id, u64 build_id) | 190 | Client(std::string path_, u64 title_id_, u64 build_id_) |
| 182 | : path(std::move(path)), title_id(title_id), build_id(build_id) {} | 191 | : path(std::move(path_)), title_id(title_id_), build_id(build_id_) {} |
| 183 | 192 | ||
| 184 | DownloadResult DownloadDataZip() { | 193 | DownloadResult DownloadDataZip() { |
| 185 | return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS, | 194 | return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS, |
| @@ -415,9 +424,9 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) | |||
| 415 | if (Settings::values.bcat_boxcat_local) { | 424 | if (Settings::values.bcat_boxcat_local) { |
| 416 | LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download."); | 425 | LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download."); |
| 417 | } else { | 426 | } else { |
| 418 | Boxcat::Client client{path, title.title_id, title.build_id}; | 427 | Client launch_client{path, title.title_id, title.build_id}; |
| 419 | 428 | ||
| 420 | const auto res = client.DownloadLaunchParam(); | 429 | const auto res = launch_client.DownloadLaunchParam(); |
| 421 | if (res != DownloadResult::Success) { | 430 | if (res != DownloadResult::Success) { |
| 422 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); | 431 | LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); |
| 423 | 432 | ||
diff --git a/src/core/hle/service/bcat/bcat.cpp b/src/core/hle/service/bcat/bcat.cpp index b31766212..5a95707de 100644 --- a/src/core/hle/service/bcat/bcat.cpp +++ b/src/core/hle/service/bcat/bcat.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::BCAT { | 7 | namespace Service::BCAT { |
| 8 | 8 | ||
| 9 | BCAT::BCAT(Core::System& system, std::shared_ptr<Module> module, | 9 | BCAT::BCAT(Core::System& system_, std::shared_ptr<Module> module_, |
| 10 | FileSystem::FileSystemController& fsc, const char* name) | 10 | FileSystem::FileSystemController& fsc_, const char* name_) |
| 11 | : Interface(system, std::move(module), fsc, name) { | 11 | : Interface(system_, std::move(module_), fsc_, name_) { |
| 12 | // clang-format off | 12 | // clang-format off |
| 13 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, | 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, |
diff --git a/src/core/hle/service/bcat/bcat.h b/src/core/hle/service/bcat/bcat.h index 6354465fc..d72798980 100644 --- a/src/core/hle/service/bcat/bcat.h +++ b/src/core/hle/service/bcat/bcat.h | |||
| @@ -14,8 +14,8 @@ namespace Service::BCAT { | |||
| 14 | 14 | ||
| 15 | class BCAT final : public Module::Interface { | 15 | class BCAT final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit BCAT(Core::System& system, std::shared_ptr<Module> module, | 17 | explicit BCAT(Core::System& system_, std::shared_ptr<Module> module_, |
| 18 | FileSystem::FileSystemController& fsc, const char* name); | 18 | FileSystem::FileSystemController& fsc_, const char* name_); |
| 19 | ~BCAT() override; | 19 | ~BCAT() override; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index c7dd04a6e..0206cbb6a 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/file_sys/vfs.h" | 13 | #include "core/file_sys/vfs.h" |
| 14 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| 15 | #include "core/hle/kernel/k_process.h" | ||
| 15 | #include "core/hle/kernel/k_readable_event.h" | 16 | #include "core/hle/kernel/k_readable_event.h" |
| 16 | #include "core/hle/kernel/k_writable_event.h" | 17 | #include "core/hle/kernel/k_writable_event.h" |
| 17 | #include "core/hle/kernel/process.h" | ||
| 18 | #include "core/hle/service/bcat/backend/backend.h" | 18 | #include "core/hle/service/bcat/backend/backend.h" |
| 19 | #include "core/hle/service/bcat/bcat.h" | 19 | #include "core/hle/service/bcat/bcat.h" |
| 20 | #include "core/hle/service/bcat/module.h" | 20 | #include "core/hle/service/bcat/module.h" |
| @@ -88,11 +88,9 @@ struct DeliveryCacheDirectoryEntry { | |||
| 88 | 88 | ||
| 89 | class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> { | 89 | class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> { |
| 90 | public: | 90 | public: |
| 91 | explicit IDeliveryCacheProgressService(Core::System& system_, | 91 | explicit IDeliveryCacheProgressService(Core::System& system_, Kernel::KReadableEvent& event_, |
| 92 | std::shared_ptr<Kernel::KReadableEvent> event_, | ||
| 93 | const DeliveryCacheProgressImpl& impl_) | 92 | const DeliveryCacheProgressImpl& impl_) |
| 94 | : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)}, | 93 | : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{event_}, impl{impl_} { |
| 95 | impl{impl_} { | ||
| 96 | // clang-format off | 94 | // clang-format off |
| 97 | static const FunctionInfo functions[] = { | 95 | static const FunctionInfo functions[] = { |
| 98 | {0, &IDeliveryCacheProgressService::GetEvent, "GetEvent"}, | 96 | {0, &IDeliveryCacheProgressService::GetEvent, "GetEvent"}, |
| @@ -121,7 +119,7 @@ private: | |||
| 121 | rb.Push(RESULT_SUCCESS); | 119 | rb.Push(RESULT_SUCCESS); |
| 122 | } | 120 | } |
| 123 | 121 | ||
| 124 | std::shared_ptr<Kernel::KReadableEvent> event; | 122 | Kernel::KReadableEvent& event; |
| 125 | const DeliveryCacheProgressImpl& impl; | 123 | const DeliveryCacheProgressImpl& impl; |
| 126 | }; | 124 | }; |
| 127 | 125 | ||
| @@ -174,9 +172,9 @@ private: | |||
| 174 | }; | 172 | }; |
| 175 | 173 | ||
| 176 | std::shared_ptr<IDeliveryCacheProgressService> CreateProgressService(SyncType type) { | 174 | std::shared_ptr<IDeliveryCacheProgressService> CreateProgressService(SyncType type) { |
| 177 | auto& backend{progress.at(static_cast<std::size_t>(type))}; | 175 | auto& progress_backend{GetProgressBackend(type)}; |
| 178 | return std::make_shared<IDeliveryCacheProgressService>(system, backend.GetEvent(), | 176 | return std::make_shared<IDeliveryCacheProgressService>(system, progress_backend.GetEvent(), |
| 179 | backend.GetImpl()); | 177 | progress_backend.GetImpl()); |
| 180 | } | 178 | } |
| 181 | 179 | ||
| 182 | void RequestSyncDeliveryCache(Kernel::HLERequestContext& ctx) { | 180 | void RequestSyncDeliveryCache(Kernel::HLERequestContext& ctx) { |
| @@ -184,7 +182,7 @@ private: | |||
| 184 | 182 | ||
| 185 | backend.Synchronize({system.CurrentProcess()->GetTitleID(), | 183 | backend.Synchronize({system.CurrentProcess()->GetTitleID(), |
| 186 | GetCurrentBuildID(system.GetCurrentProcessBuildID())}, | 184 | GetCurrentBuildID(system.GetCurrentProcessBuildID())}, |
| 187 | progress.at(static_cast<std::size_t>(SyncType::Normal))); | 185 | GetProgressBackend(SyncType::Normal)); |
| 188 | 186 | ||
| 189 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 187 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 190 | rb.Push(RESULT_SUCCESS); | 188 | rb.Push(RESULT_SUCCESS); |
| @@ -201,8 +199,7 @@ private: | |||
| 201 | 199 | ||
| 202 | backend.SynchronizeDirectory({system.CurrentProcess()->GetTitleID(), | 200 | backend.SynchronizeDirectory({system.CurrentProcess()->GetTitleID(), |
| 203 | GetCurrentBuildID(system.GetCurrentProcessBuildID())}, | 201 | GetCurrentBuildID(system.GetCurrentProcessBuildID())}, |
| 204 | name, | 202 | name, GetProgressBackend(SyncType::Directory)); |
| 205 | progress.at(static_cast<std::size_t>(SyncType::Directory))); | ||
| 206 | 203 | ||
| 207 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 204 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 208 | rb.Push(RESULT_SUCCESS); | 205 | rb.Push(RESULT_SUCCESS); |
| @@ -265,9 +262,16 @@ private: | |||
| 265 | rb.Push(RESULT_SUCCESS); | 262 | rb.Push(RESULT_SUCCESS); |
| 266 | } | 263 | } |
| 267 | 264 | ||
| 268 | Backend& backend; | 265 | ProgressServiceBackend& GetProgressBackend(SyncType type) { |
| 266 | return progress.at(static_cast<size_t>(type)); | ||
| 267 | } | ||
| 269 | 268 | ||
| 270 | std::array<ProgressServiceBackend, static_cast<std::size_t>(SyncType::Count)> progress; | 269 | const ProgressServiceBackend& GetProgressBackend(SyncType type) const { |
| 270 | return progress.at(static_cast<size_t>(type)); | ||
| 271 | } | ||
| 272 | |||
| 273 | Backend& backend; | ||
| 274 | std::array<ProgressServiceBackend, static_cast<size_t>(SyncType::Count)> progress; | ||
| 271 | }; | 275 | }; |
| 272 | 276 | ||
| 273 | void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { | 277 | void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index af3a5842d..fd97a822c 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp | |||
| @@ -17,7 +17,8 @@ namespace Service::BtDrv { | |||
| 17 | 17 | ||
| 18 | class Bt final : public ServiceFramework<Bt> { | 18 | class Bt final : public ServiceFramework<Bt> { |
| 19 | public: | 19 | public: |
| 20 | explicit Bt(Core::System& system_) : ServiceFramework{system_, "bt"} { | 20 | explicit Bt(Core::System& system_) |
| 21 | : ServiceFramework{system_, "bt"}, register_event{system.Kernel()} { | ||
| 21 | // clang-format off | 22 | // clang-format off |
| 22 | static const FunctionInfo functions[] = { | 23 | static const FunctionInfo functions[] = { |
| 23 | {0, nullptr, "LeClientReadCharacteristic"}, | 24 | {0, nullptr, "LeClientReadCharacteristic"}, |
| @@ -34,9 +35,8 @@ public: | |||
| 34 | // clang-format on | 35 | // clang-format on |
| 35 | RegisterHandlers(functions); | 36 | RegisterHandlers(functions); |
| 36 | 37 | ||
| 37 | auto& kernel = system.Kernel(); | 38 | Kernel::KAutoObject::Create(std::addressof(register_event)); |
| 38 | register_event = Kernel::KEvent::Create(kernel, "BT:RegisterEvent"); | 39 | register_event.Initialize("BT:RegisterEvent"); |
| 39 | register_event->Initialize(); | ||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | private: | 42 | private: |
| @@ -45,10 +45,10 @@ private: | |||
| 45 | 45 | ||
| 46 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 46 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 47 | rb.Push(RESULT_SUCCESS); | 47 | rb.Push(RESULT_SUCCESS); |
| 48 | rb.PushCopyObjects(register_event->GetReadableEvent()); | 48 | rb.PushCopyObjects(register_event.GetReadableEvent()); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | std::shared_ptr<Kernel::KEvent> register_event; | 51 | Kernel::KEvent register_event; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | class BtDrv final : public ServiceFramework<BtDrv> { | 54 | class BtDrv final : public ServiceFramework<BtDrv> { |
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index d1ebc2388..3b5ef69e1 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -18,7 +18,10 @@ namespace Service::BTM { | |||
| 18 | 18 | ||
| 19 | class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { | 19 | class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { |
| 20 | public: | 20 | public: |
| 21 | explicit IBtmUserCore(Core::System& system_) : ServiceFramework{system_, "IBtmUserCore"} { | 21 | explicit IBtmUserCore(Core::System& system_) |
| 22 | : ServiceFramework{system_, "IBtmUserCore"}, scan_event{system.Kernel()}, | ||
| 23 | connection_event{system.Kernel()}, service_discovery{system.Kernel()}, | ||
| 24 | config_event{system.Kernel()} { | ||
| 22 | // clang-format off | 25 | // clang-format off |
| 23 | static const FunctionInfo functions[] = { | 26 | static const FunctionInfo functions[] = { |
| 24 | {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"}, | 27 | {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"}, |
| @@ -57,15 +60,15 @@ public: | |||
| 57 | // clang-format on | 60 | // clang-format on |
| 58 | RegisterHandlers(functions); | 61 | RegisterHandlers(functions); |
| 59 | 62 | ||
| 60 | auto& kernel = system.Kernel(); | 63 | Kernel::KAutoObject::Create(std::addressof(scan_event)); |
| 61 | scan_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ScanEvent"); | 64 | Kernel::KAutoObject::Create(std::addressof(connection_event)); |
| 62 | scan_event->Initialize(); | 65 | Kernel::KAutoObject::Create(std::addressof(service_discovery)); |
| 63 | connection_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConnectionEvent"); | 66 | Kernel::KAutoObject::Create(std::addressof(config_event)); |
| 64 | connection_event->Initialize(); | 67 | |
| 65 | service_discovery = Kernel::KEvent::Create(kernel, "IBtmUserCore:Discovery"); | 68 | scan_event.Initialize("IBtmUserCore:ScanEvent"); |
| 66 | service_discovery->Initialize(); | 69 | connection_event.Initialize("IBtmUserCore:ConnectionEvent"); |
| 67 | config_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConfigEvent"); | 70 | service_discovery.Initialize("IBtmUserCore:Discovery"); |
| 68 | config_event->Initialize(); | 71 | config_event.Initialize("IBtmUserCore:ConfigEvent"); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | private: | 74 | private: |
| @@ -74,7 +77,7 @@ private: | |||
| 74 | 77 | ||
| 75 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 78 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 76 | rb.Push(RESULT_SUCCESS); | 79 | rb.Push(RESULT_SUCCESS); |
| 77 | rb.PushCopyObjects(scan_event->GetReadableEvent()); | 80 | rb.PushCopyObjects(scan_event.GetReadableEvent()); |
| 78 | } | 81 | } |
| 79 | 82 | ||
| 80 | void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) { | 83 | void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) { |
| @@ -82,7 +85,7 @@ private: | |||
| 82 | 85 | ||
| 83 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 86 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 84 | rb.Push(RESULT_SUCCESS); | 87 | rb.Push(RESULT_SUCCESS); |
| 85 | rb.PushCopyObjects(connection_event->GetReadableEvent()); | 88 | rb.PushCopyObjects(connection_event.GetReadableEvent()); |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) { | 91 | void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) { |
| @@ -90,7 +93,7 @@ private: | |||
| 90 | 93 | ||
| 91 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 94 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 92 | rb.Push(RESULT_SUCCESS); | 95 | rb.Push(RESULT_SUCCESS); |
| 93 | rb.PushCopyObjects(service_discovery->GetReadableEvent()); | 96 | rb.PushCopyObjects(service_discovery.GetReadableEvent()); |
| 94 | } | 97 | } |
| 95 | 98 | ||
| 96 | void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) { | 99 | void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) { |
| @@ -98,13 +101,13 @@ private: | |||
| 98 | 101 | ||
| 99 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 102 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 100 | rb.Push(RESULT_SUCCESS); | 103 | rb.Push(RESULT_SUCCESS); |
| 101 | rb.PushCopyObjects(config_event->GetReadableEvent()); | 104 | rb.PushCopyObjects(config_event.GetReadableEvent()); |
| 102 | } | 105 | } |
| 103 | 106 | ||
| 104 | std::shared_ptr<Kernel::KEvent> scan_event; | 107 | Kernel::KEvent scan_event; |
| 105 | std::shared_ptr<Kernel::KEvent> connection_event; | 108 | Kernel::KEvent connection_event; |
| 106 | std::shared_ptr<Kernel::KEvent> service_discovery; | 109 | Kernel::KEvent service_discovery; |
| 107 | std::shared_ptr<Kernel::KEvent> config_event; | 110 | Kernel::KEvent config_event; |
| 108 | }; | 111 | }; |
| 109 | 112 | ||
| 110 | class BTM_USR final : public ServiceFramework<BTM_USR> { | 113 | class BTM_USR final : public ServiceFramework<BTM_USR> { |
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 13147472e..432abde76 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| 15 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/k_process.h" |
| 16 | #include "core/hle/service/fatal/fatal.h" | 16 | #include "core/hle/service/fatal/fatal.h" |
| 17 | #include "core/hle/service/fatal/fatal_p.h" | 17 | #include "core/hle/service/fatal/fatal_p.h" |
| 18 | #include "core/hle/service/fatal/fatal_u.h" | 18 | #include "core/hle/service/fatal/fatal_u.h" |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 72ad273b2..67baaee9b 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include "core/file_sys/sdmc_factory.h" | 21 | #include "core/file_sys/sdmc_factory.h" |
| 22 | #include "core/file_sys/vfs.h" | 22 | #include "core/file_sys/vfs.h" |
| 23 | #include "core/file_sys/vfs_offset.h" | 23 | #include "core/file_sys/vfs_offset.h" |
| 24 | #include "core/hle/kernel/process.h" | 24 | #include "core/hle/kernel/k_process.h" |
| 25 | #include "core/hle/service/filesystem/filesystem.h" | 25 | #include "core/hle/service/filesystem/filesystem.h" |
| 26 | #include "core/hle/service/filesystem/fsp_ldr.h" | 26 | #include "core/hle/service/filesystem/fsp_ldr.h" |
| 27 | #include "core/hle/service/filesystem/fsp_pr.h" | 27 | #include "core/hle/service/filesystem/fsp_pr.h" |
| @@ -55,10 +55,15 @@ std::string VfsDirectoryServiceWrapper::GetName() const { | |||
| 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { | 55 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { |
| 56 | std::string path(Common::FS::SanitizePath(path_)); | 56 | std::string path(Common::FS::SanitizePath(path_)); |
| 57 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 57 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 58 | // dir can be nullptr if path contains subdirectories, create those prior to creating the file. | ||
| 59 | if (dir == nullptr) { | 58 | if (dir == nullptr) { |
| 60 | dir = backing->CreateSubdirectory(Common::FS::GetParentPath(path)); | 59 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 60 | } | ||
| 61 | |||
| 62 | const auto entry_type = GetEntryType(path); | ||
| 63 | if (entry_type.Code() == RESULT_SUCCESS) { | ||
| 64 | return FileSys::ERROR_PATH_ALREADY_EXISTS; | ||
| 61 | } | 65 | } |
| 66 | |||
| 62 | auto file = dir->CreateFile(Common::FS::GetFilename(path)); | 67 | auto file = dir->CreateFile(Common::FS::GetFilename(path)); |
| 63 | if (file == nullptr) { | 68 | if (file == nullptr) { |
| 64 | // TODO(DarkLordZach): Find a better error code for this | 69 | // TODO(DarkLordZach): Find a better error code for this |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index a0215c4d7..92ea27074 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include "core/file_sys/system_archive/system_archive.h" | 25 | #include "core/file_sys/system_archive/system_archive.h" |
| 26 | #include "core/file_sys/vfs.h" | 26 | #include "core/file_sys/vfs.h" |
| 27 | #include "core/hle/ipc_helpers.h" | 27 | #include "core/hle/ipc_helpers.h" |
| 28 | #include "core/hle/kernel/process.h" | 28 | #include "core/hle/kernel/k_process.h" |
| 29 | #include "core/hle/service/filesystem/filesystem.h" | 29 | #include "core/hle/service/filesystem/filesystem.h" |
| 30 | #include "core/hle/service/filesystem/fsp_srv.h" | 30 | #include "core/hle/service/filesystem/fsp_srv.h" |
| 31 | #include "core/reporter.h" | 31 | #include "core/reporter.h" |
| @@ -337,13 +337,14 @@ public: | |||
| 337 | const auto file_buffer = ctx.ReadBuffer(); | 337 | const auto file_buffer = ctx.ReadBuffer(); |
| 338 | const std::string name = Common::StringFromBuffer(file_buffer); | 338 | const std::string name = Common::StringFromBuffer(file_buffer); |
| 339 | 339 | ||
| 340 | const u64 mode = rp.Pop<u64>(); | 340 | const u64 file_mode = rp.Pop<u64>(); |
| 341 | const u32 size = rp.Pop<u32>(); | 341 | const u32 file_size = rp.Pop<u32>(); |
| 342 | 342 | ||
| 343 | LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, mode, size); | 343 | LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, file_mode, |
| 344 | file_size); | ||
| 344 | 345 | ||
| 345 | IPC::ResponseBuilder rb{ctx, 2}; | 346 | IPC::ResponseBuilder rb{ctx, 2}; |
| 346 | rb.Push(backend.CreateFile(name, size)); | 347 | rb.Push(backend.CreateFile(name, file_size)); |
| 347 | } | 348 | } |
| 348 | 349 | ||
| 349 | void DeleteFile(Kernel::HLERequestContext& ctx) { | 350 | void DeleteFile(Kernel::HLERequestContext& ctx) { |
| @@ -935,8 +936,8 @@ void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( | |||
| 935 | void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | 936 | void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { |
| 936 | LOG_DEBUG(Service_FS, "called"); | 937 | LOG_DEBUG(Service_FS, "called"); |
| 937 | 938 | ||
| 938 | auto romfs = fsc.OpenRomFSCurrentProcess(); | 939 | auto current_romfs = fsc.OpenRomFSCurrentProcess(); |
| 939 | if (romfs.Failed()) { | 940 | if (current_romfs.Failed()) { |
| 940 | // TODO (bunnei): Find the right error code to use here | 941 | // TODO (bunnei): Find the right error code to use here |
| 941 | LOG_CRITICAL(Service_FS, "no file system interface available!"); | 942 | LOG_CRITICAL(Service_FS, "no file system interface available!"); |
| 942 | IPC::ResponseBuilder rb{ctx, 2}; | 943 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -944,7 +945,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | |||
| 944 | return; | 945 | return; |
| 945 | } | 946 | } |
| 946 | 947 | ||
| 947 | auto storage = std::make_shared<IStorage>(system, std::move(romfs.Unwrap())); | 948 | auto storage = std::make_shared<IStorage>(system, std::move(current_romfs.Unwrap())); |
| 948 | 949 | ||
| 949 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 950 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 950 | rb.Push(RESULT_SUCCESS); | 951 | rb.Push(RESULT_SUCCESS); |
| @@ -1010,10 +1011,10 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx) { | |||
| 1010 | 1011 | ||
| 1011 | LOG_DEBUG(Service_FS, "called, program_index={}", program_index); | 1012 | LOG_DEBUG(Service_FS, "called, program_index={}", program_index); |
| 1012 | 1013 | ||
| 1013 | auto romfs = fsc.OpenPatchedRomFSWithProgramIndex( | 1014 | auto patched_romfs = fsc.OpenPatchedRomFSWithProgramIndex( |
| 1014 | system.CurrentProcess()->GetTitleID(), program_index, FileSys::ContentRecordType::Program); | 1015 | system.CurrentProcess()->GetTitleID(), program_index, FileSys::ContentRecordType::Program); |
| 1015 | 1016 | ||
| 1016 | if (romfs.Failed()) { | 1017 | if (patched_romfs.Failed()) { |
| 1017 | // TODO: Find the right error code to use here | 1018 | // TODO: Find the right error code to use here |
| 1018 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); | 1019 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); |
| 1019 | 1020 | ||
| @@ -1022,7 +1023,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(Kernel::HLERequestContext& ctx) { | |||
| 1022 | return; | 1023 | return; |
| 1023 | } | 1024 | } |
| 1024 | 1025 | ||
| 1025 | auto storage = std::make_shared<IStorage>(system, std::move(romfs.Unwrap())); | 1026 | auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs.Unwrap())); |
| 1026 | 1027 | ||
| 1027 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1028 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1028 | rb.Push(RESULT_SUCCESS); | 1029 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index a35979053..91c202952 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp | |||
| @@ -185,7 +185,8 @@ private: | |||
| 185 | class INotificationService final : public ServiceFramework<INotificationService> { | 185 | class INotificationService final : public ServiceFramework<INotificationService> { |
| 186 | public: | 186 | public: |
| 187 | explicit INotificationService(Common::UUID uuid_, Core::System& system_) | 187 | explicit INotificationService(Common::UUID uuid_, Core::System& system_) |
| 188 | : ServiceFramework{system_, "INotificationService"}, uuid{uuid_} { | 188 | : ServiceFramework{system_, "INotificationService"}, uuid{uuid_}, notification_event{ |
| 189 | system.Kernel()} { | ||
| 189 | // clang-format off | 190 | // clang-format off |
| 190 | static const FunctionInfo functions[] = { | 191 | static const FunctionInfo functions[] = { |
| 191 | {0, &INotificationService::GetEvent, "GetEvent"}, | 192 | {0, &INotificationService::GetEvent, "GetEvent"}, |
| @@ -196,9 +197,8 @@ public: | |||
| 196 | 197 | ||
| 197 | RegisterHandlers(functions); | 198 | RegisterHandlers(functions); |
| 198 | 199 | ||
| 199 | notification_event = | 200 | Kernel::KAutoObject::Create(std::addressof(notification_event)); |
| 200 | Kernel::KEvent::Create(system.Kernel(), "INotificationService:NotifyEvent"); | 201 | notification_event.Initialize("INotificationService:NotifyEvent"); |
| 201 | notification_event->Initialize(); | ||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | private: | 204 | private: |
| @@ -207,7 +207,7 @@ private: | |||
| 207 | 207 | ||
| 208 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 208 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 209 | rb.Push(RESULT_SUCCESS); | 209 | rb.Push(RESULT_SUCCESS); |
| 210 | rb.PushCopyObjects(notification_event->GetReadableEvent()); | 210 | rb.PushCopyObjects(notification_event.GetReadableEvent()); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | void Clear(Kernel::HLERequestContext& ctx) { | 213 | void Clear(Kernel::HLERequestContext& ctx) { |
| @@ -273,7 +273,7 @@ private: | |||
| 273 | }; | 273 | }; |
| 274 | 274 | ||
| 275 | Common::UUID uuid{Common::INVALID_UUID}; | 275 | Common::UUID uuid{Common::INVALID_UUID}; |
| 276 | std::shared_ptr<Kernel::KEvent> notification_event; | 276 | Kernel::KEvent notification_event; |
| 277 | std::queue<SizedNotificationInfo> notifications; | 277 | std::queue<SizedNotificationInfo> notifications; |
| 278 | States states{}; | 278 | States states{}; |
| 279 | }; | 279 | }; |
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 7b1c6677c..6ad62ee5a 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include "core/file_sys/control_metadata.h" | 9 | #include "core/file_sys/control_metadata.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/kernel/hle_ipc.h" | 11 | #include "core/hle/kernel/hle_ipc.h" |
| 12 | #include "core/hle/kernel/k_process.h" | ||
| 12 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/process.h" | ||
| 14 | #include "core/hle/service/glue/arp.h" | 14 | #include "core/hle/service/glue/arp.h" |
| 15 | #include "core/hle/service/glue/errors.h" | 15 | #include "core/hle/service/glue/errors.h" |
| 16 | #include "core/hle/service/glue/manager.h" | 16 | #include "core/hle/service/glue/manager.h" |
diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp index a502ab47f..f918bdf03 100644 --- a/src/core/hle/service/grc/grc.cpp +++ b/src/core/hle/service/grc/grc.cpp | |||
| @@ -12,7 +12,7 @@ namespace Service::GRC { | |||
| 12 | 12 | ||
| 13 | class GRC final : public ServiceFramework<GRC> { | 13 | class GRC final : public ServiceFramework<GRC> { |
| 14 | public: | 14 | public: |
| 15 | explicit GRC(Core::System& system) : ServiceFramework{system, "grc:c"} { | 15 | explicit GRC(Core::System& system_) : ServiceFramework{system_, "grc:c"} { |
| 16 | // clang-format off | 16 | // clang-format off |
| 17 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
| 18 | {1, nullptr, "OpenContinuousRecorder"}, | 18 | {1, nullptr, "OpenContinuousRecorder"}, |
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp new file mode 100644 index 000000000..bda6e2557 --- /dev/null +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/settings.h" | ||
| 6 | #include "core/core_timing.h" | ||
| 7 | #include "core/hle/service/hid/controllers/console_sixaxis.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; | ||
| 11 | |||
| 12 | Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_) | ||
| 13 | : ControllerBase{system_} {} | ||
| 14 | Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; | ||
| 15 | |||
| 16 | void Controller_ConsoleSixAxis::OnInit() {} | ||
| 17 | |||
| 18 | void Controller_ConsoleSixAxis::OnRelease() {} | ||
| 19 | |||
| 20 | void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | ||
| 21 | std::size_t size) { | ||
| 22 | seven_six_axis.header.timestamp = core_timing.GetCPUTicks(); | ||
| 23 | seven_six_axis.header.total_entry_count = 17; | ||
| 24 | |||
| 25 | if (!IsControllerActivated() || !is_transfer_memory_set) { | ||
| 26 | seven_six_axis.header.entry_count = 0; | ||
| 27 | seven_six_axis.header.last_entry_index = 0; | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | seven_six_axis.header.entry_count = 16; | ||
| 31 | |||
| 32 | const auto& last_entry = | ||
| 33 | seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; | ||
| 34 | seven_six_axis.header.last_entry_index = (seven_six_axis.header.last_entry_index + 1) % 17; | ||
| 35 | auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; | ||
| 36 | |||
| 37 | cur_entry.sampling_number = last_entry.sampling_number + 1; | ||
| 38 | cur_entry.sampling_number2 = cur_entry.sampling_number; | ||
| 39 | |||
| 40 | // Try to read sixaxis sensor states | ||
| 41 | MotionDevice motion_device{}; | ||
| 42 | const auto& device = motions[0]; | ||
| 43 | if (device) { | ||
| 44 | std::tie(motion_device.accel, motion_device.gyro, motion_device.rotation, | ||
| 45 | motion_device.orientation, motion_device.quaternion) = device->GetStatus(); | ||
| 46 | console_six_axis.is_seven_six_axis_sensor_at_rest = motion_device.gyro.Length2() < 0.0001f; | ||
| 47 | } | ||
| 48 | |||
| 49 | cur_entry.accel = motion_device.accel; | ||
| 50 | // Zero gyro values as they just mess up with the camera | ||
| 51 | // Note: Probably a correct sensivity setting must be set | ||
| 52 | cur_entry.gyro = {}; | ||
| 53 | cur_entry.quaternion = { | ||
| 54 | { | ||
| 55 | motion_device.quaternion.xyz.y, | ||
| 56 | motion_device.quaternion.xyz.x, | ||
| 57 | -motion_device.quaternion.w, | ||
| 58 | }, | ||
| 59 | -motion_device.quaternion.xyz.z, | ||
| 60 | }; | ||
| 61 | |||
| 62 | console_six_axis.sampling_number++; | ||
| 63 | // TODO(German77): Find the purpose of those values | ||
| 64 | console_six_axis.verticalization_error = 0.0f; | ||
| 65 | console_six_axis.gyro_bias = {0.0f, 0.0f, 0.0f}; | ||
| 66 | |||
| 67 | // Update console six axis shared memory | ||
| 68 | std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); | ||
| 69 | // Update seven six axis transfer memory | ||
| 70 | std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis)); | ||
| 71 | } | ||
| 72 | |||
| 73 | void Controller_ConsoleSixAxis::OnLoadInputDevices() { | ||
| 74 | const auto player = Settings::values.players.GetValue()[0]; | ||
| 75 | std::transform(player.motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, | ||
| 76 | player.motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions.begin(), | ||
| 77 | Input::CreateDevice<Input::MotionDevice>); | ||
| 78 | } | ||
| 79 | |||
| 80 | void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { | ||
| 81 | is_transfer_memory_set = true; | ||
| 82 | transfer_memory = t_mem; | ||
| 83 | } | ||
| 84 | |||
| 85 | void Controller_ConsoleSixAxis::ResetTimestamp() { | ||
| 86 | auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; | ||
| 87 | cur_entry.sampling_number = 0; | ||
| 88 | cur_entry.sampling_number2 = 0; | ||
| 89 | } | ||
| 90 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h new file mode 100644 index 000000000..fd8a427af --- /dev/null +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include "common/bit_field.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/quaternion.h" | ||
| 11 | #include "core/frontend/input.h" | ||
| 12 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class Controller_ConsoleSixAxis final : public ControllerBase { | ||
| 16 | public: | ||
| 17 | explicit Controller_ConsoleSixAxis(Core::System& system_); | ||
| 18 | ~Controller_ConsoleSixAxis() override; | ||
| 19 | |||
| 20 | // Called when the controller is initialized | ||
| 21 | void OnInit() override; | ||
| 22 | |||
| 23 | // When the controller is released | ||
| 24 | void OnRelease() override; | ||
| 25 | |||
| 26 | // When the controller is requesting an update for the shared memory | ||
| 27 | void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; | ||
| 28 | |||
| 29 | // Called when input devices should be loaded | ||
| 30 | void OnLoadInputDevices() override; | ||
| 31 | |||
| 32 | // Called on InitializeSevenSixAxisSensor | ||
| 33 | void SetTransferMemoryPointer(u8* t_mem); | ||
| 34 | |||
| 35 | // Called on ResetSevenSixAxisSensorTimestamp | ||
| 36 | void ResetTimestamp(); | ||
| 37 | |||
| 38 | private: | ||
| 39 | struct SevenSixAxisState { | ||
| 40 | INSERT_PADDING_WORDS(4); // unused | ||
| 41 | s64_le sampling_number{}; | ||
| 42 | s64_le sampling_number2{}; | ||
| 43 | u64 unknown{}; | ||
| 44 | Common::Vec3f accel{}; | ||
| 45 | Common::Vec3f gyro{}; | ||
| 46 | Common::Quaternion<f32> quaternion{}; | ||
| 47 | }; | ||
| 48 | static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size"); | ||
| 49 | |||
| 50 | struct SevenSixAxisMemory { | ||
| 51 | CommonHeader header{}; | ||
| 52 | std::array<SevenSixAxisState, 0x21> sevensixaxis_states{}; | ||
| 53 | }; | ||
| 54 | static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size"); | ||
| 55 | |||
| 56 | struct ConsoleSharedMemory { | ||
| 57 | u64_le sampling_number{}; | ||
| 58 | bool is_seven_six_axis_sensor_at_rest{}; | ||
| 59 | f32 verticalization_error{}; | ||
| 60 | Common::Vec3f gyro_bias{}; | ||
| 61 | }; | ||
| 62 | static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); | ||
| 63 | |||
| 64 | struct MotionDevice { | ||
| 65 | Common::Vec3f accel; | ||
| 66 | Common::Vec3f gyro; | ||
| 67 | Common::Vec3f rotation; | ||
| 68 | std::array<Common::Vec3f, 3> orientation; | ||
| 69 | Common::Quaternion<f32> quaternion; | ||
| 70 | }; | ||
| 71 | |||
| 72 | using MotionArray = | ||
| 73 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>; | ||
| 74 | MotionArray motions; | ||
| 75 | u8* transfer_memory = nullptr; | ||
| 76 | bool is_transfer_memory_set = false; | ||
| 77 | ConsoleSharedMemory console_six_axis{}; | ||
| 78 | SevenSixAxisMemory seven_six_axis{}; | ||
| 79 | }; | ||
| 80 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index 8091db9d7..9d1e6db6a 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::HID { | 7 | namespace Service::HID { |
| 8 | 8 | ||
| 9 | ControllerBase::ControllerBase(Core::System& system) : system(system) {} | 9 | ControllerBase::ControllerBase(Core::System& system_) : system(system_) {} |
| 10 | ControllerBase::~ControllerBase() = default; | 10 | ControllerBase::~ControllerBase() = default; |
| 11 | 11 | ||
| 12 | void ControllerBase::ActivateController() { | 12 | void ControllerBase::ActivateController() { |
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index f47a9e61c..1556fb08e 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h | |||
| @@ -18,7 +18,7 @@ class System; | |||
| 18 | namespace Service::HID { | 18 | namespace Service::HID { |
| 19 | class ControllerBase { | 19 | class ControllerBase { |
| 20 | public: | 20 | public: |
| 21 | explicit ControllerBase(Core::System& system); | 21 | explicit ControllerBase(Core::System& system_); |
| 22 | virtual ~ControllerBase(); | 22 | virtual ~ControllerBase(); |
| 23 | 23 | ||
| 24 | // Called when the controller is initialized | 24 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index a460f2f79..d439b8fb0 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp | |||
| @@ -14,7 +14,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | |||
| 14 | [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; | 14 | [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; |
| 15 | enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; | 15 | enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; |
| 16 | 16 | ||
| 17 | Controller_DebugPad::Controller_DebugPad(Core::System& system) : ControllerBase(system) {} | 17 | Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {} |
| 18 | Controller_DebugPad::~Controller_DebugPad() = default; | 18 | Controller_DebugPad::~Controller_DebugPad() = default; |
| 19 | 19 | ||
| 20 | void Controller_DebugPad::OnInit() {} | 20 | void Controller_DebugPad::OnInit() {} |
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 0593d7d39..1b1645184 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | namespace Service::HID { | 16 | namespace Service::HID { |
| 17 | class Controller_DebugPad final : public ControllerBase { | 17 | class Controller_DebugPad final : public ControllerBase { |
| 18 | public: | 18 | public: |
| 19 | explicit Controller_DebugPad(Core::System& system); | 19 | explicit Controller_DebugPad(Core::System& system_); |
| 20 | ~Controller_DebugPad() override; | 20 | ~Controller_DebugPad() override; |
| 21 | 21 | ||
| 22 | // Called when the controller is initialized | 22 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 155808f6a..d311f754b 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/math_util.h" | ||
| 8 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 9 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 10 | #include "core/frontend/emu_window.h" | 9 | #include "core/frontend/emu_window.h" |
| @@ -12,10 +11,19 @@ | |||
| 12 | 11 | ||
| 13 | namespace Service::HID { | 12 | namespace Service::HID { |
| 14 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; | 13 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; |
| 15 | constexpr f32 angle_threshold = 0.08f; | ||
| 16 | constexpr f32 pinch_threshold = 100.0f; | ||
| 17 | 14 | ||
| 18 | Controller_Gesture::Controller_Gesture(Core::System& system) : ControllerBase(system) {} | 15 | // HW is around 700, value is set to 400 to make it easier to trigger with mouse |
| 16 | constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s | ||
| 17 | constexpr f32 angle_threshold = 0.015f; // Threshold in radians | ||
| 18 | constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels | ||
| 19 | constexpr f32 press_delay = 0.5f; // Time in seconds | ||
| 20 | constexpr f32 double_tap_delay = 0.35f; // Time in seconds | ||
| 21 | |||
| 22 | constexpr f32 Square(s32 num) { | ||
| 23 | return static_cast<f32>(num * num); | ||
| 24 | } | ||
| 25 | |||
| 26 | Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {} | ||
| 19 | Controller_Gesture::~Controller_Gesture() = default; | 27 | Controller_Gesture::~Controller_Gesture() = default; |
| 20 | 28 | ||
| 21 | void Controller_Gesture::OnInit() { | 29 | void Controller_Gesture::OnInit() { |
| @@ -24,6 +32,8 @@ void Controller_Gesture::OnInit() { | |||
| 24 | keyboard_finger_id[id] = MAX_POINTS; | 32 | keyboard_finger_id[id] = MAX_POINTS; |
| 25 | udp_finger_id[id] = MAX_POINTS; | 33 | udp_finger_id[id] = MAX_POINTS; |
| 26 | } | 34 | } |
| 35 | shared_memory.header.entry_count = 0; | ||
| 36 | force_update = true; | ||
| 27 | } | 37 | } |
| 28 | 38 | ||
| 29 | void Controller_Gesture::OnRelease() {} | 39 | void Controller_Gesture::OnRelease() {} |
| @@ -38,17 +48,23 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 38 | shared_memory.header.last_entry_index = 0; | 48 | shared_memory.header.last_entry_index = 0; |
| 39 | return; | 49 | return; |
| 40 | } | 50 | } |
| 41 | shared_memory.header.entry_count = 16; | ||
| 42 | 51 | ||
| 43 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 52 | ReadTouchInput(); |
| 44 | shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; | ||
| 45 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 46 | 53 | ||
| 47 | cur_entry.sampling_number = last_entry.sampling_number + 1; | 54 | GestureProperties gesture = GetGestureProperties(); |
| 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 55 | f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) / |
| 56 | (1000 * 1000 * 1000); | ||
| 49 | 57 | ||
| 50 | // TODO(german77): Implement all gesture types | 58 | // Only update if necesary |
| 59 | if (!ShouldUpdateGesture(gesture, time_difference)) { | ||
| 60 | return; | ||
| 61 | } | ||
| 51 | 62 | ||
| 63 | last_update_timestamp = shared_memory.header.timestamp; | ||
| 64 | UpdateGestureSharedMemory(data, size, gesture, time_difference); | ||
| 65 | } | ||
| 66 | |||
| 67 | void Controller_Gesture::ReadTouchInput() { | ||
| 52 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); | 68 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); |
| 53 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); | 69 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); |
| 54 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { | 70 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { |
| @@ -63,50 +79,71 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 63 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); | 79 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); |
| 64 | } | 80 | } |
| 65 | } | 81 | } |
| 82 | } | ||
| 66 | 83 | ||
| 67 | TouchType type = TouchType::Idle; | 84 | bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, |
| 68 | Attribute attributes{}; | 85 | f32 time_difference) { |
| 69 | GestureProperties gesture = GetGestureProperties(); | 86 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 70 | if (last_gesture.active_points != gesture.active_points) { | 87 | if (force_update) { |
| 71 | ++last_gesture.detection_count; | 88 | force_update = false; |
| 89 | return true; | ||
| 72 | } | 90 | } |
| 73 | if (gesture.active_points > 0) { | ||
| 74 | if (last_gesture.active_points == 0) { | ||
| 75 | attributes.is_new_touch.Assign(true); | ||
| 76 | last_gesture.average_distance = gesture.average_distance; | ||
| 77 | last_gesture.angle = gesture.angle; | ||
| 78 | } | ||
| 79 | 91 | ||
| 80 | type = TouchType::Touch; | 92 | // Update if coordinates change |
| 81 | if (gesture.mid_point.x != last_entry.x || gesture.mid_point.y != last_entry.y) { | 93 | for (size_t id = 0; id < MAX_POINTS; id++) { |
| 82 | type = TouchType::Pan; | 94 | if (gesture.points[id].x != last_gesture.points[id].x || |
| 83 | } | 95 | gesture.points[id].y != last_gesture.points[id].y) { |
| 84 | if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) { | 96 | return true; |
| 85 | type = TouchType::Pinch; | ||
| 86 | } | ||
| 87 | if (std::abs(gesture.angle - last_gesture.angle) > angle_threshold) { | ||
| 88 | type = TouchType::Rotate; | ||
| 89 | } | 97 | } |
| 98 | } | ||
| 90 | 99 | ||
| 91 | cur_entry.delta_x = gesture.mid_point.x - last_entry.x; | 100 | // Update on press and hold event after 0.5 seconds |
| 92 | cur_entry.delta_y = gesture.mid_point.y - last_entry.y; | 101 | if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 && |
| 93 | // TODO: Find how velocities are calculated | 102 | time_difference > press_delay) { |
| 94 | cur_entry.vel_x = static_cast<float>(cur_entry.delta_x) * 150.1f; | 103 | return enable_press_and_tap; |
| 95 | cur_entry.vel_y = static_cast<float>(cur_entry.delta_y) * 150.1f; | 104 | } |
| 96 | 105 | ||
| 97 | // Slowdown the rate of change for less flapping | 106 | return false; |
| 98 | last_gesture.average_distance = | 107 | } |
| 99 | (last_gesture.average_distance * 0.9f) + (gesture.average_distance * 0.1f); | ||
| 100 | last_gesture.angle = (last_gesture.angle * 0.9f) + (gesture.angle * 0.1f); | ||
| 101 | 108 | ||
| 109 | void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, | ||
| 110 | GestureProperties& gesture, | ||
| 111 | f32 time_difference) { | ||
| 112 | TouchType type = TouchType::Idle; | ||
| 113 | Attribute attributes{}; | ||
| 114 | |||
| 115 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 116 | shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; | ||
| 117 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 118 | |||
| 119 | if (shared_memory.header.entry_count < 16) { | ||
| 120 | shared_memory.header.entry_count++; | ||
| 121 | } | ||
| 122 | |||
| 123 | cur_entry.sampling_number = last_entry.sampling_number + 1; | ||
| 124 | cur_entry.sampling_number2 = cur_entry.sampling_number; | ||
| 125 | |||
| 126 | // Reset values to default | ||
| 127 | cur_entry.delta_x = 0; | ||
| 128 | cur_entry.delta_y = 0; | ||
| 129 | cur_entry.vel_x = 0; | ||
| 130 | cur_entry.vel_y = 0; | ||
| 131 | cur_entry.direction = Direction::None; | ||
| 132 | cur_entry.rotation_angle = 0; | ||
| 133 | cur_entry.scale = 0; | ||
| 134 | |||
| 135 | if (gesture.active_points > 0) { | ||
| 136 | if (last_gesture.active_points == 0) { | ||
| 137 | NewGesture(gesture, type, attributes); | ||
| 138 | } else { | ||
| 139 | UpdateExistingGesture(gesture, type, time_difference); | ||
| 140 | } | ||
| 102 | } else { | 141 | } else { |
| 103 | cur_entry.delta_x = 0; | 142 | EndGesture(gesture, last_gesture, type, attributes, time_difference); |
| 104 | cur_entry.delta_y = 0; | ||
| 105 | cur_entry.vel_x = 0; | ||
| 106 | cur_entry.vel_y = 0; | ||
| 107 | } | 143 | } |
| 108 | last_gesture.active_points = gesture.active_points; | 144 | |
| 109 | cur_entry.detection_count = last_gesture.detection_count; | 145 | // Apply attributes |
| 146 | cur_entry.detection_count = gesture.detection_count; | ||
| 110 | cur_entry.type = type; | 147 | cur_entry.type = type; |
| 111 | cur_entry.attributes = attributes; | 148 | cur_entry.attributes = attributes; |
| 112 | cur_entry.x = gesture.mid_point.x; | 149 | cur_entry.x = gesture.mid_point.x; |
| @@ -116,12 +153,195 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 116 | cur_entry.points[id].x = gesture.points[id].x; | 153 | cur_entry.points[id].x = gesture.points[id].x; |
| 117 | cur_entry.points[id].y = gesture.points[id].y; | 154 | cur_entry.points[id].y = gesture.points[id].y; |
| 118 | } | 155 | } |
| 119 | cur_entry.rotation_angle = 0; | 156 | last_gesture = gesture; |
| 120 | cur_entry.scale = 0; | ||
| 121 | 157 | ||
| 122 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); | 158 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); |
| 123 | } | 159 | } |
| 124 | 160 | ||
| 161 | void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, | ||
| 162 | Attribute& attributes) { | ||
| 163 | const auto& last_entry = | ||
| 164 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 165 | gesture.detection_count++; | ||
| 166 | type = TouchType::Touch; | ||
| 167 | |||
| 168 | // New touch after cancel is not considered new | ||
| 169 | if (last_entry.type != TouchType::Cancel) { | ||
| 170 | attributes.is_new_touch.Assign(1); | ||
| 171 | enable_press_and_tap = true; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, | ||
| 176 | f32 time_difference) { | ||
| 177 | const auto& last_entry = | ||
| 178 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 179 | |||
| 180 | // Promote to pan type if touch moved | ||
| 181 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 182 | if (gesture.points[id].x != last_gesture.points[id].x || | ||
| 183 | gesture.points[id].y != last_gesture.points[id].y) { | ||
| 184 | type = TouchType::Pan; | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | // Number of fingers changed cancel the last event and clear data | ||
| 190 | if (gesture.active_points != last_gesture.active_points) { | ||
| 191 | type = TouchType::Cancel; | ||
| 192 | enable_press_and_tap = false; | ||
| 193 | gesture.active_points = 0; | ||
| 194 | gesture.mid_point = {}; | ||
| 195 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 196 | gesture.points[id].x = 0; | ||
| 197 | gesture.points[id].y = 0; | ||
| 198 | } | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | |||
| 202 | // Calculate extra parameters of panning | ||
| 203 | if (type == TouchType::Pan) { | ||
| 204 | UpdatePanEvent(gesture, last_gesture, type, time_difference); | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | // Promote to press type | ||
| 209 | if (last_entry.type == TouchType::Touch) { | ||
| 210 | type = TouchType::Press; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | void Controller_Gesture::EndGesture(GestureProperties& gesture, | ||
| 215 | GestureProperties& last_gesture_props, TouchType& type, | ||
| 216 | Attribute& attributes, f32 time_difference) { | ||
| 217 | const auto& last_entry = | ||
| 218 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 219 | if (last_gesture_props.active_points != 0) { | ||
| 220 | switch (last_entry.type) { | ||
| 221 | case TouchType::Touch: | ||
| 222 | if (enable_press_and_tap) { | ||
| 223 | SetTapEvent(gesture, last_gesture_props, type, attributes); | ||
| 224 | return; | ||
| 225 | } | ||
| 226 | type = TouchType::Cancel; | ||
| 227 | force_update = true; | ||
| 228 | break; | ||
| 229 | case TouchType::Press: | ||
| 230 | case TouchType::Tap: | ||
| 231 | case TouchType::Swipe: | ||
| 232 | case TouchType::Pinch: | ||
| 233 | case TouchType::Rotate: | ||
| 234 | type = TouchType::Complete; | ||
| 235 | force_update = true; | ||
| 236 | break; | ||
| 237 | case TouchType::Pan: | ||
| 238 | EndPanEvent(gesture, last_gesture_props, type, time_difference); | ||
| 239 | break; | ||
| 240 | default: | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | return; | ||
| 244 | } | ||
| 245 | if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) { | ||
| 246 | gesture.detection_count++; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | void Controller_Gesture::SetTapEvent(GestureProperties& gesture, | ||
| 251 | GestureProperties& last_gesture_props, TouchType& type, | ||
| 252 | Attribute& attributes) { | ||
| 253 | type = TouchType::Tap; | ||
| 254 | gesture = last_gesture_props; | ||
| 255 | force_update = true; | ||
| 256 | f32 tap_time_difference = | ||
| 257 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | ||
| 258 | last_tap_timestamp = last_update_timestamp; | ||
| 259 | if (tap_time_difference < double_tap_delay) { | ||
| 260 | attributes.is_double_tap.Assign(1); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, | ||
| 265 | GestureProperties& last_gesture_props, TouchType& type, | ||
| 266 | f32 time_difference) { | ||
| 267 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 268 | const auto& last_entry = | ||
| 269 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 270 | cur_entry.delta_x = gesture.mid_point.x - last_entry.x; | ||
| 271 | cur_entry.delta_y = gesture.mid_point.y - last_entry.y; | ||
| 272 | |||
| 273 | cur_entry.vel_x = static_cast<f32>(cur_entry.delta_x) / time_difference; | ||
| 274 | cur_entry.vel_y = static_cast<f32>(cur_entry.delta_y) / time_difference; | ||
| 275 | last_pan_time_difference = time_difference; | ||
| 276 | |||
| 277 | // Promote to pinch type | ||
| 278 | if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > | ||
| 279 | pinch_threshold) { | ||
| 280 | type = TouchType::Pinch; | ||
| 281 | cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; | ||
| 282 | } | ||
| 283 | |||
| 284 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / | ||
| 285 | (1 + (gesture.angle * last_gesture_props.angle))); | ||
| 286 | // Promote to rotate type | ||
| 287 | if (std::abs(angle_between_two_lines) > angle_threshold) { | ||
| 288 | type = TouchType::Rotate; | ||
| 289 | cur_entry.scale = 0; | ||
| 290 | cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | void Controller_Gesture::EndPanEvent(GestureProperties& gesture, | ||
| 295 | GestureProperties& last_gesture_props, TouchType& type, | ||
| 296 | f32 time_difference) { | ||
| 297 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 298 | const auto& last_entry = | ||
| 299 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 300 | cur_entry.vel_x = | ||
| 301 | static_cast<f32>(last_entry.delta_x) / (last_pan_time_difference + time_difference); | ||
| 302 | cur_entry.vel_y = | ||
| 303 | static_cast<f32>(last_entry.delta_y) / (last_pan_time_difference + time_difference); | ||
| 304 | const f32 curr_vel = | ||
| 305 | std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); | ||
| 306 | |||
| 307 | // Set swipe event with parameters | ||
| 308 | if (curr_vel > swipe_threshold) { | ||
| 309 | SetSwipeEvent(gesture, last_gesture_props, type); | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | |||
| 313 | // End panning without swipe | ||
| 314 | type = TouchType::Complete; | ||
| 315 | cur_entry.vel_x = 0; | ||
| 316 | cur_entry.vel_y = 0; | ||
| 317 | force_update = true; | ||
| 318 | } | ||
| 319 | |||
| 320 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, | ||
| 321 | GestureProperties& last_gesture_props, TouchType& type) { | ||
| 322 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 323 | const auto& last_entry = | ||
| 324 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 325 | type = TouchType::Swipe; | ||
| 326 | gesture = last_gesture_props; | ||
| 327 | force_update = true; | ||
| 328 | cur_entry.delta_x = last_entry.delta_x; | ||
| 329 | cur_entry.delta_y = last_entry.delta_y; | ||
| 330 | if (std::abs(cur_entry.delta_x) > std::abs(cur_entry.delta_y)) { | ||
| 331 | if (cur_entry.delta_x > 0) { | ||
| 332 | cur_entry.direction = Direction::Right; | ||
| 333 | return; | ||
| 334 | } | ||
| 335 | cur_entry.direction = Direction::Left; | ||
| 336 | return; | ||
| 337 | } | ||
| 338 | if (cur_entry.delta_y > 0) { | ||
| 339 | cur_entry.direction = Direction::Down; | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | cur_entry.direction = Direction::Up; | ||
| 343 | } | ||
| 344 | |||
| 125 | void Controller_Gesture::OnLoadInputDevices() { | 345 | void Controller_Gesture::OnLoadInputDevices() { |
| 126 | touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); | 346 | touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); |
| 127 | touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); | 347 | touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); |
| @@ -129,6 +349,10 @@ void Controller_Gesture::OnLoadInputDevices() { | |||
| 129 | } | 349 | } |
| 130 | 350 | ||
| 131 | std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const { | 351 | std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const { |
| 352 | // Dont assign any touch input to a point if disabled | ||
| 353 | if (!Settings::values.touchscreen.enabled) { | ||
| 354 | return std::nullopt; | ||
| 355 | } | ||
| 132 | std::size_t first_free_id = 0; | 356 | std::size_t first_free_id = 0; |
| 133 | while (first_free_id < MAX_POINTS) { | 357 | while (first_free_id < MAX_POINTS) { |
| 134 | if (!fingers[first_free_id].pressed) { | 358 | if (!fingers[first_free_id].pressed) { |
| @@ -179,23 +403,33 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() | |||
| 179 | 403 | ||
| 180 | for (size_t id = 0; id < gesture.active_points; ++id) { | 404 | for (size_t id = 0; id < gesture.active_points; ++id) { |
| 181 | gesture.points[id].x = | 405 | gesture.points[id].x = |
| 182 | static_cast<int>(active_fingers[id].x * Layout::ScreenUndocked::Width); | 406 | static_cast<s32>(active_fingers[id].x * Layout::ScreenUndocked::Width); |
| 183 | gesture.points[id].y = | 407 | gesture.points[id].y = |
| 184 | static_cast<int>(active_fingers[id].y * Layout::ScreenUndocked::Height); | 408 | static_cast<s32>(active_fingers[id].y * Layout::ScreenUndocked::Height); |
| 185 | gesture.mid_point.x += static_cast<int>(gesture.points[id].x / gesture.active_points); | 409 | |
| 186 | gesture.mid_point.y += static_cast<int>(gesture.points[id].y / gesture.active_points); | 410 | // Hack: There is no touch in docked but games still allow it |
| 411 | if (Settings::values.use_docked_mode.GetValue()) { | ||
| 412 | gesture.points[id].x = | ||
| 413 | static_cast<s32>(active_fingers[id].x * Layout::ScreenDocked::Width); | ||
| 414 | gesture.points[id].y = | ||
| 415 | static_cast<s32>(active_fingers[id].y * Layout::ScreenDocked::Height); | ||
| 416 | } | ||
| 417 | |||
| 418 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | ||
| 419 | gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); | ||
| 187 | } | 420 | } |
| 188 | 421 | ||
| 189 | for (size_t id = 0; id < gesture.active_points; ++id) { | 422 | for (size_t id = 0; id < gesture.active_points; ++id) { |
| 190 | const double distance = | 423 | const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + |
| 191 | std::pow(static_cast<float>(gesture.mid_point.x - gesture.points[id].x), 2) + | 424 | Square(gesture.mid_point.y - gesture.points[id].y)); |
| 192 | std::pow(static_cast<float>(gesture.mid_point.y - gesture.points[id].y), 2); | 425 | gesture.average_distance += distance / static_cast<f32>(gesture.active_points); |
| 193 | gesture.average_distance += | ||
| 194 | static_cast<float>(distance) / static_cast<float>(gesture.active_points); | ||
| 195 | } | 426 | } |
| 196 | 427 | ||
| 197 | gesture.angle = std::atan2(static_cast<float>(gesture.mid_point.y - gesture.points[0].y), | 428 | gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), |
| 198 | static_cast<float>(gesture.mid_point.x - gesture.points[0].x)); | 429 | static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); |
| 430 | |||
| 431 | gesture.detection_count = last_gesture.detection_count; | ||
| 432 | |||
| 199 | return gesture; | 433 | return gesture; |
| 200 | } | 434 | } |
| 201 | 435 | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 60ecc7822..f46e29411 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -7,14 +7,13 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/swap.h" | ||
| 11 | #include "core/frontend/input.h" | 10 | #include "core/frontend/input.h" |
| 12 | #include "core/hle/service/hid/controllers/controller_base.h" | 11 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 13 | 12 | ||
| 14 | namespace Service::HID { | 13 | namespace Service::HID { |
| 15 | class Controller_Gesture final : public ControllerBase { | 14 | class Controller_Gesture final : public ControllerBase { |
| 16 | public: | 15 | public: |
| 17 | explicit Controller_Gesture(Core::System& system); | 16 | explicit Controller_Gesture(Core::System& system_); |
| 18 | ~Controller_Gesture() override; | 17 | ~Controller_Gesture() override; |
| 19 | 18 | ||
| 20 | // Called when the controller is initialized | 19 | // Called when the controller is initialized |
| @@ -35,10 +34,10 @@ private: | |||
| 35 | 34 | ||
| 36 | enum class TouchType : u32 { | 35 | enum class TouchType : u32 { |
| 37 | Idle, // Nothing touching the screen | 36 | Idle, // Nothing touching the screen |
| 38 | Complete, // Unknown. End of touch? | 37 | Complete, // Set at the end of a touch event |
| 39 | Cancel, // Never triggered | 38 | Cancel, // Set when the number of fingers change |
| 40 | Touch, // Pressing without movement | 39 | Touch, // A finger just touched the screen |
| 41 | Press, // Never triggered | 40 | Press, // Set if last type is touch and the finger hasn't moved |
| 42 | Tap, // Fast press then release | 41 | Tap, // Fast press then release |
| 43 | Pan, // All points moving together across the screen | 42 | Pan, // All points moving together across the screen |
| 44 | Swipe, // Fast press movement and release of a single point | 43 | Swipe, // Fast press movement and release of a single point |
| @@ -58,8 +57,8 @@ private: | |||
| 58 | union { | 57 | union { |
| 59 | u32_le raw{}; | 58 | u32_le raw{}; |
| 60 | 59 | ||
| 61 | BitField<0, 1, u32> is_new_touch; | 60 | BitField<4, 1, u32> is_new_touch; |
| 62 | BitField<1, 1, u32> is_double_tap; | 61 | BitField<8, 1, u32> is_double_tap; |
| 63 | }; | 62 | }; |
| 64 | }; | 63 | }; |
| 65 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); | 64 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); |
| @@ -73,10 +72,9 @@ private: | |||
| 73 | struct GestureState { | 72 | struct GestureState { |
| 74 | s64_le sampling_number; | 73 | s64_le sampling_number; |
| 75 | s64_le sampling_number2; | 74 | s64_le sampling_number2; |
| 76 | |||
| 77 | s64_le detection_count; | 75 | s64_le detection_count; |
| 78 | TouchType type; | 76 | TouchType type; |
| 79 | Direction dir; | 77 | Direction direction; |
| 80 | s32_le x; | 78 | s32_le x; |
| 81 | s32_le y; | 79 | s32_le y; |
| 82 | s32_le delta_x; | 80 | s32_le delta_x; |
| @@ -84,8 +82,8 @@ private: | |||
| 84 | f32 vel_x; | 82 | f32 vel_x; |
| 85 | f32 vel_y; | 83 | f32 vel_y; |
| 86 | Attribute attributes; | 84 | Attribute attributes; |
| 87 | u32 scale; | 85 | f32 scale; |
| 88 | u32 rotation_angle; | 86 | f32 rotation_angle; |
| 89 | s32_le point_count; | 87 | s32_le point_count; |
| 90 | std::array<Points, 4> points; | 88 | std::array<Points, 4> points; |
| 91 | }; | 89 | }; |
| @@ -109,17 +107,55 @@ private: | |||
| 109 | Points mid_point{}; | 107 | Points mid_point{}; |
| 110 | s64_le detection_count{}; | 108 | s64_le detection_count{}; |
| 111 | u64_le delta_time{}; | 109 | u64_le delta_time{}; |
| 112 | float average_distance{}; | 110 | f32 average_distance{}; |
| 113 | float angle{}; | 111 | f32 angle{}; |
| 114 | }; | 112 | }; |
| 115 | 113 | ||
| 116 | // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned | 114 | // Reads input from all available input engines |
| 115 | void ReadTouchInput(); | ||
| 116 | |||
| 117 | // Returns true if gesture state needs to be updated | ||
| 118 | bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference); | ||
| 119 | |||
| 120 | // Updates the shared memory to the next state | ||
| 121 | void UpdateGestureSharedMemory(u8* data, std::size_t size, GestureProperties& gesture, | ||
| 122 | f32 time_difference); | ||
| 123 | |||
| 124 | // Initializes new gesture | ||
| 125 | void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes); | ||
| 126 | |||
| 127 | // Updates existing gesture state | ||
| 128 | void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); | ||
| 129 | |||
| 130 | // Terminates exiting gesture | ||
| 131 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 132 | TouchType& type, Attribute& attributes, f32 time_difference); | ||
| 133 | |||
| 134 | // Set current event to a tap event | ||
| 135 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 136 | TouchType& type, Attribute& attributes); | ||
| 137 | |||
| 138 | // Calculates and set the extra parameters related to a pan event | ||
| 139 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 140 | TouchType& type, f32 time_difference); | ||
| 141 | |||
| 142 | // Terminates the pan event | ||
| 143 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 144 | TouchType& type, f32 time_difference); | ||
| 145 | |||
| 146 | // Set current event to a swipe event | ||
| 147 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 148 | TouchType& type); | ||
| 149 | |||
| 150 | // Returns an unused finger id, if there is no fingers available std::nullopt is returned. | ||
| 117 | std::optional<size_t> GetUnusedFingerID() const; | 151 | std::optional<size_t> GetUnusedFingerID() const; |
| 118 | 152 | ||
| 119 | /** If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no | 153 | /** |
| 154 | * If the touch is new it tries to assign a new finger id, if there is no fingers available no | ||
| 120 | * changes will be made. Updates the coordinates if the finger id it's already set. If the touch | 155 | * changes will be made. Updates the coordinates if the finger id it's already set. If the touch |
| 121 | * ends delays the output by one frame to set the end_touch flag before finally freeing the | 156 | * ends delays the output by one frame to set the end_touch flag before finally freeing the |
| 122 | * finger id */ | 157 | * finger id |
| 158 | */ | ||
| 123 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, | 159 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, |
| 124 | size_t finger_id); | 160 | size_t finger_id); |
| 125 | 161 | ||
| @@ -134,6 +170,11 @@ private: | |||
| 134 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; | 170 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; |
| 135 | std::array<size_t, MAX_FINGERS> udp_finger_id; | 171 | std::array<size_t, MAX_FINGERS> udp_finger_id; |
| 136 | std::array<Finger, MAX_POINTS> fingers; | 172 | std::array<Finger, MAX_POINTS> fingers; |
| 137 | GestureProperties last_gesture; | 173 | GestureProperties last_gesture{}; |
| 174 | s64_le last_update_timestamp{}; | ||
| 175 | s64_le last_tap_timestamp{}; | ||
| 176 | f32 last_pan_time_difference{}; | ||
| 177 | bool force_update{false}; | ||
| 178 | bool enable_press_and_tap{false}; | ||
| 138 | }; | 179 | }; |
| 139 | } // namespace Service::HID | 180 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 18b76038f..c6c620008 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp | |||
| @@ -12,7 +12,7 @@ namespace Service::HID { | |||
| 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; | 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; |
| 13 | constexpr u8 KEYS_PER_BYTE = 8; | 13 | constexpr u8 KEYS_PER_BYTE = 8; |
| 14 | 14 | ||
| 15 | Controller_Keyboard::Controller_Keyboard(Core::System& system) : ControllerBase(system) {} | 15 | Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {} |
| 16 | Controller_Keyboard::~Controller_Keyboard() = default; | 16 | Controller_Keyboard::~Controller_Keyboard() = default; |
| 17 | 17 | ||
| 18 | void Controller_Keyboard::OnInit() {} | 18 | void Controller_Keyboard::OnInit() {} |
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index e72948591..172a80e9c 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | namespace Service::HID { | 16 | namespace Service::HID { |
| 17 | class Controller_Keyboard final : public ControllerBase { | 17 | class Controller_Keyboard final : public ControllerBase { |
| 18 | public: | 18 | public: |
| 19 | explicit Controller_Keyboard(Core::System& system); | 19 | explicit Controller_Keyboard(Core::System& system_); |
| 20 | ~Controller_Keyboard() override; | 20 | ~Controller_Keyboard() override; |
| 21 | 21 | ||
| 22 | // Called when the controller is initialized | 22 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 2e7457604..544a71948 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | namespace Service::HID { | 11 | namespace Service::HID { |
| 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; | 12 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; |
| 13 | 13 | ||
| 14 | Controller_Mouse::Controller_Mouse(Core::System& system) : ControllerBase(system) {} | 14 | Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {} |
| 15 | Controller_Mouse::~Controller_Mouse() = default; | 15 | Controller_Mouse::~Controller_Mouse() = default; |
| 16 | 16 | ||
| 17 | void Controller_Mouse::OnInit() {} | 17 | void Controller_Mouse::OnInit() {} |
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 0ec0c2b94..3d391a798 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | class Controller_Mouse final : public ControllerBase { | 16 | class Controller_Mouse final : public ControllerBase { |
| 17 | public: | 17 | public: |
| 18 | explicit Controller_Mouse(Core::System& system); | 18 | explicit Controller_Mouse(Core::System& system_); |
| 19 | ~Controller_Mouse() override; | 19 | ~Controller_Mouse() override; |
| 20 | 20 | ||
| 21 | // Called when the controller is initialized | 21 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 113a41254..7acad3798 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -147,7 +147,7 @@ bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { | |||
| 147 | device_handle.device_index < DeviceIndex::MaxDeviceIndex; | 147 | device_handle.device_index < DeviceIndex::MaxDeviceIndex; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system) { | 150 | Controller_NPad::Controller_NPad(Core::System& system_) : ControllerBase{system_} { |
| 151 | latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}); | 151 | latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| @@ -159,7 +159,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 159 | const auto controller_type = connected_controllers[controller_idx].type; | 159 | const auto controller_type = connected_controllers[controller_idx].type; |
| 160 | auto& controller = shared_memory_entries[controller_idx]; | 160 | auto& controller = shared_memory_entries[controller_idx]; |
| 161 | if (controller_type == NPadControllerType::None) { | 161 | if (controller_type == NPadControllerType::None) { |
| 162 | styleset_changed_events[controller_idx]->GetWritableEvent()->Signal(); | 162 | styleset_changed_events[controller_idx]->GetWritableEvent().Signal(); |
| 163 | return; | 163 | return; |
| 164 | } | 164 | } |
| 165 | controller.style_set.raw = 0; // Zero out | 165 | controller.style_set.raw = 0; // Zero out |
| @@ -253,9 +253,8 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 253 | void Controller_NPad::OnInit() { | 253 | void Controller_NPad::OnInit() { |
| 254 | auto& kernel = system.Kernel(); | 254 | auto& kernel = system.Kernel(); |
| 255 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { | 255 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { |
| 256 | styleset_changed_events[i] = | 256 | styleset_changed_events[i] = Kernel::KEvent::Create(kernel); |
| 257 | Kernel::KEvent::Create(kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); | 257 | styleset_changed_events[i]->Initialize(fmt::format("npad:NpadStyleSetChanged_{}", i)); |
| 258 | styleset_changed_events[i]->Initialize(); | ||
| 259 | } | 258 | } |
| 260 | 259 | ||
| 261 | if (!IsControllerActivated()) { | 260 | if (!IsControllerActivated()) { |
| @@ -341,6 +340,11 @@ void Controller_NPad::OnRelease() { | |||
| 341 | VibrateControllerAtIndex(npad_idx, device_idx, {}); | 340 | VibrateControllerAtIndex(npad_idx, device_idx, {}); |
| 342 | } | 341 | } |
| 343 | } | 342 | } |
| 343 | |||
| 344 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { | ||
| 345 | styleset_changed_events[i]->Close(); | ||
| 346 | styleset_changed_events[i] = nullptr; | ||
| 347 | } | ||
| 344 | } | 348 | } |
| 345 | 349 | ||
| 346 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | 350 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { |
| @@ -654,8 +658,8 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 654 | const auto& device = motions[i][e]; | 658 | const auto& device = motions[i][e]; |
| 655 | if (device) { | 659 | if (device) { |
| 656 | std::tie(motion_devices[e].accel, motion_devices[e].gyro, | 660 | std::tie(motion_devices[e].accel, motion_devices[e].gyro, |
| 657 | motion_devices[e].rotation, motion_devices[e].orientation) = | 661 | motion_devices[e].rotation, motion_devices[e].orientation, |
| 658 | device->GetStatus(); | 662 | motion_devices[e].quaternion) = device->GetStatus(); |
| 659 | sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f; | 663 | sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f; |
| 660 | } | 664 | } |
| 661 | } | 665 | } |
| @@ -955,14 +959,12 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev | |||
| 955 | return vibration_devices_mounted[npad_index][device_index]; | 959 | return vibration_devices_mounted[npad_index][device_index]; |
| 956 | } | 960 | } |
| 957 | 961 | ||
| 958 | std::shared_ptr<Kernel::KReadableEvent> Controller_NPad::GetStyleSetChangedEvent( | 962 | Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { |
| 959 | u32 npad_id) const { | 963 | return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent(); |
| 960 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; | ||
| 961 | return styleset_event->GetReadableEvent(); | ||
| 962 | } | 964 | } |
| 963 | 965 | ||
| 964 | void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { | 966 | void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { |
| 965 | styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent()->Signal(); | 967 | styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal(); |
| 966 | } | 968 | } |
| 967 | 969 | ||
| 968 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { | 970 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index c3b07bd41..c050c9a44 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -8,9 +8,9 @@ | |||
| 8 | #include <atomic> | 8 | #include <atomic> |
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/quaternion.h" | ||
| 11 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 12 | #include "core/frontend/input.h" | 13 | #include "core/frontend/input.h" |
| 13 | #include "core/hle/kernel/object.h" | ||
| 14 | #include "core/hle/service/hid/controllers/controller_base.h" | 14 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| @@ -25,7 +25,7 @@ constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this? | |||
| 25 | 25 | ||
| 26 | class Controller_NPad final : public ControllerBase { | 26 | class Controller_NPad final : public ControllerBase { |
| 27 | public: | 27 | public: |
| 28 | explicit Controller_NPad(Core::System& system); | 28 | explicit Controller_NPad(Core::System& system_); |
| 29 | ~Controller_NPad() override; | 29 | ~Controller_NPad() override; |
| 30 | 30 | ||
| 31 | // Called when the controller is initialized | 31 | // Called when the controller is initialized |
| @@ -198,7 +198,7 @@ public: | |||
| 198 | 198 | ||
| 199 | bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; | 199 | bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; |
| 200 | 200 | ||
| 201 | std::shared_ptr<Kernel::KReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 201 | Kernel::KReadableEvent& GetStyleSetChangedEvent(u32 npad_id); |
| 202 | void SignalStyleSetChangedEvent(u32 npad_id) const; | 202 | void SignalStyleSetChangedEvent(u32 npad_id) const; |
| 203 | 203 | ||
| 204 | // Adds a new controller at an index. | 204 | // Adds a new controller at an index. |
| @@ -467,6 +467,7 @@ private: | |||
| 467 | Common::Vec3f gyro; | 467 | Common::Vec3f gyro; |
| 468 | Common::Vec3f rotation; | 468 | Common::Vec3f rotation; |
| 469 | std::array<Common::Vec3f, 3> orientation; | 469 | std::array<Common::Vec3f, 3> orientation; |
| 470 | Common::Quaternion<f32> quaternion; | ||
| 470 | }; | 471 | }; |
| 471 | 472 | ||
| 472 | struct NfcXcdHandle { | 473 | struct NfcXcdHandle { |
| @@ -571,8 +572,9 @@ private: | |||
| 571 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 572 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 572 | NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; | 573 | NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; |
| 573 | // Each controller should have their own styleset changed event | 574 | // Each controller should have their own styleset changed event |
| 574 | std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events; | 575 | std::array<Kernel::KEvent*, 10> styleset_changed_events{}; |
| 575 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; | 576 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> |
| 577 | last_vibration_timepoints{}; | ||
| 576 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | 578 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; |
| 577 | bool permit_vibration_session_enabled{false}; | 579 | bool permit_vibration_session_enabled{false}; |
| 578 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | 580 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; |
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index e7483bfa2..772c20453 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | namespace Service::HID { | 10 | namespace Service::HID { |
| 11 | 11 | ||
| 12 | Controller_Stubbed::Controller_Stubbed(Core::System& system) : ControllerBase(system) {} | 12 | Controller_Stubbed::Controller_Stubbed(Core::System& system_) : ControllerBase{system_} {} |
| 13 | Controller_Stubbed::~Controller_Stubbed() = default; | 13 | Controller_Stubbed::~Controller_Stubbed() = default; |
| 14 | 14 | ||
| 15 | void Controller_Stubbed::OnInit() {} | 15 | void Controller_Stubbed::OnInit() {} |
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 4fa83ac85..21092af0d 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | namespace Service::HID { | 10 | namespace Service::HID { |
| 11 | class Controller_Stubbed final : public ControllerBase { | 11 | class Controller_Stubbed final : public ControllerBase { |
| 12 | public: | 12 | public: |
| 13 | explicit Controller_Stubbed(Core::System& system); | 13 | explicit Controller_Stubbed(Core::System& system_); |
| 14 | ~Controller_Stubbed() override; | 14 | ~Controller_Stubbed() override; |
| 15 | 15 | ||
| 16 | // Called when the controller is initialized | 16 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index b5f8077be..ac9112c40 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; | 16 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; |
| 17 | 17 | ||
| 18 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : ControllerBase(system) {} | 18 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {} |
| 19 | Controller_Touchscreen::~Controller_Touchscreen() = default; | 19 | Controller_Touchscreen::~Controller_Touchscreen() = default; |
| 20 | 20 | ||
| 21 | void Controller_Touchscreen::OnInit() { | 21 | void Controller_Touchscreen::OnInit() { |
| @@ -105,6 +105,10 @@ void Controller_Touchscreen::OnLoadInputDevices() { | |||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const { | 107 | std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const { |
| 108 | // Dont assign any touch input to a finger if disabled | ||
| 109 | if (!Settings::values.touchscreen.enabled) { | ||
| 110 | return std::nullopt; | ||
| 111 | } | ||
| 108 | std::size_t first_free_id = 0; | 112 | std::size_t first_free_id = 0; |
| 109 | while (first_free_id < MAX_FINGERS) { | 113 | while (first_free_id < MAX_FINGERS) { |
| 110 | if (!fingers[first_free_id].pressed) { | 114 | if (!fingers[first_free_id].pressed) { |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 784124e25..2869d0cfd 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | namespace Service::HID { | 14 | namespace Service::HID { |
| 15 | class Controller_Touchscreen final : public ControllerBase { | 15 | class Controller_Touchscreen final : public ControllerBase { |
| 16 | public: | 16 | public: |
| 17 | explicit Controller_Touchscreen(Core::System& system); | 17 | explicit Controller_Touchscreen(Core::System& system_); |
| 18 | ~Controller_Touchscreen() override; | 18 | ~Controller_Touchscreen() override; |
| 19 | 19 | ||
| 20 | // Called when the controller is initialized | 20 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index 2503ef241..41dc22cf9 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | namespace Service::HID { | 10 | namespace Service::HID { |
| 11 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; | 11 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; |
| 12 | 12 | ||
| 13 | Controller_XPad::Controller_XPad(Core::System& system) : ControllerBase(system) {} | 13 | Controller_XPad::Controller_XPad(Core::System& system_) : ControllerBase{system_} {} |
| 14 | Controller_XPad::~Controller_XPad() = default; | 14 | Controller_XPad::~Controller_XPad() = default; |
| 15 | 15 | ||
| 16 | void Controller_XPad::OnInit() {} | 16 | void Controller_XPad::OnInit() {} |
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index 5b59961bd..f9ab5facf 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | namespace Service::HID { | 13 | namespace Service::HID { |
| 14 | class Controller_XPad final : public ControllerBase { | 14 | class Controller_XPad final : public ControllerBase { |
| 15 | public: | 15 | public: |
| 16 | explicit Controller_XPad(Core::System& system); | 16 | explicit Controller_XPad(Core::System& system_); |
| 17 | ~Controller_XPad() override; | 17 | ~Controller_XPad() override; |
| 18 | 18 | ||
| 19 | // Called when the controller is initialized | 19 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 2aa1942cb..49c17fd14 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -13,19 +13,20 @@ | |||
| 13 | #include "core/frontend/input.h" | 13 | #include "core/frontend/input.h" |
| 14 | #include "core/hardware_properties.h" | 14 | #include "core/hardware_properties.h" |
| 15 | #include "core/hle/ipc_helpers.h" | 15 | #include "core/hle/ipc_helpers.h" |
| 16 | #include "core/hle/kernel/client_port.h" | 16 | #include "core/hle/kernel/k_client_port.h" |
| 17 | #include "core/hle/kernel/client_session.h" | ||
| 18 | #include "core/hle/kernel/k_readable_event.h" | 17 | #include "core/hle/kernel/k_readable_event.h" |
| 19 | #include "core/hle/kernel/k_shared_memory.h" | 18 | #include "core/hle/kernel/k_shared_memory.h" |
| 19 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 20 | #include "core/hle/kernel/k_writable_event.h" | 20 | #include "core/hle/kernel/k_writable_event.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 21 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/transfer_memory.h" | ||
| 23 | #include "core/hle/service/hid/errors.h" | 22 | #include "core/hle/service/hid/errors.h" |
| 24 | #include "core/hle/service/hid/hid.h" | 23 | #include "core/hle/service/hid/hid.h" |
| 25 | #include "core/hle/service/hid/irs.h" | 24 | #include "core/hle/service/hid/irs.h" |
| 26 | #include "core/hle/service/hid/xcd.h" | 25 | #include "core/hle/service/hid/xcd.h" |
| 27 | #include "core/hle/service/service.h" | 26 | #include "core/hle/service/service.h" |
| 27 | #include "core/memory.h" | ||
| 28 | 28 | ||
| 29 | #include "core/hle/service/hid/controllers/console_sixaxis.h" | ||
| 29 | #include "core/hle/service/hid/controllers/controller_base.h" | 30 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 30 | #include "core/hle/service/hid/controllers/debug_pad.h" | 31 | #include "core/hle/service/hid/controllers/debug_pad.h" |
| 31 | #include "core/hle/service/hid/controllers/gesture.h" | 32 | #include "core/hle/service/hid/controllers/gesture.h" |
| @@ -52,9 +53,6 @@ IAppletResource::IAppletResource(Core::System& system_) | |||
| 52 | }; | 53 | }; |
| 53 | RegisterHandlers(functions); | 54 | RegisterHandlers(functions); |
| 54 | 55 | ||
| 55 | auto& kernel = system.Kernel(); | ||
| 56 | shared_mem = SharedFrom(&kernel.GetHidSharedMem()); | ||
| 57 | |||
| 58 | MakeController<Controller_DebugPad>(HidController::DebugPad); | 56 | MakeController<Controller_DebugPad>(HidController::DebugPad); |
| 59 | MakeController<Controller_Touchscreen>(HidController::Touchscreen); | 57 | MakeController<Controller_Touchscreen>(HidController::Touchscreen); |
| 60 | MakeController<Controller_Mouse>(HidController::Mouse); | 58 | MakeController<Controller_Mouse>(HidController::Mouse); |
| @@ -67,7 +65,7 @@ IAppletResource::IAppletResource(Core::System& system_) | |||
| 67 | MakeController<Controller_Stubbed>(HidController::UniquePad); | 65 | MakeController<Controller_Stubbed>(HidController::UniquePad); |
| 68 | MakeController<Controller_NPad>(HidController::NPad); | 66 | MakeController<Controller_NPad>(HidController::NPad); |
| 69 | MakeController<Controller_Gesture>(HidController::Gesture); | 67 | MakeController<Controller_Gesture>(HidController::Gesture); |
| 70 | MakeController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor); | 68 | MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor); |
| 71 | 69 | ||
| 72 | // Homebrew doesn't try to activate some controllers, so we activate them by default | 70 | // Homebrew doesn't try to activate some controllers, so we activate them by default |
| 73 | GetController<Controller_NPad>(HidController::NPad).ActivateController(); | 71 | GetController<Controller_NPad>(HidController::NPad).ActivateController(); |
| @@ -78,8 +76,6 @@ IAppletResource::IAppletResource(Core::System& system_) | |||
| 78 | GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000); | 76 | GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000); |
| 79 | GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200); | 77 | GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200); |
| 80 | GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); | 78 | GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00); |
| 81 | GetController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor) | ||
| 82 | .SetCommonHeaderOffset(0x3C200); | ||
| 83 | 79 | ||
| 84 | // Register update callbacks | 80 | // Register update callbacks |
| 85 | pad_update_event = Core::Timing::CreateEvent( | 81 | pad_update_event = Core::Timing::CreateEvent( |
| @@ -119,7 +115,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 119 | 115 | ||
| 120 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 116 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 121 | rb.Push(RESULT_SUCCESS); | 117 | rb.Push(RESULT_SUCCESS); |
| 122 | rb.PushCopyObjects(shared_mem); | 118 | rb.PushCopyObjects(&system.Kernel().GetHidSharedMem()); |
| 123 | } | 119 | } |
| 124 | 120 | ||
| 125 | void IAppletResource::UpdateControllers(std::uintptr_t user_data, | 121 | void IAppletResource::UpdateControllers(std::uintptr_t user_data, |
| @@ -131,7 +127,8 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, | |||
| 131 | if (should_reload) { | 127 | if (should_reload) { |
| 132 | controller->OnLoadInputDevices(); | 128 | controller->OnLoadInputDevices(); |
| 133 | } | 129 | } |
| 134 | controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); | 130 | controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), |
| 131 | SHARED_MEMORY_SIZE); | ||
| 135 | } | 132 | } |
| 136 | 133 | ||
| 137 | // If ns_late is higher than the update rate ignore the delay | 134 | // If ns_late is higher than the update rate ignore the delay |
| @@ -146,7 +143,7 @@ void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose | |||
| 146 | auto& core_timing = system.CoreTiming(); | 143 | auto& core_timing = system.CoreTiming(); |
| 147 | 144 | ||
| 148 | controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate( | 145 | controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate( |
| 149 | core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); | 146 | core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); |
| 150 | 147 | ||
| 151 | // If ns_late is higher than the update rate ignore the delay | 148 | // If ns_late is higher than the update rate ignore the delay |
| 152 | if (ns_late > motion_update_ns) { | 149 | if (ns_late > motion_update_ns) { |
| @@ -1404,8 +1401,9 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 1404 | IPC::RequestParser rp{ctx}; | 1401 | IPC::RequestParser rp{ctx}; |
| 1405 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1402 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1406 | 1403 | ||
| 1407 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | 1404 | applet_resource->ActivateController(HidController::ConsoleSixAxisSensor); |
| 1408 | applet_resource_user_id); | 1405 | |
| 1406 | LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 1409 | 1407 | ||
| 1410 | IPC::ResponseBuilder rb{ctx, 2}; | 1408 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1411 | rb.Push(RESULT_SUCCESS); | 1409 | rb.Push(RESULT_SUCCESS); |
| @@ -1455,8 +1453,9 @@ void Hid::ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 1455 | IPC::RequestParser rp{ctx}; | 1453 | IPC::RequestParser rp{ctx}; |
| 1456 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1454 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1457 | 1455 | ||
| 1458 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | 1456 | applet_resource->ActivateController(HidController::ConsoleSixAxisSensor); |
| 1459 | applet_resource_user_id); | 1457 | |
| 1458 | LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 1460 | 1459 | ||
| 1461 | IPC::ResponseBuilder rb{ctx, 2}; | 1460 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1462 | rb.Push(RESULT_SUCCESS); | 1461 | rb.Push(RESULT_SUCCESS); |
| @@ -1495,20 +1494,20 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 1495 | ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes"); | 1494 | ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes"); |
| 1496 | ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes"); | 1495 | ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes"); |
| 1497 | 1496 | ||
| 1498 | auto t_mem_1 = | 1497 | auto t_mem_1 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( |
| 1499 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_1_handle); | 1498 | t_mem_1_handle); |
| 1500 | 1499 | ||
| 1501 | if (t_mem_1 == nullptr) { | 1500 | if (t_mem_1.IsNull()) { |
| 1502 | LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle); | 1501 | LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle); |
| 1503 | IPC::ResponseBuilder rb{ctx, 2}; | 1502 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1504 | rb.Push(RESULT_UNKNOWN); | 1503 | rb.Push(RESULT_UNKNOWN); |
| 1505 | return; | 1504 | return; |
| 1506 | } | 1505 | } |
| 1507 | 1506 | ||
| 1508 | auto t_mem_2 = | 1507 | auto t_mem_2 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( |
| 1509 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_2_handle); | 1508 | t_mem_2_handle); |
| 1510 | 1509 | ||
| 1511 | if (t_mem_2 == nullptr) { | 1510 | if (t_mem_2.IsNull()) { |
| 1512 | LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle); | 1511 | LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle); |
| 1513 | IPC::ResponseBuilder rb{ctx, 2}; | 1512 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1514 | rb.Push(RESULT_UNKNOWN); | 1513 | rb.Push(RESULT_UNKNOWN); |
| @@ -1518,8 +1517,15 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 1518 | ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size"); | 1517 | ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size"); |
| 1519 | ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size"); | 1518 | ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size"); |
| 1520 | 1519 | ||
| 1520 | // Activate console six axis controller | ||
| 1521 | applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) | ||
| 1522 | .ActivateController(); | ||
| 1523 | |||
| 1524 | applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) | ||
| 1525 | .SetTransferMemoryPointer(system.Memory().GetPointer(t_mem_1->GetSourceAddress())); | ||
| 1526 | |||
| 1521 | LOG_WARNING(Service_HID, | 1527 | LOG_WARNING(Service_HID, |
| 1522 | "(STUBBED) called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, " | 1528 | "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, " |
| 1523 | "applet_resource_user_id={}", | 1529 | "applet_resource_user_id={}", |
| 1524 | t_mem_1_handle, t_mem_2_handle, applet_resource_user_id); | 1530 | t_mem_1_handle, t_mem_2_handle, applet_resource_user_id); |
| 1525 | 1531 | ||
| @@ -1542,8 +1548,10 @@ void Hid::ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx) { | |||
| 1542 | IPC::RequestParser rp{ctx}; | 1548 | IPC::RequestParser rp{ctx}; |
| 1543 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1549 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1544 | 1550 | ||
| 1545 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | 1551 | applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor) |
| 1546 | applet_resource_user_id); | 1552 | .ResetTimestamp(); |
| 1553 | |||
| 1554 | LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 1547 | 1555 | ||
| 1548 | IPC::ResponseBuilder rb{ctx, 2}; | 1556 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1549 | rb.Push(RESULT_SUCCESS); | 1557 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index c2bdd39a3..aa3307955 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -13,10 +13,6 @@ namespace Core::Timing { | |||
| 13 | struct EventType; | 13 | struct EventType; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace Kernel { | ||
| 17 | class KSharedMemory; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Service::SM { | 16 | namespace Service::SM { |
| 21 | class ServiceManager; | 17 | class ServiceManager; |
| 22 | } | 18 | } |
| @@ -69,8 +65,6 @@ private: | |||
| 69 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 65 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 70 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 66 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 71 | 67 | ||
| 72 | std::shared_ptr<Kernel::KSharedMemory> shared_mem; | ||
| 73 | |||
| 74 | std::shared_ptr<Core::Timing::EventType> pad_update_event; | 68 | std::shared_ptr<Core::Timing::EventType> pad_update_event; |
| 75 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | 69 | std::shared_ptr<Core::Timing::EventType> motion_update_event; |
| 76 | 70 | ||
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 2dfa936fb..3c6085990 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -37,10 +37,6 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { | |||
| 37 | // clang-format on | 37 | // clang-format on |
| 38 | 38 | ||
| 39 | RegisterHandlers(functions); | 39 | RegisterHandlers(functions); |
| 40 | |||
| 41 | auto& kernel = system.Kernel(); | ||
| 42 | |||
| 43 | shared_mem = SharedFrom(&kernel.GetIrsSharedMem()); | ||
| 44 | } | 40 | } |
| 45 | 41 | ||
| 46 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { | 42 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { |
| @@ -62,7 +58,7 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 62 | 58 | ||
| 63 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 59 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 64 | rb.Push(RESULT_SUCCESS); | 60 | rb.Push(RESULT_SUCCESS); |
| 65 | rb.PushCopyObjects(shared_mem); | 61 | rb.PushCopyObjects(&system.Kernel().GetIrsSharedMem()); |
| 66 | } | 62 | } |
| 67 | 63 | ||
| 68 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { | 64 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index b0c8c7168..9bc6462b0 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h | |||
| @@ -4,17 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/object.h" | ||
| 8 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 9 | 8 | ||
| 10 | namespace Core { | 9 | namespace Core { |
| 11 | class System; | 10 | class System; |
| 12 | } | 11 | } |
| 13 | 12 | ||
| 14 | namespace Kernel { | ||
| 15 | class KSharedMemory; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Service::HID { | 13 | namespace Service::HID { |
| 19 | 14 | ||
| 20 | class IRS final : public ServiceFramework<IRS> { | 15 | class IRS final : public ServiceFramework<IRS> { |
| @@ -42,7 +37,6 @@ private: | |||
| 42 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); | 37 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); |
| 43 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); | 38 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); |
| 44 | 39 | ||
| 45 | std::shared_ptr<Kernel::KSharedMemory> shared_mem; | ||
| 46 | const u32 device_handle{0xABCD}; | 40 | const u32 device_handle{0xABCD}; |
| 47 | }; | 41 | }; |
| 48 | 42 | ||
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp index e11a0c45a..3a5a2f4f5 100644 --- a/src/core/hle/service/lbl/lbl.cpp +++ b/src/core/hle/service/lbl/lbl.cpp | |||
| @@ -312,7 +312,6 @@ private: | |||
| 312 | 312 | ||
| 313 | bool vr_mode_enabled = false; | 313 | bool vr_mode_enabled = false; |
| 314 | float current_brightness = 1.0f; | 314 | float current_brightness = 1.0f; |
| 315 | float backlight_brightness = 1.0f; | ||
| 316 | float ambient_light_value = 0.0f; | 315 | float ambient_light_value = 0.0f; |
| 317 | float current_vr_brightness = 1.0f; | 316 | float current_vr_brightness = 1.0f; |
| 318 | bool dimming = true; | 317 | bool dimming = true; |
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index c8bc60ad1..c3948eb8e 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| 14 | #include "core/hle/kernel/k_page_table.h" | 14 | #include "core/hle/kernel/k_page_table.h" |
| 15 | #include "core/hle/kernel/k_process.h" | ||
| 15 | #include "core/hle/kernel/k_system_control.h" | 16 | #include "core/hle/kernel/k_system_control.h" |
| 16 | #include "core/hle/kernel/process.h" | ||
| 17 | #include "core/hle/kernel/svc_results.h" | 17 | #include "core/hle/kernel/svc_results.h" |
| 18 | #include "core/hle/service/ldr/ldr.h" | 18 | #include "core/hle/service/ldr/ldr.h" |
| 19 | #include "core/hle/service/service.h" | 19 | #include "core/hle/service/service.h" |
| @@ -321,7 +321,7 @@ public: | |||
| 321 | return addr; | 321 | return addr; |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::Process* process, VAddr baseAddress, | 324 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr baseAddress, |
| 325 | u64 size) const { | 325 | u64 size) const { |
| 326 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { | 326 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { |
| 327 | auto& page_table{process->PageTable()}; | 327 | auto& page_table{process->PageTable()}; |
| @@ -342,7 +342,7 @@ public: | |||
| 342 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; | 342 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | ResultVal<VAddr> MapNro(Kernel::Process* process, VAddr nro_addr, std::size_t nro_size, | 345 | ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size, |
| 346 | VAddr bss_addr, std::size_t bss_size, std::size_t size) const { | 346 | VAddr bss_addr, std::size_t bss_size, std::size_t size) const { |
| 347 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { | 347 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { |
| 348 | auto& page_table{process->PageTable()}; | 348 | auto& page_table{process->PageTable()}; |
| @@ -378,7 +378,7 @@ public: | |||
| 378 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; | 378 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | ResultCode LoadNro(Kernel::Process* process, const NROHeader& nro_header, VAddr nro_addr, | 381 | ResultCode LoadNro(Kernel::KProcess* process, const NROHeader& nro_header, VAddr nro_addr, |
| 382 | VAddr start) const { | 382 | VAddr start) const { |
| 383 | const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset}; | 383 | const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset}; |
| 384 | const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset}; | 384 | const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset}; |
| @@ -387,11 +387,9 @@ public: | |||
| 387 | const VAddr bss_end_addr{ | 387 | const VAddr bss_end_addr{ |
| 388 | Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; | 388 | Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; |
| 389 | 389 | ||
| 390 | auto CopyCode{[&](VAddr src_addr, VAddr dst_addr, u64 size) { | 390 | const auto CopyCode = [this, process](VAddr src_addr, VAddr dst_addr, u64 size) { |
| 391 | std::vector<u8> source_data(size); | 391 | system.Memory().CopyBlock(*process, dst_addr, src_addr, size); |
| 392 | system.Memory().ReadBlock(src_addr, source_data.data(), source_data.size()); | 392 | }; |
| 393 | system.Memory().WriteBlock(dst_addr, source_data.data(), source_data.size()); | ||
| 394 | }}; | ||
| 395 | CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, | 393 | CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, |
| 396 | nro_header.segment_headers[TEXT_INDEX].memory_size); | 394 | nro_header.segment_headers[TEXT_INDEX].memory_size); |
| 397 | CopyCode(nro_addr + nro_header.segment_headers[RO_INDEX].memory_offset, ro_start, | 395 | CopyCode(nro_addr + nro_header.segment_headers[RO_INDEX].memory_offset, ro_start, |
diff --git a/src/core/hle/service/mii/manager.h b/src/core/hle/service/mii/manager.h index 2106a528a..ec7efa5f7 100644 --- a/src/core/hle/service/mii/manager.h +++ b/src/core/hle/service/mii/manager.h | |||
| @@ -89,7 +89,7 @@ static_assert(std::has_unique_object_representations_v<MiiInfo>, | |||
| 89 | #pragma pack(push, 4) | 89 | #pragma pack(push, 4) |
| 90 | 90 | ||
| 91 | struct MiiInfoElement { | 91 | struct MiiInfoElement { |
| 92 | MiiInfoElement(const MiiInfo& info, Source source) : info{info}, source{source} {} | 92 | MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {} |
| 93 | 93 | ||
| 94 | MiiInfo info{}; | 94 | MiiInfo info{}; |
| 95 | Source source{}; | 95 | Source source{}; |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 26be9e45b..81f150a88 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -253,8 +253,8 @@ private: | |||
| 253 | 253 | ||
| 254 | class MiiDBModule final : public ServiceFramework<MiiDBModule> { | 254 | class MiiDBModule final : public ServiceFramework<MiiDBModule> { |
| 255 | public: | 255 | public: |
| 256 | explicit MiiDBModule(Core::System& system_, const char* name) | 256 | explicit MiiDBModule(Core::System& system_, const char* name_) |
| 257 | : ServiceFramework{system_, name} { | 257 | : ServiceFramework{system_, name_} { |
| 258 | // clang-format off | 258 | // clang-format off |
| 259 | static const FunctionInfo functions[] = { | 259 | static const FunctionInfo functions[] = { |
| 260 | {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, | 260 | {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, |
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index b0cb07d24..c8519e2db 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/client_session.h" | ||
| 8 | #include "core/hle/service/mm/mm_u.h" | 7 | #include "core/hle/service/mm/mm_u.h" |
| 9 | #include "core/hle/service/sm/sm.h" | 8 | #include "core/hle/service/sm/sm.h" |
| 10 | 9 | ||
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 2d1d4d67f..d25b20ab5 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/kernel/k_event.h" | ||
| 12 | #include "core/hle/kernel/k_readable_event.h" | 11 | #include "core/hle/kernel/k_readable_event.h" |
| 13 | #include "core/hle/kernel/k_thread.h" | 12 | #include "core/hle/kernel/k_thread.h" |
| 14 | #include "core/hle/kernel/k_writable_event.h" | 13 | #include "core/hle/kernel/k_writable_event.h" |
| @@ -24,10 +23,9 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); | |||
| 24 | 23 | ||
| 25 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, | 24 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, |
| 26 | const char* name) | 25 | const char* name) |
| 27 | : ServiceFramework{system_, name}, module{std::move(module_)} { | 26 | : ServiceFramework{system_, name}, nfc_tag_load{system.Kernel()}, module{std::move(module_)} { |
| 28 | auto& kernel = system.Kernel(); | 27 | Kernel::KAutoObject::Create(std::addressof(nfc_tag_load)); |
| 29 | nfc_tag_load = Kernel::KEvent::Create(kernel, "IUser:NFCTagDetected"); | 28 | nfc_tag_load.Initialize("IUser:NFCTagDetected"); |
| 30 | nfc_tag_load->Initialize(); | ||
| 31 | } | 29 | } |
| 32 | 30 | ||
| 33 | Module::Interface::~Interface() = default; | 31 | Module::Interface::~Interface() = default; |
| @@ -35,7 +33,8 @@ Module::Interface::~Interface() = default; | |||
| 35 | class IUser final : public ServiceFramework<IUser> { | 33 | class IUser final : public ServiceFramework<IUser> { |
| 36 | public: | 34 | public: |
| 37 | explicit IUser(Module::Interface& nfp_interface_, Core::System& system_) | 35 | explicit IUser(Module::Interface& nfp_interface_, Core::System& system_) |
| 38 | : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_} { | 36 | : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_}, |
| 37 | deactivate_event{system.Kernel()}, availability_change_event{system.Kernel()} { | ||
| 39 | static const FunctionInfo functions[] = { | 38 | static const FunctionInfo functions[] = { |
| 40 | {0, &IUser::Initialize, "Initialize"}, | 39 | {0, &IUser::Initialize, "Initialize"}, |
| 41 | {1, &IUser::Finalize, "Finalize"}, | 40 | {1, &IUser::Finalize, "Finalize"}, |
| @@ -65,11 +64,11 @@ public: | |||
| 65 | }; | 64 | }; |
| 66 | RegisterHandlers(functions); | 65 | RegisterHandlers(functions); |
| 67 | 66 | ||
| 68 | auto& kernel = system.Kernel(); | 67 | Kernel::KAutoObject::Create(std::addressof(deactivate_event)); |
| 69 | deactivate_event = Kernel::KEvent::Create(kernel, "IUser:DeactivateEvent"); | 68 | Kernel::KAutoObject::Create(std::addressof(availability_change_event)); |
| 70 | deactivate_event->Initialize(); | 69 | |
| 71 | availability_change_event = Kernel::KEvent::Create(kernel, "IUser:AvailabilityChangeEvent"); | 70 | deactivate_event.Initialize("IUser:DeactivateEvent"); |
| 72 | availability_change_event->Initialize(); | 71 | availability_change_event.Initialize("IUser:AvailabilityChangeEvent"); |
| 73 | } | 72 | } |
| 74 | 73 | ||
| 75 | private: | 74 | private: |
| @@ -167,7 +166,7 @@ private: | |||
| 167 | 166 | ||
| 168 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 167 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 169 | rb.Push(RESULT_SUCCESS); | 168 | rb.Push(RESULT_SUCCESS); |
| 170 | rb.PushCopyObjects(deactivate_event->GetReadableEvent()); | 169 | rb.PushCopyObjects(deactivate_event.GetReadableEvent()); |
| 171 | } | 170 | } |
| 172 | 171 | ||
| 173 | void StopDetection(Kernel::HLERequestContext& ctx) { | 172 | void StopDetection(Kernel::HLERequestContext& ctx) { |
| @@ -176,7 +175,7 @@ private: | |||
| 176 | switch (device_state) { | 175 | switch (device_state) { |
| 177 | case DeviceState::TagFound: | 176 | case DeviceState::TagFound: |
| 178 | case DeviceState::TagNearby: | 177 | case DeviceState::TagNearby: |
| 179 | deactivate_event->GetWritableEvent()->Signal(); | 178 | deactivate_event.GetWritableEvent().Signal(); |
| 180 | device_state = DeviceState::Initialized; | 179 | device_state = DeviceState::Initialized; |
| 181 | break; | 180 | break; |
| 182 | case DeviceState::SearchingForTag: | 181 | case DeviceState::SearchingForTag: |
| @@ -265,7 +264,7 @@ private: | |||
| 265 | 264 | ||
| 266 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 265 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 267 | rb.Push(RESULT_SUCCESS); | 266 | rb.Push(RESULT_SUCCESS); |
| 268 | rb.PushCopyObjects(availability_change_event->GetReadableEvent()); | 267 | rb.PushCopyObjects(availability_change_event.GetReadableEvent()); |
| 269 | } | 268 | } |
| 270 | 269 | ||
| 271 | void GetRegisterInfo(Kernel::HLERequestContext& ctx) { | 270 | void GetRegisterInfo(Kernel::HLERequestContext& ctx) { |
| @@ -319,9 +318,9 @@ private: | |||
| 319 | const u32 npad_id{0}; // Player 1 controller | 318 | const u32 npad_id{0}; // Player 1 controller |
| 320 | State state{State::NonInitialized}; | 319 | State state{State::NonInitialized}; |
| 321 | DeviceState device_state{DeviceState::Initialized}; | 320 | DeviceState device_state{DeviceState::Initialized}; |
| 322 | std::shared_ptr<Kernel::KEvent> deactivate_event; | 321 | Module::Interface& nfp_interface; |
| 323 | std::shared_ptr<Kernel::KEvent> availability_change_event; | 322 | Kernel::KEvent deactivate_event; |
| 324 | const Module::Interface& nfp_interface; | 323 | Kernel::KEvent availability_change_event; |
| 325 | }; | 324 | }; |
| 326 | 325 | ||
| 327 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { | 326 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { |
| @@ -339,12 +338,12 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { | |||
| 339 | } | 338 | } |
| 340 | 339 | ||
| 341 | std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); | 340 | std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); |
| 342 | nfc_tag_load->GetWritableEvent()->Signal(); | 341 | nfc_tag_load.GetWritableEvent().Signal(); |
| 343 | return true; | 342 | return true; |
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | const std::shared_ptr<Kernel::KReadableEvent>& Module::Interface::GetNFCEvent() const { | 345 | Kernel::KReadableEvent& Module::Interface::GetNFCEvent() { |
| 347 | return nfc_tag_load->GetReadableEvent(); | 346 | return nfc_tag_load.GetReadableEvent(); |
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { | 349 | const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { |
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index c46551760..5e4e49bc6 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "core/hle/kernel/k_event.h" | ||
| 10 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 11 | 12 | ||
| 12 | namespace Kernel { | 13 | namespace Kernel { |
| @@ -38,11 +39,11 @@ public: | |||
| 38 | 39 | ||
| 39 | void CreateUserInterface(Kernel::HLERequestContext& ctx); | 40 | void CreateUserInterface(Kernel::HLERequestContext& ctx); |
| 40 | bool LoadAmiibo(const std::vector<u8>& buffer); | 41 | bool LoadAmiibo(const std::vector<u8>& buffer); |
| 41 | const std::shared_ptr<Kernel::KReadableEvent>& GetNFCEvent() const; | 42 | Kernel::KReadableEvent& GetNFCEvent(); |
| 42 | const AmiiboFile& GetAmiiboBuffer() const; | 43 | const AmiiboFile& GetAmiiboBuffer() const; |
| 43 | 44 | ||
| 44 | private: | 45 | private: |
| 45 | std::shared_ptr<Kernel::KEvent> nfc_tag_load; | 46 | Kernel::KEvent nfc_tag_load; |
| 46 | AmiiboFile amiibo{}; | 47 | AmiiboFile amiibo{}; |
| 47 | 48 | ||
| 48 | protected: | 49 | protected: |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 9f110df8e..76e3832df 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -127,7 +127,8 @@ public: | |||
| 127 | 127 | ||
| 128 | class IRequest final : public ServiceFramework<IRequest> { | 128 | class IRequest final : public ServiceFramework<IRequest> { |
| 129 | public: | 129 | public: |
| 130 | explicit IRequest(Core::System& system_) : ServiceFramework{system_, "IRequest"} { | 130 | explicit IRequest(Core::System& system_) |
| 131 | : ServiceFramework{system_, "IRequest"}, event1{system.Kernel()}, event2{system.Kernel()} { | ||
| 131 | static const FunctionInfo functions[] = { | 132 | static const FunctionInfo functions[] = { |
| 132 | {0, &IRequest::GetRequestState, "GetRequestState"}, | 133 | {0, &IRequest::GetRequestState, "GetRequestState"}, |
| 133 | {1, &IRequest::GetResult, "GetResult"}, | 134 | {1, &IRequest::GetResult, "GetResult"}, |
| @@ -157,12 +158,11 @@ public: | |||
| 157 | }; | 158 | }; |
| 158 | RegisterHandlers(functions); | 159 | RegisterHandlers(functions); |
| 159 | 160 | ||
| 160 | auto& kernel = system.Kernel(); | 161 | Kernel::KAutoObject::Create(std::addressof(event1)); |
| 162 | Kernel::KAutoObject::Create(std::addressof(event2)); | ||
| 161 | 163 | ||
| 162 | event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1"); | 164 | event1.Initialize("IRequest:Event1"); |
| 163 | event1->Initialize(); | 165 | event2.Initialize("IRequest:Event2"); |
| 164 | event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2"); | ||
| 165 | event2->Initialize(); | ||
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | private: | 168 | private: |
| @@ -198,7 +198,7 @@ private: | |||
| 198 | 198 | ||
| 199 | IPC::ResponseBuilder rb{ctx, 2, 2}; | 199 | IPC::ResponseBuilder rb{ctx, 2, 2}; |
| 200 | rb.Push(RESULT_SUCCESS); | 200 | rb.Push(RESULT_SUCCESS); |
| 201 | rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent()); | 201 | rb.PushCopyObjects(event1.GetReadableEvent(), event2.GetReadableEvent()); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | void Cancel(Kernel::HLERequestContext& ctx) { | 204 | void Cancel(Kernel::HLERequestContext& ctx) { |
| @@ -229,7 +229,7 @@ private: | |||
| 229 | rb.Push<u32>(0); | 229 | rb.Push<u32>(0); |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | std::shared_ptr<Kernel::KEvent> event1, event2; | 232 | Kernel::KEvent event1, event2; |
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| 235 | class INetworkProfile final : public ServiceFramework<INetworkProfile> { | 235 | class INetworkProfile final : public ServiceFramework<INetworkProfile> { |
| @@ -368,7 +368,7 @@ private: | |||
| 368 | }, | 368 | }, |
| 369 | }; | 369 | }; |
| 370 | 370 | ||
| 371 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(IpConfigInfo) / sizeof(u32)}; | 371 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; |
| 372 | rb.Push(RESULT_SUCCESS); | 372 | rb.Push(RESULT_SUCCESS); |
| 373 | rb.PushRaw<IpConfigInfo>(ip_config_info); | 373 | rb.PushRaw<IpConfigInfo>(ip_config_info); |
| 374 | } | 374 | } |
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index fee360ab9..420a5a075 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp | |||
| @@ -300,7 +300,8 @@ class IEnsureNetworkClockAvailabilityService final | |||
| 300 | : public ServiceFramework<IEnsureNetworkClockAvailabilityService> { | 300 | : public ServiceFramework<IEnsureNetworkClockAvailabilityService> { |
| 301 | public: | 301 | public: |
| 302 | explicit IEnsureNetworkClockAvailabilityService(Core::System& system_) | 302 | explicit IEnsureNetworkClockAvailabilityService(Core::System& system_) |
| 303 | : ServiceFramework{system_, "IEnsureNetworkClockAvailabilityService"} { | 303 | : ServiceFramework{system_, "IEnsureNetworkClockAvailabilityService"}, |
| 304 | finished_event{system.Kernel()} { | ||
| 304 | static const FunctionInfo functions[] = { | 305 | static const FunctionInfo functions[] = { |
| 305 | {0, &IEnsureNetworkClockAvailabilityService::StartTask, "StartTask"}, | 306 | {0, &IEnsureNetworkClockAvailabilityService::StartTask, "StartTask"}, |
| 306 | {1, &IEnsureNetworkClockAvailabilityService::GetFinishNotificationEvent, | 307 | {1, &IEnsureNetworkClockAvailabilityService::GetFinishNotificationEvent, |
| @@ -312,19 +313,17 @@ public: | |||
| 312 | }; | 313 | }; |
| 313 | RegisterHandlers(functions); | 314 | RegisterHandlers(functions); |
| 314 | 315 | ||
| 315 | auto& kernel = system.Kernel(); | 316 | Kernel::KAutoObject::Create(std::addressof(finished_event)); |
| 316 | finished_event = | 317 | finished_event.Initialize("IEnsureNetworkClockAvailabilityService:FinishEvent"); |
| 317 | Kernel::KEvent::Create(kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent"); | ||
| 318 | finished_event->Initialize(); | ||
| 319 | } | 318 | } |
| 320 | 319 | ||
| 321 | private: | 320 | private: |
| 322 | std::shared_ptr<Kernel::KEvent> finished_event; | 321 | Kernel::KEvent finished_event; |
| 323 | 322 | ||
| 324 | void StartTask(Kernel::HLERequestContext& ctx) { | 323 | void StartTask(Kernel::HLERequestContext& ctx) { |
| 325 | // No need to connect to the internet, just finish the task straight away. | 324 | // No need to connect to the internet, just finish the task straight away. |
| 326 | LOG_DEBUG(Service_NIM, "called"); | 325 | LOG_DEBUG(Service_NIM, "called"); |
| 327 | finished_event->GetWritableEvent()->Signal(); | 326 | finished_event.GetWritableEvent().Signal(); |
| 328 | IPC::ResponseBuilder rb{ctx, 2}; | 327 | IPC::ResponseBuilder rb{ctx, 2}; |
| 329 | rb.Push(RESULT_SUCCESS); | 328 | rb.Push(RESULT_SUCCESS); |
| 330 | } | 329 | } |
| @@ -334,7 +333,7 @@ private: | |||
| 334 | 333 | ||
| 335 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 334 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 336 | rb.Push(RESULT_SUCCESS); | 335 | rb.Push(RESULT_SUCCESS); |
| 337 | rb.PushCopyObjects(finished_event->GetReadableEvent()); | 336 | rb.PushCopyObjects(finished_event.GetReadableEvent()); |
| 338 | } | 337 | } |
| 339 | 338 | ||
| 340 | void GetResult(Kernel::HLERequestContext& ctx) { | 339 | void GetResult(Kernel::HLERequestContext& ctx) { |
| @@ -346,7 +345,7 @@ private: | |||
| 346 | 345 | ||
| 347 | void Cancel(Kernel::HLERequestContext& ctx) { | 346 | void Cancel(Kernel::HLERequestContext& ctx) { |
| 348 | LOG_DEBUG(Service_NIM, "called"); | 347 | LOG_DEBUG(Service_NIM, "called"); |
| 349 | finished_event->GetWritableEvent()->Clear(); | 348 | finished_event.GetWritableEvent().Clear(); |
| 350 | IPC::ResponseBuilder rb{ctx, 2}; | 349 | IPC::ResponseBuilder rb{ctx, 2}; |
| 351 | rb.Push(RESULT_SUCCESS); | 350 | rb.Push(RESULT_SUCCESS); |
| 352 | } | 351 | } |
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index da139fdc4..e14acce58 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp | |||
| @@ -130,9 +130,6 @@ struct PL_U::Impl { | |||
| 130 | } | 130 | } |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | /// Handle to shared memory region designated for a shared font | ||
| 134 | std::shared_ptr<Kernel::KSharedMemory> shared_font_mem; | ||
| 135 | |||
| 136 | /// Backing memory for the shared font data | 133 | /// Backing memory for the shared font data |
| 137 | std::shared_ptr<Kernel::PhysicalMemory> shared_font; | 134 | std::shared_ptr<Kernel::PhysicalMemory> shared_font; |
| 138 | 135 | ||
| @@ -260,14 +257,13 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | |||
| 260 | 257 | ||
| 261 | // Create shared font memory object | 258 | // Create shared font memory object |
| 262 | auto& kernel = system.Kernel(); | 259 | auto& kernel = system.Kernel(); |
| 263 | impl->shared_font_mem = SharedFrom(&kernel.GetFontSharedMem()); | ||
| 264 | 260 | ||
| 265 | std::memcpy(impl->shared_font_mem->GetPointer(), impl->shared_font->data(), | 261 | std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(), |
| 266 | impl->shared_font->size()); | 262 | impl->shared_font->size()); |
| 267 | 263 | ||
| 268 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 264 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 269 | rb.Push(RESULT_SUCCESS); | 265 | rb.Push(RESULT_SUCCESS); |
| 270 | rb.PushCopyObjects(impl->shared_font_mem); | 266 | rb.PushCopyObjects(&kernel.GetFontSharedMem()); |
| 271 | } | 267 | } |
| 272 | 268 | ||
| 273 | void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { | 269 | void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index b37f023df..5b73a5a34 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -21,7 +21,7 @@ namespace Service::Nvidia::Devices { | |||
| 21 | /// implement the ioctl interface. | 21 | /// implement the ioctl interface. |
| 22 | class nvdevice { | 22 | class nvdevice { |
| 23 | public: | 23 | public: |
| 24 | explicit nvdevice(Core::System& system) : system{system} {} | 24 | explicit nvdevice(Core::System& system_) : system{system_} {} |
| 25 | virtual ~nvdevice() = default; | 25 | virtual ~nvdevice() = default; |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 5ab7e39b0..2cc0da124 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | 14 | ||
| 15 | namespace Service::Nvidia::Devices { | 15 | namespace Service::Nvidia::Devices { |
| 16 | 16 | ||
| 17 | nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | 17 | nvdisp_disp0::nvdisp_disp0(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_) |
| 18 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | 18 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)} {} |
| 19 | nvdisp_disp0 ::~nvdisp_disp0() = default; | 19 | nvdisp_disp0 ::~nvdisp_disp0() = default; |
| 20 | 20 | ||
| 21 | NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 21 | NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| @@ -52,7 +52,6 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 52 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), | 52 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), |
| 53 | transform, crop_rect}; | 53 | transform, crop_rect}; |
| 54 | 54 | ||
| 55 | system.GetPerfStats().EndGameFrame(); | ||
| 56 | system.GetPerfStats().EndSystemFrame(); | 55 | system.GetPerfStats().EndSystemFrame(); |
| 57 | system.GPU().SwapBuffers(&framebuffer); | 56 | system.GPU().SwapBuffers(&framebuffer); |
| 58 | system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); | 57 | system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 59c9b6101..de01e1d5f 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | |||
| @@ -17,7 +17,7 @@ class nvmap; | |||
| 17 | 17 | ||
| 18 | class nvdisp_disp0 final : public nvdevice { | 18 | class nvdisp_disp0 final : public nvdevice { |
| 19 | public: | 19 | public: |
| 20 | explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 20 | explicit nvdisp_disp0(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_); |
| 21 | ~nvdisp_disp0() override; | 21 | ~nvdisp_disp0() override; |
| 22 | 22 | ||
| 23 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 23 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index f7b3dc317..7dc41d875 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | namespace Service::Nvidia::Devices { | 18 | namespace Service::Nvidia::Devices { |
| 19 | 19 | ||
| 20 | nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | 20 | nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_) |
| 21 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | 21 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)} {} |
| 22 | nvhost_as_gpu::~nvhost_as_gpu() = default; | 22 | nvhost_as_gpu::~nvhost_as_gpu() = default; |
| 23 | 23 | ||
| 24 | NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 24 | NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index d86a9cab6..24e3151cb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -30,7 +30,7 @@ DECLARE_ENUM_FLAG_OPERATORS(AddressSpaceFlags); | |||
| 30 | 30 | ||
| 31 | class nvhost_as_gpu final : public nvdevice { | 31 | class nvhost_as_gpu final : public nvdevice { |
| 32 | public: | 32 | public: |
| 33 | explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 33 | explicit nvhost_as_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_); |
| 34 | ~nvhost_as_gpu() override; | 34 | ~nvhost_as_gpu() override; |
| 35 | 35 | ||
| 36 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 36 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| @@ -48,13 +48,13 @@ private: | |||
| 48 | public: | 48 | public: |
| 49 | constexpr BufferMap() = default; | 49 | constexpr BufferMap() = default; |
| 50 | 50 | ||
| 51 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size) | 51 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_) |
| 52 | : start_addr{start_addr}, end_addr{start_addr + size} {} | 52 | : start_addr{start_addr_}, end_addr{start_addr_ + size_} {} |
| 53 | 53 | ||
| 54 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size, VAddr cpu_addr, | 54 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_, VAddr cpu_addr_, |
| 55 | bool is_allocated) | 55 | bool is_allocated_) |
| 56 | : start_addr{start_addr}, end_addr{start_addr + size}, cpu_addr{cpu_addr}, | 56 | : start_addr{start_addr_}, end_addr{start_addr_ + size_}, cpu_addr{cpu_addr_}, |
| 57 | is_allocated{is_allocated} {} | 57 | is_allocated{is_allocated_} {} |
| 58 | 58 | ||
| 59 | constexpr VAddr StartAddr() const { | 59 | constexpr VAddr StartAddr() const { |
| 60 | return start_addr; | 60 | return start_addr; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 9f00d5cb0..775e76330 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -15,9 +15,10 @@ | |||
| 15 | 15 | ||
| 16 | namespace Service::Nvidia::Devices { | 16 | namespace Service::Nvidia::Devices { |
| 17 | 17 | ||
| 18 | nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface, | 18 | nvhost_ctrl::nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, |
| 19 | SyncpointManager& syncpoint_manager) | 19 | SyncpointManager& syncpoint_manager_) |
| 20 | : nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {} | 20 | : nvdevice{system_}, events_interface{events_interface_}, syncpoint_manager{ |
| 21 | syncpoint_manager_} {} | ||
| 21 | nvhost_ctrl::~nvhost_ctrl() = default; | 22 | nvhost_ctrl::~nvhost_ctrl() = default; |
| 22 | 23 | ||
| 23 | NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 24 | NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| @@ -101,20 +102,20 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 101 | return NvResult::Success; | 102 | return NvResult::Success; |
| 102 | } | 103 | } |
| 103 | 104 | ||
| 104 | auto event = events_interface.events[event_id]; | 105 | auto& event = events_interface.events[event_id]; |
| 105 | auto& gpu = system.GPU(); | 106 | auto& gpu = system.GPU(); |
| 106 | 107 | ||
| 107 | // This is mostly to take into account unimplemented features. As synced | 108 | // This is mostly to take into account unimplemented features. As synced |
| 108 | // gpu is always synced. | 109 | // gpu is always synced. |
| 109 | if (!gpu.IsAsync()) { | 110 | if (!gpu.IsAsync()) { |
| 110 | event.event->GetWritableEvent()->Signal(); | 111 | event.event->GetWritableEvent().Signal(); |
| 111 | return NvResult::Success; | 112 | return NvResult::Success; |
| 112 | } | 113 | } |
| 113 | auto lock = gpu.LockSync(); | 114 | auto lock = gpu.LockSync(); |
| 114 | const u32 current_syncpoint_value = event.fence.value; | 115 | const u32 current_syncpoint_value = event.fence.value; |
| 115 | const s32 diff = current_syncpoint_value - params.threshold; | 116 | const s32 diff = current_syncpoint_value - params.threshold; |
| 116 | if (diff >= 0) { | 117 | if (diff >= 0) { |
| 117 | event.event->GetWritableEvent()->Signal(); | 118 | event.event->GetWritableEvent().Signal(); |
| 118 | params.value = current_syncpoint_value; | 119 | params.value = current_syncpoint_value; |
| 119 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 120 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 120 | return NvResult::Success; | 121 | return NvResult::Success; |
| @@ -141,7 +142,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 141 | params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; | 142 | params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; |
| 142 | } | 143 | } |
| 143 | params.value |= event_id; | 144 | params.value |= event_id; |
| 144 | event.event->GetWritableEvent()->Clear(); | 145 | event.event->GetWritableEvent().Clear(); |
| 145 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); | 146 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); |
| 146 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 147 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 147 | return NvResult::Timeout; | 148 | return NvResult::Timeout; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 9178789c3..cdf03887d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -14,8 +14,8 @@ namespace Service::Nvidia::Devices { | |||
| 14 | 14 | ||
| 15 | class nvhost_ctrl final : public nvdevice { | 15 | class nvhost_ctrl final : public nvdevice { |
| 16 | public: | 16 | public: |
| 17 | explicit nvhost_ctrl(Core::System& system, EventInterface& events_interface, | 17 | explicit nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, |
| 18 | SyncpointManager& syncpoint_manager); | 18 | SyncpointManager& syncpoint_manager_); |
| 19 | ~nvhost_ctrl() override; | 19 | ~nvhost_ctrl() override; |
| 20 | 20 | ||
| 21 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 21 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 2edd803f3..d8b684f4f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Service::Nvidia::Devices { | 13 | namespace Service::Nvidia::Devices { |
| 14 | 14 | ||
| 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {} | 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_) : nvdevice{system_} {} |
| 16 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; | 16 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; |
| 17 | 17 | ||
| 18 | NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 18 | NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index f98aa841a..898d00a17 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | |||
| @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { | |||
| 13 | 13 | ||
| 14 | class nvhost_ctrl_gpu final : public nvdevice { | 14 | class nvhost_ctrl_gpu final : public nvdevice { |
| 15 | public: | 15 | public: |
| 16 | explicit nvhost_ctrl_gpu(Core::System& system); | 16 | explicit nvhost_ctrl_gpu(Core::System& system_); |
| 17 | ~nvhost_ctrl_gpu() override; | 17 | ~nvhost_ctrl_gpu() override; |
| 18 | 18 | ||
| 19 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 19 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index e83aaa798..c0a380088 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -14,11 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | namespace Service::Nvidia::Devices { | 15 | namespace Service::Nvidia::Devices { |
| 16 | 16 | ||
| 17 | nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 17 | nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 18 | SyncpointManager& syncpoint_manager) | 18 | SyncpointManager& syncpoint_manager_) |
| 19 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)), syncpoint_manager{syncpoint_manager} { | 19 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, syncpoint_manager{syncpoint_manager_} { |
| 20 | channel_fence.id = syncpoint_manager.AllocateSyncpoint(); | 20 | channel_fence.id = syncpoint_manager_.AllocateSyncpoint(); |
| 21 | channel_fence.value = system.GPU().GetSyncpointValue(channel_fence.id); | 21 | channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | nvhost_gpu::~nvhost_gpu() = default; | 24 | nvhost_gpu::~nvhost_gpu() = default; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 12a1a1133..f27a82bff 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -22,8 +22,8 @@ namespace Service::Nvidia::Devices { | |||
| 22 | class nvmap; | 22 | class nvmap; |
| 23 | class nvhost_gpu final : public nvdevice { | 23 | class nvhost_gpu final : public nvdevice { |
| 24 | public: | 24 | public: |
| 25 | explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 25 | explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 26 | SyncpointManager& syncpoint_manager); | 26 | SyncpointManager& syncpoint_manager_); |
| 27 | ~nvhost_gpu() override; | 27 | ~nvhost_gpu() override; |
| 28 | 28 | ||
| 29 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 29 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index e2f671d8e..6c1edce33 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -11,9 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | 13 | ||
| 14 | nvhost_nvdec::nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 14 | nvhost_nvdec::nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 15 | SyncpointManager& syncpoint_manager) | 15 | SyncpointManager& syncpoint_manager_) |
| 16 | : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) {} | 16 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {} |
| 17 | nvhost_nvdec::~nvhost_nvdec() = default; | 17 | nvhost_nvdec::~nvhost_nvdec() = default; |
| 18 | 18 | ||
| 19 | NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 19 | NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 6c38a8c24..523d96e3a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | |||
| @@ -11,8 +11,8 @@ namespace Service::Nvidia::Devices { | |||
| 11 | 11 | ||
| 12 | class nvhost_nvdec final : public nvhost_nvdec_common { | 12 | class nvhost_nvdec final : public nvhost_nvdec_common { |
| 13 | public: | 13 | public: |
| 14 | explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 14 | explicit nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 15 | SyncpointManager& syncpoint_manager); | 15 | SyncpointManager& syncpoint_manager_); |
| 16 | ~nvhost_nvdec() override; | 16 | ~nvhost_nvdec() override; |
| 17 | 17 | ||
| 18 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 18 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index c2f152190..98e6296f1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -42,9 +42,9 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s | |||
| 42 | } | 42 | } |
| 43 | } // Anonymous namespace | 43 | } // Anonymous namespace |
| 44 | 44 | ||
| 45 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 45 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 46 | SyncpointManager& syncpoint_manager) | 46 | SyncpointManager& syncpoint_manager_) |
| 47 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)), syncpoint_manager(syncpoint_manager) {} | 47 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, syncpoint_manager{syncpoint_manager_} {} |
| 48 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; | 48 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; |
| 49 | 49 | ||
| 50 | NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { | 50 | NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 4c9d4ba41..da10f5f41 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -18,8 +18,8 @@ class nvmap; | |||
| 18 | 18 | ||
| 19 | class nvhost_nvdec_common : public nvdevice { | 19 | class nvhost_nvdec_common : public nvdevice { |
| 20 | public: | 20 | public: |
| 21 | explicit nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 21 | explicit nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 22 | SyncpointManager& syncpoint_manager); | 22 | SyncpointManager& syncpoint_manager_); |
| 23 | ~nvhost_nvdec_common() override; | 23 | ~nvhost_nvdec_common() override; |
| 24 | 24 | ||
| 25 | protected: | 25 | protected: |
| @@ -27,13 +27,13 @@ protected: | |||
| 27 | public: | 27 | public: |
| 28 | constexpr BufferMap() = default; | 28 | constexpr BufferMap() = default; |
| 29 | 29 | ||
| 30 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size) | 30 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_) |
| 31 | : start_addr{start_addr}, end_addr{start_addr + size} {} | 31 | : start_addr{start_addr_}, end_addr{start_addr_ + size_} {} |
| 32 | 32 | ||
| 33 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size, VAddr cpu_addr, | 33 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_, VAddr cpu_addr_, |
| 34 | bool is_allocated) | 34 | bool is_allocated_) |
| 35 | : start_addr{start_addr}, end_addr{start_addr + size}, cpu_addr{cpu_addr}, | 35 | : start_addr{start_addr_}, end_addr{start_addr_ + size_}, cpu_addr{cpu_addr_}, |
| 36 | is_allocated{is_allocated} {} | 36 | is_allocated{is_allocated_} {} |
| 37 | 37 | ||
| 38 | constexpr VAddr StartAddr() const { | 38 | constexpr VAddr StartAddr() const { |
| 39 | return start_addr; | 39 | return start_addr; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 0a9c35c01..c2be3cea7 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::Nvidia::Devices { | 11 | namespace Service::Nvidia::Devices { |
| 12 | 12 | ||
| 13 | nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {} | 13 | nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {} |
| 14 | nvhost_nvjpg::~nvhost_nvjpg() = default; | 14 | nvhost_nvjpg::~nvhost_nvjpg() = default; |
| 15 | 15 | ||
| 16 | NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 16 | NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 1f97b642f..6045e5cbd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | |||
| @@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices { | |||
| 13 | 13 | ||
| 14 | class nvhost_nvjpg final : public nvdevice { | 14 | class nvhost_nvjpg final : public nvdevice { |
| 15 | public: | 15 | public: |
| 16 | explicit nvhost_nvjpg(Core::System& system); | 16 | explicit nvhost_nvjpg(Core::System& system_); |
| 17 | ~nvhost_nvjpg() override; | 17 | ~nvhost_nvjpg() override; |
| 18 | 18 | ||
| 19 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 19 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 301efe8a1..21d101e8a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -10,9 +10,9 @@ | |||
| 10 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 11 | 11 | ||
| 12 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 13 | nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 14 | SyncpointManager& syncpoint_manager) | 14 | SyncpointManager& syncpoint_manager_) |
| 15 | : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) {} | 15 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {} |
| 16 | 16 | ||
| 17 | nvhost_vic::~nvhost_vic() = default; | 17 | nvhost_vic::~nvhost_vic() = default; |
| 18 | 18 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index cebefad71..6d7fda9d1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Nvidia::Devices { | |||
| 10 | 10 | ||
| 11 | class nvhost_vic final : public nvhost_nvdec_common { | 11 | class nvhost_vic final : public nvhost_nvdec_common { |
| 12 | public: | 12 | public: |
| 13 | explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 13 | explicit nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 14 | SyncpointManager& syncpoint_manager); | 14 | SyncpointManager& syncpoint_manager_); |
| 15 | ~nvhost_vic(); | 15 | ~nvhost_vic(); |
| 16 | 16 | ||
| 17 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 17 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index dd1355522..dc59b4494 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | 13 | ||
| 14 | nvmap::nvmap(Core::System& system) : nvdevice(system) { | 14 | nvmap::nvmap(Core::System& system_) : nvdevice{system_} { |
| 15 | // Handle 0 appears to be used when remapping, so we create a placeholder empty nvmap object to | 15 | // Handle 0 appears to be used when remapping, so we create a placeholder empty nvmap object to |
| 16 | // represent this. | 16 | // represent this. |
| 17 | CreateObject(0); | 17 | CreateObject(0); |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 208875845..d90b69e5a 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices { | |||
| 16 | 16 | ||
| 17 | class nvmap final : public nvdevice { | 17 | class nvmap final : public nvdevice { |
| 18 | public: | 18 | public: |
| 19 | explicit nvmap(Core::System& system); | 19 | explicit nvmap(Core::System& system_); |
| 20 | ~nvmap() override; | 20 | ~nvmap() override; |
| 21 | 21 | ||
| 22 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 22 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 2e1150867..dc9b9341f 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -22,19 +22,30 @@ void NVDRV::SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { | |||
| 22 | 22 | ||
| 23 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { | 23 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { |
| 24 | LOG_DEBUG(Service_NVDRV, "called"); | 24 | LOG_DEBUG(Service_NVDRV, "called"); |
| 25 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 26 | rb.Push(RESULT_SUCCESS); | ||
| 25 | 27 | ||
| 26 | if (!is_initialized) { | 28 | if (!is_initialized) { |
| 27 | ServiceError(ctx, NvResult::NotInitialized); | 29 | rb.Push<DeviceFD>(0); |
| 30 | rb.PushEnum(NvResult::NotInitialized); | ||
| 31 | |||
| 28 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | 32 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); |
| 29 | return; | 33 | return; |
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | const auto& buffer = ctx.ReadBuffer(); | 36 | const auto& buffer = ctx.ReadBuffer(); |
| 33 | const std::string device_name(buffer.begin(), buffer.end()); | 37 | const std::string device_name(buffer.begin(), buffer.end()); |
| 38 | |||
| 39 | if (device_name == "/dev/nvhost-prof-gpu") { | ||
| 40 | rb.Push<DeviceFD>(0); | ||
| 41 | rb.PushEnum(NvResult::NotSupported); | ||
| 42 | |||
| 43 | LOG_WARNING(Service_NVDRV, "/dev/nvhost-prof-gpu cannot be opened in production"); | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | |||
| 34 | DeviceFD fd = nvdrv->Open(device_name); | 47 | DeviceFD fd = nvdrv->Open(device_name); |
| 35 | 48 | ||
| 36 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 37 | rb.Push(RESULT_SUCCESS); | ||
| 38 | rb.Push<DeviceFD>(fd); | 49 | rb.Push<DeviceFD>(fd); |
| 39 | rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); | 50 | rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); |
| 40 | } | 51 | } |
| @@ -176,8 +187,8 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { | |||
| 176 | if (event_id < MaxNvEvents) { | 187 | if (event_id < MaxNvEvents) { |
| 177 | IPC::ResponseBuilder rb{ctx, 3, 1}; | 188 | IPC::ResponseBuilder rb{ctx, 3, 1}; |
| 178 | rb.Push(RESULT_SUCCESS); | 189 | rb.Push(RESULT_SUCCESS); |
| 179 | auto event = nvdrv->GetEvent(event_id); | 190 | auto& event = nvdrv->GetEvent(event_id); |
| 180 | event->Clear(); | 191 | event.Clear(); |
| 181 | rb.PushCopyObjects(event); | 192 | rb.PushCopyObjects(event); |
| 182 | rb.PushEnum(NvResult::Success); | 193 | rb.PushEnum(NvResult::Success); |
| 183 | } else { | 194 | } else { |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index ede77858a..74796dce1 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -42,9 +42,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger | |||
| 42 | Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} { | 42 | Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} { |
| 43 | auto& kernel = system.Kernel(); | 43 | auto& kernel = system.Kernel(); |
| 44 | for (u32 i = 0; i < MaxNvEvents; i++) { | 44 | for (u32 i = 0; i < MaxNvEvents; i++) { |
| 45 | std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); | 45 | events_interface.events[i].event = Kernel::KEvent::Create(kernel); |
| 46 | events_interface.events[i] = {Kernel::KEvent::Create(kernel, std::move(event_label))}; | 46 | events_interface.events[i].event->Initialize(fmt::format("NVDRV::NvEvent_{}", i)); |
| 47 | events_interface.events[i].event->Initialize(); | ||
| 48 | events_interface.status[i] = EventState::Free; | 47 | events_interface.status[i] = EventState::Free; |
| 49 | events_interface.registered[i] = false; | 48 | events_interface.registered[i] = false; |
| 50 | } | 49 | } |
| @@ -64,7 +63,12 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} { | |||
| 64 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager); | 63 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager); |
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | Module::~Module() = default; | 66 | Module::~Module() { |
| 67 | for (u32 i = 0; i < MaxNvEvents; i++) { | ||
| 68 | events_interface.events[i].event->Close(); | ||
| 69 | events_interface.events[i].event = nullptr; | ||
| 70 | } | ||
| 71 | } | ||
| 68 | 72 | ||
| 69 | NvResult Module::VerifyFD(DeviceFD fd) const { | 73 | NvResult Module::VerifyFD(DeviceFD fd) const { |
| 70 | if (fd < 0) { | 74 | if (fd < 0) { |
| @@ -172,16 +176,16 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { | |||
| 172 | if (events_interface.assigned_syncpt[i] == syncpoint_id && | 176 | if (events_interface.assigned_syncpt[i] == syncpoint_id && |
| 173 | events_interface.assigned_value[i] == value) { | 177 | events_interface.assigned_value[i] == value) { |
| 174 | events_interface.LiberateEvent(i); | 178 | events_interface.LiberateEvent(i); |
| 175 | events_interface.events[i].event->GetWritableEvent()->Signal(); | 179 | events_interface.events[i].event->GetWritableEvent().Signal(); |
| 176 | } | 180 | } |
| 177 | } | 181 | } |
| 178 | } | 182 | } |
| 179 | 183 | ||
| 180 | std::shared_ptr<Kernel::KReadableEvent> Module::GetEvent(const u32 event_id) const { | 184 | Kernel::KReadableEvent& Module::GetEvent(const u32 event_id) { |
| 181 | return events_interface.events[event_id].event->GetReadableEvent(); | 185 | return events_interface.events[event_id].event->GetReadableEvent(); |
| 182 | } | 186 | } |
| 183 | 187 | ||
| 184 | std::shared_ptr<Kernel::KWritableEvent> Module::GetEventWriteable(const u32 event_id) const { | 188 | Kernel::KWritableEvent& Module::GetEventWriteable(const u32 event_id) { |
| 185 | return events_interface.events[event_id].event->GetWritableEvent(); | 189 | return events_interface.events[event_id].event->GetWritableEvent(); |
| 186 | } | 190 | } |
| 187 | 191 | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 53719aadd..a43ceb7ae 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -35,7 +35,7 @@ class nvdevice; | |||
| 35 | 35 | ||
| 36 | /// Represents an Nvidia event | 36 | /// Represents an Nvidia event |
| 37 | struct NvEvent { | 37 | struct NvEvent { |
| 38 | std::shared_ptr<Kernel::KEvent> event; | 38 | Kernel::KEvent* event{}; |
| 39 | Fence fence{}; | 39 | Fence fence{}; |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| @@ -136,9 +136,9 @@ public: | |||
| 136 | 136 | ||
| 137 | void SignalSyncpt(const u32 syncpoint_id, const u32 value); | 137 | void SignalSyncpt(const u32 syncpoint_id, const u32 value); |
| 138 | 138 | ||
| 139 | std::shared_ptr<Kernel::KReadableEvent> GetEvent(u32 event_id) const; | 139 | Kernel::KReadableEvent& GetEvent(u32 event_id); |
| 140 | 140 | ||
| 141 | std::shared_ptr<Kernel::KWritableEvent> GetEventWriteable(u32 event_id) const; | 141 | Kernel::KWritableEvent& GetEventWriteable(u32 event_id); |
| 142 | 142 | ||
| 143 | private: | 143 | private: |
| 144 | /// Manages syncpoints on the host | 144 | /// Manages syncpoints on the host |
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/syncpoint_manager.cpp index 0151a03b7..3b6f55526 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/syncpoint_manager.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Nvidia { | 9 | namespace Service::Nvidia { |
| 10 | 10 | ||
| 11 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu) : gpu{gpu} {} | 11 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {} |
| 12 | 12 | ||
| 13 | SyncpointManager::~SyncpointManager() = default; | 13 | SyncpointManager::~SyncpointManager() = default; |
| 14 | 14 | ||
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.h b/src/core/hle/service/nvdrv/syncpoint_manager.h index d395c5d0b..99f286474 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/syncpoint_manager.h | |||
| @@ -18,7 +18,7 @@ namespace Service::Nvidia { | |||
| 18 | 18 | ||
| 19 | class SyncpointManager final { | 19 | class SyncpointManager final { |
| 20 | public: | 20 | public: |
| 21 | explicit SyncpointManager(Tegra::GPU& gpu); | 21 | explicit SyncpointManager(Tegra::GPU& gpu_); |
| 22 | ~SyncpointManager(); | 22 | ~SyncpointManager(); |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 7842a82ed..59ddf6298 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp | |||
| @@ -7,17 +7,16 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/k_event.h" | ||
| 11 | #include "core/hle/kernel/k_writable_event.h" | 10 | #include "core/hle/kernel/k_writable_event.h" |
| 12 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/service/nvflinger/buffer_queue.h" | 12 | #include "core/hle/service/nvflinger/buffer_queue.h" |
| 14 | 13 | ||
| 15 | namespace Service::NVFlinger { | 14 | namespace Service::NVFlinger { |
| 16 | 15 | ||
| 17 | BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) | 16 | BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_) |
| 18 | : id(id), layer_id(layer_id) { | 17 | : id(id_), layer_id(layer_id_), buffer_wait_event{kernel} { |
| 19 | buffer_wait_event = Kernel::KEvent::Create(kernel, "BufferQueue:WaitEvent"); | 18 | Kernel::KAutoObject::Create(std::addressof(buffer_wait_event)); |
| 20 | buffer_wait_event->Initialize(); | 19 | buffer_wait_event.Initialize("BufferQueue:WaitEvent"); |
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | BufferQueue::~BufferQueue() = default; | 22 | BufferQueue::~BufferQueue() = default; |
| @@ -42,7 +41,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) | |||
| 42 | .multi_fence = {}, | 41 | .multi_fence = {}, |
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | buffer_wait_event->GetWritableEvent()->Signal(); | 44 | buffer_wait_event.GetWritableEvent().Signal(); |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, | 47 | std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, |
| @@ -120,7 +119,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult | |||
| 120 | } | 119 | } |
| 121 | free_buffers_condition.notify_one(); | 120 | free_buffers_condition.notify_one(); |
| 122 | 121 | ||
| 123 | buffer_wait_event->GetWritableEvent()->Signal(); | 122 | buffer_wait_event.GetWritableEvent().Signal(); |
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { | 125 | std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { |
| @@ -155,7 +154,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) { | |||
| 155 | } | 154 | } |
| 156 | free_buffers_condition.notify_one(); | 155 | free_buffers_condition.notify_one(); |
| 157 | 156 | ||
| 158 | buffer_wait_event->GetWritableEvent()->Signal(); | 157 | buffer_wait_event.GetWritableEvent().Signal(); |
| 159 | } | 158 | } |
| 160 | 159 | ||
| 161 | void BufferQueue::Connect() { | 160 | void BufferQueue::Connect() { |
| @@ -170,7 +169,7 @@ void BufferQueue::Disconnect() { | |||
| 170 | std::unique_lock lock{queue_sequence_mutex}; | 169 | std::unique_lock lock{queue_sequence_mutex}; |
| 171 | queue_sequence.clear(); | 170 | queue_sequence.clear(); |
| 172 | } | 171 | } |
| 173 | buffer_wait_event->GetWritableEvent()->Signal(); | 172 | buffer_wait_event.GetWritableEvent().Signal(); |
| 174 | is_connect = false; | 173 | is_connect = false; |
| 175 | free_buffers_condition.notify_one(); | 174 | free_buffers_condition.notify_one(); |
| 176 | } | 175 | } |
| @@ -189,12 +188,12 @@ u32 BufferQueue::Query(QueryType type) { | |||
| 189 | return 0; | 188 | return 0; |
| 190 | } | 189 | } |
| 191 | 190 | ||
| 192 | std::shared_ptr<Kernel::KWritableEvent> BufferQueue::GetWritableBufferWaitEvent() const { | 191 | Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() { |
| 193 | return buffer_wait_event->GetWritableEvent(); | 192 | return buffer_wait_event.GetWritableEvent(); |
| 194 | } | 193 | } |
| 195 | 194 | ||
| 196 | std::shared_ptr<Kernel::KReadableEvent> BufferQueue::GetBufferWaitEvent() const { | 195 | Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() { |
| 197 | return buffer_wait_event->GetReadableEvent(); | 196 | return buffer_wait_event.GetReadableEvent(); |
| 198 | } | 197 | } |
| 199 | 198 | ||
| 200 | } // namespace Service::NVFlinger | 199 | } // namespace Service::NVFlinger |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 163fa4c54..61e337ac5 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h | |||
| @@ -13,7 +13,8 @@ | |||
| 13 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| 14 | #include "common/math_util.h" | 14 | #include "common/math_util.h" |
| 15 | #include "common/swap.h" | 15 | #include "common/swap.h" |
| 16 | #include "core/hle/kernel/object.h" | 16 | #include "core/hle/kernel/k_event.h" |
| 17 | #include "core/hle/kernel/k_readable_event.h" | ||
| 17 | #include "core/hle/service/nvdrv/nvdata.h" | 18 | #include "core/hle/service/nvdrv/nvdata.h" |
| 18 | 19 | ||
| 19 | namespace Kernel { | 20 | namespace Kernel { |
| @@ -53,7 +54,7 @@ public: | |||
| 53 | NativeWindowFormat = 2, | 54 | NativeWindowFormat = 2, |
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | explicit BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id); | 57 | explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_); |
| 57 | ~BufferQueue(); | 58 | ~BufferQueue(); |
| 58 | 59 | ||
| 59 | enum class BufferTransformFlags : u32 { | 60 | enum class BufferTransformFlags : u32 { |
| @@ -115,9 +116,9 @@ public: | |||
| 115 | return is_connect; | 116 | return is_connect; |
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | std::shared_ptr<Kernel::KWritableEvent> GetWritableBufferWaitEvent() const; | 119 | Kernel::KWritableEvent& GetWritableBufferWaitEvent(); |
| 119 | 120 | ||
| 120 | std::shared_ptr<Kernel::KReadableEvent> GetBufferWaitEvent() const; | 121 | Kernel::KReadableEvent& GetBufferWaitEvent(); |
| 121 | 122 | ||
| 122 | private: | 123 | private: |
| 123 | BufferQueue(const BufferQueue&) = delete; | 124 | BufferQueue(const BufferQueue&) = delete; |
| @@ -129,7 +130,7 @@ private: | |||
| 129 | std::list<u32> free_buffers; | 130 | std::list<u32> free_buffers; |
| 130 | std::array<Buffer, buffer_slots> buffers; | 131 | std::array<Buffer, buffer_slots> buffers; |
| 131 | std::list<u32> queue_sequence; | 132 | std::list<u32> queue_sequence; |
| 132 | std::shared_ptr<Kernel::KEvent> buffer_wait_event; | 133 | Kernel::KEvent buffer_wait_event; |
| 133 | 134 | ||
| 134 | std::mutex free_buffers_mutex; | 135 | std::mutex free_buffers_mutex; |
| 135 | std::condition_variable free_buffers_condition; | 136 | std::condition_variable free_buffers_condition; |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 539b02bc4..d1dbc659b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -61,7 +61,7 @@ void NVFlinger::SplitVSync() { | |||
| 61 | } | 61 | } |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | NVFlinger::NVFlinger(Core::System& system) : system(system) { | 64 | NVFlinger::NVFlinger(Core::System& system_) : system(system_) { |
| 65 | displays.emplace_back(0, "Default", system); | 65 | displays.emplace_back(0, "Default", system); |
| 66 | displays.emplace_back(1, "External", system); | 66 | displays.emplace_back(1, "External", system); |
| 67 | displays.emplace_back(2, "Edid", system); | 67 | displays.emplace_back(2, "Edid", system); |
| @@ -72,7 +72,7 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { | |||
| 72 | // Schedule the screen composition events | 72 | // Schedule the screen composition events |
| 73 | composition_event = Core::Timing::CreateEvent( | 73 | composition_event = Core::Timing::CreateEvent( |
| 74 | "ScreenComposition", [this](std::uintptr_t, std::chrono::nanoseconds ns_late) { | 74 | "ScreenComposition", [this](std::uintptr_t, std::chrono::nanoseconds ns_late) { |
| 75 | const auto guard = Lock(); | 75 | const auto lock_guard = Lock(); |
| 76 | Compose(); | 76 | Compose(); |
| 77 | 77 | ||
| 78 | const auto ticks = std::chrono::nanoseconds{GetNextTicks()}; | 78 | const auto ticks = std::chrono::nanoseconds{GetNextTicks()}; |
| @@ -112,7 +112,7 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { | 114 | std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { |
| 115 | const auto guard = Lock(); | 115 | const auto lock_guard = Lock(); |
| 116 | 116 | ||
| 117 | LOG_DEBUG(Service, "Opening \"{}\" display", name); | 117 | LOG_DEBUG(Service, "Opening \"{}\" display", name); |
| 118 | 118 | ||
| @@ -131,7 +131,7 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { | 133 | std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { |
| 134 | const auto guard = Lock(); | 134 | const auto lock_guard = Lock(); |
| 135 | auto* const display = FindDisplay(display_id); | 135 | auto* const display = FindDisplay(display_id); |
| 136 | 136 | ||
| 137 | if (display == nullptr) { | 137 | if (display == nullptr) { |
| @@ -139,24 +139,28 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | const u64 layer_id = next_layer_id++; | 141 | const u64 layer_id = next_layer_id++; |
| 142 | CreateLayerAtId(*display, layer_id); | ||
| 143 | return layer_id; | ||
| 144 | } | ||
| 145 | |||
| 146 | void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | ||
| 142 | const u32 buffer_queue_id = next_buffer_queue_id++; | 147 | const u32 buffer_queue_id = next_buffer_queue_id++; |
| 143 | buffer_queues.emplace_back( | 148 | buffer_queues.emplace_back( |
| 144 | std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id)); | 149 | std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id)); |
| 145 | display->CreateLayer(layer_id, *buffer_queues.back()); | 150 | display.CreateLayer(layer_id, *buffer_queues.back()); |
| 146 | return layer_id; | ||
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | void NVFlinger::CloseLayer(u64 layer_id) { | 153 | void NVFlinger::CloseLayer(u64 layer_id) { |
| 150 | const auto guard = Lock(); | 154 | const auto lock_guard = Lock(); |
| 151 | 155 | ||
| 152 | for (auto& display : displays) { | 156 | for (auto& display : displays) { |
| 153 | display.CloseLayer(layer_id); | 157 | display.CloseLayer(layer_id); |
| 154 | } | 158 | } |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { | 161 | std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { |
| 158 | const auto guard = Lock(); | 162 | const auto lock_guard = Lock(); |
| 159 | const auto* const layer = FindLayer(display_id, layer_id); | 163 | const auto* const layer = FindOrCreateLayer(display_id, layer_id); |
| 160 | 164 | ||
| 161 | if (layer == nullptr) { | 165 | if (layer == nullptr) { |
| 162 | return std::nullopt; | 166 | return std::nullopt; |
| @@ -165,19 +169,19 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co | |||
| 165 | return layer->GetBufferQueue().GetId(); | 169 | return layer->GetBufferQueue().GetId(); |
| 166 | } | 170 | } |
| 167 | 171 | ||
| 168 | std::shared_ptr<Kernel::KReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const { | 172 | Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) { |
| 169 | const auto guard = Lock(); | 173 | const auto lock_guard = Lock(); |
| 170 | auto* const display = FindDisplay(display_id); | 174 | auto* const display = FindDisplay(display_id); |
| 171 | 175 | ||
| 172 | if (display == nullptr) { | 176 | if (display == nullptr) { |
| 173 | return nullptr; | 177 | return nullptr; |
| 174 | } | 178 | } |
| 175 | 179 | ||
| 176 | return display->GetVSyncEvent(); | 180 | return &display->GetVSyncEvent(); |
| 177 | } | 181 | } |
| 178 | 182 | ||
| 179 | BufferQueue* NVFlinger::FindBufferQueue(u32 id) { | 183 | BufferQueue* NVFlinger::FindBufferQueue(u32 id) { |
| 180 | const auto guard = Lock(); | 184 | const auto lock_guard = Lock(); |
| 181 | const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(), | 185 | const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(), |
| 182 | [id](const auto& queue) { return queue->GetId() == id; }); | 186 | [id](const auto& queue) { return queue->GetId() == id; }); |
| 183 | 187 | ||
| @@ -232,6 +236,24 @@ const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { | |||
| 232 | return display->FindLayer(layer_id); | 236 | return display->FindLayer(layer_id); |
| 233 | } | 237 | } |
| 234 | 238 | ||
| 239 | VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { | ||
| 240 | auto* const display = FindDisplay(display_id); | ||
| 241 | |||
| 242 | if (display == nullptr) { | ||
| 243 | return nullptr; | ||
| 244 | } | ||
| 245 | |||
| 246 | auto* layer = display->FindLayer(layer_id); | ||
| 247 | |||
| 248 | if (layer == nullptr) { | ||
| 249 | LOG_DEBUG(Service, "Layer at id {} not found. Trying to create it.", layer_id); | ||
| 250 | CreateLayerAtId(*display, layer_id); | ||
| 251 | return display->FindLayer(layer_id); | ||
| 252 | } | ||
| 253 | |||
| 254 | return layer; | ||
| 255 | } | ||
| 256 | |||
| 235 | void NVFlinger::Compose() { | 257 | void NVFlinger::Compose() { |
| 236 | for (auto& display : displays) { | 258 | for (auto& display : displays) { |
| 237 | // Trigger vsync for this display at the end of drawing | 259 | // Trigger vsync for this display at the end of drawing |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 6fe2c7f2a..d80fd07ef 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <list> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | #include <optional> | 11 | #include <optional> |
| @@ -14,7 +15,6 @@ | |||
| 14 | #include <vector> | 15 | #include <vector> |
| 15 | 16 | ||
| 16 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 17 | #include "core/hle/kernel/object.h" | ||
| 18 | 18 | ||
| 19 | namespace Common { | 19 | namespace Common { |
| 20 | class Event; | 20 | class Event; |
| @@ -45,7 +45,7 @@ class BufferQueue; | |||
| 45 | 45 | ||
| 46 | class NVFlinger final { | 46 | class NVFlinger final { |
| 47 | public: | 47 | public: |
| 48 | explicit NVFlinger(Core::System& system); | 48 | explicit NVFlinger(Core::System& system_); |
| 49 | ~NVFlinger(); | 49 | ~NVFlinger(); |
| 50 | 50 | ||
| 51 | /// Sets the NVDrv module instance to use to send buffers to the GPU. | 51 | /// Sets the NVDrv module instance to use to send buffers to the GPU. |
| @@ -67,12 +67,12 @@ public: | |||
| 67 | /// Finds the buffer queue ID of the specified layer in the specified display. | 67 | /// Finds the buffer queue ID of the specified layer in the specified display. |
| 68 | /// | 68 | /// |
| 69 | /// If an invalid display ID or layer ID is provided, then an empty optional is returned. | 69 | /// If an invalid display ID or layer ID is provided, then an empty optional is returned. |
| 70 | [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const; | 70 | [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id); |
| 71 | 71 | ||
| 72 | /// Gets the vsync event for the specified display. | 72 | /// Gets the vsync event for the specified display. |
| 73 | /// | 73 | /// |
| 74 | /// If an invalid display ID is provided, then nullptr is returned. | 74 | /// If an invalid display ID is provided, then nullptr is returned. |
| 75 | [[nodiscard]] std::shared_ptr<Kernel::KReadableEvent> FindVsyncEvent(u64 display_id) const; | 75 | [[nodiscard]] Kernel::KReadableEvent* FindVsyncEvent(u64 display_id); |
| 76 | 76 | ||
| 77 | /// Obtains a buffer queue identified by the ID. | 77 | /// Obtains a buffer queue identified by the ID. |
| 78 | [[nodiscard]] BufferQueue* FindBufferQueue(u32 id); | 78 | [[nodiscard]] BufferQueue* FindBufferQueue(u32 id); |
| @@ -100,13 +100,21 @@ private: | |||
| 100 | /// Finds the layer identified by the specified ID in the desired display. | 100 | /// Finds the layer identified by the specified ID in the desired display. |
| 101 | [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; | 101 | [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; |
| 102 | 102 | ||
| 103 | /// Finds the layer identified by the specified ID in the desired display, | ||
| 104 | /// or creates the layer if it is not found. | ||
| 105 | /// To be used when the system expects the specified ID to already exist. | ||
| 106 | [[nodiscard]] VI::Layer* FindOrCreateLayer(u64 display_id, u64 layer_id); | ||
| 107 | |||
| 108 | /// Creates a layer with the specified layer ID in the desired display. | ||
| 109 | void CreateLayerAtId(VI::Display& display, u64 layer_id); | ||
| 110 | |||
| 103 | static void VSyncThread(NVFlinger& nv_flinger); | 111 | static void VSyncThread(NVFlinger& nv_flinger); |
| 104 | 112 | ||
| 105 | void SplitVSync(); | 113 | void SplitVSync(); |
| 106 | 114 | ||
| 107 | std::shared_ptr<Nvidia::Module> nvdrv; | 115 | std::shared_ptr<Nvidia::Module> nvdrv; |
| 108 | 116 | ||
| 109 | std::vector<VI::Display> displays; | 117 | std::list<VI::Display> displays; |
| 110 | std::vector<std::unique_ptr<BufferQueue>> buffer_queues; | 118 | std::vector<std::unique_ptr<BufferQueue>> buffer_queues; |
| 111 | 119 | ||
| 112 | /// Id to use for the next layer that is created, this counter is shared among all displays. | 120 | /// Id to use for the next layer that is created, this counter is shared among all displays. |
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp index dc59702f1..1c3d81143 100644 --- a/src/core/hle/service/pctl/module.cpp +++ b/src/core/hle/service/pctl/module.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/file_sys/control_metadata.h" | 7 | #include "core/file_sys/control_metadata.h" |
| 8 | #include "core/file_sys/patch_manager.h" | 8 | #include "core/file_sys/patch_manager.h" |
| 9 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/k_process.h" |
| 11 | #include "core/hle/service/pctl/module.h" | 11 | #include "core/hle/service/pctl/module.h" |
| 12 | #include "core/hle/service/pctl/pctl.h" | 12 | #include "core/hle/service/pctl/pctl.h" |
| 13 | 13 | ||
| @@ -24,9 +24,8 @@ constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; | |||
| 24 | 24 | ||
| 25 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { | 25 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { |
| 26 | public: | 26 | public: |
| 27 | explicit IParentalControlService(Core::System& system_, Capability capability) | 27 | explicit IParentalControlService(Core::System& system_, Capability capability_) |
| 28 | : ServiceFramework{system_, "IParentalControlService"}, system(system_), | 28 | : ServiceFramework{system_, "IParentalControlService"}, capability{capability_} { |
| 29 | capability(capability) { | ||
| 30 | // clang-format off | 29 | // clang-format off |
| 31 | static const FunctionInfo functions[] = { | 30 | static const FunctionInfo functions[] = { |
| 32 | {1, &IParentalControlService::Initialize, "Initialize"}, | 31 | {1, &IParentalControlService::Initialize, "Initialize"}, |
| @@ -362,8 +361,6 @@ private: | |||
| 362 | States states{}; | 361 | States states{}; |
| 363 | ParentalControlSettings settings{}; | 362 | ParentalControlSettings settings{}; |
| 364 | std::array<char, 8> pin_code{}; | 363 | std::array<char, 8> pin_code{}; |
| 365 | bool can_use_stereo_vision = true; | ||
| 366 | Core::System& system; | ||
| 367 | Capability capability{}; | 364 | Capability capability{}; |
| 368 | }; | 365 | }; |
| 369 | 366 | ||
| @@ -386,8 +383,8 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext | |||
| 386 | } | 383 | } |
| 387 | 384 | ||
| 388 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, | 385 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, |
| 389 | const char* name, Capability capability) | 386 | const char* name_, Capability capability_) |
| 390 | : ServiceFramework{system_, name}, module{std::move(module_)}, capability(capability) {} | 387 | : ServiceFramework{system_, name_}, module{std::move(module_)}, capability{capability_} {} |
| 391 | 388 | ||
| 392 | Module::Interface::~Interface() = default; | 389 | Module::Interface::~Interface() = default; |
| 393 | 390 | ||
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h index 032481b00..f25c5c557 100644 --- a/src/core/hle/service/pctl/module.h +++ b/src/core/hle/service/pctl/module.h | |||
| @@ -28,8 +28,8 @@ class Module final { | |||
| 28 | public: | 28 | public: |
| 29 | class Interface : public ServiceFramework<Interface> { | 29 | class Interface : public ServiceFramework<Interface> { |
| 30 | public: | 30 | public: |
| 31 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name, | 31 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, |
| 32 | Capability capability); | 32 | const char* name_, Capability capability_); |
| 33 | ~Interface() override; | 33 | ~Interface() override; |
| 34 | 34 | ||
| 35 | void CreateService(Kernel::HLERequestContext& ctx); | 35 | void CreateService(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp index e4d155c86..908e0a1e3 100644 --- a/src/core/hle/service/pctl/pctl.cpp +++ b/src/core/hle/service/pctl/pctl.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | namespace Service::PCTL { | 7 | namespace Service::PCTL { |
| 8 | 8 | ||
| 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, | 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 10 | Capability capability) | 10 | Capability capability_) |
| 11 | : Interface{system_, std::move(module_), name, capability} { | 11 | : Interface{system_, std::move(module_), name, capability_} { |
| 12 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 13 | {0, &PCTL::CreateService, "CreateService"}, | 13 | {0, &PCTL::CreateService, "CreateService"}, |
| 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, | 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, |
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h index fd0a1e486..ea3b97823 100644 --- a/src/core/hle/service/pctl/pctl.h +++ b/src/core/hle/service/pctl/pctl.h | |||
| @@ -15,7 +15,7 @@ namespace Service::PCTL { | |||
| 15 | class PCTL final : public Module::Interface { | 15 | class PCTL final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, | 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 18 | Capability capability); | 18 | Capability capability_); |
| 19 | ~PCTL() override; | 19 | ~PCTL() override; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 68736c40c..a43185c44 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/k_process.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | 8 | #include "core/hle/kernel/kernel.h" |
| 8 | #include "core/hle/kernel/process.h" | ||
| 9 | #include "core/hle/service/pm/pm.h" | 9 | #include "core/hle/service/pm/pm.h" |
| 10 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 11 | 11 | ||
| @@ -17,9 +17,9 @@ constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; | |||
| 17 | 17 | ||
| 18 | constexpr u64 NO_PROCESS_FOUND_PID{0}; | 18 | constexpr u64 NO_PROCESS_FOUND_PID{0}; |
| 19 | 19 | ||
| 20 | std::optional<std::shared_ptr<Kernel::Process>> SearchProcessList( | 20 | std::optional<Kernel::KProcess*> SearchProcessList( |
| 21 | const std::vector<std::shared_ptr<Kernel::Process>>& process_list, | 21 | const std::vector<Kernel::KProcess*>& process_list, |
| 22 | std::function<bool(const std::shared_ptr<Kernel::Process>&)> predicate) { | 22 | std::function<bool(Kernel::KProcess*)> predicate) { |
| 23 | const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); | 23 | const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); |
| 24 | 24 | ||
| 25 | if (iter == process_list.end()) { | 25 | if (iter == process_list.end()) { |
| @@ -30,9 +30,9 @@ std::optional<std::shared_ptr<Kernel::Process>> SearchProcessList( | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, | 32 | void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, |
| 33 | const std::vector<std::shared_ptr<Kernel::Process>>& process_list) { | 33 | const std::vector<Kernel::KProcess*>& process_list) { |
| 34 | const auto process = SearchProcessList(process_list, [](const auto& process) { | 34 | const auto process = SearchProcessList(process_list, [](const auto& proc) { |
| 35 | return process->GetProcessID() == Kernel::Process::ProcessIDMin; | 35 | return proc->GetProcessID() == Kernel::KProcess::ProcessIDMin; |
| 36 | }); | 36 | }); |
| 37 | 37 | ||
| 38 | IPC::ResponseBuilder rb{ctx, 4}; | 38 | IPC::ResponseBuilder rb{ctx, 4}; |
| @@ -100,8 +100,8 @@ private: | |||
| 100 | LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); | 100 | LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); |
| 101 | 101 | ||
| 102 | const auto process = | 102 | const auto process = |
| 103 | SearchProcessList(kernel.GetProcessList(), [title_id](const auto& process) { | 103 | SearchProcessList(kernel.GetProcessList(), [title_id](const auto& proc) { |
| 104 | return process->GetTitleID() == title_id; | 104 | return proc->GetTitleID() == title_id; |
| 105 | }); | 105 | }); |
| 106 | 106 | ||
| 107 | if (!process.has_value()) { | 107 | if (!process.has_value()) { |
| @@ -125,8 +125,7 @@ private: | |||
| 125 | 125 | ||
| 126 | class Info final : public ServiceFramework<Info> { | 126 | class Info final : public ServiceFramework<Info> { |
| 127 | public: | 127 | public: |
| 128 | explicit Info(Core::System& system_, | 128 | explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) |
| 129 | const std::vector<std::shared_ptr<Kernel::Process>>& process_list_) | ||
| 130 | : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { | 129 | : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { |
| 131 | static const FunctionInfo functions[] = { | 130 | static const FunctionInfo functions[] = { |
| 132 | {0, &Info::GetTitleId, "GetTitleId"}, | 131 | {0, &Info::GetTitleId, "GetTitleId"}, |
| @@ -141,8 +140,8 @@ private: | |||
| 141 | 140 | ||
| 142 | LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); | 141 | LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); |
| 143 | 142 | ||
| 144 | const auto process = SearchProcessList(process_list, [process_id](const auto& process) { | 143 | const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { |
| 145 | return process->GetProcessID() == process_id; | 144 | return proc->GetProcessID() == process_id; |
| 146 | }); | 145 | }); |
| 147 | 146 | ||
| 148 | if (!process.has_value()) { | 147 | if (!process.has_value()) { |
| @@ -156,7 +155,7 @@ private: | |||
| 156 | rb.Push((*process)->GetTitleID()); | 155 | rb.Push((*process)->GetTitleID()); |
| 157 | } | 156 | } |
| 158 | 157 | ||
| 159 | const std::vector<std::shared_ptr<Kernel::Process>>& process_list; | 158 | const std::vector<Kernel::KProcess*>& process_list; |
| 160 | }; | 159 | }; |
| 161 | 160 | ||
| 162 | class Shell final : public ServiceFramework<Shell> { | 161 | class Shell final : public ServiceFramework<Shell> { |
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index d5b3b17a5..c914f8145 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 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/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/process.h" | 9 | #include "core/hle/kernel/k_process.h" |
| 10 | #include "core/hle/service/acc/profile_manager.h" | 10 | #include "core/hle/service/acc/profile_manager.h" |
| 11 | #include "core/hle/service/prepo/prepo.h" | 11 | #include "core/hle/service/prepo/prepo.h" |
| 12 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| @@ -60,7 +60,7 @@ private: | |||
| 60 | const auto process_id = rp.PopRaw<u64>(); | 60 | const auto process_id = rp.PopRaw<u64>(); |
| 61 | 61 | ||
| 62 | const auto data1 = ctx.ReadBuffer(0); | 62 | const auto data1 = ctx.ReadBuffer(0); |
| 63 | const auto data2 = [ctx] { | 63 | const auto data2 = [&ctx] { |
| 64 | if (ctx.CanReadBuffer(1)) { | 64 | if (ctx.CanReadBuffer(1)) { |
| 65 | return ctx.ReadBuffer(1); | 65 | return ctx.ReadBuffer(1); |
| 66 | } | 66 | } |
| @@ -87,7 +87,7 @@ private: | |||
| 87 | const auto process_id = rp.PopRaw<u64>(); | 87 | const auto process_id = rp.PopRaw<u64>(); |
| 88 | 88 | ||
| 89 | const auto data1 = ctx.ReadBuffer(0); | 89 | const auto data1 = ctx.ReadBuffer(0); |
| 90 | const auto data2 = [ctx] { | 90 | const auto data2 = [&ctx] { |
| 91 | if (ctx.CanReadBuffer(1)) { | 91 | if (ctx.CanReadBuffer(1)) { |
| 92 | return ctx.ReadBuffer(1); | 92 | return ctx.ReadBuffer(1); |
| 93 | } | 93 | } |
| @@ -139,7 +139,7 @@ private: | |||
| 139 | const auto title_id = rp.PopRaw<u64>(); | 139 | const auto title_id = rp.PopRaw<u64>(); |
| 140 | 140 | ||
| 141 | const auto data1 = ctx.ReadBuffer(0); | 141 | const auto data1 = ctx.ReadBuffer(0); |
| 142 | const auto data2 = [ctx] { | 142 | const auto data2 = [&ctx] { |
| 143 | if (ctx.CanReadBuffer(1)) { | 143 | if (ctx.CanReadBuffer(1)) { |
| 144 | return ctx.ReadBuffer(1); | 144 | return ctx.ReadBuffer(1); |
| 145 | } | 145 | } |
| @@ -163,7 +163,7 @@ private: | |||
| 163 | const auto title_id = rp.PopRaw<u64>(); | 163 | const auto title_id = rp.PopRaw<u64>(); |
| 164 | 164 | ||
| 165 | const auto data1 = ctx.ReadBuffer(0); | 165 | const auto data1 = ctx.ReadBuffer(0); |
| 166 | const auto data2 = [ctx] { | 166 | const auto data2 = [&ctx] { |
| 167 | if (ctx.CanReadBuffer(1)) { | 167 | if (ctx.CanReadBuffer(1)) { |
| 168 | return ctx.ReadBuffer(1); | 168 | return ctx.ReadBuffer(1); |
| 169 | } | 169 | } |
diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 26ed52273..bb7af9217 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp | |||
| @@ -19,7 +19,8 @@ namespace Service::PSM { | |||
| 19 | 19 | ||
| 20 | class IPsmSession final : public ServiceFramework<IPsmSession> { | 20 | class IPsmSession final : public ServiceFramework<IPsmSession> { |
| 21 | public: | 21 | public: |
| 22 | explicit IPsmSession(Core::System& system_) : ServiceFramework{system_, "IPsmSession"} { | 22 | explicit IPsmSession(Core::System& system_) |
| 23 | : ServiceFramework{system_, "IPsmSession"}, state_change_event{system.Kernel()} { | ||
| 23 | // clang-format off | 24 | // clang-format off |
| 24 | static const FunctionInfo functions[] = { | 25 | static const FunctionInfo functions[] = { |
| 25 | {0, &IPsmSession::BindStateChangeEvent, "BindStateChangeEvent"}, | 26 | {0, &IPsmSession::BindStateChangeEvent, "BindStateChangeEvent"}, |
| @@ -32,28 +33,27 @@ public: | |||
| 32 | 33 | ||
| 33 | RegisterHandlers(functions); | 34 | RegisterHandlers(functions); |
| 34 | 35 | ||
| 35 | state_change_event = | 36 | Kernel::KAutoObject::Create(std::addressof(state_change_event)); |
| 36 | Kernel::KEvent::Create(system_.Kernel(), "IPsmSession::state_change_event"); | 37 | state_change_event.Initialize("IPsmSession::state_change_event"); |
| 37 | state_change_event->Initialize(); | ||
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | ~IPsmSession() override = default; | 40 | ~IPsmSession() override = default; |
| 41 | 41 | ||
| 42 | void SignalChargerTypeChanged() { | 42 | void SignalChargerTypeChanged() { |
| 43 | if (should_signal && should_signal_charger_type) { | 43 | if (should_signal && should_signal_charger_type) { |
| 44 | state_change_event->GetWritableEvent()->Signal(); | 44 | state_change_event.GetWritableEvent().Signal(); |
| 45 | } | 45 | } |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | void SignalPowerSupplyChanged() { | 48 | void SignalPowerSupplyChanged() { |
| 49 | if (should_signal && should_signal_power_supply) { | 49 | if (should_signal && should_signal_power_supply) { |
| 50 | state_change_event->GetWritableEvent()->Signal(); | 50 | state_change_event.GetWritableEvent().Signal(); |
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void SignalBatteryVoltageStateChanged() { | 54 | void SignalBatteryVoltageStateChanged() { |
| 55 | if (should_signal && should_signal_battery_voltage) { | 55 | if (should_signal && should_signal_battery_voltage) { |
| 56 | state_change_event->GetWritableEvent()->Signal(); | 56 | state_change_event.GetWritableEvent().Signal(); |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -65,7 +65,7 @@ private: | |||
| 65 | 65 | ||
| 66 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 66 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 67 | rb.Push(RESULT_SUCCESS); | 67 | rb.Push(RESULT_SUCCESS); |
| 68 | rb.PushCopyObjects(state_change_event->GetReadableEvent()); | 68 | rb.PushCopyObjects(state_change_event.GetReadableEvent()); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { | 71 | void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { |
| @@ -114,7 +114,7 @@ private: | |||
| 114 | bool should_signal_power_supply{}; | 114 | bool should_signal_power_supply{}; |
| 115 | bool should_signal_battery_voltage{}; | 115 | bool should_signal_battery_voltage{}; |
| 116 | bool should_signal{}; | 116 | bool should_signal{}; |
| 117 | std::shared_ptr<Kernel::KEvent> state_change_event; | 117 | Kernel::KEvent state_change_event; |
| 118 | }; | 118 | }; |
| 119 | 119 | ||
| 120 | class PSM final : public ServiceFramework<PSM> { | 120 | class PSM final : public ServiceFramework<PSM> { |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 41a502d8d..2c9b2ce6d 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -11,11 +11,11 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/hle/ipc.h" | 12 | #include "core/hle/ipc.h" |
| 13 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| 14 | #include "core/hle/kernel/client_port.h" | 14 | #include "core/hle/kernel/k_client_port.h" |
| 15 | #include "core/hle/kernel/k_process.h" | ||
| 16 | #include "core/hle/kernel/k_server_port.h" | ||
| 15 | #include "core/hle/kernel/k_thread.h" | 17 | #include "core/hle/kernel/k_thread.h" |
| 16 | #include "core/hle/kernel/kernel.h" | 18 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/process.h" | ||
| 18 | #include "core/hle/kernel/server_port.h" | ||
| 19 | #include "core/hle/service/acc/acc.h" | 19 | #include "core/hle/service/acc/acc.h" |
| 20 | #include "core/hle/service/am/am.h" | 20 | #include "core/hle/service/am/am.h" |
| 21 | #include "core/hle/service/aoc/aoc_u.h" | 21 | #include "core/hle/service/aoc/aoc_u.h" |
| @@ -111,16 +111,18 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) | |||
| 111 | port_installed = true; | 111 | port_installed = true; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) { | 114 | Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) { |
| 115 | const auto guard = LockService(); | 115 | const auto guard = LockService(); |
| 116 | 116 | ||
| 117 | ASSERT(!port_installed); | 117 | ASSERT(!port_installed); |
| 118 | 118 | ||
| 119 | auto [server_port, client_port] = | 119 | auto* port = Kernel::KPort::Create(kernel); |
| 120 | Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name); | 120 | port->Initialize(max_sessions, false, service_name); |
| 121 | server_port->SetHleHandler(shared_from_this()); | 121 | port->GetServerPort().SetHleHandler(shared_from_this()); |
| 122 | kernel.AddNamedPort(service_name, std::move(client_port)); | 122 | |
| 123 | port_installed = true; | 123 | port_installed = true; |
| 124 | |||
| 125 | return port->GetClientPort(); | ||
| 124 | } | 126 | } |
| 125 | 127 | ||
| 126 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { | 128 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { |
| @@ -131,6 +133,16 @@ void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* function | |||
| 131 | } | 133 | } |
| 132 | } | 134 | } |
| 133 | 135 | ||
| 136 | void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, | ||
| 137 | std::size_t n) { | ||
| 138 | handlers_tipc.reserve(handlers_tipc.size() + n); | ||
| 139 | for (std::size_t i = 0; i < n; ++i) { | ||
| 140 | // Usually this array is sorted by id already, so hint to insert at the end | ||
| 141 | handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, | ||
| 142 | functions[i]); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 134 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, | 146 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, |
| 135 | const FunctionInfoBase* info) { | 147 | const FunctionInfoBase* info) { |
| 136 | auto cmd_buf = ctx.CommandBuffer(); | 148 | auto cmd_buf = ctx.CommandBuffer(); |
| @@ -165,33 +177,55 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { | |||
| 165 | handler_invoker(this, info->handler_callback, ctx); | 177 | handler_invoker(this, info->handler_callback, ctx); |
| 166 | } | 178 | } |
| 167 | 179 | ||
| 168 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) { | 180 | void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { |
| 181 | boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; | ||
| 182 | |||
| 183 | itr = handlers_tipc.find(ctx.GetCommand()); | ||
| 184 | |||
| 185 | const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; | ||
| 186 | if (info == nullptr || info->handler_callback == nullptr) { | ||
| 187 | return ReportUnimplementedFunction(ctx, info); | ||
| 188 | } | ||
| 189 | |||
| 190 | LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); | ||
| 191 | handler_invoker(this, info->handler_callback, ctx); | ||
| 192 | } | ||
| 193 | |||
| 194 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | ||
| 195 | Kernel::HLERequestContext& ctx) { | ||
| 169 | const auto guard = LockService(); | 196 | const auto guard = LockService(); |
| 170 | 197 | ||
| 171 | switch (context.GetCommandType()) { | 198 | switch (ctx.GetCommandType()) { |
| 172 | case IPC::CommandType::Close: { | 199 | case IPC::CommandType::Close: |
| 173 | IPC::ResponseBuilder rb{context, 2}; | 200 | case IPC::CommandType::TIPC_Close: { |
| 201 | session.Close(); | ||
| 202 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 174 | rb.Push(RESULT_SUCCESS); | 203 | rb.Push(RESULT_SUCCESS); |
| 175 | return IPC::ERR_REMOTE_PROCESS_DEAD; | 204 | return IPC::ERR_REMOTE_PROCESS_DEAD; |
| 176 | } | 205 | } |
| 177 | case IPC::CommandType::ControlWithContext: | 206 | case IPC::CommandType::ControlWithContext: |
| 178 | case IPC::CommandType::Control: { | 207 | case IPC::CommandType::Control: { |
| 179 | system.ServiceManager().InvokeControlRequest(context); | 208 | system.ServiceManager().InvokeControlRequest(ctx); |
| 180 | break; | 209 | break; |
| 181 | } | 210 | } |
| 182 | case IPC::CommandType::RequestWithContext: | 211 | case IPC::CommandType::RequestWithContext: |
| 183 | case IPC::CommandType::Request: { | 212 | case IPC::CommandType::Request: { |
| 184 | InvokeRequest(context); | 213 | InvokeRequest(ctx); |
| 185 | break; | 214 | break; |
| 186 | } | 215 | } |
| 187 | default: | 216 | default: |
| 188 | UNIMPLEMENTED_MSG("command_type={}", context.GetCommandType()); | 217 | if (ctx.IsTipc()) { |
| 218 | InvokeRequestTipc(ctx); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 222 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); | ||
| 189 | } | 223 | } |
| 190 | 224 | ||
| 191 | // If emulation was shutdown, we are closing service threads, do not write the response back to | 225 | // If emulation was shutdown, we are closing service threads, do not write the response back to |
| 192 | // memory that may be shutting down as well. | 226 | // memory that may be shutting down as well. |
| 193 | if (system.IsPoweredOn()) { | 227 | if (system.IsPoweredOn()) { |
| 194 | context.WriteToOutgoingCommandBuffer(context.GetThread()); | 228 | ctx.WriteToOutgoingCommandBuffer(ctx.GetThread()); |
| 195 | } | 229 | } |
| 196 | 230 | ||
| 197 | return RESULT_SUCCESS; | 231 | return RESULT_SUCCESS; |
| @@ -206,7 +240,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system | |||
| 206 | 240 | ||
| 207 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | 241 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); |
| 208 | 242 | ||
| 209 | SM::ServiceManager::InstallInterfaces(sm, system); | 243 | system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); |
| 210 | 244 | ||
| 211 | Account::InstallInterfaces(system); | 245 | Account::InstallInterfaces(system); |
| 212 | AM::InstallInterfaces(*sm, *nv_flinger, system); | 246 | AM::InstallInterfaces(*sm, *nv_flinger, system); |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 916445517..4c048173b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/spin_lock.h" | 12 | #include "common/spin_lock.h" |
| 13 | #include "core/hle/kernel/hle_ipc.h" | 13 | #include "core/hle/kernel/hle_ipc.h" |
| 14 | #include "core/hle/kernel/object.h" | ||
| 15 | 14 | ||
| 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 17 | // Namespace Service | 16 | // Namespace Service |
| @@ -21,10 +20,9 @@ class System; | |||
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | namespace Kernel { | 22 | namespace Kernel { |
| 24 | class ClientPort; | ||
| 25 | class ServerPort; | ||
| 26 | class ServerSession; | ||
| 27 | class HLERequestContext; | 23 | class HLERequestContext; |
| 24 | class KClientPort; | ||
| 25 | class KServerSession; | ||
| 28 | } // namespace Kernel | 26 | } // namespace Kernel |
| 29 | 27 | ||
| 30 | namespace Service { | 28 | namespace Service { |
| @@ -68,12 +66,19 @@ public: | |||
| 68 | 66 | ||
| 69 | /// Creates a port pair and registers this service with the given ServiceManager. | 67 | /// Creates a port pair and registers this service with the given ServiceManager. |
| 70 | void InstallAsService(SM::ServiceManager& service_manager); | 68 | void InstallAsService(SM::ServiceManager& service_manager); |
| 71 | /// Creates a port pair and registers it on the kernel's global port registry. | 69 | |
| 72 | void InstallAsNamedPort(Kernel::KernelCore& kernel); | 70 | /// Invokes a service request routine using the HIPC protocol. |
| 73 | /// Invokes a service request routine. | ||
| 74 | void InvokeRequest(Kernel::HLERequestContext& ctx); | 71 | void InvokeRequest(Kernel::HLERequestContext& ctx); |
| 72 | |||
| 73 | /// Invokes a service request routine using the HIPC protocol. | ||
| 74 | void InvokeRequestTipc(Kernel::HLERequestContext& ctx); | ||
| 75 | |||
| 76 | /// Creates a port pair and registers it on the kernel's global port registry. | ||
| 77 | Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); | ||
| 78 | |||
| 75 | /// Handles a synchronization request for the service. | 79 | /// Handles a synchronization request for the service. |
| 76 | ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) override; | 80 | ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 81 | Kernel::HLERequestContext& context) override; | ||
| 77 | 82 | ||
| 78 | protected: | 83 | protected: |
| 79 | /// Member-function pointer type of SyncRequest handlers. | 84 | /// Member-function pointer type of SyncRequest handlers. |
| @@ -106,6 +111,7 @@ private: | |||
| 106 | ~ServiceFrameworkBase() override; | 111 | ~ServiceFrameworkBase() override; |
| 107 | 112 | ||
| 108 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); | 113 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); |
| 114 | void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); | ||
| 109 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); | 115 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); |
| 110 | 116 | ||
| 111 | /// Identifier string used to connect to the service. | 117 | /// Identifier string used to connect to the service. |
| @@ -120,6 +126,7 @@ private: | |||
| 120 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. | 126 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. |
| 121 | InvokerFn* handler_invoker; | 127 | InvokerFn* handler_invoker; |
| 122 | boost::container::flat_map<u32, FunctionInfoBase> handlers; | 128 | boost::container::flat_map<u32, FunctionInfoBase> handlers; |
| 129 | boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc; | ||
| 123 | 130 | ||
| 124 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. | 131 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. |
| 125 | Common::SpinLock lock_service; | 132 | Common::SpinLock lock_service; |
| @@ -148,17 +155,17 @@ protected: | |||
| 148 | /** | 155 | /** |
| 149 | * Constructs a FunctionInfo for a function. | 156 | * Constructs a FunctionInfo for a function. |
| 150 | * | 157 | * |
| 151 | * @param expected_header request header in the command buffer which will trigger dispatch | 158 | * @param expected_header_ request header in the command buffer which will trigger dispatch |
| 152 | * to this handler | 159 | * to this handler |
| 153 | * @param handler_callback member function in this service which will be called to handle | 160 | * @param handler_callback_ member function in this service which will be called to handle |
| 154 | * the request | 161 | * the request |
| 155 | * @param name human-friendly name for the request. Used mostly for logging purposes. | 162 | * @param name_ human-friendly name for the request. Used mostly for logging purposes. |
| 156 | */ | 163 | */ |
| 157 | FunctionInfo(u32 expected_header, HandlerFnP<Self> handler_callback, const char* name) | 164 | FunctionInfo(u32 expected_header_, HandlerFnP<Self> handler_callback_, const char* name_) |
| 158 | : FunctionInfoBase{ | 165 | : FunctionInfoBase{ |
| 159 | expected_header, | 166 | expected_header_, |
| 160 | // Type-erase member function pointer by casting it down to the base class. | 167 | // Type-erase member function pointer by casting it down to the base class. |
| 161 | static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback), name} {} | 168 | static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {} |
| 162 | }; | 169 | }; |
| 163 | 170 | ||
| 164 | /** | 171 | /** |
| @@ -187,6 +194,20 @@ protected: | |||
| 187 | RegisterHandlersBase(functions, n); | 194 | RegisterHandlersBase(functions, n); |
| 188 | } | 195 | } |
| 189 | 196 | ||
| 197 | /// Registers handlers in the service. | ||
| 198 | template <std::size_t N> | ||
| 199 | void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) { | ||
| 200 | RegisterHandlersTipc(functions, N); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Registers handlers in the service. Usually prefer using the other RegisterHandlers | ||
| 205 | * overload in order to avoid needing to specify the array size. | ||
| 206 | */ | ||
| 207 | void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) { | ||
| 208 | RegisterHandlersBaseTipc(functions, n); | ||
| 209 | } | ||
| 210 | |||
| 190 | private: | 211 | private: |
| 191 | /** | 212 | /** |
| 192 | * This function is used to allow invocation of pointers to handlers stored in the base class | 213 | * This function is used to allow invocation of pointers to handlers stored in the base class |
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 5909fdd85..4f1ffe55f 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/file_sys/errors.h" | 7 | #include "core/file_sys/errors.h" |
| 8 | #include "core/file_sys/system_archive/system_version.h" | 8 | #include "core/file_sys/system_archive/system_version.h" |
| 9 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/client_port.h" | 10 | #include "core/hle/kernel/k_client_port.h" |
| 11 | #include "core/hle/service/filesystem/filesystem.h" | 11 | #include "core/hle/service/filesystem/filesystem.h" |
| 12 | #include "core/hle/service/set/set_sys.h" | 12 | #include "core/hle/service/set/set_sys.h" |
| 13 | 13 | ||
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index 916177efd..de530cbfb 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp | |||
| @@ -5,16 +5,16 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/hle/ipc_helpers.h" | 7 | #include "core/hle/ipc_helpers.h" |
| 8 | #include "core/hle/kernel/client_session.h" | 8 | #include "core/hle/kernel/k_client_session.h" |
| 9 | #include "core/hle/kernel/server_session.h" | 9 | #include "core/hle/kernel/k_server_session.h" |
| 10 | #include "core/hle/kernel/session.h" | 10 | #include "core/hle/kernel/k_session.h" |
| 11 | #include "core/hle/service/sm/controller.h" | 11 | #include "core/hle/service/sm/controller.h" |
| 12 | 12 | ||
| 13 | namespace Service::SM { | 13 | namespace Service::SM { |
| 14 | 14 | ||
| 15 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { | 15 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { |
| 16 | ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain"); | 16 | ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain"); |
| 17 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId()); | 17 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); |
| 18 | ctx.Session()->ConvertToDomain(); | 18 | ctx.Session()->ConvertToDomain(); |
| 19 | 19 | ||
| 20 | IPC::ResponseBuilder rb{ctx, 3}; | 20 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -26,15 +26,23 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | |||
| 26 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong | 26 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong |
| 27 | // and that we probably want to actually make an entirely new Session, but we still need to | 27 | // and that we probably want to actually make an entirely new Session, but we still need to |
| 28 | // verify this on hardware. | 28 | // verify this on hardware. |
| 29 | |||
| 29 | LOG_DEBUG(Service, "called"); | 30 | LOG_DEBUG(Service, "called"); |
| 30 | 31 | ||
| 32 | auto session = ctx.Session()->GetParent(); | ||
| 33 | |||
| 34 | // Open a reference to the session to simulate a new one being created. | ||
| 35 | session->Open(); | ||
| 36 | session->GetClientSession().Open(); | ||
| 37 | session->GetServerSession().Open(); | ||
| 38 | |||
| 31 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 39 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 32 | rb.Push(RESULT_SUCCESS); | 40 | rb.Push(RESULT_SUCCESS); |
| 33 | rb.PushMoveObjects(ctx.Session()->GetParent()->Client()); | 41 | rb.PushMoveObjects(session->GetClientSession()); |
| 34 | } | 42 | } |
| 35 | 43 | ||
| 36 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { | 44 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { |
| 37 | LOG_WARNING(Service, "(STUBBED) called, using CloneCurrentObject"); | 45 | LOG_DEBUG(Service, "called"); |
| 38 | 46 | ||
| 39 | CloneCurrentObject(ctx); | 47 | CloneCurrentObject(ctx); |
| 40 | } | 48 | } |
| @@ -44,7 +52,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 44 | 52 | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | 53 | IPC::ResponseBuilder rb{ctx, 3}; |
| 46 | rb.Push(RESULT_SUCCESS); | 54 | rb.Push(RESULT_SUCCESS); |
| 47 | rb.Push<u16>(0x1000); | 55 | rb.Push<u16>(0x8000); |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 50 | // https://switchbrew.org/wiki/IPC_Marshalling | 58 | // https://switchbrew.org/wiki/IPC_Marshalling |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 94608d529..8cc9aee8a 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -6,15 +6,20 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/client_port.h" | 9 | #include "core/hle/kernel/k_client_port.h" |
| 10 | #include "core/hle/kernel/client_session.h" | 10 | #include "core/hle/kernel/k_client_session.h" |
| 11 | #include "core/hle/kernel/server_port.h" | 11 | #include "core/hle/kernel/k_port.h" |
| 12 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 13 | #include "core/hle/kernel/k_server_port.h" | ||
| 14 | #include "core/hle/kernel/k_server_session.h" | ||
| 15 | #include "core/hle/kernel/k_session.h" | ||
| 12 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| 13 | #include "core/hle/service/sm/controller.h" | 17 | #include "core/hle/service/sm/controller.h" |
| 14 | #include "core/hle/service/sm/sm.h" | 18 | #include "core/hle/service/sm/sm.h" |
| 15 | 19 | ||
| 16 | namespace Service::SM { | 20 | namespace Service::SM { |
| 17 | 21 | ||
| 22 | constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2); | ||
| 18 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); | 23 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); |
| 19 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); | 24 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); |
| 20 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); | 25 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); |
| @@ -31,24 +36,21 @@ static ResultCode ValidateServiceName(const std::string& name) { | |||
| 31 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); | 36 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); |
| 32 | return ERR_INVALID_NAME; | 37 | return ERR_INVALID_NAME; |
| 33 | } | 38 | } |
| 34 | if (name.rfind('\0') != std::string::npos) { | ||
| 35 | LOG_ERROR(Service_SM, "A non null terminated service was passed"); | ||
| 36 | return ERR_INVALID_NAME; | ||
| 37 | } | ||
| 38 | return RESULT_SUCCESS; | 39 | return RESULT_SUCCESS; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { | 42 | Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { |
| 42 | ASSERT(self->sm_interface.expired()); | 43 | ASSERT(self.sm_interface.expired()); |
| 43 | 44 | ||
| 44 | auto sm = std::make_shared<SM>(self, system); | 45 | auto sm = std::make_shared<SM>(self, system); |
| 45 | sm->InstallAsNamedPort(system.Kernel()); | 46 | self.sm_interface = sm; |
| 46 | self->sm_interface = sm; | 47 | self.controller_interface = std::make_unique<Controller>(system); |
| 47 | self->controller_interface = std::make_unique<Controller>(system); | 48 | |
| 49 | return sm->CreatePort(system.Kernel()); | ||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(std::string name, | 52 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, |
| 51 | u32 max_sessions) { | 53 | u32 max_sessions) { |
| 52 | 54 | ||
| 53 | CASCADE_CODE(ValidateServiceName(name)); | 55 | CASCADE_CODE(ValidateServiceName(name)); |
| 54 | 56 | ||
| @@ -57,11 +59,12 @@ ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(s | |||
| 57 | return ERR_ALREADY_REGISTERED; | 59 | return ERR_ALREADY_REGISTERED; |
| 58 | } | 60 | } |
| 59 | 61 | ||
| 60 | auto [server_port, client_port] = | 62 | auto* port = Kernel::KPort::Create(kernel); |
| 61 | Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name); | 63 | port->Initialize(max_sessions, false, name); |
| 62 | 64 | ||
| 63 | registered_services.emplace(std::move(name), std::move(client_port)); | 65 | registered_services.emplace(std::move(name), port); |
| 64 | return MakeResult(std::move(server_port)); | 66 | |
| 67 | return MakeResult(&port->GetServerPort()); | ||
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | ResultCode ServiceManager::UnregisterService(const std::string& name) { | 70 | ResultCode ServiceManager::UnregisterService(const std::string& name) { |
| @@ -72,12 +75,14 @@ ResultCode ServiceManager::UnregisterService(const std::string& name) { | |||
| 72 | LOG_ERROR(Service_SM, "Server is not registered! service={}", name); | 75 | LOG_ERROR(Service_SM, "Server is not registered! service={}", name); |
| 73 | return ERR_SERVICE_NOT_REGISTERED; | 76 | return ERR_SERVICE_NOT_REGISTERED; |
| 74 | } | 77 | } |
| 78 | |||
| 79 | iter->second->Close(); | ||
| 80 | |||
| 75 | registered_services.erase(iter); | 81 | registered_services.erase(iter); |
| 76 | return RESULT_SUCCESS; | 82 | return RESULT_SUCCESS; |
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | ResultVal<std::shared_ptr<Kernel::ClientPort>> ServiceManager::GetServicePort( | 85 | ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { |
| 80 | const std::string& name) { | ||
| 81 | 86 | ||
| 82 | CASCADE_CODE(ValidateServiceName(name)); | 87 | CASCADE_CODE(ValidateServiceName(name)); |
| 83 | auto it = registered_services.find(name); | 88 | auto it = registered_services.find(name); |
| @@ -89,13 +94,6 @@ ResultVal<std::shared_ptr<Kernel::ClientPort>> ServiceManager::GetServicePort( | |||
| 89 | return MakeResult(it->second); | 94 | return MakeResult(it->second); |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 92 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ServiceManager::ConnectToService( | ||
| 93 | const std::string& name) { | ||
| 94 | |||
| 95 | CASCADE_RESULT(auto client_port, GetServicePort(name)); | ||
| 96 | return client_port->Connect(); | ||
| 97 | } | ||
| 98 | |||
| 99 | SM::~SM() = default; | 97 | SM::~SM() = default; |
| 100 | 98 | ||
| 101 | /** | 99 | /** |
| @@ -108,50 +106,81 @@ SM::~SM() = default; | |||
| 108 | void SM::Initialize(Kernel::HLERequestContext& ctx) { | 106 | void SM::Initialize(Kernel::HLERequestContext& ctx) { |
| 109 | LOG_DEBUG(Service_SM, "called"); | 107 | LOG_DEBUG(Service_SM, "called"); |
| 110 | 108 | ||
| 109 | is_initialized = true; | ||
| 110 | |||
| 111 | IPC::ResponseBuilder rb{ctx, 2}; | 111 | IPC::ResponseBuilder rb{ctx, 2}; |
| 112 | rb.Push(RESULT_SUCCESS); | 112 | rb.Push(RESULT_SUCCESS); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | void SM::GetService(Kernel::HLERequestContext& ctx) { | 115 | void SM::GetService(Kernel::HLERequestContext& ctx) { |
| 116 | IPC::RequestParser rp{ctx}; | 116 | auto result = GetServiceImpl(ctx); |
| 117 | if (result.Succeeded()) { | ||
| 118 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 119 | rb.Push(result.Code()); | ||
| 120 | rb.PushMoveObjects(result.Unwrap()); | ||
| 121 | } else { | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(result.Code()); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { | ||
| 128 | auto result = GetServiceImpl(ctx); | ||
| 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 130 | rb.Push(result.Code()); | ||
| 131 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | ||
| 132 | } | ||
| 133 | |||
| 134 | static std::string PopServiceName(IPC::RequestParser& rp) { | ||
| 117 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); | 135 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); |
| 118 | auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | 136 | std::string result; |
| 137 | for (const auto& c : name_buf) { | ||
| 138 | if (c >= ' ' && c <= '~') { | ||
| 139 | result.push_back(c); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return result; | ||
| 143 | } | ||
| 119 | 144 | ||
| 120 | std::string name(name_buf.begin(), end); | 145 | ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) { |
| 146 | if (!is_initialized) { | ||
| 147 | return ERR_NOT_INITIALIZED; | ||
| 148 | } | ||
| 121 | 149 | ||
| 122 | auto client_port = service_manager->GetServicePort(name); | 150 | IPC::RequestParser rp{ctx}; |
| 123 | if (client_port.Failed()) { | 151 | std::string name(PopServiceName(rp)); |
| 124 | IPC::ResponseBuilder rb{ctx, 2}; | 152 | |
| 125 | rb.Push(client_port.Code()); | 153 | auto result = service_manager.GetServicePort(name); |
| 126 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, client_port.Code().raw); | 154 | if (result.Failed()) { |
| 127 | if (name.length() == 0) | 155 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); |
| 128 | return; // LibNX Fix | 156 | return result.Code(); |
| 129 | UNIMPLEMENTED(); | ||
| 130 | return; | ||
| 131 | } | 157 | } |
| 132 | 158 | ||
| 133 | auto [client, server] = Kernel::Session::Create(kernel, name); | 159 | auto* port = result.Unwrap(); |
| 160 | |||
| 161 | // Kernel::KScopedResourceReservation session_reservation( | ||
| 162 | // kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions); | ||
| 163 | // R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached); | ||
| 164 | |||
| 165 | auto* session = Kernel::KSession::Create(kernel); | ||
| 166 | session->Initialize(&port->GetClientPort(), std::move(name)); | ||
| 134 | 167 | ||
| 135 | const auto& server_port = client_port.Unwrap()->GetServerPort(); | 168 | // Commit the session reservation. |
| 136 | if (server_port->GetHLEHandler()) { | 169 | // session_reservation.Commit(); |
| 137 | server_port->GetHLEHandler()->ClientConnected(server); | 170 | |
| 171 | if (port->GetServerPort().GetHLEHandler()) { | ||
| 172 | port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession()); | ||
| 138 | } else { | 173 | } else { |
| 139 | server_port->AppendPendingSession(server); | 174 | port->EnqueueSession(&session->GetServerSession()); |
| 140 | } | 175 | } |
| 141 | 176 | ||
| 142 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId()); | 177 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
| 143 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 178 | return MakeResult(&session->GetClientSession()); |
| 144 | rb.Push(RESULT_SUCCESS); | ||
| 145 | rb.PushMoveObjects(std::move(client)); | ||
| 146 | } | 179 | } |
| 147 | 180 | ||
| 148 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { | 181 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { |
| 149 | IPC::RequestParser rp{ctx}; | 182 | IPC::RequestParser rp{ctx}; |
| 150 | 183 | std::string name(PopServiceName(rp)); | |
| 151 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 152 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 153 | |||
| 154 | const std::string name(name_buf.begin(), end); | ||
| 155 | 184 | ||
| 156 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); | 185 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); |
| 157 | const auto max_session_count = rp.PopRaw<u32>(); | 186 | const auto max_session_count = rp.PopRaw<u32>(); |
| @@ -159,7 +188,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 159 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, | 188 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, |
| 160 | max_session_count, is_light); | 189 | max_session_count, is_light); |
| 161 | 190 | ||
| 162 | auto handle = service_manager->RegisterService(name, max_session_count); | 191 | auto handle = service_manager.RegisterService(name, max_session_count); |
| 163 | if (handle.Failed()) { | 192 | if (handle.Failed()) { |
| 164 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", | 193 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", |
| 165 | handle.Code().raw); | 194 | handle.Code().raw); |
| @@ -170,33 +199,38 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 170 | 199 | ||
| 171 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 200 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 172 | rb.Push(handle.Code()); | 201 | rb.Push(handle.Code()); |
| 173 | rb.PushMoveObjects(std::move(handle).Unwrap()); | 202 | |
| 203 | auto server_port = handle.Unwrap(); | ||
| 204 | rb.PushMoveObjects(server_port); | ||
| 174 | } | 205 | } |
| 175 | 206 | ||
| 176 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | 207 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { |
| 177 | IPC::RequestParser rp{ctx}; | 208 | IPC::RequestParser rp{ctx}; |
| 209 | std::string name(PopServiceName(rp)); | ||
| 178 | 210 | ||
| 179 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 180 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 181 | |||
| 182 | const std::string name(name_buf.begin(), end); | ||
| 183 | LOG_DEBUG(Service_SM, "called with name={}", name); | 211 | LOG_DEBUG(Service_SM, "called with name={}", name); |
| 184 | 212 | ||
| 185 | IPC::ResponseBuilder rb{ctx, 2}; | 213 | IPC::ResponseBuilder rb{ctx, 2}; |
| 186 | rb.Push(service_manager->UnregisterService(name)); | 214 | rb.Push(service_manager.UnregisterService(name)); |
| 187 | } | 215 | } |
| 188 | 216 | ||
| 189 | SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) | 217 | SM::SM(ServiceManager& service_manager_, Core::System& system_) |
| 190 | : ServiceFramework{system_, "sm:", 4}, | 218 | : ServiceFramework{system_, "sm:", 4}, |
| 191 | service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { | 219 | service_manager{service_manager_}, kernel{system_.Kernel()} { |
| 192 | static const FunctionInfo functions[] = { | 220 | RegisterHandlers({ |
| 193 | {0, &SM::Initialize, "Initialize"}, | 221 | {0, &SM::Initialize, "Initialize"}, |
| 194 | {1, &SM::GetService, "GetService"}, | 222 | {1, &SM::GetService, "GetService"}, |
| 195 | {2, &SM::RegisterService, "RegisterService"}, | 223 | {2, &SM::RegisterService, "RegisterService"}, |
| 196 | {3, &SM::UnregisterService, "UnregisterService"}, | 224 | {3, &SM::UnregisterService, "UnregisterService"}, |
| 197 | {4, nullptr, "DetachClient"}, | 225 | {4, nullptr, "DetachClient"}, |
| 198 | }; | 226 | }); |
| 199 | RegisterHandlers(functions); | 227 | RegisterHandlersTipc({ |
| 228 | {0, &SM::Initialize, "Initialize"}, | ||
| 229 | {1, &SM::GetServiceTipc, "GetService"}, | ||
| 230 | {2, &SM::RegisterService, "RegisterService"}, | ||
| 231 | {3, &SM::UnregisterService, "UnregisterService"}, | ||
| 232 | {4, nullptr, "DetachClient"}, | ||
| 233 | }); | ||
| 200 | } | 234 | } |
| 201 | 235 | ||
| 202 | } // namespace Service::SM | 236 | } // namespace Service::SM |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 3f46ae44f..60f0b3f8a 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -10,9 +10,7 @@ | |||
| 10 | #include <unordered_map> | 10 | #include <unordered_map> |
| 11 | 11 | ||
| 12 | #include "common/concepts.h" | 12 | #include "common/concepts.h" |
| 13 | #include "core/hle/kernel/client_port.h" | 13 | #include "core/hle/kernel/k_port.h" |
| 14 | #include "core/hle/kernel/object.h" | ||
| 15 | #include "core/hle/kernel/server_port.h" | ||
| 16 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 17 | #include "core/hle/service/service.h" | 15 | #include "core/hle/service/service.h" |
| 18 | 16 | ||
| @@ -21,10 +19,11 @@ class System; | |||
| 21 | } | 19 | } |
| 22 | 20 | ||
| 23 | namespace Kernel { | 21 | namespace Kernel { |
| 24 | class ClientPort; | 22 | class KClientPort; |
| 25 | class ClientSession; | 23 | class KClientSession; |
| 26 | class KernelCore; | 24 | class KernelCore; |
| 27 | class ServerPort; | 25 | class KPort; |
| 26 | class KServerPort; | ||
| 28 | class SessionRequestHandler; | 27 | class SessionRequestHandler; |
| 29 | } // namespace Kernel | 28 | } // namespace Kernel |
| 30 | 29 | ||
| @@ -35,31 +34,33 @@ class Controller; | |||
| 35 | /// Interface to "sm:" service | 34 | /// Interface to "sm:" service |
| 36 | class SM final : public ServiceFramework<SM> { | 35 | class SM final : public ServiceFramework<SM> { |
| 37 | public: | 36 | public: |
| 38 | explicit SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_); | 37 | explicit SM(ServiceManager& service_manager_, Core::System& system_); |
| 39 | ~SM() override; | 38 | ~SM() override; |
| 40 | 39 | ||
| 41 | private: | 40 | private: |
| 42 | void Initialize(Kernel::HLERequestContext& ctx); | 41 | void Initialize(Kernel::HLERequestContext& ctx); |
| 43 | void GetService(Kernel::HLERequestContext& ctx); | 42 | void GetService(Kernel::HLERequestContext& ctx); |
| 43 | void GetServiceTipc(Kernel::HLERequestContext& ctx); | ||
| 44 | void RegisterService(Kernel::HLERequestContext& ctx); | 44 | void RegisterService(Kernel::HLERequestContext& ctx); |
| 45 | void UnregisterService(Kernel::HLERequestContext& ctx); | 45 | void UnregisterService(Kernel::HLERequestContext& ctx); |
| 46 | 46 | ||
| 47 | std::shared_ptr<ServiceManager> service_manager; | 47 | ResultVal<Kernel::KClientSession*> GetServiceImpl(Kernel::HLERequestContext& ctx); |
| 48 | |||
| 49 | ServiceManager& service_manager; | ||
| 50 | bool is_initialized{}; | ||
| 48 | Kernel::KernelCore& kernel; | 51 | Kernel::KernelCore& kernel; |
| 49 | }; | 52 | }; |
| 50 | 53 | ||
| 51 | class ServiceManager { | 54 | class ServiceManager { |
| 52 | public: | 55 | public: |
| 53 | static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system); | 56 | static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); |
| 54 | 57 | ||
| 55 | explicit ServiceManager(Kernel::KernelCore& kernel_); | 58 | explicit ServiceManager(Kernel::KernelCore& kernel_); |
| 56 | ~ServiceManager(); | 59 | ~ServiceManager(); |
| 57 | 60 | ||
| 58 | ResultVal<std::shared_ptr<Kernel::ServerPort>> RegisterService(std::string name, | 61 | ResultVal<Kernel::KServerPort*> RegisterService(std::string name, u32 max_sessions); |
| 59 | u32 max_sessions); | ||
| 60 | ResultCode UnregisterService(const std::string& name); | 62 | ResultCode UnregisterService(const std::string& name); |
| 61 | ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name); | 63 | ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); |
| 62 | ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name); | ||
| 63 | 64 | ||
| 64 | template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> | 65 | template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> |
| 65 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 66 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
| @@ -68,11 +69,11 @@ public: | |||
| 68 | LOG_DEBUG(Service, "Can't find service: {}", service_name); | 69 | LOG_DEBUG(Service, "Can't find service: {}", service_name); |
| 69 | return nullptr; | 70 | return nullptr; |
| 70 | } | 71 | } |
| 71 | auto port = service->second->GetServerPort(); | 72 | auto* port = service->second; |
| 72 | if (port == nullptr) { | 73 | if (port == nullptr) { |
| 73 | return nullptr; | 74 | return nullptr; |
| 74 | } | 75 | } |
| 75 | return std::static_pointer_cast<T>(port->GetHLEHandler()); | 76 | return std::static_pointer_cast<T>(port->GetServerPort().GetHLEHandler()); |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | void InvokeControlRequest(Kernel::HLERequestContext& context); | 79 | void InvokeControlRequest(Kernel::HLERequestContext& context); |
| @@ -81,8 +82,8 @@ private: | |||
| 81 | std::weak_ptr<SM> sm_interface; | 82 | std::weak_ptr<SM> sm_interface; |
| 82 | std::unique_ptr<Controller> controller_interface; | 83 | std::unique_ptr<Controller> controller_interface; |
| 83 | 84 | ||
| 84 | /// Map of registered services, retrieved using GetServicePort or ConnectToService. | 85 | /// Map of registered services, retrieved using GetServicePort. |
| 85 | std::unordered_map<std::string, std::shared_ptr<Kernel::ClientPort>> registered_services; | 86 | std::unordered_map<std::string, Kernel::KPort*> registered_services; |
| 86 | 87 | ||
| 87 | /// Kernel context | 88 | /// Kernel context |
| 88 | Kernel::KernelCore& kernel; | 89 | Kernel::KernelCore& kernel; |
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index dc2baca4a..3b072f6bc 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp | |||
| @@ -10,6 +10,11 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::SSL { | 11 | namespace Service::SSL { |
| 12 | 12 | ||
| 13 | enum class CertificateFormat : u32 { | ||
| 14 | Pem = 1, | ||
| 15 | Der = 2, | ||
| 16 | }; | ||
| 17 | |||
| 13 | class ISslConnection final : public ServiceFramework<ISslConnection> { | 18 | class ISslConnection final : public ServiceFramework<ISslConnection> { |
| 14 | public: | 19 | public: |
| 15 | explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { | 20 | explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { |
| @@ -58,8 +63,8 @@ public: | |||
| 58 | {1, nullptr, "GetOption"}, | 63 | {1, nullptr, "GetOption"}, |
| 59 | {2, &ISslContext::CreateConnection, "CreateConnection"}, | 64 | {2, &ISslContext::CreateConnection, "CreateConnection"}, |
| 60 | {3, nullptr, "GetConnectionCount"}, | 65 | {3, nullptr, "GetConnectionCount"}, |
| 61 | {4, nullptr, "ImportServerPki"}, | 66 | {4, &ISslContext::ImportServerPki, "ImportServerPki"}, |
| 62 | {5, nullptr, "ImportClientPki"}, | 67 | {5, &ISslContext::ImportClientPki, "ImportClientPki"}, |
| 63 | {6, nullptr, "RemoveServerPki"}, | 68 | {6, nullptr, "RemoveServerPki"}, |
| 64 | {7, nullptr, "RemoveClientPki"}, | 69 | {7, nullptr, "RemoveClientPki"}, |
| 65 | {8, nullptr, "RegisterInternalPki"}, | 70 | {8, nullptr, "RegisterInternalPki"}, |
| @@ -94,6 +99,39 @@ private: | |||
| 94 | rb.Push(RESULT_SUCCESS); | 99 | rb.Push(RESULT_SUCCESS); |
| 95 | rb.PushIpcInterface<ISslConnection>(system); | 100 | rb.PushIpcInterface<ISslConnection>(system); |
| 96 | } | 101 | } |
| 102 | |||
| 103 | void ImportServerPki(Kernel::HLERequestContext& ctx) { | ||
| 104 | IPC::RequestParser rp{ctx}; | ||
| 105 | const auto certificate_format = rp.PopEnum<CertificateFormat>(); | ||
| 106 | const auto pkcs_12_certificates = ctx.ReadBuffer(0); | ||
| 107 | |||
| 108 | constexpr u64 server_id = 0; | ||
| 109 | |||
| 110 | LOG_WARNING(Service_SSL, "(STUBBED) called, certificate_format={}", certificate_format); | ||
| 111 | |||
| 112 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 113 | rb.Push(RESULT_SUCCESS); | ||
| 114 | rb.Push(server_id); | ||
| 115 | } | ||
| 116 | |||
| 117 | void ImportClientPki(Kernel::HLERequestContext& ctx) { | ||
| 118 | const auto pkcs_12_certificate = ctx.ReadBuffer(0); | ||
| 119 | const auto ascii_password = [&ctx] { | ||
| 120 | if (ctx.CanReadBuffer(1)) { | ||
| 121 | return ctx.ReadBuffer(1); | ||
| 122 | } | ||
| 123 | |||
| 124 | return std::vector<u8>{}; | ||
| 125 | }(); | ||
| 126 | |||
| 127 | constexpr u64 client_id = 0; | ||
| 128 | |||
| 129 | LOG_WARNING(Service_SSL, "(STUBBED) called"); | ||
| 130 | |||
| 131 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 132 | rb.Push(RESULT_SUCCESS); | ||
| 133 | rb.Push(client_id); | ||
| 134 | } | ||
| 97 | }; | 135 | }; |
| 98 | 136 | ||
| 99 | class SSL final : public ServiceFramework<SSL> { | 137 | class SSL final : public ServiceFramework<SSL> { |
diff --git a/src/core/hle/service/time/ephemeral_network_system_clock_core.h b/src/core/hle/service/time/ephemeral_network_system_clock_core.h index 4c6cdef86..d12cb5335 100644 --- a/src/core/hle/service/time/ephemeral_network_system_clock_core.h +++ b/src/core/hle/service/time/ephemeral_network_system_clock_core.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Time::Clock { | |||
| 10 | 10 | ||
| 11 | class EphemeralNetworkSystemClockCore final : public SystemClockCore { | 11 | class EphemeralNetworkSystemClockCore final : public SystemClockCore { |
| 12 | public: | 12 | public: |
| 13 | explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core) | 13 | explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 14 | : SystemClockCore{steady_clock_core} {} | 14 | : SystemClockCore{steady_clock_core_} {} |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | } // namespace Service::Time::Clock | 17 | } // namespace Service::Time::Clock |
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp index a01d9e0ff..53a204796 100644 --- a/src/core/hle/service/time/interface.cpp +++ b/src/core/hle/service/time/interface.cpp | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Time { | 7 | namespace Service::Time { |
| 8 | 8 | ||
| 9 | Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* name) | 9 | Time::Time(std::shared_ptr<Module> module_, Core::System& system_, const char* name_) |
| 10 | : Interface(std::move(module), system, name) { | 10 | : Interface{std::move(module_), system_, name_} { |
| 11 | // clang-format off | 11 | // clang-format off |
| 12 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 13 | {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | 13 | {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, |
diff --git a/src/core/hle/service/time/interface.h b/src/core/hle/service/time/interface.h index 4f49e1f07..c41766f1a 100644 --- a/src/core/hle/service/time/interface.h +++ b/src/core/hle/service/time/interface.h | |||
| @@ -14,7 +14,7 @@ namespace Service::Time { | |||
| 14 | 14 | ||
| 15 | class Time final : public Module::Interface { | 15 | class Time final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit Time(std::shared_ptr<Module> time, Core::System& system, const char* name); | 17 | explicit Time(std::shared_ptr<Module> time, Core::System& system_, const char* name_); |
| 18 | ~Time() override; | 18 | ~Time() override; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
diff --git a/src/core/hle/service/time/local_system_clock_context_writer.h b/src/core/hle/service/time/local_system_clock_context_writer.h index 7050844c6..490d0ef3e 100644 --- a/src/core/hle/service/time/local_system_clock_context_writer.h +++ b/src/core/hle/service/time/local_system_clock_context_writer.h | |||
| @@ -12,8 +12,8 @@ namespace Service::Time::Clock { | |||
| 12 | 12 | ||
| 13 | class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback { | 13 | class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback { |
| 14 | public: | 14 | public: |
| 15 | explicit LocalSystemClockContextWriter(SharedMemory& shared_memory) | 15 | explicit LocalSystemClockContextWriter(SharedMemory& shared_memory_) |
| 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {} | 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} |
| 17 | 17 | ||
| 18 | protected: | 18 | protected: |
| 19 | ResultCode Update() override { | 19 | ResultCode Update() override { |
diff --git a/src/core/hle/service/time/network_system_clock_context_writer.h b/src/core/hle/service/time/network_system_clock_context_writer.h index 94d8788ff..e2920b8eb 100644 --- a/src/core/hle/service/time/network_system_clock_context_writer.h +++ b/src/core/hle/service/time/network_system_clock_context_writer.h | |||
| @@ -12,8 +12,8 @@ namespace Service::Time::Clock { | |||
| 12 | 12 | ||
| 13 | class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback { | 13 | class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback { |
| 14 | public: | 14 | public: |
| 15 | explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory) | 15 | explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory_) |
| 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {} | 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} |
| 17 | 17 | ||
| 18 | protected: | 18 | protected: |
| 19 | ResultCode Update() override { | 19 | ResultCode Update() override { |
diff --git a/src/core/hle/service/time/standard_local_system_clock_core.h b/src/core/hle/service/time/standard_local_system_clock_core.h index 8c1882eb1..6320c7af1 100644 --- a/src/core/hle/service/time/standard_local_system_clock_core.h +++ b/src/core/hle/service/time/standard_local_system_clock_core.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Time::Clock { | |||
| 10 | 10 | ||
| 11 | class StandardLocalSystemClockCore final : public SystemClockCore { | 11 | class StandardLocalSystemClockCore final : public SystemClockCore { |
| 12 | public: | 12 | public: |
| 13 | explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core) | 13 | explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 14 | : SystemClockCore{steady_clock_core} {} | 14 | : SystemClockCore{steady_clock_core_} {} |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | } // namespace Service::Time::Clock | 17 | } // namespace Service::Time::Clock |
diff --git a/src/core/hle/service/time/standard_network_system_clock_core.h b/src/core/hle/service/time/standard_network_system_clock_core.h index c993bdf79..9d0aeaedb 100644 --- a/src/core/hle/service/time/standard_network_system_clock_core.h +++ b/src/core/hle/service/time/standard_network_system_clock_core.h | |||
| @@ -16,21 +16,21 @@ namespace Service::Time::Clock { | |||
| 16 | 16 | ||
| 17 | class StandardNetworkSystemClockCore final : public SystemClockCore { | 17 | class StandardNetworkSystemClockCore final : public SystemClockCore { |
| 18 | public: | 18 | public: |
| 19 | explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core) | 19 | explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 20 | : SystemClockCore{steady_clock_core} {} | 20 | : SystemClockCore{steady_clock_core_} {} |
| 21 | 21 | ||
| 22 | void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) { | 22 | void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) { |
| 23 | standard_network_clock_sufficient_accuracy = value; | 23 | standard_network_clock_sufficient_accuracy = value; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const { | 26 | bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const { |
| 27 | SystemClockContext context{}; | 27 | SystemClockContext clock_ctx{}; |
| 28 | if (GetClockContext(system, context) != RESULT_SUCCESS) { | 28 | if (GetClockContext(system, clock_ctx) != RESULT_SUCCESS) { |
| 29 | return {}; | 29 | return {}; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | s64 span{}; | 32 | s64 span{}; |
| 33 | if (context.steady_time_point.GetSpanBetween( | 33 | if (clock_ctx.steady_time_point.GetSpanBetween( |
| 34 | GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) { | 34 | GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) { |
| 35 | return {}; | 35 | return {}; |
| 36 | } | 36 | } |
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.cpp b/src/core/hle/service/time/standard_user_system_clock_core.cpp index b9faa474e..41bc01abd 100644 --- a/src/core/hle/service/time/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/time/standard_user_system_clock_core.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 8 | #include "core/hle/service/time/standard_local_system_clock_core.h" | 7 | #include "core/hle/service/time/standard_local_system_clock_core.h" |
| 9 | #include "core/hle/service/time/standard_network_system_clock_core.h" | 8 | #include "core/hle/service/time/standard_network_system_clock_core.h" |
| 10 | #include "core/hle/service/time/standard_user_system_clock_core.h" | 9 | #include "core/hle/service/time/standard_user_system_clock_core.h" |
| @@ -12,15 +11,15 @@ | |||
| 12 | namespace Service::Time::Clock { | 11 | namespace Service::Time::Clock { |
| 13 | 12 | ||
| 14 | StandardUserSystemClockCore::StandardUserSystemClockCore( | 13 | StandardUserSystemClockCore::StandardUserSystemClockCore( |
| 15 | StandardLocalSystemClockCore& local_system_clock_core, | 14 | StandardLocalSystemClockCore& local_system_clock_core_, |
| 16 | StandardNetworkSystemClockCore& network_system_clock_core, Core::System& system) | 15 | StandardNetworkSystemClockCore& network_system_clock_core_, Core::System& system_) |
| 17 | : SystemClockCore(local_system_clock_core.GetSteadyClockCore()), | 16 | : SystemClockCore(local_system_clock_core_.GetSteadyClockCore()), |
| 18 | local_system_clock_core{local_system_clock_core}, | 17 | local_system_clock_core{local_system_clock_core_}, |
| 19 | network_system_clock_core{network_system_clock_core}, auto_correction_enabled{}, | 18 | network_system_clock_core{network_system_clock_core_}, |
| 20 | auto_correction_time{SteadyClockTimePoint::GetRandom()}, | 19 | auto_correction_time{SteadyClockTimePoint::GetRandom()}, auto_correction_event{ |
| 21 | auto_correction_event{Kernel::KEvent::Create( | 20 | system_.Kernel()} { |
| 22 | system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} { | 21 | Kernel::KAutoObject::Create(std::addressof(auto_correction_event)); |
| 23 | auto_correction_event->Initialize(); | 22 | auto_correction_event.Initialize("StandardUserSystemClockCore:AutoCorrectionEvent"); |
| 24 | } | 23 | } |
| 25 | 24 | ||
| 26 | ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system, | 25 | ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system, |
| @@ -36,21 +35,21 @@ ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::Syst | |||
| 36 | } | 35 | } |
| 37 | 36 | ||
| 38 | ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, | 37 | ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, |
| 39 | SystemClockContext& context) const { | 38 | SystemClockContext& ctx) const { |
| 40 | if (const ResultCode result{ApplyAutomaticCorrection(system, false)}; | 39 | if (const ResultCode result{ApplyAutomaticCorrection(system, false)}; |
| 41 | result != RESULT_SUCCESS) { | 40 | result != RESULT_SUCCESS) { |
| 42 | return result; | 41 | return result; |
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | return local_system_clock_core.GetClockContext(system, context); | 44 | return local_system_clock_core.GetClockContext(system, ctx); |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext& context) { | 47 | ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext&) { |
| 49 | UNREACHABLE(); | 48 | UNREACHABLE(); |
| 50 | return ERROR_NOT_IMPLEMENTED; | 49 | return ERROR_NOT_IMPLEMENTED; |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | ResultCode StandardUserSystemClockCore::SetClockContext(const SystemClockContext& context) { | 52 | ResultCode StandardUserSystemClockCore::SetClockContext(const SystemClockContext&) { |
| 54 | UNREACHABLE(); | 53 | UNREACHABLE(); |
| 55 | return ERROR_NOT_IMPLEMENTED; | 54 | return ERROR_NOT_IMPLEMENTED; |
| 56 | } | 55 | } |
| @@ -65,13 +64,13 @@ ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& s | |||
| 65 | return ERROR_UNINITIALIZED_CLOCK; | 64 | return ERROR_UNINITIALIZED_CLOCK; |
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | SystemClockContext context{}; | 67 | SystemClockContext ctx{}; |
| 69 | if (const ResultCode result{network_system_clock_core.GetClockContext(system, context)}; | 68 | if (const ResultCode result{network_system_clock_core.GetClockContext(system, ctx)}; |
| 70 | result != RESULT_SUCCESS) { | 69 | result != RESULT_SUCCESS) { |
| 71 | return result; | 70 | return result; |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 74 | local_system_clock_core.SetClockContext(context); | 73 | local_system_clock_core.SetClockContext(ctx); |
| 75 | 74 | ||
| 76 | return RESULT_SUCCESS; | 75 | return RESULT_SUCCESS; |
| 77 | } | 76 | } |
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.h b/src/core/hle/service/time/standard_user_system_clock_core.h index aac44d72f..bf9ec5e42 100644 --- a/src/core/hle/service/time/standard_user_system_clock_core.h +++ b/src/core/hle/service/time/standard_user_system_clock_core.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/service/time/clock_types.h" | 8 | #include "core/hle/service/time/clock_types.h" |
| 8 | #include "core/hle/service/time/system_clock_core.h" | 9 | #include "core/hle/service/time/system_clock_core.h" |
| 9 | 10 | ||
| @@ -22,13 +23,13 @@ class StandardNetworkSystemClockCore; | |||
| 22 | 23 | ||
| 23 | class StandardUserSystemClockCore final : public SystemClockCore { | 24 | class StandardUserSystemClockCore final : public SystemClockCore { |
| 24 | public: | 25 | public: |
| 25 | StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core, | 26 | StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core_, |
| 26 | StandardNetworkSystemClockCore& network_system_clock_core, | 27 | StandardNetworkSystemClockCore& network_system_clock_core_, |
| 27 | Core::System& system); | 28 | Core::System& system_); |
| 28 | 29 | ||
| 29 | ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value); | 30 | ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value); |
| 30 | 31 | ||
| 31 | ResultCode GetClockContext(Core::System& system, SystemClockContext& context) const override; | 32 | ResultCode GetClockContext(Core::System& system, SystemClockContext& ctx) const override; |
| 32 | 33 | ||
| 33 | bool IsAutomaticCorrectionEnabled() const { | 34 | bool IsAutomaticCorrectionEnabled() const { |
| 34 | return auto_correction_enabled; | 35 | return auto_correction_enabled; |
| @@ -39,7 +40,7 @@ public: | |||
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | protected: | 42 | protected: |
| 42 | ResultCode Flush(const SystemClockContext& context) override; | 43 | ResultCode Flush(const SystemClockContext&) override; |
| 43 | 44 | ||
| 44 | ResultCode SetClockContext(const SystemClockContext&) override; | 45 | ResultCode SetClockContext(const SystemClockContext&) override; |
| 45 | 46 | ||
| @@ -54,7 +55,7 @@ private: | |||
| 54 | StandardNetworkSystemClockCore& network_system_clock_core; | 55 | StandardNetworkSystemClockCore& network_system_clock_core; |
| 55 | bool auto_correction_enabled{}; | 56 | bool auto_correction_enabled{}; |
| 56 | SteadyClockTimePoint auto_correction_time; | 57 | SteadyClockTimePoint auto_correction_time; |
| 57 | std::shared_ptr<Kernel::KEvent> auto_correction_event; | 58 | Kernel::KEvent auto_correction_event; |
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | } // namespace Service::Time::Clock | 61 | } // namespace Service::Time::Clock |
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp index d31d4e2ca..2ef442b56 100644 --- a/src/core/hle/service/time/system_clock_core.cpp +++ b/src/core/hle/service/time/system_clock_core.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Time::Clock { | 9 | namespace Service::Time::Clock { |
| 10 | 10 | ||
| 11 | SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core) | 11 | SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_) |
| 12 | : steady_clock_core{steady_clock_core} { | 12 | : steady_clock_core{steady_clock_core_} { |
| 13 | context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId(); | 13 | context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId(); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| @@ -45,18 +45,18 @@ ResultCode SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) | |||
| 45 | return Flush(clock_context); | 45 | return Flush(clock_context); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | ResultCode SystemClockCore::Flush(const SystemClockContext& context) { | 48 | ResultCode SystemClockCore::Flush(const SystemClockContext& clock_context) { |
| 49 | if (!system_clock_context_update_callback) { | 49 | if (!system_clock_context_update_callback) { |
| 50 | return RESULT_SUCCESS; | 50 | return RESULT_SUCCESS; |
| 51 | } | 51 | } |
| 52 | return system_clock_context_update_callback->Update(context); | 52 | return system_clock_context_update_callback->Update(clock_context); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | ResultCode SystemClockCore::SetSystemClockContext(const SystemClockContext& context) { | 55 | ResultCode SystemClockCore::SetSystemClockContext(const SystemClockContext& clock_context) { |
| 56 | if (const ResultCode result{SetClockContext(context)}; result != RESULT_SUCCESS) { | 56 | if (const ResultCode result{SetClockContext(clock_context)}; result != RESULT_SUCCESS) { |
| 57 | return result; | 57 | return result; |
| 58 | } | 58 | } |
| 59 | return Flush(context); | 59 | return Flush(clock_context); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | bool SystemClockCore::IsClockSetup(Core::System& system) const { | 62 | bool SystemClockCore::IsClockSetup(Core::System& system) const { |
diff --git a/src/core/hle/service/time/system_clock_core.h b/src/core/hle/service/time/system_clock_core.h index 608dd3b2e..b8e6122bf 100644 --- a/src/core/hle/service/time/system_clock_core.h +++ b/src/core/hle/service/time/system_clock_core.h | |||
| @@ -21,7 +21,7 @@ class SystemClockContextUpdateCallback; | |||
| 21 | 21 | ||
| 22 | class SystemClockCore { | 22 | class SystemClockCore { |
| 23 | public: | 23 | public: |
| 24 | explicit SystemClockCore(SteadyClockCore& steady_clock_core); | 24 | explicit SystemClockCore(SteadyClockCore& steady_clock_core_); |
| 25 | virtual ~SystemClockCore(); | 25 | virtual ~SystemClockCore(); |
| 26 | 26 | ||
| 27 | SteadyClockCore& GetSteadyClockCore() const { | 27 | SteadyClockCore& GetSteadyClockCore() const { |
| @@ -43,7 +43,7 @@ public: | |||
| 43 | return RESULT_SUCCESS; | 43 | return RESULT_SUCCESS; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | virtual ResultCode Flush(const SystemClockContext& context); | 46 | virtual ResultCode Flush(const SystemClockContext& clock_context); |
| 47 | 47 | ||
| 48 | void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) { | 48 | void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) { |
| 49 | system_clock_context_update_callback = std::move(callback); | 49 | system_clock_context_update_callback = std::move(callback); |
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 32f372d71..e7991012b 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | #include "core/core_timing_util.h" | 8 | #include "core/core_timing_util.h" |
| 9 | #include "core/hardware_properties.h" | 9 | #include "core/hardware_properties.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/kernel/client_port.h" | 11 | #include "core/hle/kernel/k_client_port.h" |
| 12 | #include "core/hle/kernel/client_session.h" | ||
| 13 | #include "core/hle/kernel/k_scheduler.h" | 12 | #include "core/hle/kernel/k_scheduler.h" |
| 14 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 15 | #include "core/hle/service/time/interface.h" | 14 | #include "core/hle/service/time/interface.h" |
| @@ -393,7 +392,7 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c | |||
| 393 | LOG_DEBUG(Service_Time, "called"); | 392 | LOG_DEBUG(Service_Time, "called"); |
| 394 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 393 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 395 | rb.Push(RESULT_SUCCESS); | 394 | rb.Push(RESULT_SUCCESS); |
| 396 | rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem())); | 395 | rb.PushCopyObjects(&system.Kernel().GetTimeSharedMem()); |
| 397 | } | 396 | } |
| 398 | 397 | ||
| 399 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, | 398 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, |
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp index f89c5aaad..4f9684de8 100644 --- a/src/core/hle/service/time/time_manager.cpp +++ b/src/core/hle/service/time/time_manager.cpp | |||
| @@ -129,7 +129,7 @@ struct TimeManager::Impl final { | |||
| 129 | return 0; | 129 | return 0; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | 132 | void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id, |
| 133 | Clock::TimeSpanType setup_value, | 133 | Clock::TimeSpanType setup_value, |
| 134 | Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { | 134 | Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { |
| 135 | standard_steady_clock_core.SetClockSourceId(clock_source_id); | 135 | standard_steady_clock_core.SetClockSourceId(clock_source_id); |
| @@ -137,21 +137,21 @@ struct TimeManager::Impl final { | |||
| 137 | standard_steady_clock_core.SetInternalOffset(internal_offset); | 137 | standard_steady_clock_core.SetInternalOffset(internal_offset); |
| 138 | standard_steady_clock_core.MarkAsInitialized(); | 138 | standard_steady_clock_core.MarkAsInitialized(); |
| 139 | 139 | ||
| 140 | const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; | 140 | const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system_)}; |
| 141 | shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); | 141 | shared_memory.SetupStandardSteadyClock(clock_source_id, current_time_point); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | void SetupStandardLocalSystemClock(Core::System& system, | 144 | void SetupStandardLocalSystemClock(Core::System& system_, |
| 145 | Clock::SystemClockContext clock_context, s64 posix_time) { | 145 | Clock::SystemClockContext clock_context, s64 posix_time) { |
| 146 | standard_local_system_clock_core.SetUpdateCallbackInstance( | 146 | standard_local_system_clock_core.SetUpdateCallbackInstance( |
| 147 | local_system_clock_context_writer); | 147 | local_system_clock_context_writer); |
| 148 | 148 | ||
| 149 | const auto current_time_point{ | 149 | const auto current_time_point{ |
| 150 | standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; | 150 | standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system_)}; |
| 151 | if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { | 151 | if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { |
| 152 | standard_local_system_clock_core.SetSystemClockContext(clock_context); | 152 | standard_local_system_clock_core.SetSystemClockContext(clock_context); |
| 153 | } else { | 153 | } else { |
| 154 | if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != | 154 | if (standard_local_system_clock_core.SetCurrentTime(system_, posix_time) != |
| 155 | RESULT_SUCCESS) { | 155 | RESULT_SUCCESS) { |
| 156 | UNREACHABLE(); | 156 | UNREACHABLE(); |
| 157 | return; | 157 | return; |
| @@ -177,10 +177,10 @@ struct TimeManager::Impl final { | |||
| 177 | standard_network_system_clock_core.MarkAsInitialized(); | 177 | standard_network_system_clock_core.MarkAsInitialized(); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled, | 180 | void SetupStandardUserSystemClock(Core::System& system_, bool is_automatic_correction_enabled, |
| 181 | Clock::SteadyClockTimePoint steady_clock_time_point) { | 181 | Clock::SteadyClockTimePoint steady_clock_time_point) { |
| 182 | if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( | 182 | if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( |
| 183 | system, is_automatic_correction_enabled) != RESULT_SUCCESS) { | 183 | system_, is_automatic_correction_enabled) != RESULT_SUCCESS) { |
| 184 | UNREACHABLE(); | 184 | UNREACHABLE(); |
| 185 | return; | 185 | return; |
| 186 | } | 186 | } |
| @@ -196,10 +196,10 @@ struct TimeManager::Impl final { | |||
| 196 | ephemeral_network_system_clock_core.MarkAsInitialized(); | 196 | ephemeral_network_system_clock_core.MarkAsInitialized(); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | void UpdateLocalSystemClockTime(Core::System& system, s64 posix_time) { | 199 | void UpdateLocalSystemClockTime(Core::System& system_, s64 posix_time) { |
| 200 | const auto timespan{Service::Time::Clock::TimeSpanType::FromSeconds(posix_time)}; | 200 | const auto timespan{Clock::TimeSpanType::FromSeconds(posix_time)}; |
| 201 | if (GetStandardLocalSystemClockCore() | 201 | if (GetStandardLocalSystemClockCore() |
| 202 | .SetCurrentTime(system, timespan.ToSeconds()) | 202 | .SetCurrentTime(system_, timespan.ToSeconds()) |
| 203 | .IsError()) { | 203 | .IsError()) { |
| 204 | UNREACHABLE(); | 204 | UNREACHABLE(); |
| 205 | return; | 205 | return; |
| @@ -223,7 +223,7 @@ struct TimeManager::Impl final { | |||
| 223 | TimeZone::TimeZoneContentManager time_zone_content_manager; | 223 | TimeZone::TimeZoneContentManager time_zone_content_manager; |
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | TimeManager::TimeManager(Core::System& system) : system{system} {} | 226 | TimeManager::TimeManager(Core::System& system_) : system{system_} {} |
| 227 | 227 | ||
| 228 | TimeManager::~TimeManager() = default; | 228 | TimeManager::~TimeManager() = default; |
| 229 | 229 | ||
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h index 4db8cc0e1..3af868d87 100644 --- a/src/core/hle/service/time/time_manager.h +++ b/src/core/hle/service/time/time_manager.h | |||
| @@ -30,7 +30,7 @@ class NetworkSystemClockContextWriter; | |||
| 30 | 30 | ||
| 31 | class TimeManager final { | 31 | class TimeManager final { |
| 32 | public: | 32 | public: |
| 33 | explicit TimeManager(Core::System& system); | 33 | explicit TimeManager(Core::System& system_); |
| 34 | ~TimeManager(); | 34 | ~TimeManager(); |
| 35 | 35 | ||
| 36 | void Initialize(); | 36 | void Initialize(); |
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index 4d8de81be..176ad0eee 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp | |||
| @@ -15,19 +15,13 @@ namespace Service::Time { | |||
| 15 | 15 | ||
| 16 | static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000}; | 16 | static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000}; |
| 17 | 17 | ||
| 18 | SharedMemory::SharedMemory(Core::System& system) : system(system) { | 18 | SharedMemory::SharedMemory(Core::System& system_) : system(system_) { |
| 19 | shared_memory_holder = SharedFrom(&system.Kernel().GetTimeSharedMem()); | 19 | std::memset(system.Kernel().GetTimeSharedMem().GetPointer(), 0, SHARED_MEMORY_SIZE); |
| 20 | std::memset(shared_memory_holder->GetPointer(), 0, SHARED_MEMORY_SIZE); | ||
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | SharedMemory::~SharedMemory() = default; | 22 | SharedMemory::~SharedMemory() = default; |
| 24 | 23 | ||
| 25 | std::shared_ptr<Kernel::KSharedMemory> SharedMemory::GetSharedMemoryHolder() const { | 24 | void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id, |
| 26 | return shared_memory_holder; | ||
| 27 | } | ||
| 28 | |||
| 29 | void SharedMemory::SetupStandardSteadyClock(Core::System& system, | ||
| 30 | const Common::UUID& clock_source_id, | ||
| 31 | Clock::TimeSpanType current_time_point) { | 25 | Clock::TimeSpanType current_time_point) { |
| 32 | const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( | 26 | const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( |
| 33 | system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; | 27 | system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)}; |
| @@ -35,22 +29,22 @@ void SharedMemory::SetupStandardSteadyClock(Core::System& system, | |||
| 35 | static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), | 29 | static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), |
| 36 | clock_source_id}; | 30 | clock_source_id}; |
| 37 | shared_memory_format.standard_steady_clock_timepoint.StoreData( | 31 | shared_memory_format.standard_steady_clock_timepoint.StoreData( |
| 38 | shared_memory_holder->GetPointer(), context); | 32 | system.Kernel().GetTimeSharedMem().GetPointer(), context); |
| 39 | } | 33 | } |
| 40 | 34 | ||
| 41 | void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) { | 35 | void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) { |
| 42 | shared_memory_format.standard_local_system_clock_context.StoreData( | 36 | shared_memory_format.standard_local_system_clock_context.StoreData( |
| 43 | shared_memory_holder->GetPointer(), context); | 37 | system.Kernel().GetTimeSharedMem().GetPointer(), context); |
| 44 | } | 38 | } |
| 45 | 39 | ||
| 46 | void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) { | 40 | void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) { |
| 47 | shared_memory_format.standard_network_system_clock_context.StoreData( | 41 | shared_memory_format.standard_network_system_clock_context.StoreData( |
| 48 | shared_memory_holder->GetPointer(), context); | 42 | system.Kernel().GetTimeSharedMem().GetPointer(), context); |
| 49 | } | 43 | } |
| 50 | 44 | ||
| 51 | void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) { | 45 | void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) { |
| 52 | shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( | 46 | shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( |
| 53 | shared_memory_holder->GetPointer(), is_enabled); | 47 | system.Kernel().GetTimeSharedMem().GetPointer(), is_enabled); |
| 54 | } | 48 | } |
| 55 | 49 | ||
| 56 | } // namespace Service::Time | 50 | } // namespace Service::Time |
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h index 299680517..d471b5d18 100644 --- a/src/core/hle/service/time/time_sharedmemory.h +++ b/src/core/hle/service/time/time_sharedmemory.h | |||
| @@ -14,12 +14,9 @@ namespace Service::Time { | |||
| 14 | 14 | ||
| 15 | class SharedMemory final { | 15 | class SharedMemory final { |
| 16 | public: | 16 | public: |
| 17 | explicit SharedMemory(Core::System& system); | 17 | explicit SharedMemory(Core::System& system_); |
| 18 | ~SharedMemory(); | 18 | ~SharedMemory(); |
| 19 | 19 | ||
| 20 | // Return the shared memory handle | ||
| 21 | std::shared_ptr<Kernel::KSharedMemory> GetSharedMemoryHolder() const; | ||
| 22 | |||
| 23 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? | 20 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? |
| 24 | template <typename T, std::size_t Offset> | 21 | template <typename T, std::size_t Offset> |
| 25 | struct MemoryBarrier { | 22 | struct MemoryBarrier { |
| @@ -56,14 +53,13 @@ public: | |||
| 56 | }; | 53 | }; |
| 57 | static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); | 54 | static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); |
| 58 | 55 | ||
| 59 | void SetupStandardSteadyClock(Core::System& system, const Common::UUID& clock_source_id, | 56 | void SetupStandardSteadyClock(const Common::UUID& clock_source_id, |
| 60 | Clock::TimeSpanType currentTimePoint); | 57 | Clock::TimeSpanType current_time_point); |
| 61 | void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context); | 58 | void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context); |
| 62 | void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context); | 59 | void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context); |
| 63 | void SetAutomaticCorrectionEnabled(bool is_enabled); | 60 | void SetAutomaticCorrectionEnabled(bool is_enabled); |
| 64 | 61 | ||
| 65 | private: | 62 | private: |
| 66 | std::shared_ptr<Kernel::KSharedMemory> shared_memory_holder; | ||
| 67 | Core::System& system; | 63 | Core::System& system; |
| 68 | Format shared_memory_format{}; | 64 | Format shared_memory_format{}; |
| 69 | }; | 65 | }; |
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index 3c8e71a3c..57f71e6f0 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -68,8 +68,8 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) { | |||
| 68 | return location_name_cache; | 68 | return location_name_cache; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | TimeZoneContentManager::TimeZoneContentManager(Core::System& system) | 71 | TimeZoneContentManager::TimeZoneContentManager(Core::System& system_) |
| 72 | : system{system}, location_name_cache{BuildLocationNameCache(system)} {} | 72 | : system{system_}, location_name_cache{BuildLocationNameCache(system)} {} |
| 73 | 73 | ||
| 74 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { | 74 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { |
| 75 | std::string location_name; | 75 | std::string location_name; |
diff --git a/src/core/hle/service/time/time_zone_content_manager.h b/src/core/hle/service/time/time_zone_content_manager.h index 52dd1a020..cfa601084 100644 --- a/src/core/hle/service/time/time_zone_content_manager.h +++ b/src/core/hle/service/time/time_zone_content_manager.h | |||
| @@ -21,7 +21,7 @@ namespace Service::Time::TimeZone { | |||
| 21 | 21 | ||
| 22 | class TimeZoneContentManager final { | 22 | class TimeZoneContentManager final { |
| 23 | public: | 23 | public: |
| 24 | explicit TimeZoneContentManager(Core::System& system); | 24 | explicit TimeZoneContentManager(Core::System& system_); |
| 25 | 25 | ||
| 26 | void Initialize(TimeManager& time_manager); | 26 | void Initialize(TimeManager& time_manager); |
| 27 | 27 | ||
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 7f42aa4a0..0dd342dbf 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -17,10 +17,10 @@ | |||
| 17 | 17 | ||
| 18 | namespace Service::VI { | 18 | namespace Service::VI { |
| 19 | 19 | ||
| 20 | Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} { | 20 | Display::Display(u64 id, std::string name_, Core::System& system) |
| 21 | auto& kernel = system.Kernel(); | 21 | : display_id{id}, name{std::move(name_)}, vsync_event{system.Kernel()} { |
| 22 | vsync_event = Kernel::KEvent::Create(kernel, fmt::format("Display VSync Event {}", id)); | 22 | Kernel::KAutoObject::Create(std::addressof(vsync_event)); |
| 23 | vsync_event->Initialize(); | 23 | vsync_event.Initialize(fmt::format("Display VSync Event {}", id)); |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | Display::~Display() = default; | 26 | Display::~Display() = default; |
| @@ -33,32 +33,30 @@ const Layer& Display::GetLayer(std::size_t index) const { | |||
| 33 | return *layers.at(index); | 33 | return *layers.at(index); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | std::shared_ptr<Kernel::KReadableEvent> Display::GetVSyncEvent() const { | 36 | Kernel::KReadableEvent& Display::GetVSyncEvent() { |
| 37 | return vsync_event->GetReadableEvent(); | 37 | return vsync_event.GetReadableEvent(); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | void Display::SignalVSyncEvent() { | 40 | void Display::SignalVSyncEvent() { |
| 41 | vsync_event->GetWritableEvent()->Signal(); | 41 | vsync_event.GetWritableEvent().Signal(); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) { | 44 | void Display::CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue) { |
| 45 | // TODO(Subv): Support more than 1 layer. | 45 | // TODO(Subv): Support more than 1 layer. |
| 46 | ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); | 46 | ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); |
| 47 | 47 | ||
| 48 | layers.emplace_back(std::make_shared<Layer>(id, buffer_queue)); | 48 | layers.emplace_back(std::make_shared<Layer>(layer_id, buffer_queue)); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | void Display::CloseLayer(u64 id) { | 51 | void Display::CloseLayer(u64 layer_id) { |
| 52 | layers.erase( | 52 | std::erase_if(layers, [layer_id](const auto& layer) { return layer->GetID() == layer_id; }); |
| 53 | std::remove_if(layers.begin(), layers.end(), | ||
| 54 | [id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; }), | ||
| 55 | layers.end()); | ||
| 56 | } | 53 | } |
| 57 | 54 | ||
| 58 | Layer* Display::FindLayer(u64 id) { | 55 | Layer* Display::FindLayer(u64 layer_id) { |
| 59 | const auto itr = | 56 | const auto itr = |
| 60 | std::find_if(layers.begin(), layers.end(), | 57 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::shared_ptr<Layer>& layer) { |
| 61 | [id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; }); | 58 | return layer->GetID() == layer_id; |
| 59 | }); | ||
| 62 | 60 | ||
| 63 | if (itr == layers.end()) { | 61 | if (itr == layers.end()) { |
| 64 | return nullptr; | 62 | return nullptr; |
| @@ -67,10 +65,11 @@ Layer* Display::FindLayer(u64 id) { | |||
| 67 | return itr->get(); | 65 | return itr->get(); |
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | const Layer* Display::FindLayer(u64 id) const { | 68 | const Layer* Display::FindLayer(u64 layer_id) const { |
| 71 | const auto itr = | 69 | const auto itr = |
| 72 | std::find_if(layers.begin(), layers.end(), | 70 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::shared_ptr<Layer>& layer) { |
| 73 | [id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; }); | 71 | return layer->GetID() == layer_id; |
| 72 | }); | ||
| 74 | 73 | ||
| 75 | if (itr == layers.end()) { | 74 | if (itr == layers.end()) { |
| 76 | return nullptr; | 75 | return nullptr; |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 931c898f6..166f2a4cc 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | 13 | ||
| 13 | namespace Kernel { | 14 | namespace Kernel { |
| @@ -24,24 +25,21 @@ class Layer; | |||
| 24 | 25 | ||
| 25 | /// Represents a single display type | 26 | /// Represents a single display type |
| 26 | class Display { | 27 | class Display { |
| 28 | YUZU_NON_COPYABLE(Display); | ||
| 29 | YUZU_NON_MOVEABLE(Display); | ||
| 30 | |||
| 27 | public: | 31 | public: |
| 28 | /// Constructs a display with a given unique ID and name. | 32 | /// Constructs a display with a given unique ID and name. |
| 29 | /// | 33 | /// |
| 30 | /// @param id The unique ID for this display. | 34 | /// @param id The unique ID for this display. |
| 31 | /// @param name The name for this display. | 35 | /// @param name_ The name for this display. |
| 32 | /// | 36 | /// |
| 33 | Display(u64 id, std::string name, Core::System& system); | 37 | Display(u64 id, std::string name_, Core::System& system); |
| 34 | ~Display(); | 38 | ~Display(); |
| 35 | 39 | ||
| 36 | Display(const Display&) = delete; | ||
| 37 | Display& operator=(const Display&) = delete; | ||
| 38 | |||
| 39 | Display(Display&&) = default; | ||
| 40 | Display& operator=(Display&&) = default; | ||
| 41 | |||
| 42 | /// Gets the unique ID assigned to this display. | 40 | /// Gets the unique ID assigned to this display. |
| 43 | u64 GetID() const { | 41 | u64 GetID() const { |
| 44 | return id; | 42 | return display_id; |
| 45 | } | 43 | } |
| 46 | 44 | ||
| 47 | /// Gets the name of this display | 45 | /// Gets the name of this display |
| @@ -61,48 +59,48 @@ public: | |||
| 61 | const Layer& GetLayer(std::size_t index) const; | 59 | const Layer& GetLayer(std::size_t index) const; |
| 62 | 60 | ||
| 63 | /// Gets the readable vsync event. | 61 | /// Gets the readable vsync event. |
| 64 | std::shared_ptr<Kernel::KReadableEvent> GetVSyncEvent() const; | 62 | Kernel::KReadableEvent& GetVSyncEvent(); |
| 65 | 63 | ||
| 66 | /// Signals the internal vsync event. | 64 | /// Signals the internal vsync event. |
| 67 | void SignalVSyncEvent(); | 65 | void SignalVSyncEvent(); |
| 68 | 66 | ||
| 69 | /// Creates and adds a layer to this display with the given ID. | 67 | /// Creates and adds a layer to this display with the given ID. |
| 70 | /// | 68 | /// |
| 71 | /// @param id The ID to assign to the created layer. | 69 | /// @param layer_id The ID to assign to the created layer. |
| 72 | /// @param buffer_queue The buffer queue for the layer instance to use. | 70 | /// @param buffer_queue The buffer queue for the layer instance to use. |
| 73 | /// | 71 | /// |
| 74 | void CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue); | 72 | void CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue); |
| 75 | 73 | ||
| 76 | /// Closes and removes a layer from this display with the given ID. | 74 | /// Closes and removes a layer from this display with the given ID. |
| 77 | /// | 75 | /// |
| 78 | /// @param id The ID assigned to the layer to close. | 76 | /// @param layer_id The ID assigned to the layer to close. |
| 79 | /// | 77 | /// |
| 80 | void CloseLayer(u64 id); | 78 | void CloseLayer(u64 layer_id); |
| 81 | 79 | ||
| 82 | /// Attempts to find a layer with the given ID. | 80 | /// Attempts to find a layer with the given ID. |
| 83 | /// | 81 | /// |
| 84 | /// @param id The layer ID. | 82 | /// @param layer_id The layer ID. |
| 85 | /// | 83 | /// |
| 86 | /// @returns If found, the Layer instance with the given ID. | 84 | /// @returns If found, the Layer instance with the given ID. |
| 87 | /// If not found, then nullptr is returned. | 85 | /// If not found, then nullptr is returned. |
| 88 | /// | 86 | /// |
| 89 | Layer* FindLayer(u64 id); | 87 | Layer* FindLayer(u64 layer_id); |
| 90 | 88 | ||
| 91 | /// Attempts to find a layer with the given ID. | 89 | /// Attempts to find a layer with the given ID. |
| 92 | /// | 90 | /// |
| 93 | /// @param id The layer ID. | 91 | /// @param layer_id The layer ID. |
| 94 | /// | 92 | /// |
| 95 | /// @returns If found, the Layer instance with the given ID. | 93 | /// @returns If found, the Layer instance with the given ID. |
| 96 | /// If not found, then nullptr is returned. | 94 | /// If not found, then nullptr is returned. |
| 97 | /// | 95 | /// |
| 98 | const Layer* FindLayer(u64 id) const; | 96 | const Layer* FindLayer(u64 layer_id) const; |
| 99 | 97 | ||
| 100 | private: | 98 | private: |
| 101 | u64 id; | 99 | u64 display_id; |
| 102 | std::string name; | 100 | std::string name; |
| 103 | 101 | ||
| 104 | std::vector<std::shared_ptr<Layer>> layers; | 102 | std::vector<std::shared_ptr<Layer>> layers; |
| 105 | std::shared_ptr<Kernel::KEvent> vsync_event; | 103 | Kernel::KEvent vsync_event; |
| 106 | }; | 104 | }; |
| 107 | 105 | ||
| 108 | } // namespace Service::VI | 106 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp index 954225c26..9bc382587 100644 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ b/src/core/hle/service/vi/layer/vi_layer.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::VI { | 7 | namespace Service::VI { |
| 8 | 8 | ||
| 9 | Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : id{id}, buffer_queue{queue} {} | 9 | Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : layer_id{id}, buffer_queue{queue} {} |
| 10 | 10 | ||
| 11 | Layer::~Layer() = default; | 11 | Layer::~Layer() = default; |
| 12 | 12 | ||
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index c6bfd01f6..ebdd85505 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h | |||
| @@ -31,7 +31,7 @@ public: | |||
| 31 | 31 | ||
| 32 | /// Gets the ID for this layer. | 32 | /// Gets the ID for this layer. |
| 33 | u64 GetID() const { | 33 | u64 GetID() const { |
| 34 | return id; | 34 | return layer_id; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Gets a reference to the buffer queue this layer is using. | 37 | /// Gets a reference to the buffer queue this layer is using. |
| @@ -45,7 +45,7 @@ public: | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
| 48 | u64 id; | 48 | u64 layer_id; |
| 49 | NVFlinger::BufferQueue& buffer_queue; | 49 | NVFlinger::BufferQueue& buffer_queue; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 7ae07d072..fdd2b4b4f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -212,7 +212,7 @@ private: | |||
| 212 | 212 | ||
| 213 | class IGBPConnectRequestParcel : public Parcel { | 213 | class IGBPConnectRequestParcel : public Parcel { |
| 214 | public: | 214 | public: |
| 215 | explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 215 | explicit IGBPConnectRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 216 | Deserialize(); | 216 | Deserialize(); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| @@ -274,8 +274,8 @@ private: | |||
| 274 | 274 | ||
| 275 | class IGBPSetPreallocatedBufferRequestParcel : public Parcel { | 275 | class IGBPSetPreallocatedBufferRequestParcel : public Parcel { |
| 276 | public: | 276 | public: |
| 277 | explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer) | 277 | explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer_) |
| 278 | : Parcel(std::move(buffer)) { | 278 | : Parcel(std::move(buffer_)) { |
| 279 | Deserialize(); | 279 | Deserialize(); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| @@ -312,7 +312,7 @@ protected: | |||
| 312 | 312 | ||
| 313 | class IGBPCancelBufferRequestParcel : public Parcel { | 313 | class IGBPCancelBufferRequestParcel : public Parcel { |
| 314 | public: | 314 | public: |
| 315 | explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 315 | explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 316 | Deserialize(); | 316 | Deserialize(); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| @@ -338,7 +338,7 @@ protected: | |||
| 338 | 338 | ||
| 339 | class IGBPDequeueBufferRequestParcel : public Parcel { | 339 | class IGBPDequeueBufferRequestParcel : public Parcel { |
| 340 | public: | 340 | public: |
| 341 | explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 341 | explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 342 | Deserialize(); | 342 | Deserialize(); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| @@ -360,8 +360,8 @@ public: | |||
| 360 | 360 | ||
| 361 | class IGBPDequeueBufferResponseParcel : public Parcel { | 361 | class IGBPDequeueBufferResponseParcel : public Parcel { |
| 362 | public: | 362 | public: |
| 363 | explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) | 363 | explicit IGBPDequeueBufferResponseParcel(u32 slot_, Nvidia::MultiFence& multi_fence_) |
| 364 | : slot(slot), multi_fence(multi_fence) {} | 364 | : slot(slot_), multi_fence(multi_fence_) {} |
| 365 | 365 | ||
| 366 | protected: | 366 | protected: |
| 367 | void SerializeData() override { | 367 | void SerializeData() override { |
| @@ -377,7 +377,7 @@ protected: | |||
| 377 | 377 | ||
| 378 | class IGBPRequestBufferRequestParcel : public Parcel { | 378 | class IGBPRequestBufferRequestParcel : public Parcel { |
| 379 | public: | 379 | public: |
| 380 | explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 380 | explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 381 | Deserialize(); | 381 | Deserialize(); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| @@ -391,7 +391,7 @@ public: | |||
| 391 | 391 | ||
| 392 | class IGBPRequestBufferResponseParcel : public Parcel { | 392 | class IGBPRequestBufferResponseParcel : public Parcel { |
| 393 | public: | 393 | public: |
| 394 | explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer) : buffer(buffer) {} | 394 | explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer_) : buffer(buffer_) {} |
| 395 | ~IGBPRequestBufferResponseParcel() override = default; | 395 | ~IGBPRequestBufferResponseParcel() override = default; |
| 396 | 396 | ||
| 397 | protected: | 397 | protected: |
| @@ -408,7 +408,7 @@ protected: | |||
| 408 | 408 | ||
| 409 | class IGBPQueueBufferRequestParcel : public Parcel { | 409 | class IGBPQueueBufferRequestParcel : public Parcel { |
| 410 | public: | 410 | public: |
| 411 | explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 411 | explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 412 | Deserialize(); | 412 | Deserialize(); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| @@ -470,7 +470,7 @@ private: | |||
| 470 | 470 | ||
| 471 | class IGBPQueryRequestParcel : public Parcel { | 471 | class IGBPQueryRequestParcel : public Parcel { |
| 472 | public: | 472 | public: |
| 473 | explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 473 | explicit IGBPQueryRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 474 | Deserialize(); | 474 | Deserialize(); |
| 475 | } | 475 | } |
| 476 | 476 | ||
| @@ -484,7 +484,7 @@ public: | |||
| 484 | 484 | ||
| 485 | class IGBPQueryResponseParcel : public Parcel { | 485 | class IGBPQueryResponseParcel : public Parcel { |
| 486 | public: | 486 | public: |
| 487 | explicit IGBPQueryResponseParcel(u32 value) : value(value) {} | 487 | explicit IGBPQueryResponseParcel(u32 value_) : value{value_} {} |
| 488 | ~IGBPQueryResponseParcel() override = default; | 488 | ~IGBPQueryResponseParcel() override = default; |
| 489 | 489 | ||
| 490 | protected: | 490 | protected: |
| @@ -669,12 +669,10 @@ private: | |||
| 669 | 669 | ||
| 670 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); | 670 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); |
| 671 | 671 | ||
| 672 | const auto& buffer_queue = *nv_flinger.FindBufferQueue(id); | ||
| 673 | |||
| 674 | // TODO(Subv): Find out what this actually is. | 672 | // TODO(Subv): Find out what this actually is. |
| 675 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 673 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 676 | rb.Push(RESULT_SUCCESS); | 674 | rb.Push(RESULT_SUCCESS); |
| 677 | rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent()); | 675 | rb.PushCopyObjects(nv_flinger.FindBufferQueue(id)->GetBufferWaitEvent()); |
| 678 | } | 676 | } |
| 679 | 677 | ||
| 680 | NVFlinger::NVFlinger& nv_flinger; | 678 | NVFlinger::NVFlinger& nv_flinger; |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 4a10211f6..022885c1b 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/romfs_factory.h" | 14 | #include "core/file_sys/romfs_factory.h" |
| 15 | #include "core/hle/kernel/k_page_table.h" | 15 | #include "core/hle/kernel/k_page_table.h" |
| 16 | #include "core/hle/kernel/k_process.h" | ||
| 16 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/process.h" | ||
| 18 | #include "core/hle/service/filesystem/filesystem.h" | 18 | #include "core/hle/service/filesystem/filesystem.h" |
| 19 | #include "core/loader/deconstructed_rom_directory.h" | 19 | #include "core/loader/deconstructed_rom_directory.h" |
| 20 | #include "core/loader/nso.h" | 20 | #include "core/loader/nso.h" |
| @@ -22,12 +22,12 @@ | |||
| 22 | namespace Loader { | 22 | namespace Loader { |
| 23 | 23 | ||
| 24 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, | 24 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, |
| 25 | bool override_update) | 25 | bool override_update_) |
| 26 | : AppLoader(std::move(file_)), override_update(override_update) { | 26 | : AppLoader(std::move(file_)), override_update(override_update_) { |
| 27 | const auto dir = file->GetContainingDirectory(); | 27 | const auto file_dir = file->GetContainingDirectory(); |
| 28 | 28 | ||
| 29 | // Title ID | 29 | // Title ID |
| 30 | const auto npdm = dir->GetFile("main.npdm"); | 30 | const auto npdm = file_dir->GetFile("main.npdm"); |
| 31 | if (npdm != nullptr) { | 31 | if (npdm != nullptr) { |
| 32 | const auto res = metadata.Load(npdm); | 32 | const auto res = metadata.Load(npdm); |
| 33 | if (res == ResultStatus::Success) | 33 | if (res == ResultStatus::Success) |
| @@ -37,7 +37,7 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 37 | // Icon | 37 | // Icon |
| 38 | FileSys::VirtualFile icon_file = nullptr; | 38 | FileSys::VirtualFile icon_file = nullptr; |
| 39 | for (const auto& language : FileSys::LANGUAGE_NAMES) { | 39 | for (const auto& language : FileSys::LANGUAGE_NAMES) { |
| 40 | icon_file = dir->GetFile("icon_" + std::string(language) + ".dat"); | 40 | icon_file = file_dir->GetFile("icon_" + std::string(language) + ".dat"); |
| 41 | if (icon_file != nullptr) { | 41 | if (icon_file != nullptr) { |
| 42 | icon_data = icon_file->ReadAllBytes(); | 42 | icon_data = icon_file->ReadAllBytes(); |
| 43 | break; | 43 | break; |
| @@ -46,24 +46,23 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 46 | 46 | ||
| 47 | if (icon_data.empty()) { | 47 | if (icon_data.empty()) { |
| 48 | // Any png, jpeg, or bmp file | 48 | // Any png, jpeg, or bmp file |
| 49 | const auto& files = dir->GetFiles(); | 49 | const auto& files = file_dir->GetFiles(); |
| 50 | const auto icon_iter = | 50 | const auto icon_iter = |
| 51 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 51 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) { |
| 52 | return file->GetExtension() == "png" || file->GetExtension() == "jpg" || | 52 | return f->GetExtension() == "png" || f->GetExtension() == "jpg" || |
| 53 | file->GetExtension() == "bmp" || file->GetExtension() == "jpeg"; | 53 | f->GetExtension() == "bmp" || f->GetExtension() == "jpeg"; |
| 54 | }); | 54 | }); |
| 55 | if (icon_iter != files.end()) | 55 | if (icon_iter != files.end()) |
| 56 | icon_data = (*icon_iter)->ReadAllBytes(); | 56 | icon_data = (*icon_iter)->ReadAllBytes(); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | // Metadata | 59 | // Metadata |
| 60 | FileSys::VirtualFile nacp_file = dir->GetFile("control.nacp"); | 60 | FileSys::VirtualFile nacp_file = file_dir->GetFile("control.nacp"); |
| 61 | if (nacp_file == nullptr) { | 61 | if (nacp_file == nullptr) { |
| 62 | const auto& files = dir->GetFiles(); | 62 | const auto& files = file_dir->GetFiles(); |
| 63 | const auto nacp_iter = | 63 | const auto nacp_iter = |
| 64 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 64 | std::find_if(files.begin(), files.end(), |
| 65 | return file->GetExtension() == "nacp"; | 65 | [](const FileSys::VirtualFile& f) { return f->GetExtension() == "nacp"; }); |
| 66 | }); | ||
| 67 | if (nacp_iter != files.end()) | 66 | if (nacp_iter != files.end()) |
| 68 | nacp_file = *nacp_iter; | 67 | nacp_file = *nacp_iter; |
| 69 | } | 68 | } |
| @@ -75,12 +74,12 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 75 | } | 74 | } |
| 76 | 75 | ||
| 77 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( | 76 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( |
| 78 | FileSys::VirtualDir directory, bool override_update) | 77 | FileSys::VirtualDir directory, bool override_update_) |
| 79 | : AppLoader(directory->GetFile("main")), dir(std::move(directory)), | 78 | : AppLoader(directory->GetFile("main")), dir(std::move(directory)), |
| 80 | override_update(override_update) {} | 79 | override_update(override_update_) {} |
| 81 | 80 | ||
| 82 | FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) { | 81 | FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { |
| 83 | if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) { | 82 | if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) { |
| 84 | return FileType::DeconstructedRomDirectory; | 83 | return FileType::DeconstructedRomDirectory; |
| 85 | } | 84 | } |
| 86 | 85 | ||
| @@ -88,7 +87,7 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua | |||
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load( | 89 | AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load( |
| 91 | Kernel::Process& process, Core::System& system) { | 90 | Kernel::KProcess& process, Core::System& system) { |
| 92 | if (is_loaded) { | 91 | if (is_loaded) { |
| 93 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 92 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 94 | } | 93 | } |
| @@ -184,8 +183,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect | |||
| 184 | // Find the RomFS by searching for a ".romfs" file in this directory | 183 | // Find the RomFS by searching for a ".romfs" file in this directory |
| 185 | const auto& files = dir->GetFiles(); | 184 | const auto& files = dir->GetFiles(); |
| 186 | const auto romfs_iter = | 185 | const auto romfs_iter = |
| 187 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 186 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) { |
| 188 | return file->GetName().find(".romfs") != std::string::npos; | 187 | return f->GetName().find(".romfs") != std::string::npos; |
| 189 | }); | 188 | }); |
| 190 | 189 | ||
| 191 | // Register the RomFS if a ".romfs" file was found | 190 | // Register the RomFS if a ".romfs" file was found |
| @@ -200,17 +199,21 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect | |||
| 200 | LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; | 199 | LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}}; |
| 201 | } | 200 | } |
| 202 | 201 | ||
| 203 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) { | 202 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& out_dir) { |
| 204 | if (romfs == nullptr) | 203 | if (romfs == nullptr) { |
| 205 | return ResultStatus::ErrorNoRomFS; | 204 | return ResultStatus::ErrorNoRomFS; |
| 206 | dir = romfs; | 205 | } |
| 206 | |||
| 207 | out_dir = romfs; | ||
| 207 | return ResultStatus::Success; | 208 | return ResultStatus::Success; |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& buffer) { | 211 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& out_buffer) { |
| 211 | if (icon_data.empty()) | 212 | if (icon_data.empty()) { |
| 212 | return ResultStatus::ErrorNoIcon; | 213 | return ResultStatus::ErrorNoIcon; |
| 213 | buffer = icon_data; | 214 | } |
| 215 | |||
| 216 | out_buffer = icon_data; | ||
| 214 | return ResultStatus::Success; | 217 | return ResultStatus::Success; |
| 215 | } | 218 | } |
| 216 | 219 | ||
| @@ -219,10 +222,12 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program | |||
| 219 | return ResultStatus::Success; | 222 | return ResultStatus::Success; |
| 220 | } | 223 | } |
| 221 | 224 | ||
| 222 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title) { | 225 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& out_title) { |
| 223 | if (name.empty()) | 226 | if (name.empty()) { |
| 224 | return ResultStatus::ErrorNoControl; | 227 | return ResultStatus::ErrorNoControl; |
| 225 | title = name; | 228 | } |
| 229 | |||
| 230 | out_title = name; | ||
| 226 | return ResultStatus::Success; | 231 | return ResultStatus::Success; |
| 227 | } | 232 | } |
| 228 | 233 | ||
| @@ -230,12 +235,12 @@ bool AppLoader_DeconstructedRomDirectory::IsRomFSUpdatable() const { | |||
| 230 | return false; | 235 | return false; |
| 231 | } | 236 | } |
| 232 | 237 | ||
| 233 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadNSOModules(Modules& modules) { | 238 | ResultStatus AppLoader_DeconstructedRomDirectory::ReadNSOModules(Modules& out_modules) { |
| 234 | if (!is_loaded) { | 239 | if (!is_loaded) { |
| 235 | return ResultStatus::ErrorNotInitialized; | 240 | return ResultStatus::ErrorNotInitialized; |
| 236 | } | 241 | } |
| 237 | 242 | ||
| 238 | modules = this->modules; | 243 | out_modules = this->modules; |
| 239 | return ResultStatus::Success; | 244 | return ResultStatus::Success; |
| 240 | } | 245 | } |
| 241 | 246 | ||
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index 3c968580f..79a4d4db5 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h | |||
| @@ -24,32 +24,35 @@ namespace Loader { | |||
| 24 | class AppLoader_DeconstructedRomDirectory final : public AppLoader { | 24 | class AppLoader_DeconstructedRomDirectory final : public AppLoader { |
| 25 | public: | 25 | public: |
| 26 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file, | 26 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file, |
| 27 | bool override_update = false); | 27 | bool override_update_ = false); |
| 28 | 28 | ||
| 29 | // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' | 29 | // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' |
| 30 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory, | 30 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory, |
| 31 | bool override_update = false); | 31 | bool override_update_ = false); |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * Returns the type of the file | 34 | * Identifies whether or not the given file is a deconstructed ROM directory. |
| 35 | * @param file open file | 35 | * |
| 36 | * @return FileType found, or FileType::Error if this loader doesn't know it | 36 | * @param dir_file The file to verify. |
| 37 | * | ||
| 38 | * @return FileType::DeconstructedRomDirectory, or FileType::Error | ||
| 39 | * if the file is not a deconstructed ROM directory. | ||
| 37 | */ | 40 | */ |
| 38 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 41 | static FileType IdentifyType(const FileSys::VirtualFile& dir_file); |
| 39 | 42 | ||
| 40 | FileType GetFileType() const override { | 43 | FileType GetFileType() const override { |
| 41 | return IdentifyType(file); | 44 | return IdentifyType(file); |
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 47 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 45 | 48 | ||
| 46 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 49 | ResultStatus ReadRomFS(FileSys::VirtualFile& out_dir) override; |
| 47 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 50 | ResultStatus ReadIcon(std::vector<u8>& out_buffer) override; |
| 48 | ResultStatus ReadProgramId(u64& out_program_id) override; | 51 | ResultStatus ReadProgramId(u64& out_program_id) override; |
| 49 | ResultStatus ReadTitle(std::string& title) override; | 52 | ResultStatus ReadTitle(std::string& title) override; |
| 50 | bool IsRomFSUpdatable() const override; | 53 | bool IsRomFSUpdatable() const override; |
| 51 | 54 | ||
| 52 | ResultStatus ReadNSOModules(Modules& modules) override; | 55 | ResultStatus ReadNSOModules(Modules& out_modules) override; |
| 53 | 56 | ||
| 54 | private: | 57 | private: |
| 55 | FileSys::ProgramMetadata metadata; | 58 | FileSys::ProgramMetadata metadata; |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index f4a339390..c062a4259 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "core/hle/kernel/code_set.h" | 12 | #include "core/hle/kernel/code_set.h" |
| 13 | #include "core/hle/kernel/k_page_table.h" | 13 | #include "core/hle/kernel/k_page_table.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/k_process.h" |
| 15 | #include "core/loader/elf.h" | 15 | #include "core/loader/elf.h" |
| 16 | #include "core/memory.h" | 16 | #include "core/memory.h" |
| 17 | 17 | ||
| @@ -364,26 +364,29 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const | |||
| 364 | 364 | ||
| 365 | namespace Loader { | 365 | namespace Loader { |
| 366 | 366 | ||
| 367 | AppLoader_ELF::AppLoader_ELF(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} | 367 | AppLoader_ELF::AppLoader_ELF(FileSys::VirtualFile file_) : AppLoader(std::move(file_)) {} |
| 368 | 368 | ||
| 369 | FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) { | 369 | FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& elf_file) { |
| 370 | static constexpr u16 ELF_MACHINE_ARM{0x28}; | 370 | static constexpr u16 ELF_MACHINE_ARM{0x28}; |
| 371 | 371 | ||
| 372 | u32 magic = 0; | 372 | u32 magic = 0; |
| 373 | if (4 != file->ReadObject(&magic)) | 373 | if (4 != elf_file->ReadObject(&magic)) { |
| 374 | return FileType::Error; | 374 | return FileType::Error; |
| 375 | } | ||
| 375 | 376 | ||
| 376 | u16 machine = 0; | 377 | u16 machine = 0; |
| 377 | if (2 != file->ReadObject(&machine, 18)) | 378 | if (2 != elf_file->ReadObject(&machine, 18)) { |
| 378 | return FileType::Error; | 379 | return FileType::Error; |
| 380 | } | ||
| 379 | 381 | ||
| 380 | if (Common::MakeMagic('\x7f', 'E', 'L', 'F') == magic && ELF_MACHINE_ARM == machine) | 382 | if (Common::MakeMagic('\x7f', 'E', 'L', 'F') == magic && ELF_MACHINE_ARM == machine) { |
| 381 | return FileType::ELF; | 383 | return FileType::ELF; |
| 384 | } | ||
| 382 | 385 | ||
| 383 | return FileType::Error; | 386 | return FileType::Error; |
| 384 | } | 387 | } |
| 385 | 388 | ||
| 386 | AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process, | 389 | AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::KProcess& process, |
| 387 | [[maybe_unused]] Core::System& system) { | 390 | [[maybe_unused]] Core::System& system) { |
| 388 | if (is_loaded) { | 391 | if (is_loaded) { |
| 389 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 392 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 2067932c7..890299a20 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h | |||
| @@ -20,17 +20,19 @@ public: | |||
| 20 | explicit AppLoader_ELF(FileSys::VirtualFile file); | 20 | explicit AppLoader_ELF(FileSys::VirtualFile file); |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * Returns the type of the file | 23 | * Identifies whether or not the given file is an ELF file. |
| 24 | * @param file open file | 24 | * |
| 25 | * @return FileType found, or FileType::Error if this loader doesn't know it | 25 | * @param elf_file The file to identify. |
| 26 | * | ||
| 27 | * @return FileType::ELF, or FileType::Error if the file is not an ELF file. | ||
| 26 | */ | 28 | */ |
| 27 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 29 | static FileType IdentifyType(const FileSys::VirtualFile& elf_file); |
| 28 | 30 | ||
| 29 | FileType GetFileType() const override { | 31 | FileType GetFileType() const override { |
| 30 | return IdentifyType(file); | 32 | return IdentifyType(file); |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 35 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | } // namespace Loader | 38 | } // namespace Loader |
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 55e6de794..3ae9e6e0e 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/file_sys/program_metadata.h" | 7 | #include "core/file_sys/program_metadata.h" |
| 8 | #include "core/hle/kernel/code_set.h" | 8 | #include "core/hle/kernel/code_set.h" |
| 9 | #include "core/hle/kernel/k_page_table.h" | 9 | #include "core/hle/kernel/k_page_table.h" |
| 10 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/k_process.h" |
| 11 | #include "core/loader/kip.h" | 11 | #include "core/loader/kip.h" |
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | 13 | ||
| @@ -24,9 +24,9 @@ AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_) | |||
| 24 | 24 | ||
| 25 | AppLoader_KIP::~AppLoader_KIP() = default; | 25 | AppLoader_KIP::~AppLoader_KIP() = default; |
| 26 | 26 | ||
| 27 | FileType AppLoader_KIP::IdentifyType(const FileSys::VirtualFile& file) { | 27 | FileType AppLoader_KIP::IdentifyType(const FileSys::VirtualFile& in_file) { |
| 28 | u32_le magic{}; | 28 | u32_le magic{}; |
| 29 | if (file->GetSize() < sizeof(u32) || file->ReadObject(&magic) != sizeof(u32)) { | 29 | if (in_file->GetSize() < sizeof(u32) || in_file->ReadObject(&magic) != sizeof(u32)) { |
| 30 | return FileType::Error; | 30 | return FileType::Error; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| @@ -42,7 +42,7 @@ FileType AppLoader_KIP::GetFileType() const { | |||
| 42 | : FileType::Error; | 42 | : FileType::Error; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process, | 45 | AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, |
| 46 | [[maybe_unused]] Core::System& system) { | 46 | [[maybe_unused]] Core::System& system) { |
| 47 | if (is_loaded) { | 47 | if (is_loaded) { |
| 48 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 48 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| @@ -56,10 +56,10 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process, | |||
| 56 | return {kip->GetStatus(), {}}; | 56 | return {kip->GetStatus(), {}}; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | const auto get_kip_address_space_type = [](const auto& kip) { | 59 | const auto get_kip_address_space_type = [](const auto& kip_type) { |
| 60 | return kip.Is64Bit() | 60 | return kip_type.Is64Bit() |
| 61 | ? (kip.Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit | 61 | ? (kip_type.Is39BitAddressSpace() ? FileSys::ProgramAddressSpaceType::Is39Bit |
| 62 | : FileSys::ProgramAddressSpaceType::Is36Bit) | 62 | : FileSys::ProgramAddressSpaceType::Is36Bit) |
| 63 | : FileSys::ProgramAddressSpaceType::Is32Bit; | 63 | : FileSys::ProgramAddressSpaceType::Is32Bit; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
diff --git a/src/core/loader/kip.h b/src/core/loader/kip.h index 14a85e295..5f914b4a8 100644 --- a/src/core/loader/kip.h +++ b/src/core/loader/kip.h | |||
| @@ -22,15 +22,17 @@ public: | |||
| 22 | ~AppLoader_KIP() override; | 22 | ~AppLoader_KIP() override; |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * Returns the type of the file | 25 | * Identifies whether or not the given file is a KIP. |
| 26 | * @param file open file | 26 | * |
| 27 | * @return FileType found, or FileType::Error if this loader doesn't know it | 27 | * @param in_file The file to identify. |
| 28 | * | ||
| 29 | * @return FileType::KIP if found, or FileType::Error if unknown. | ||
| 28 | */ | 30 | */ |
| 29 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 31 | static FileType IdentifyType(const FileSys::VirtualFile& in_file); |
| 30 | 32 | ||
| 31 | FileType GetFileType() const override; | 33 | FileType GetFileType() const override; |
| 32 | 34 | ||
| 33 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 35 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 34 | 36 | ||
| 35 | private: | 37 | private: |
| 36 | std::unique_ptr<FileSys::KIP> kip; | 38 | std::unique_ptr<FileSys::KIP> kip; |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index e4f5fd40c..d4808fb5b 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/string_util.h" | 12 | #include "common/string_util.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/k_process.h" |
| 15 | #include "core/loader/deconstructed_rom_directory.h" | 15 | #include "core/loader/deconstructed_rom_directory.h" |
| 16 | #include "core/loader/elf.h" | 16 | #include "core/loader/elf.h" |
| 17 | #include "core/loader/kip.h" | 17 | #include "core/loader/kip.h" |
| @@ -194,7 +194,7 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status) { | |||
| 194 | return os; | 194 | return os; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | AppLoader::AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {} | 197 | AppLoader::AppLoader(FileSys::VirtualFile file_) : file(std::move(file_)) {} |
| 198 | AppLoader::~AppLoader() = default; | 198 | AppLoader::~AppLoader() = default; |
| 199 | 199 | ||
| 200 | /** | 200 | /** |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index b2e5b13de..edc8bb257 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -25,7 +25,7 @@ class NACP; | |||
| 25 | 25 | ||
| 26 | namespace Kernel { | 26 | namespace Kernel { |
| 27 | struct AddressMapping; | 27 | struct AddressMapping; |
| 28 | class Process; | 28 | class KProcess; |
| 29 | } // namespace Kernel | 29 | } // namespace Kernel |
| 30 | 30 | ||
| 31 | namespace Loader { | 31 | namespace Loader { |
| @@ -147,26 +147,31 @@ public: | |||
| 147 | }; | 147 | }; |
| 148 | using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>; | 148 | using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>; |
| 149 | 149 | ||
| 150 | explicit AppLoader(FileSys::VirtualFile file); | 150 | explicit AppLoader(FileSys::VirtualFile file_); |
| 151 | virtual ~AppLoader(); | 151 | virtual ~AppLoader(); |
| 152 | 152 | ||
| 153 | /** | 153 | /** |
| 154 | * Returns the type of this file | 154 | * Returns the type of this file |
| 155 | * | ||
| 155 | * @return FileType corresponding to the loaded file | 156 | * @return FileType corresponding to the loaded file |
| 156 | */ | 157 | */ |
| 157 | virtual FileType GetFileType() const = 0; | 158 | virtual FileType GetFileType() const = 0; |
| 158 | 159 | ||
| 159 | /** | 160 | /** |
| 160 | * Load the application and return the created Process instance | 161 | * Load the application and return the created Process instance |
| 162 | * | ||
| 161 | * @param process The newly created process. | 163 | * @param process The newly created process. |
| 162 | * @param system The system that this process is being loaded under. | 164 | * @param system The system that this process is being loaded under. |
| 165 | * | ||
| 163 | * @return The status result of the operation. | 166 | * @return The status result of the operation. |
| 164 | */ | 167 | */ |
| 165 | virtual LoadResult Load(Kernel::Process& process, Core::System& system) = 0; | 168 | virtual LoadResult Load(Kernel::KProcess& process, Core::System& system) = 0; |
| 166 | 169 | ||
| 167 | /** | 170 | /** |
| 168 | * Get the code (typically .code section) of the application | 171 | * Get the code (typically .code section) of the application |
| 169 | * @param buffer Reference to buffer to store data | 172 | * |
| 173 | * @param[out] buffer Reference to buffer to store data | ||
| 174 | * | ||
| 170 | * @return ResultStatus result of function | 175 | * @return ResultStatus result of function |
| 171 | */ | 176 | */ |
| 172 | virtual ResultStatus ReadCode(std::vector<u8>& buffer) { | 177 | virtual ResultStatus ReadCode(std::vector<u8>& buffer) { |
| @@ -175,7 +180,9 @@ public: | |||
| 175 | 180 | ||
| 176 | /** | 181 | /** |
| 177 | * Get the icon (typically icon section) of the application | 182 | * Get the icon (typically icon section) of the application |
| 178 | * @param buffer Reference to buffer to store data | 183 | * |
| 184 | * @param[out] buffer Reference to buffer to store data | ||
| 185 | * | ||
| 179 | * @return ResultStatus result of function | 186 | * @return ResultStatus result of function |
| 180 | */ | 187 | */ |
| 181 | virtual ResultStatus ReadIcon(std::vector<u8>& buffer) { | 188 | virtual ResultStatus ReadIcon(std::vector<u8>& buffer) { |
| @@ -186,7 +193,9 @@ public: | |||
| 186 | * Get the banner (typically banner section) of the application | 193 | * Get the banner (typically banner section) of the application |
| 187 | * In the context of NX, this is the animation that displays in the bottom right of the screen | 194 | * In the context of NX, this is the animation that displays in the bottom right of the screen |
| 188 | * when a game boots. Stored in GIF format. | 195 | * when a game boots. Stored in GIF format. |
| 189 | * @param buffer Reference to buffer to store data | 196 | * |
| 197 | * @param[out] buffer Reference to buffer to store data | ||
| 198 | * | ||
| 190 | * @return ResultStatus result of function | 199 | * @return ResultStatus result of function |
| 191 | */ | 200 | */ |
| 192 | virtual ResultStatus ReadBanner(std::vector<u8>& buffer) { | 201 | virtual ResultStatus ReadBanner(std::vector<u8>& buffer) { |
| @@ -197,7 +206,9 @@ public: | |||
| 197 | * Get the logo (typically logo section) of the application | 206 | * Get the logo (typically logo section) of the application |
| 198 | * In the context of NX, this is the static image that displays in the top left of the screen | 207 | * In the context of NX, this is the static image that displays in the top left of the screen |
| 199 | * when a game boots. Stored in JPEG format. | 208 | * when a game boots. Stored in JPEG format. |
| 200 | * @param buffer Reference to buffer to store data | 209 | * |
| 210 | * @param[out] buffer Reference to buffer to store data | ||
| 211 | * | ||
| 201 | * @return ResultStatus result of function | 212 | * @return ResultStatus result of function |
| 202 | */ | 213 | */ |
| 203 | virtual ResultStatus ReadLogo(std::vector<u8>& buffer) { | 214 | virtual ResultStatus ReadLogo(std::vector<u8>& buffer) { |
| @@ -206,7 +217,9 @@ public: | |||
| 206 | 217 | ||
| 207 | /** | 218 | /** |
| 208 | * Get the program id of the application | 219 | * Get the program id of the application |
| 209 | * @param out_program_id Reference to store program id into | 220 | * |
| 221 | * @param[out] out_program_id Reference to store program id into | ||
| 222 | * | ||
| 210 | * @return ResultStatus result of function | 223 | * @return ResultStatus result of function |
| 211 | */ | 224 | */ |
| 212 | virtual ResultStatus ReadProgramId(u64& out_program_id) { | 225 | virtual ResultStatus ReadProgramId(u64& out_program_id) { |
| @@ -216,19 +229,23 @@ public: | |||
| 216 | /** | 229 | /** |
| 217 | * Get the RomFS of the application | 230 | * Get the RomFS of the application |
| 218 | * Since the RomFS can be huge, we return a file reference instead of copying to a buffer | 231 | * Since the RomFS can be huge, we return a file reference instead of copying to a buffer |
| 219 | * @param file The directory containing the RomFS | 232 | * |
| 233 | * @param[out] out_file The directory containing the RomFS | ||
| 234 | * | ||
| 220 | * @return ResultStatus result of function | 235 | * @return ResultStatus result of function |
| 221 | */ | 236 | */ |
| 222 | virtual ResultStatus ReadRomFS(FileSys::VirtualFile& file) { | 237 | virtual ResultStatus ReadRomFS(FileSys::VirtualFile& out_file) { |
| 223 | return ResultStatus::ErrorNotImplemented; | 238 | return ResultStatus::ErrorNotImplemented; |
| 224 | } | 239 | } |
| 225 | 240 | ||
| 226 | /** | 241 | /** |
| 227 | * Get the raw update of the application, should it come packed with one | 242 | * Get the raw update of the application, should it come packed with one |
| 228 | * @param file The raw update NCA file (Program-type | 243 | * |
| 244 | * @param[out] out_file The raw update NCA file (Program-type) | ||
| 245 | * | ||
| 229 | * @return ResultStatus result of function | 246 | * @return ResultStatus result of function |
| 230 | */ | 247 | */ |
| 231 | virtual ResultStatus ReadUpdateRaw(FileSys::VirtualFile& file) { | 248 | virtual ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) { |
| 232 | return ResultStatus::ErrorNotImplemented; | 249 | return ResultStatus::ErrorNotImplemented; |
| 233 | } | 250 | } |
| 234 | 251 | ||
| @@ -236,7 +253,8 @@ public: | |||
| 236 | * Get whether or not updates can be applied to the RomFS. | 253 | * Get whether or not updates can be applied to the RomFS. |
| 237 | * By default, this is true, however for formats where it cannot be guaranteed that the RomFS is | 254 | * By default, this is true, however for formats where it cannot be guaranteed that the RomFS is |
| 238 | * the base game it should be set to false. | 255 | * the base game it should be set to false. |
| 239 | * @return bool whether or not updatable. | 256 | * |
| 257 | * @return bool indicating whether or not the RomFS is updatable. | ||
| 240 | */ | 258 | */ |
| 241 | virtual bool IsRomFSUpdatable() const { | 259 | virtual bool IsRomFSUpdatable() const { |
| 242 | return true; | 260 | return true; |
| @@ -244,8 +262,9 @@ public: | |||
| 244 | 262 | ||
| 245 | /** | 263 | /** |
| 246 | * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS) | 264 | * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS) |
| 247 | * data. Needed for bktr patching. | 265 | * data. Needed for BKTR patching. |
| 248 | * @return IVFC offset for romfs. | 266 | * |
| 267 | * @return IVFC offset for RomFS. | ||
| 249 | */ | 268 | */ |
| 250 | virtual u64 ReadRomFSIVFCOffset() const { | 269 | virtual u64 ReadRomFSIVFCOffset() const { |
| 251 | return 0; | 270 | return 0; |
| @@ -253,7 +272,9 @@ public: | |||
| 253 | 272 | ||
| 254 | /** | 273 | /** |
| 255 | * Get the title of the application | 274 | * Get the title of the application |
| 256 | * @param title Reference to store the application title into | 275 | * |
| 276 | * @param[out] title Reference to store the application title into | ||
| 277 | * | ||
| 257 | * @return ResultStatus result of function | 278 | * @return ResultStatus result of function |
| 258 | */ | 279 | */ |
| 259 | virtual ResultStatus ReadTitle(std::string& title) { | 280 | virtual ResultStatus ReadTitle(std::string& title) { |
| @@ -262,7 +283,9 @@ public: | |||
| 262 | 283 | ||
| 263 | /** | 284 | /** |
| 264 | * Get the control data (CNMT) of the application | 285 | * Get the control data (CNMT) of the application |
| 265 | * @param control Reference to store the application control data into | 286 | * |
| 287 | * @param[out] control Reference to store the application control data into | ||
| 288 | * | ||
| 266 | * @return ResultStatus result of function | 289 | * @return ResultStatus result of function |
| 267 | */ | 290 | */ |
| 268 | virtual ResultStatus ReadControlData(FileSys::NACP& control) { | 291 | virtual ResultStatus ReadControlData(FileSys::NACP& control) { |
| @@ -271,10 +294,12 @@ public: | |||
| 271 | 294 | ||
| 272 | /** | 295 | /** |
| 273 | * Get the RomFS of the manual of the application | 296 | * Get the RomFS of the manual of the application |
| 274 | * @param file The raw manual RomFS of the game | 297 | * |
| 298 | * @param[out] out_file The raw manual RomFS of the game | ||
| 299 | * | ||
| 275 | * @return ResultStatus result of function | 300 | * @return ResultStatus result of function |
| 276 | */ | 301 | */ |
| 277 | virtual ResultStatus ReadManualRomFS(FileSys::VirtualFile& file) { | 302 | virtual ResultStatus ReadManualRomFS(FileSys::VirtualFile& out_file) { |
| 278 | return ResultStatus::ErrorNotImplemented; | 303 | return ResultStatus::ErrorNotImplemented; |
| 279 | } | 304 | } |
| 280 | 305 | ||
diff --git a/src/core/loader/nax.cpp b/src/core/loader/nax.cpp index 49028177b..aceb66414 100644 --- a/src/core/loader/nax.cpp +++ b/src/core/loader/nax.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "core/file_sys/content_archive.h" | 6 | #include "core/file_sys/content_archive.h" |
| 7 | #include "core/file_sys/romfs.h" | 7 | #include "core/file_sys/romfs.h" |
| 8 | #include "core/file_sys/xts_archive.h" | 8 | #include "core/file_sys/xts_archive.h" |
| 9 | #include "core/hle/kernel/process.h" | 9 | #include "core/hle/kernel/k_process.h" |
| 10 | #include "core/loader/nax.h" | 10 | #include "core/loader/nax.h" |
| 11 | #include "core/loader/nca.h" | 11 | #include "core/loader/nca.h" |
| 12 | 12 | ||
| @@ -26,14 +26,14 @@ FileType IdentifyTypeImpl(const FileSys::NAX& nax) { | |||
| 26 | } | 26 | } |
| 27 | } // Anonymous namespace | 27 | } // Anonymous namespace |
| 28 | 28 | ||
| 29 | AppLoader_NAX::AppLoader_NAX(FileSys::VirtualFile file) | 29 | AppLoader_NAX::AppLoader_NAX(FileSys::VirtualFile file_) |
| 30 | : AppLoader(file), nax(std::make_unique<FileSys::NAX>(file)), | 30 | : AppLoader(file_), nax(std::make_unique<FileSys::NAX>(file_)), |
| 31 | nca_loader(std::make_unique<AppLoader_NCA>(nax->GetDecrypted())) {} | 31 | nca_loader(std::make_unique<AppLoader_NCA>(nax->GetDecrypted())) {} |
| 32 | 32 | ||
| 33 | AppLoader_NAX::~AppLoader_NAX() = default; | 33 | AppLoader_NAX::~AppLoader_NAX() = default; |
| 34 | 34 | ||
| 35 | FileType AppLoader_NAX::IdentifyType(const FileSys::VirtualFile& file) { | 35 | FileType AppLoader_NAX::IdentifyType(const FileSys::VirtualFile& nax_file) { |
| 36 | const FileSys::NAX nax(file); | 36 | const FileSys::NAX nax(nax_file); |
| 37 | return IdentifyTypeImpl(nax); | 37 | return IdentifyTypeImpl(nax); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| @@ -41,8 +41,7 @@ FileType AppLoader_NAX::GetFileType() const { | |||
| 41 | return IdentifyTypeImpl(*nax); | 41 | return IdentifyTypeImpl(*nax); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process, | 44 | AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::KProcess& process, Core::System& system) { |
| 45 | [[maybe_unused]] Core::System& system) { | ||
| 46 | if (is_loaded) { | 45 | if (is_loaded) { |
| 47 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 46 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 48 | } | 47 | } |
diff --git a/src/core/loader/nax.h b/src/core/loader/nax.h index a5b5e2ae1..b3a50894f 100644 --- a/src/core/loader/nax.h +++ b/src/core/loader/nax.h | |||
| @@ -23,19 +23,21 @@ class AppLoader_NCA; | |||
| 23 | /// Loads a NAX file | 23 | /// Loads a NAX file |
| 24 | class AppLoader_NAX final : public AppLoader { | 24 | class AppLoader_NAX final : public AppLoader { |
| 25 | public: | 25 | public: |
| 26 | explicit AppLoader_NAX(FileSys::VirtualFile file); | 26 | explicit AppLoader_NAX(FileSys::VirtualFile file_); |
| 27 | ~AppLoader_NAX() override; | 27 | ~AppLoader_NAX() override; |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
| 30 | * Returns the type of the file | 30 | * Identifies whether or not the given file is a NAX file. |
| 31 | * @param file open file | 31 | * |
| 32 | * @return FileType found, or FileType::Error if this loader doesn't know it | 32 | * @param nax_file The file to identify. |
| 33 | * | ||
| 34 | * @return FileType::NAX, or FileType::Error if the file is not a NAX file. | ||
| 33 | */ | 35 | */ |
| 34 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 36 | static FileType IdentifyType(const FileSys::VirtualFile& nax_file); |
| 35 | 37 | ||
| 36 | FileType GetFileType() const override; | 38 | FileType GetFileType() const override; |
| 37 | 39 | ||
| 38 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 40 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 39 | 41 | ||
| 40 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 42 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 41 | u64 ReadRomFSIVFCOffset() const override; | 43 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index fa694de37..418cbf61b 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/file_sys/content_archive.h" | 10 | #include "core/file_sys/content_archive.h" |
| 11 | #include "core/file_sys/romfs_factory.h" | 11 | #include "core/file_sys/romfs_factory.h" |
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/k_process.h" |
| 13 | #include "core/hle/service/filesystem/filesystem.h" | 13 | #include "core/hle/service/filesystem/filesystem.h" |
| 14 | #include "core/loader/deconstructed_rom_directory.h" | 14 | #include "core/loader/deconstructed_rom_directory.h" |
| 15 | #include "core/loader/nca.h" | 15 | #include "core/loader/nca.h" |
| @@ -21,17 +21,18 @@ AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file_) | |||
| 21 | 21 | ||
| 22 | AppLoader_NCA::~AppLoader_NCA() = default; | 22 | AppLoader_NCA::~AppLoader_NCA() = default; |
| 23 | 23 | ||
| 24 | FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) { | 24 | FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& nca_file) { |
| 25 | FileSys::NCA nca(file); | 25 | const FileSys::NCA nca(nca_file); |
| 26 | 26 | ||
| 27 | if (nca.GetStatus() == ResultStatus::Success && | 27 | if (nca.GetStatus() == ResultStatus::Success && |
| 28 | nca.GetType() == FileSys::NCAContentType::Program) | 28 | nca.GetType() == FileSys::NCAContentType::Program) { |
| 29 | return FileType::NCA; | 29 | return FileType::NCA; |
| 30 | } | ||
| 30 | 31 | ||
| 31 | return FileType::Error; | 32 | return FileType::Error; |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::System& system) { | 35 | AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::System& system) { |
| 35 | if (is_loaded) { | 36 | if (is_loaded) { |
| 36 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 37 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 37 | } | 38 | } |
| @@ -67,43 +68,59 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::Sy | |||
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { | 70 | ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { |
| 70 | if (nca == nullptr) | 71 | if (nca == nullptr) { |
| 71 | return ResultStatus::ErrorNotInitialized; | 72 | return ResultStatus::ErrorNotInitialized; |
| 72 | if (nca->GetRomFS() == nullptr || nca->GetRomFS()->GetSize() == 0) | 73 | } |
| 74 | |||
| 75 | if (nca->GetRomFS() == nullptr || nca->GetRomFS()->GetSize() == 0) { | ||
| 73 | return ResultStatus::ErrorNoRomFS; | 76 | return ResultStatus::ErrorNoRomFS; |
| 77 | } | ||
| 78 | |||
| 74 | dir = nca->GetRomFS(); | 79 | dir = nca->GetRomFS(); |
| 75 | return ResultStatus::Success; | 80 | return ResultStatus::Success; |
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | u64 AppLoader_NCA::ReadRomFSIVFCOffset() const { | 83 | u64 AppLoader_NCA::ReadRomFSIVFCOffset() const { |
| 79 | if (nca == nullptr) | 84 | if (nca == nullptr) { |
| 80 | return 0; | 85 | return 0; |
| 86 | } | ||
| 87 | |||
| 81 | return nca->GetBaseIVFCOffset(); | 88 | return nca->GetBaseIVFCOffset(); |
| 82 | } | 89 | } |
| 83 | 90 | ||
| 84 | ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { | 91 | ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { |
| 85 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) | 92 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) { |
| 86 | return ResultStatus::ErrorNotInitialized; | 93 | return ResultStatus::ErrorNotInitialized; |
| 94 | } | ||
| 95 | |||
| 87 | out_program_id = nca->GetTitleId(); | 96 | out_program_id = nca->GetTitleId(); |
| 88 | return ResultStatus::Success; | 97 | return ResultStatus::Success; |
| 89 | } | 98 | } |
| 90 | 99 | ||
| 91 | ResultStatus AppLoader_NCA::ReadBanner(std::vector<u8>& buffer) { | 100 | ResultStatus AppLoader_NCA::ReadBanner(std::vector<u8>& buffer) { |
| 92 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) | 101 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) { |
| 93 | return ResultStatus::ErrorNotInitialized; | 102 | return ResultStatus::ErrorNotInitialized; |
| 103 | } | ||
| 104 | |||
| 94 | const auto logo = nca->GetLogoPartition(); | 105 | const auto logo = nca->GetLogoPartition(); |
| 95 | if (logo == nullptr) | 106 | if (logo == nullptr) { |
| 96 | return ResultStatus::ErrorNoIcon; | 107 | return ResultStatus::ErrorNoIcon; |
| 108 | } | ||
| 109 | |||
| 97 | buffer = logo->GetFile("StartupMovie.gif")->ReadAllBytes(); | 110 | buffer = logo->GetFile("StartupMovie.gif")->ReadAllBytes(); |
| 98 | return ResultStatus::Success; | 111 | return ResultStatus::Success; |
| 99 | } | 112 | } |
| 100 | 113 | ||
| 101 | ResultStatus AppLoader_NCA::ReadLogo(std::vector<u8>& buffer) { | 114 | ResultStatus AppLoader_NCA::ReadLogo(std::vector<u8>& buffer) { |
| 102 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) | 115 | if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) { |
| 103 | return ResultStatus::ErrorNotInitialized; | 116 | return ResultStatus::ErrorNotInitialized; |
| 117 | } | ||
| 118 | |||
| 104 | const auto logo = nca->GetLogoPartition(); | 119 | const auto logo = nca->GetLogoPartition(); |
| 105 | if (logo == nullptr) | 120 | if (logo == nullptr) { |
| 106 | return ResultStatus::ErrorNoIcon; | 121 | return ResultStatus::ErrorNoIcon; |
| 122 | } | ||
| 123 | |||
| 107 | buffer = logo->GetFile("NintendoLogo.png")->ReadAllBytes(); | 124 | buffer = logo->GetFile("NintendoLogo.png")->ReadAllBytes(); |
| 108 | return ResultStatus::Success; | 125 | return ResultStatus::Success; |
| 109 | } | 126 | } |
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h index 918792800..f2ff080bb 100644 --- a/src/core/loader/nca.h +++ b/src/core/loader/nca.h | |||
| @@ -23,21 +23,23 @@ class AppLoader_DeconstructedRomDirectory; | |||
| 23 | /// Loads an NCA file | 23 | /// Loads an NCA file |
| 24 | class AppLoader_NCA final : public AppLoader { | 24 | class AppLoader_NCA final : public AppLoader { |
| 25 | public: | 25 | public: |
| 26 | explicit AppLoader_NCA(FileSys::VirtualFile file); | 26 | explicit AppLoader_NCA(FileSys::VirtualFile file_); |
| 27 | ~AppLoader_NCA() override; | 27 | ~AppLoader_NCA() override; |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
| 30 | * Returns the type of the file | 30 | * Identifies whether or not the given file is an NCA file. |
| 31 | * @param file open file | 31 | * |
| 32 | * @return FileType found, or FileType::Error if this loader doesn't know it | 32 | * @param nca_file The file to identify. |
| 33 | * | ||
| 34 | * @return FileType::NCA, or FileType::Error if the file is not an NCA file. | ||
| 33 | */ | 35 | */ |
| 34 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 36 | static FileType IdentifyType(const FileSys::VirtualFile& nca_file); |
| 35 | 37 | ||
| 36 | FileType GetFileType() const override { | 38 | FileType GetFileType() const override { |
| 37 | return IdentifyType(file); | 39 | return IdentifyType(file); |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 42 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 41 | 43 | ||
| 42 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; | 44 | ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; |
| 43 | u64 ReadRomFSIVFCOffset() const override; | 45 | u64 ReadRomFSIVFCOffset() const override; |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 0115ed0c4..ef54fa574 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include "core/file_sys/vfs_offset.h" | 17 | #include "core/file_sys/vfs_offset.h" |
| 18 | #include "core/hle/kernel/code_set.h" | 18 | #include "core/hle/kernel/code_set.h" |
| 19 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 20 | #include "core/hle/kernel/k_process.h" | ||
| 20 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 21 | #include "core/hle/kernel/process.h" | ||
| 22 | #include "core/hle/service/filesystem/filesystem.h" | 22 | #include "core/hle/service/filesystem/filesystem.h" |
| 23 | #include "core/loader/nro.h" | 23 | #include "core/loader/nro.h" |
| 24 | #include "core/loader/nso.h" | 24 | #include "core/loader/nso.h" |
| @@ -72,7 +72,7 @@ struct AssetHeader { | |||
| 72 | }; | 72 | }; |
| 73 | static_assert(sizeof(AssetHeader) == 0x38, "AssetHeader has incorrect size."); | 73 | static_assert(sizeof(AssetHeader) == 0x38, "AssetHeader has incorrect size."); |
| 74 | 74 | ||
| 75 | AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(file) { | 75 | AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file_) : AppLoader(std::move(file_)) { |
| 76 | NroHeader nro_header{}; | 76 | NroHeader nro_header{}; |
| 77 | if (file->ReadObject(&nro_header) != sizeof(NroHeader)) { | 77 | if (file->ReadObject(&nro_header) != sizeof(NroHeader)) { |
| 78 | return; | 78 | return; |
| @@ -114,10 +114,10 @@ AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(file) { | |||
| 114 | 114 | ||
| 115 | AppLoader_NRO::~AppLoader_NRO() = default; | 115 | AppLoader_NRO::~AppLoader_NRO() = default; |
| 116 | 116 | ||
| 117 | FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) { | 117 | FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& nro_file) { |
| 118 | // Read NSO header | 118 | // Read NSO header |
| 119 | NroHeader nro_header{}; | 119 | NroHeader nro_header{}; |
| 120 | if (sizeof(NroHeader) != file->ReadObject(&nro_header)) { | 120 | if (sizeof(NroHeader) != nro_file->ReadObject(&nro_header)) { |
| 121 | return FileType::Error; | 121 | return FileType::Error; |
| 122 | } | 122 | } |
| 123 | if (nro_header.magic == Common::MakeMagic('N', 'R', 'O', '0')) { | 123 | if (nro_header.magic == Common::MakeMagic('N', 'R', 'O', '0')) { |
| @@ -130,8 +130,7 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 130 | return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK); | 130 | return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data, | 133 | static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) { |
| 134 | const std::string& name) { | ||
| 135 | if (data.size() < sizeof(NroHeader)) { | 134 | if (data.size() < sizeof(NroHeader)) { |
| 136 | return {}; | 135 | return {}; |
| 137 | } | 136 | } |
| @@ -200,11 +199,11 @@ static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data, | |||
| 200 | return true; | 199 | return true; |
| 201 | } | 200 | } |
| 202 | 201 | ||
| 203 | bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& file) { | 202 | bool AppLoader_NRO::LoadNro(Kernel::KProcess& process, const FileSys::VfsFile& nro_file) { |
| 204 | return LoadNroImpl(process, file.ReadAllBytes(), file.GetName()); | 203 | return LoadNroImpl(process, nro_file.ReadAllBytes()); |
| 205 | } | 204 | } |
| 206 | 205 | ||
| 207 | AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process, Core::System& system) { | 206 | AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::KProcess& process, Core::System& system) { |
| 208 | if (is_loaded) { | 207 | if (is_loaded) { |
| 209 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 208 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 210 | } | 209 | } |
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index a82b66221..fd453b402 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h | |||
| @@ -19,7 +19,7 @@ class NACP; | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | namespace Kernel { | 21 | namespace Kernel { |
| 22 | class Process; | 22 | class KProcess; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | namespace Loader { | 25 | namespace Loader { |
| @@ -27,21 +27,23 @@ namespace Loader { | |||
| 27 | /// Loads an NRO file | 27 | /// Loads an NRO file |
| 28 | class AppLoader_NRO final : public AppLoader { | 28 | class AppLoader_NRO final : public AppLoader { |
| 29 | public: | 29 | public: |
| 30 | explicit AppLoader_NRO(FileSys::VirtualFile file); | 30 | explicit AppLoader_NRO(FileSys::VirtualFile file_); |
| 31 | ~AppLoader_NRO() override; | 31 | ~AppLoader_NRO() override; |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * Returns the type of the file | 34 | * Identifies whether or not the given file is an NRO file. |
| 35 | * @param file open file | 35 | * |
| 36 | * @return FileType found, or FileType::Error if this loader doesn't know it | 36 | * @param nro_file The file to identify. |
| 37 | * | ||
| 38 | * @return FileType::NRO, or FileType::Error if the file is not an NRO file. | ||
| 37 | */ | 39 | */ |
| 38 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 40 | static FileType IdentifyType(const FileSys::VirtualFile& nro_file); |
| 39 | 41 | ||
| 40 | FileType GetFileType() const override { | 42 | FileType GetFileType() const override { |
| 41 | return IdentifyType(file); | 43 | return IdentifyType(file); |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 46 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 45 | 47 | ||
| 46 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 48 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
| 47 | ResultStatus ReadProgramId(u64& out_program_id) override; | 49 | ResultStatus ReadProgramId(u64& out_program_id) override; |
| @@ -51,7 +53,7 @@ public: | |||
| 51 | bool IsRomFSUpdatable() const override; | 53 | bool IsRomFSUpdatable() const override; |
| 52 | 54 | ||
| 53 | private: | 55 | private: |
| 54 | bool LoadNro(Kernel::Process& process, const FileSys::VfsFile& file); | 56 | bool LoadNro(Kernel::KProcess& process, const FileSys::VfsFile& nro_file); |
| 55 | 57 | ||
| 56 | std::vector<u8> icon_data; | 58 | std::vector<u8> icon_data; |
| 57 | std::unique_ptr<FileSys::NACP> nacp; | 59 | std::unique_ptr<FileSys::NACP> nacp; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 0c83dd666..df59412cf 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include "core/file_sys/patch_manager.h" | 17 | #include "core/file_sys/patch_manager.h" |
| 18 | #include "core/hle/kernel/code_set.h" | 18 | #include "core/hle/kernel/code_set.h" |
| 19 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 20 | #include "core/hle/kernel/k_process.h" | ||
| 20 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 21 | #include "core/hle/kernel/process.h" | ||
| 22 | #include "core/loader/nso.h" | 22 | #include "core/loader/nso.h" |
| 23 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 24 | 24 | ||
| @@ -56,11 +56,11 @@ bool NSOHeader::IsSegmentCompressed(size_t segment_num) const { | |||
| 56 | return ((flags >> segment_num) & 1) != 0; | 56 | return ((flags >> segment_num) & 1) != 0; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} | 59 | AppLoader_NSO::AppLoader_NSO(FileSys::VirtualFile file_) : AppLoader(std::move(file_)) {} |
| 60 | 60 | ||
| 61 | FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) { | 61 | FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& in_file) { |
| 62 | u32 magic = 0; | 62 | u32 magic = 0; |
| 63 | if (file->ReadObject(&magic) != sizeof(magic)) { | 63 | if (in_file->ReadObject(&magic) != sizeof(magic)) { |
| 64 | return FileType::Error; | 64 | return FileType::Error; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -71,16 +71,16 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 71 | return FileType::NSO; | 71 | return FileType::NSO; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::System& system, | 74 | std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::System& system, |
| 75 | const FileSys::VfsFile& file, VAddr load_base, | 75 | const FileSys::VfsFile& nso_file, VAddr load_base, |
| 76 | bool should_pass_arguments, bool load_into_process, | 76 | bool should_pass_arguments, bool load_into_process, |
| 77 | std::optional<FileSys::PatchManager> pm) { | 77 | std::optional<FileSys::PatchManager> pm) { |
| 78 | if (file.GetSize() < sizeof(NSOHeader)) { | 78 | if (nso_file.GetSize() < sizeof(NSOHeader)) { |
| 79 | return std::nullopt; | 79 | return std::nullopt; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | NSOHeader nso_header{}; | 82 | NSOHeader nso_header{}; |
| 83 | if (sizeof(NSOHeader) != file.ReadObject(&nso_header)) { | 83 | if (sizeof(NSOHeader) != nso_file.ReadObject(&nso_header)) { |
| 84 | return std::nullopt; | 84 | return std::nullopt; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -92,8 +92,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S | |||
| 92 | Kernel::CodeSet codeset; | 92 | Kernel::CodeSet codeset; |
| 93 | Kernel::PhysicalMemory program_image; | 93 | Kernel::PhysicalMemory program_image; |
| 94 | for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { | 94 | for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { |
| 95 | std::vector<u8> data = | 95 | std::vector<u8> data = nso_file.ReadBytes(nso_header.segments_compressed_size[i], |
| 96 | file.ReadBytes(nso_header.segments_compressed_size[i], nso_header.segments[i].offset); | 96 | nso_header.segments[i].offset); |
| 97 | if (nso_header.IsSegmentCompressed(i)) { | 97 | if (nso_header.IsSegmentCompressed(i)) { |
| 98 | data = DecompressSegment(data, nso_header.segments[i]); | 98 | data = DecompressSegment(data, nso_header.segments[i]); |
| 99 | } | 99 | } |
| @@ -136,7 +136,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S | |||
| 136 | pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(), | 136 | pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(), |
| 137 | program_image.data() + program_image.size()); | 137 | program_image.data() + program_image.size()); |
| 138 | 138 | ||
| 139 | pi_header = pm->PatchNSO(pi_header, file.GetName()); | 139 | pi_header = pm->PatchNSO(pi_header, nso_file.GetName()); |
| 140 | 140 | ||
| 141 | std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data()); | 141 | std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data()); |
| 142 | } | 142 | } |
| @@ -162,7 +162,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S | |||
| 162 | return load_base + image_size; | 162 | return load_base + image_size; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::System& system) { | 165 | AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::System& system) { |
| 166 | if (is_loaded) { | 166 | if (is_loaded) { |
| 167 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 167 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 168 | } | 168 | } |
| @@ -183,8 +183,8 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::Sy | |||
| 183 | Core::Memory::DEFAULT_STACK_SIZE}}; | 183 | Core::Memory::DEFAULT_STACK_SIZE}}; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | ResultStatus AppLoader_NSO::ReadNSOModules(Modules& modules) { | 186 | ResultStatus AppLoader_NSO::ReadNSOModules(Modules& out_modules) { |
| 187 | modules = this->modules; | 187 | out_modules = this->modules; |
| 188 | return ResultStatus::Success; | 188 | return ResultStatus::Success; |
| 189 | } | 189 | } |
| 190 | 190 | ||
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 3af461b5f..f7b61bc2d 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -17,7 +17,7 @@ class System; | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace Kernel { | 19 | namespace Kernel { |
| 20 | class Process; | 20 | class KProcess; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | namespace Loader { | 23 | namespace Loader { |
| @@ -71,27 +71,29 @@ static_assert(sizeof(NSOArgumentHeader) == 0x20, "NSOArgumentHeader has incorrec | |||
| 71 | /// Loads an NSO file | 71 | /// Loads an NSO file |
| 72 | class AppLoader_NSO final : public AppLoader { | 72 | class AppLoader_NSO final : public AppLoader { |
| 73 | public: | 73 | public: |
| 74 | explicit AppLoader_NSO(FileSys::VirtualFile file); | 74 | explicit AppLoader_NSO(FileSys::VirtualFile file_); |
| 75 | 75 | ||
| 76 | /** | 76 | /** |
| 77 | * Returns the type of the file | 77 | * Identifies whether or not the given file is a form of NSO file. |
| 78 | * @param file open file | 78 | * |
| 79 | * @return FileType found, or FileType::Error if this loader doesn't know it | 79 | * @param in_file The file to be identified. |
| 80 | * | ||
| 81 | * @return FileType::NSO if found, or FileType::Error if some other type of file. | ||
| 80 | */ | 82 | */ |
| 81 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 83 | static FileType IdentifyType(const FileSys::VirtualFile& in_file); |
| 82 | 84 | ||
| 83 | FileType GetFileType() const override { | 85 | FileType GetFileType() const override { |
| 84 | return IdentifyType(file); | 86 | return IdentifyType(file); |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | static std::optional<VAddr> LoadModule(Kernel::Process& process, Core::System& system, | 89 | static std::optional<VAddr> LoadModule(Kernel::KProcess& process, Core::System& system, |
| 88 | const FileSys::VfsFile& file, VAddr load_base, | 90 | const FileSys::VfsFile& nso_file, VAddr load_base, |
| 89 | bool should_pass_arguments, bool load_into_process, | 91 | bool should_pass_arguments, bool load_into_process, |
| 90 | std::optional<FileSys::PatchManager> pm = {}); | 92 | std::optional<FileSys::PatchManager> pm = {}); |
| 91 | 93 | ||
| 92 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 94 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 93 | 95 | ||
| 94 | ResultStatus ReadNSOModules(Modules& modules) override; | 96 | ResultStatus ReadNSOModules(Modules& out_modules) override; |
| 95 | 97 | ||
| 96 | private: | 98 | private: |
| 97 | Modules modules; | 99 | Modules modules; |
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 928f64c8c..d815a7cd3 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/file_sys/submission_package.h" | 15 | #include "core/file_sys/submission_package.h" |
| 16 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/k_process.h" |
| 17 | #include "core/hle/service/filesystem/filesystem.h" | 17 | #include "core/hle/service/filesystem/filesystem.h" |
| 18 | #include "core/loader/deconstructed_rom_directory.h" | 18 | #include "core/loader/deconstructed_rom_directory.h" |
| 19 | #include "core/loader/nca.h" | 19 | #include "core/loader/nca.h" |
| @@ -21,11 +21,11 @@ | |||
| 21 | 21 | ||
| 22 | namespace Loader { | 22 | namespace Loader { |
| 23 | 23 | ||
| 24 | AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file, | 24 | AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_, |
| 25 | const Service::FileSystem::FileSystemController& fsc, | 25 | const Service::FileSystem::FileSystemController& fsc, |
| 26 | const FileSys::ContentProvider& content_provider, | 26 | const FileSys::ContentProvider& content_provider, |
| 27 | std::size_t program_index) | 27 | std::size_t program_index) |
| 28 | : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file, program_index)), | 28 | : AppLoader(file_), nsp(std::make_unique<FileSys::NSP>(file_, program_index)), |
| 29 | title_id(nsp->GetProgramTitleID()) { | 29 | title_id(nsp->GetProgramTitleID()) { |
| 30 | 30 | ||
| 31 | if (nsp->GetStatus() != ResultStatus::Success) { | 31 | if (nsp->GetStatus() != ResultStatus::Success) { |
| @@ -57,8 +57,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file, | |||
| 57 | 57 | ||
| 58 | AppLoader_NSP::~AppLoader_NSP() = default; | 58 | AppLoader_NSP::~AppLoader_NSP() = default; |
| 59 | 59 | ||
| 60 | FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { | 60 | FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& nsp_file) { |
| 61 | FileSys::NSP nsp(file); | 61 | const FileSys::NSP nsp(nsp_file); |
| 62 | 62 | ||
| 63 | if (nsp.GetStatus() == ResultStatus::Success) { | 63 | if (nsp.GetStatus() == ResultStatus::Success) { |
| 64 | // Extracted Type case | 64 | // Extracted Type case |
| @@ -79,7 +79,7 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 79 | return FileType::Error; | 79 | return FileType::Error; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::System& system) { | 82 | AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::System& system) { |
| 83 | if (is_loaded) { | 83 | if (is_loaded) { |
| 84 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 84 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 85 | } | 85 | } |
| @@ -121,67 +121,80 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::Sy | |||
| 121 | return result; | 121 | return result; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) { | 124 | ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& out_file) { |
| 125 | return secondary_loader->ReadRomFS(file); | 125 | return secondary_loader->ReadRomFS(out_file); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | u64 AppLoader_NSP::ReadRomFSIVFCOffset() const { | 128 | u64 AppLoader_NSP::ReadRomFSIVFCOffset() const { |
| 129 | return secondary_loader->ReadRomFSIVFCOffset(); | 129 | return secondary_loader->ReadRomFSIVFCOffset(); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& file) { | 132 | ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) { |
| 133 | if (nsp->IsExtractedType()) | 133 | if (nsp->IsExtractedType()) { |
| 134 | return ResultStatus::ErrorNoPackedUpdate; | 134 | return ResultStatus::ErrorNoPackedUpdate; |
| 135 | } | ||
| 135 | 136 | ||
| 136 | const auto read = | 137 | const auto read = |
| 137 | nsp->GetNCAFile(FileSys::GetUpdateTitleID(title_id), FileSys::ContentRecordType::Program); | 138 | nsp->GetNCAFile(FileSys::GetUpdateTitleID(title_id), FileSys::ContentRecordType::Program); |
| 138 | 139 | ||
| 139 | if (read == nullptr) | 140 | if (read == nullptr) { |
| 140 | return ResultStatus::ErrorNoPackedUpdate; | 141 | return ResultStatus::ErrorNoPackedUpdate; |
| 141 | const auto nca_test = std::make_shared<FileSys::NCA>(read); | 142 | } |
| 142 | 143 | ||
| 143 | if (nca_test->GetStatus() != ResultStatus::ErrorMissingBKTRBaseRomFS) | 144 | const auto nca_test = std::make_shared<FileSys::NCA>(read); |
| 145 | if (nca_test->GetStatus() != ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 144 | return nca_test->GetStatus(); | 146 | return nca_test->GetStatus(); |
| 147 | } | ||
| 145 | 148 | ||
| 146 | file = read; | 149 | out_file = read; |
| 147 | return ResultStatus::Success; | 150 | return ResultStatus::Success; |
| 148 | } | 151 | } |
| 149 | 152 | ||
| 150 | ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) { | 153 | ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) { |
| 151 | if (title_id == 0) | 154 | if (title_id == 0) { |
| 152 | return ResultStatus::ErrorNotInitialized; | 155 | return ResultStatus::ErrorNotInitialized; |
| 156 | } | ||
| 157 | |||
| 153 | out_program_id = title_id; | 158 | out_program_id = title_id; |
| 154 | return ResultStatus::Success; | 159 | return ResultStatus::Success; |
| 155 | } | 160 | } |
| 156 | 161 | ||
| 157 | ResultStatus AppLoader_NSP::ReadIcon(std::vector<u8>& buffer) { | 162 | ResultStatus AppLoader_NSP::ReadIcon(std::vector<u8>& buffer) { |
| 158 | if (icon_file == nullptr) | 163 | if (icon_file == nullptr) { |
| 159 | return ResultStatus::ErrorNoControl; | 164 | return ResultStatus::ErrorNoControl; |
| 165 | } | ||
| 166 | |||
| 160 | buffer = icon_file->ReadAllBytes(); | 167 | buffer = icon_file->ReadAllBytes(); |
| 161 | return ResultStatus::Success; | 168 | return ResultStatus::Success; |
| 162 | } | 169 | } |
| 163 | 170 | ||
| 164 | ResultStatus AppLoader_NSP::ReadTitle(std::string& title) { | 171 | ResultStatus AppLoader_NSP::ReadTitle(std::string& title) { |
| 165 | if (nacp_file == nullptr) | 172 | if (nacp_file == nullptr) { |
| 166 | return ResultStatus::ErrorNoControl; | 173 | return ResultStatus::ErrorNoControl; |
| 174 | } | ||
| 175 | |||
| 167 | title = nacp_file->GetApplicationName(); | 176 | title = nacp_file->GetApplicationName(); |
| 168 | return ResultStatus::Success; | 177 | return ResultStatus::Success; |
| 169 | } | 178 | } |
| 170 | 179 | ||
| 171 | ResultStatus AppLoader_NSP::ReadControlData(FileSys::NACP& nacp) { | 180 | ResultStatus AppLoader_NSP::ReadControlData(FileSys::NACP& nacp) { |
| 172 | if (nacp_file == nullptr) | 181 | if (nacp_file == nullptr) { |
| 173 | return ResultStatus::ErrorNoControl; | 182 | return ResultStatus::ErrorNoControl; |
| 183 | } | ||
| 184 | |||
| 174 | nacp = *nacp_file; | 185 | nacp = *nacp_file; |
| 175 | return ResultStatus::Success; | 186 | return ResultStatus::Success; |
| 176 | } | 187 | } |
| 177 | 188 | ||
| 178 | ResultStatus AppLoader_NSP::ReadManualRomFS(FileSys::VirtualFile& file) { | 189 | ResultStatus AppLoader_NSP::ReadManualRomFS(FileSys::VirtualFile& out_file) { |
| 179 | const auto nca = | 190 | const auto nca = |
| 180 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::HtmlDocument); | 191 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::HtmlDocument); |
| 181 | if (nsp->GetStatus() != ResultStatus::Success || nca == nullptr) | 192 | if (nsp->GetStatus() != ResultStatus::Success || nca == nullptr) { |
| 182 | return ResultStatus::ErrorNoRomFS; | 193 | return ResultStatus::ErrorNoRomFS; |
| 183 | file = nca->GetRomFS(); | 194 | } |
| 184 | return file == nullptr ? ResultStatus::ErrorNoRomFS : ResultStatus::Success; | 195 | |
| 196 | out_file = nca->GetRomFS(); | ||
| 197 | return out_file == nullptr ? ResultStatus::ErrorNoRomFS : ResultStatus::Success; | ||
| 185 | } | 198 | } |
| 186 | 199 | ||
| 187 | ResultStatus AppLoader_NSP::ReadBanner(std::vector<u8>& buffer) { | 200 | ResultStatus AppLoader_NSP::ReadBanner(std::vector<u8>& buffer) { |
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h index d48d87f2c..644c0ff58 100644 --- a/src/core/loader/nsp.h +++ b/src/core/loader/nsp.h | |||
| @@ -26,33 +26,35 @@ class AppLoader_NCA; | |||
| 26 | /// Loads an XCI file | 26 | /// Loads an XCI file |
| 27 | class AppLoader_NSP final : public AppLoader { | 27 | class AppLoader_NSP final : public AppLoader { |
| 28 | public: | 28 | public: |
| 29 | explicit AppLoader_NSP(FileSys::VirtualFile file, | 29 | explicit AppLoader_NSP(FileSys::VirtualFile file_, |
| 30 | const Service::FileSystem::FileSystemController& fsc, | 30 | const Service::FileSystem::FileSystemController& fsc, |
| 31 | const FileSys::ContentProvider& content_provider, | 31 | const FileSys::ContentProvider& content_provider, |
| 32 | std::size_t program_index); | 32 | std::size_t program_index); |
| 33 | ~AppLoader_NSP() override; | 33 | ~AppLoader_NSP() override; |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | * Returns the type of the file | 36 | * Identifies whether or not the given file is an NSP file. |
| 37 | * @param file open file | 37 | * |
| 38 | * @return FileType found, or FileType::Error if this loader doesn't know it | 38 | * @param nsp_file The file to identify. |
| 39 | * | ||
| 40 | * @return FileType::NSP, or FileType::Error if the file is not an NSP. | ||
| 39 | */ | 41 | */ |
| 40 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 42 | static FileType IdentifyType(const FileSys::VirtualFile& nsp_file); |
| 41 | 43 | ||
| 42 | FileType GetFileType() const override { | 44 | FileType GetFileType() const override { |
| 43 | return IdentifyType(file); | 45 | return IdentifyType(file); |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 48 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 47 | 49 | ||
| 48 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; | 50 | ResultStatus ReadRomFS(FileSys::VirtualFile& out_file) override; |
| 49 | u64 ReadRomFSIVFCOffset() const override; | 51 | u64 ReadRomFSIVFCOffset() const override; |
| 50 | ResultStatus ReadUpdateRaw(FileSys::VirtualFile& file) override; | 52 | ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; |
| 51 | ResultStatus ReadProgramId(u64& out_program_id) override; | 53 | ResultStatus ReadProgramId(u64& out_program_id) override; |
| 52 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 54 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
| 53 | ResultStatus ReadTitle(std::string& title) override; | 55 | ResultStatus ReadTitle(std::string& title) override; |
| 54 | ResultStatus ReadControlData(FileSys::NACP& nacp) override; | 56 | ResultStatus ReadControlData(FileSys::NACP& nacp) override; |
| 55 | ResultStatus ReadManualRomFS(FileSys::VirtualFile& file) override; | 57 | ResultStatus ReadManualRomFS(FileSys::VirtualFile& out_file) override; |
| 56 | 58 | ||
| 57 | ResultStatus ReadBanner(std::vector<u8>& buffer) override; | 59 | ResultStatus ReadBanner(std::vector<u8>& buffer) override; |
| 58 | ResultStatus ReadLogo(std::vector<u8>& buffer) override; | 60 | ResultStatus ReadLogo(std::vector<u8>& buffer) override; |
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index aaa250cea..635d6ae15 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp | |||
| @@ -13,18 +13,18 @@ | |||
| 13 | #include "core/file_sys/registered_cache.h" | 13 | #include "core/file_sys/registered_cache.h" |
| 14 | #include "core/file_sys/romfs.h" | 14 | #include "core/file_sys/romfs.h" |
| 15 | #include "core/file_sys/submission_package.h" | 15 | #include "core/file_sys/submission_package.h" |
| 16 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/k_process.h" |
| 17 | #include "core/hle/service/filesystem/filesystem.h" | 17 | #include "core/hle/service/filesystem/filesystem.h" |
| 18 | #include "core/loader/nca.h" | 18 | #include "core/loader/nca.h" |
| 19 | #include "core/loader/xci.h" | 19 | #include "core/loader/xci.h" |
| 20 | 20 | ||
| 21 | namespace Loader { | 21 | namespace Loader { |
| 22 | 22 | ||
| 23 | AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file, | 23 | AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file_, |
| 24 | const Service::FileSystem::FileSystemController& fsc, | 24 | const Service::FileSystem::FileSystemController& fsc, |
| 25 | const FileSys::ContentProvider& content_provider, | 25 | const FileSys::ContentProvider& content_provider, |
| 26 | std::size_t program_index) | 26 | std::size_t program_index) |
| 27 | : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file, program_index)), | 27 | : AppLoader(file_), xci(std::make_unique<FileSys::XCI>(file_, program_index)), |
| 28 | nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { | 28 | nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { |
| 29 | if (xci->GetStatus() != ResultStatus::Success) { | 29 | if (xci->GetStatus() != ResultStatus::Success) { |
| 30 | return; | 30 | return; |
| @@ -43,8 +43,8 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file, | |||
| 43 | 43 | ||
| 44 | AppLoader_XCI::~AppLoader_XCI() = default; | 44 | AppLoader_XCI::~AppLoader_XCI() = default; |
| 45 | 45 | ||
| 46 | FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) { | 46 | FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& xci_file) { |
| 47 | FileSys::XCI xci(file); | 47 | const FileSys::XCI xci(xci_file); |
| 48 | 48 | ||
| 49 | if (xci.GetStatus() == ResultStatus::Success && | 49 | if (xci.GetStatus() == ResultStatus::Success && |
| 50 | xci.GetNCAByType(FileSys::NCAContentType::Program) != nullptr && | 50 | xci.GetNCAByType(FileSys::NCAContentType::Program) != nullptr && |
| @@ -56,7 +56,7 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 56 | return FileType::Error; | 56 | return FileType::Error; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::System& system) { | 59 | AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::KProcess& process, Core::System& system) { |
| 60 | if (is_loaded) { | 60 | if (is_loaded) { |
| 61 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 61 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 62 | } | 62 | } |
| @@ -87,31 +87,33 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::Sy | |||
| 87 | return result; | 87 | return result; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) { | 90 | ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& out_file) { |
| 91 | return nca_loader->ReadRomFS(file); | 91 | return nca_loader->ReadRomFS(out_file); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | u64 AppLoader_XCI::ReadRomFSIVFCOffset() const { | 94 | u64 AppLoader_XCI::ReadRomFSIVFCOffset() const { |
| 95 | return nca_loader->ReadRomFSIVFCOffset(); | 95 | return nca_loader->ReadRomFSIVFCOffset(); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | ResultStatus AppLoader_XCI::ReadUpdateRaw(FileSys::VirtualFile& file) { | 98 | ResultStatus AppLoader_XCI::ReadUpdateRaw(FileSys::VirtualFile& out_file) { |
| 99 | u64 program_id{}; | 99 | u64 program_id{}; |
| 100 | nca_loader->ReadProgramId(program_id); | 100 | nca_loader->ReadProgramId(program_id); |
| 101 | if (program_id == 0) | 101 | if (program_id == 0) { |
| 102 | return ResultStatus::ErrorXCIMissingProgramNCA; | 102 | return ResultStatus::ErrorXCIMissingProgramNCA; |
| 103 | } | ||
| 103 | 104 | ||
| 104 | const auto read = xci->GetSecurePartitionNSP()->GetNCAFile( | 105 | const auto read = xci->GetSecurePartitionNSP()->GetNCAFile( |
| 105 | FileSys::GetUpdateTitleID(program_id), FileSys::ContentRecordType::Program); | 106 | FileSys::GetUpdateTitleID(program_id), FileSys::ContentRecordType::Program); |
| 106 | 107 | if (read == nullptr) { | |
| 107 | if (read == nullptr) | ||
| 108 | return ResultStatus::ErrorNoPackedUpdate; | 108 | return ResultStatus::ErrorNoPackedUpdate; |
| 109 | const auto nca_test = std::make_shared<FileSys::NCA>(read); | 109 | } |
| 110 | 110 | ||
| 111 | if (nca_test->GetStatus() != ResultStatus::ErrorMissingBKTRBaseRomFS) | 111 | const auto nca_test = std::make_shared<FileSys::NCA>(read); |
| 112 | if (nca_test->GetStatus() != ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 112 | return nca_test->GetStatus(); | 113 | return nca_test->GetStatus(); |
| 114 | } | ||
| 113 | 115 | ||
| 114 | file = read; | 116 | out_file = read; |
| 115 | return ResultStatus::Success; | 117 | return ResultStatus::Success; |
| 116 | } | 118 | } |
| 117 | 119 | ||
| @@ -120,33 +122,41 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) { | |||
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) { | 124 | ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) { |
| 123 | if (icon_file == nullptr) | 125 | if (icon_file == nullptr) { |
| 124 | return ResultStatus::ErrorNoControl; | 126 | return ResultStatus::ErrorNoControl; |
| 127 | } | ||
| 128 | |||
| 125 | buffer = icon_file->ReadAllBytes(); | 129 | buffer = icon_file->ReadAllBytes(); |
| 126 | return ResultStatus::Success; | 130 | return ResultStatus::Success; |
| 127 | } | 131 | } |
| 128 | 132 | ||
| 129 | ResultStatus AppLoader_XCI::ReadTitle(std::string& title) { | 133 | ResultStatus AppLoader_XCI::ReadTitle(std::string& title) { |
| 130 | if (nacp_file == nullptr) | 134 | if (nacp_file == nullptr) { |
| 131 | return ResultStatus::ErrorNoControl; | 135 | return ResultStatus::ErrorNoControl; |
| 136 | } | ||
| 137 | |||
| 132 | title = nacp_file->GetApplicationName(); | 138 | title = nacp_file->GetApplicationName(); |
| 133 | return ResultStatus::Success; | 139 | return ResultStatus::Success; |
| 134 | } | 140 | } |
| 135 | 141 | ||
| 136 | ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) { | 142 | ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) { |
| 137 | if (nacp_file == nullptr) | 143 | if (nacp_file == nullptr) { |
| 138 | return ResultStatus::ErrorNoControl; | 144 | return ResultStatus::ErrorNoControl; |
| 145 | } | ||
| 146 | |||
| 139 | control = *nacp_file; | 147 | control = *nacp_file; |
| 140 | return ResultStatus::Success; | 148 | return ResultStatus::Success; |
| 141 | } | 149 | } |
| 142 | 150 | ||
| 143 | ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& file) { | 151 | ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& out_file) { |
| 144 | const auto nca = xci->GetSecurePartitionNSP()->GetNCA(xci->GetProgramTitleID(), | 152 | const auto nca = xci->GetSecurePartitionNSP()->GetNCA(xci->GetProgramTitleID(), |
| 145 | FileSys::ContentRecordType::HtmlDocument); | 153 | FileSys::ContentRecordType::HtmlDocument); |
| 146 | if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) | 154 | if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) { |
| 147 | return ResultStatus::ErrorXCIMissingPartition; | 155 | return ResultStatus::ErrorXCIMissingPartition; |
| 148 | file = nca->GetRomFS(); | 156 | } |
| 149 | return file == nullptr ? ResultStatus::ErrorNoRomFS : ResultStatus::Success; | 157 | |
| 158 | out_file = nca->GetRomFS(); | ||
| 159 | return out_file == nullptr ? ResultStatus::ErrorNoRomFS : ResultStatus::Success; | ||
| 150 | } | 160 | } |
| 151 | 161 | ||
| 152 | ResultStatus AppLoader_XCI::ReadBanner(std::vector<u8>& buffer) { | 162 | ResultStatus AppLoader_XCI::ReadBanner(std::vector<u8>& buffer) { |
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h index 9f0ceb5ef..708155c30 100644 --- a/src/core/loader/xci.h +++ b/src/core/loader/xci.h | |||
| @@ -26,33 +26,35 @@ class AppLoader_NCA; | |||
| 26 | /// Loads an XCI file | 26 | /// Loads an XCI file |
| 27 | class AppLoader_XCI final : public AppLoader { | 27 | class AppLoader_XCI final : public AppLoader { |
| 28 | public: | 28 | public: |
| 29 | explicit AppLoader_XCI(FileSys::VirtualFile file, | 29 | explicit AppLoader_XCI(FileSys::VirtualFile file_, |
| 30 | const Service::FileSystem::FileSystemController& fsc, | 30 | const Service::FileSystem::FileSystemController& fsc, |
| 31 | const FileSys::ContentProvider& content_provider, | 31 | const FileSys::ContentProvider& content_provider, |
| 32 | std::size_t program_index); | 32 | std::size_t program_index); |
| 33 | ~AppLoader_XCI() override; | 33 | ~AppLoader_XCI() override; |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | * Returns the type of the file | 36 | * Identifies whether or not the given file is an XCI file. |
| 37 | * @param file open file | 37 | * |
| 38 | * @return FileType found, or FileType::Error if this loader doesn't know it | 38 | * @param xci_file The file to identify. |
| 39 | * | ||
| 40 | * @return FileType::XCI, or FileType::Error if the file is not an XCI file. | ||
| 39 | */ | 41 | */ |
| 40 | static FileType IdentifyType(const FileSys::VirtualFile& file); | 42 | static FileType IdentifyType(const FileSys::VirtualFile& xci_file); |
| 41 | 43 | ||
| 42 | FileType GetFileType() const override { | 44 | FileType GetFileType() const override { |
| 43 | return IdentifyType(file); | 45 | return IdentifyType(file); |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | LoadResult Load(Kernel::Process& process, Core::System& system) override; | 48 | LoadResult Load(Kernel::KProcess& process, Core::System& system) override; |
| 47 | 49 | ||
| 48 | ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; | 50 | ResultStatus ReadRomFS(FileSys::VirtualFile& out_file) override; |
| 49 | u64 ReadRomFSIVFCOffset() const override; | 51 | u64 ReadRomFSIVFCOffset() const override; |
| 50 | ResultStatus ReadUpdateRaw(FileSys::VirtualFile& file) override; | 52 | ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; |
| 51 | ResultStatus ReadProgramId(u64& out_program_id) override; | 53 | ResultStatus ReadProgramId(u64& out_program_id) override; |
| 52 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; | 54 | ResultStatus ReadIcon(std::vector<u8>& buffer) override; |
| 53 | ResultStatus ReadTitle(std::string& title) override; | 55 | ResultStatus ReadTitle(std::string& title) override; |
| 54 | ResultStatus ReadControlData(FileSys::NACP& control) override; | 56 | ResultStatus ReadControlData(FileSys::NACP& control) override; |
| 55 | ResultStatus ReadManualRomFS(FileSys::VirtualFile& file) override; | 57 | ResultStatus ReadManualRomFS(FileSys::VirtualFile& out_file) override; |
| 56 | 58 | ||
| 57 | ResultStatus ReadBanner(std::vector<u8>& buffer) override; | 59 | ResultStatus ReadBanner(std::vector<u8>& buffer) override; |
| 58 | ResultStatus ReadLogo(std::vector<u8>& buffer) override; | 60 | ResultStatus ReadLogo(std::vector<u8>& buffer) override; |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index b9dd3e275..b4c56e1c1 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/device_memory.h" | 18 | #include "core/device_memory.h" |
| 19 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 20 | #include "core/hle/kernel/k_process.h" | ||
| 20 | #include "core/hle/kernel/physical_memory.h" | 21 | #include "core/hle/kernel/physical_memory.h" |
| 21 | #include "core/hle/kernel/process.h" | ||
| 22 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 23 | #include "video_core/gpu.h" | 23 | #include "video_core/gpu.h" |
| 24 | 24 | ||
| @@ -30,7 +30,7 @@ namespace Core::Memory { | |||
| 30 | struct Memory::Impl { | 30 | struct Memory::Impl { |
| 31 | explicit Impl(Core::System& system_) : system{system_} {} | 31 | explicit Impl(Core::System& system_) : system{system_} {} |
| 32 | 32 | ||
| 33 | void SetCurrentPageTable(Kernel::Process& process, u32 core_id) { | 33 | void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { |
| 34 | current_page_table = &process.PageTable().PageTableImpl(); | 34 | current_page_table = &process.PageTable().PageTableImpl(); |
| 35 | 35 | ||
| 36 | const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); | 36 | const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); |
| @@ -50,7 +50,7 @@ struct Memory::Impl { | |||
| 50 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); | 50 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { | 53 | bool IsValidVirtualAddress(const Kernel::KProcess& process, const VAddr vaddr) const { |
| 54 | const auto& page_table = process.PageTable().PageTableImpl(); | 54 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 55 | const auto [pointer, type] = page_table.pointers[vaddr >> PAGE_BITS].PointerType(); | 55 | const auto [pointer, type] = page_table.pointers[vaddr >> PAGE_BITS].PointerType(); |
| 56 | return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory; | 56 | return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory; |
| @@ -82,6 +82,22 @@ struct Memory::Impl { | |||
| 82 | return nullptr; | 82 | return nullptr; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | u8* GetKernelBuffer(VAddr start_vaddr, size_t size) { | ||
| 86 | // TODO(bunnei): This is just a workaround until we have kernel memory layout mapped & | ||
| 87 | // managed. Until then, we use this to allocate and access kernel memory regions. | ||
| 88 | |||
| 89 | auto search = kernel_memory_regions.find(start_vaddr); | ||
| 90 | if (search != kernel_memory_regions.end()) { | ||
| 91 | return search->second.get(); | ||
| 92 | } | ||
| 93 | |||
| 94 | std::unique_ptr<u8[]> new_memory_region{new u8[size]}; | ||
| 95 | u8* raw_ptr = new_memory_region.get(); | ||
| 96 | kernel_memory_regions[start_vaddr] = std::move(new_memory_region); | ||
| 97 | |||
| 98 | return raw_ptr; | ||
| 99 | } | ||
| 100 | |||
| 85 | u8 Read8(const VAddr addr) { | 101 | u8 Read8(const VAddr addr) { |
| 86 | return Read<u8>(addr); | 102 | return Read<u8>(addr); |
| 87 | } | 103 | } |
| @@ -178,7 +194,7 @@ struct Memory::Impl { | |||
| 178 | return string; | 194 | return string; |
| 179 | } | 195 | } |
| 180 | 196 | ||
| 181 | void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | 197 | void ReadBlock(const Kernel::KProcess& process, const VAddr src_addr, void* dest_buffer, |
| 182 | const std::size_t size) { | 198 | const std::size_t size) { |
| 183 | const auto& page_table = process.PageTable().PageTableImpl(); | 199 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 184 | 200 | ||
| @@ -223,7 +239,7 @@ struct Memory::Impl { | |||
| 223 | } | 239 | } |
| 224 | } | 240 | } |
| 225 | 241 | ||
| 226 | void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | 242 | void ReadBlockUnsafe(const Kernel::KProcess& process, const VAddr src_addr, void* dest_buffer, |
| 227 | const std::size_t size) { | 243 | const std::size_t size) { |
| 228 | const auto& page_table = process.PageTable().PageTableImpl(); | 244 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 229 | 245 | ||
| @@ -275,7 +291,7 @@ struct Memory::Impl { | |||
| 275 | ReadBlockUnsafe(*system.CurrentProcess(), src_addr, dest_buffer, size); | 291 | ReadBlockUnsafe(*system.CurrentProcess(), src_addr, dest_buffer, size); |
| 276 | } | 292 | } |
| 277 | 293 | ||
| 278 | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | 294 | void WriteBlock(const Kernel::KProcess& process, const VAddr dest_addr, const void* src_buffer, |
| 279 | const std::size_t size) { | 295 | const std::size_t size) { |
| 280 | const auto& page_table = process.PageTable().PageTableImpl(); | 296 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 281 | std::size_t remaining_size = size; | 297 | std::size_t remaining_size = size; |
| @@ -318,7 +334,7 @@ struct Memory::Impl { | |||
| 318 | } | 334 | } |
| 319 | } | 335 | } |
| 320 | 336 | ||
| 321 | void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr, | 337 | void WriteBlockUnsafe(const Kernel::KProcess& process, const VAddr dest_addr, |
| 322 | const void* src_buffer, const std::size_t size) { | 338 | const void* src_buffer, const std::size_t size) { |
| 323 | const auto& page_table = process.PageTable().PageTableImpl(); | 339 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 324 | std::size_t remaining_size = size; | 340 | std::size_t remaining_size = size; |
| @@ -368,7 +384,7 @@ struct Memory::Impl { | |||
| 368 | WriteBlockUnsafe(*system.CurrentProcess(), dest_addr, src_buffer, size); | 384 | WriteBlockUnsafe(*system.CurrentProcess(), dest_addr, src_buffer, size); |
| 369 | } | 385 | } |
| 370 | 386 | ||
| 371 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | 387 | void ZeroBlock(const Kernel::KProcess& process, const VAddr dest_addr, const std::size_t size) { |
| 372 | const auto& page_table = process.PageTable().PageTableImpl(); | 388 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 373 | std::size_t remaining_size = size; | 389 | std::size_t remaining_size = size; |
| 374 | std::size_t page_index = dest_addr >> PAGE_BITS; | 390 | std::size_t page_index = dest_addr >> PAGE_BITS; |
| @@ -413,7 +429,7 @@ struct Memory::Impl { | |||
| 413 | ZeroBlock(*system.CurrentProcess(), dest_addr, size); | 429 | ZeroBlock(*system.CurrentProcess(), dest_addr, size); |
| 414 | } | 430 | } |
| 415 | 431 | ||
| 416 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | 432 | void CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, |
| 417 | const std::size_t size) { | 433 | const std::size_t size) { |
| 418 | const auto& page_table = process.PageTable().PageTableImpl(); | 434 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 419 | std::size_t remaining_size = size; | 435 | std::size_t remaining_size = size; |
| @@ -711,13 +727,21 @@ struct Memory::Impl { | |||
| 711 | } | 727 | } |
| 712 | 728 | ||
| 713 | Common::PageTable* current_page_table = nullptr; | 729 | Common::PageTable* current_page_table = nullptr; |
| 730 | std::unordered_map<VAddr, std::unique_ptr<u8[]>> kernel_memory_regions; | ||
| 714 | Core::System& system; | 731 | Core::System& system; |
| 715 | }; | 732 | }; |
| 716 | 733 | ||
| 717 | Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {} | 734 | Memory::Memory(Core::System& system_) : system{system_} { |
| 735 | Reset(); | ||
| 736 | } | ||
| 737 | |||
| 718 | Memory::~Memory() = default; | 738 | Memory::~Memory() = default; |
| 719 | 739 | ||
| 720 | void Memory::SetCurrentPageTable(Kernel::Process& process, u32 core_id) { | 740 | void Memory::Reset() { |
| 741 | impl = std::make_unique<Impl>(system); | ||
| 742 | } | ||
| 743 | |||
| 744 | void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { | ||
| 721 | impl->SetCurrentPageTable(process, core_id); | 745 | impl->SetCurrentPageTable(process, core_id); |
| 722 | } | 746 | } |
| 723 | 747 | ||
| @@ -729,7 +753,7 @@ void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { | |||
| 729 | impl->UnmapRegion(page_table, base, size); | 753 | impl->UnmapRegion(page_table, base, size); |
| 730 | } | 754 | } |
| 731 | 755 | ||
| 732 | bool Memory::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { | 756 | bool Memory::IsValidVirtualAddress(const Kernel::KProcess& process, const VAddr vaddr) const { |
| 733 | return impl->IsValidVirtualAddress(process, vaddr); | 757 | return impl->IsValidVirtualAddress(process, vaddr); |
| 734 | } | 758 | } |
| 735 | 759 | ||
| @@ -741,6 +765,10 @@ u8* Memory::GetPointer(VAddr vaddr) { | |||
| 741 | return impl->GetPointer(vaddr); | 765 | return impl->GetPointer(vaddr); |
| 742 | } | 766 | } |
| 743 | 767 | ||
| 768 | u8* Memory::GetKernelBuffer(VAddr start_vaddr, size_t size) { | ||
| 769 | return impl->GetKernelBuffer(start_vaddr, size); | ||
| 770 | } | ||
| 771 | |||
| 744 | const u8* Memory::GetPointer(VAddr vaddr) const { | 772 | const u8* Memory::GetPointer(VAddr vaddr) const { |
| 745 | return impl->GetPointer(vaddr); | 773 | return impl->GetPointer(vaddr); |
| 746 | } | 774 | } |
| @@ -801,7 +829,7 @@ std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { | |||
| 801 | return impl->ReadCString(vaddr, max_length); | 829 | return impl->ReadCString(vaddr, max_length); |
| 802 | } | 830 | } |
| 803 | 831 | ||
| 804 | void Memory::ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | 832 | void Memory::ReadBlock(const Kernel::KProcess& process, const VAddr src_addr, void* dest_buffer, |
| 805 | const std::size_t size) { | 833 | const std::size_t size) { |
| 806 | impl->ReadBlock(process, src_addr, dest_buffer, size); | 834 | impl->ReadBlock(process, src_addr, dest_buffer, size); |
| 807 | } | 835 | } |
| @@ -810,7 +838,7 @@ void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_ | |||
| 810 | impl->ReadBlock(src_addr, dest_buffer, size); | 838 | impl->ReadBlock(src_addr, dest_buffer, size); |
| 811 | } | 839 | } |
| 812 | 840 | ||
| 813 | void Memory::ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, | 841 | void Memory::ReadBlockUnsafe(const Kernel::KProcess& process, const VAddr src_addr, |
| 814 | void* dest_buffer, const std::size_t size) { | 842 | void* dest_buffer, const std::size_t size) { |
| 815 | impl->ReadBlockUnsafe(process, src_addr, dest_buffer, size); | 843 | impl->ReadBlockUnsafe(process, src_addr, dest_buffer, size); |
| 816 | } | 844 | } |
| @@ -819,7 +847,7 @@ void Memory::ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std: | |||
| 819 | impl->ReadBlockUnsafe(src_addr, dest_buffer, size); | 847 | impl->ReadBlockUnsafe(src_addr, dest_buffer, size); |
| 820 | } | 848 | } |
| 821 | 849 | ||
| 822 | void Memory::WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | 850 | void Memory::WriteBlock(const Kernel::KProcess& process, VAddr dest_addr, const void* src_buffer, |
| 823 | std::size_t size) { | 851 | std::size_t size) { |
| 824 | impl->WriteBlock(process, dest_addr, src_buffer, size); | 852 | impl->WriteBlock(process, dest_addr, src_buffer, size); |
| 825 | } | 853 | } |
| @@ -828,7 +856,7 @@ void Memory::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std | |||
| 828 | impl->WriteBlock(dest_addr, src_buffer, size); | 856 | impl->WriteBlock(dest_addr, src_buffer, size); |
| 829 | } | 857 | } |
| 830 | 858 | ||
| 831 | void Memory::WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr, | 859 | void Memory::WriteBlockUnsafe(const Kernel::KProcess& process, VAddr dest_addr, |
| 832 | const void* src_buffer, std::size_t size) { | 860 | const void* src_buffer, std::size_t size) { |
| 833 | impl->WriteBlockUnsafe(process, dest_addr, src_buffer, size); | 861 | impl->WriteBlockUnsafe(process, dest_addr, src_buffer, size); |
| 834 | } | 862 | } |
| @@ -838,7 +866,7 @@ void Memory::WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer, | |||
| 838 | impl->WriteBlockUnsafe(dest_addr, src_buffer, size); | 866 | impl->WriteBlockUnsafe(dest_addr, src_buffer, size); |
| 839 | } | 867 | } |
| 840 | 868 | ||
| 841 | void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { | 869 | void Memory::ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size) { |
| 842 | impl->ZeroBlock(process, dest_addr, size); | 870 | impl->ZeroBlock(process, dest_addr, size); |
| 843 | } | 871 | } |
| 844 | 872 | ||
| @@ -846,7 +874,7 @@ void Memory::ZeroBlock(VAddr dest_addr, std::size_t size) { | |||
| 846 | impl->ZeroBlock(dest_addr, size); | 874 | impl->ZeroBlock(dest_addr, size); |
| 847 | } | 875 | } |
| 848 | 876 | ||
| 849 | void Memory::CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | 877 | void Memory::CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, |
| 850 | const std::size_t size) { | 878 | const std::size_t size) { |
| 851 | impl->CopyBlock(process, dest_addr, src_addr, size); | 879 | impl->CopyBlock(process, dest_addr, src_addr, size); |
| 852 | } | 880 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 6d34fcfe2..345fd870d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -19,7 +19,7 @@ class System; | |||
| 19 | 19 | ||
| 20 | namespace Kernel { | 20 | namespace Kernel { |
| 21 | class PhysicalMemory; | 21 | class PhysicalMemory; |
| 22 | class Process; | 22 | class KProcess; |
| 23 | } // namespace Kernel | 23 | } // namespace Kernel |
| 24 | 24 | ||
| 25 | namespace Core::Memory { | 25 | namespace Core::Memory { |
| @@ -59,11 +59,16 @@ public: | |||
| 59 | Memory& operator=(Memory&&) = default; | 59 | Memory& operator=(Memory&&) = default; |
| 60 | 60 | ||
| 61 | /** | 61 | /** |
| 62 | * Resets the state of the Memory system. | ||
| 63 | */ | ||
| 64 | void Reset(); | ||
| 65 | |||
| 66 | /** | ||
| 62 | * Changes the currently active page table to that of the given process instance. | 67 | * Changes the currently active page table to that of the given process instance. |
| 63 | * | 68 | * |
| 64 | * @param process The process to use the page table of. | 69 | * @param process The process to use the page table of. |
| 65 | */ | 70 | */ |
| 66 | void SetCurrentPageTable(Kernel::Process& process, u32 core_id); | 71 | void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id); |
| 67 | 72 | ||
| 68 | /** | 73 | /** |
| 69 | * Maps an allocated buffer onto a region of the emulated process address space. | 74 | * Maps an allocated buffer onto a region of the emulated process address space. |
| @@ -94,7 +99,7 @@ public: | |||
| 94 | * | 99 | * |
| 95 | * @returns True if the given virtual address is valid, false otherwise. | 100 | * @returns True if the given virtual address is valid, false otherwise. |
| 96 | */ | 101 | */ |
| 97 | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr) const; | 102 | bool IsValidVirtualAddress(const Kernel::KProcess& process, VAddr vaddr) const; |
| 98 | 103 | ||
| 99 | /** | 104 | /** |
| 100 | * Checks whether or not the supplied address is a valid virtual | 105 | * Checks whether or not the supplied address is a valid virtual |
| @@ -116,6 +121,15 @@ public: | |||
| 116 | */ | 121 | */ |
| 117 | u8* GetPointer(VAddr vaddr); | 122 | u8* GetPointer(VAddr vaddr); |
| 118 | 123 | ||
| 124 | /** | ||
| 125 | * Gets a pointer to the start of a kernel heap allocated memory region. Will allocate one if it | ||
| 126 | * does not already exist. | ||
| 127 | * | ||
| 128 | * @param start_vaddr Start virtual address for the memory region. | ||
| 129 | * @param size Size of the memory region. | ||
| 130 | */ | ||
| 131 | u8* GetKernelBuffer(VAddr start_vaddr, size_t size); | ||
| 132 | |||
| 119 | template <typename T> | 133 | template <typename T> |
| 120 | T* GetPointer(VAddr vaddr) { | 134 | T* GetPointer(VAddr vaddr) { |
| 121 | return reinterpret_cast<T*>(GetPointer(vaddr)); | 135 | return reinterpret_cast<T*>(GetPointer(vaddr)); |
| @@ -319,7 +333,7 @@ public: | |||
| 319 | * @post The range [dest_buffer, size) contains the read bytes from the | 333 | * @post The range [dest_buffer, size) contains the read bytes from the |
| 320 | * process' address space. | 334 | * process' address space. |
| 321 | */ | 335 | */ |
| 322 | void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, | 336 | void ReadBlock(const Kernel::KProcess& process, VAddr src_addr, void* dest_buffer, |
| 323 | std::size_t size); | 337 | std::size_t size); |
| 324 | 338 | ||
| 325 | /** | 339 | /** |
| @@ -340,7 +354,7 @@ public: | |||
| 340 | * @post The range [dest_buffer, size) contains the read bytes from the | 354 | * @post The range [dest_buffer, size) contains the read bytes from the |
| 341 | * process' address space. | 355 | * process' address space. |
| 342 | */ | 356 | */ |
| 343 | void ReadBlockUnsafe(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, | 357 | void ReadBlockUnsafe(const Kernel::KProcess& process, VAddr src_addr, void* dest_buffer, |
| 344 | std::size_t size); | 358 | std::size_t size); |
| 345 | 359 | ||
| 346 | /** | 360 | /** |
| @@ -400,7 +414,7 @@ public: | |||
| 400 | * and will mark that region as invalidated to caches that the active | 414 | * and will mark that region as invalidated to caches that the active |
| 401 | * graphics backend may be maintaining over the course of execution. | 415 | * graphics backend may be maintaining over the course of execution. |
| 402 | */ | 416 | */ |
| 403 | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | 417 | void WriteBlock(const Kernel::KProcess& process, VAddr dest_addr, const void* src_buffer, |
| 404 | std::size_t size); | 418 | std::size_t size); |
| 405 | 419 | ||
| 406 | /** | 420 | /** |
| @@ -420,7 +434,7 @@ public: | |||
| 420 | * will be ignored and an error will be logged. | 434 | * will be ignored and an error will be logged. |
| 421 | * | 435 | * |
| 422 | */ | 436 | */ |
| 423 | void WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | 437 | void WriteBlockUnsafe(const Kernel::KProcess& process, VAddr dest_addr, const void* src_buffer, |
| 424 | std::size_t size); | 438 | std::size_t size); |
| 425 | 439 | ||
| 426 | /** | 440 | /** |
| @@ -472,7 +486,7 @@ public: | |||
| 472 | * @post The range [dest_addr, size) within the process' address space is | 486 | * @post The range [dest_addr, size) within the process' address space is |
| 473 | * filled with zeroes. | 487 | * filled with zeroes. |
| 474 | */ | 488 | */ |
| 475 | void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size); | 489 | void ZeroBlock(const Kernel::KProcess& process, VAddr dest_addr, std::size_t size); |
| 476 | 490 | ||
| 477 | /** | 491 | /** |
| 478 | * Fills the specified address range within the current process' address space with zeroes. | 492 | * Fills the specified address range within the current process' address space with zeroes. |
| @@ -497,7 +511,7 @@ public: | |||
| 497 | * @post The range [dest_addr, size) within the process' address space contains the | 511 | * @post The range [dest_addr, size) within the process' address space contains the |
| 498 | * same data within the range [src_addr, size). | 512 | * same data within the range [src_addr, size). |
| 499 | */ | 513 | */ |
| 500 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | 514 | void CopyBlock(const Kernel::KProcess& process, VAddr dest_addr, VAddr src_addr, |
| 501 | std::size_t size); | 515 | std::size_t size); |
| 502 | 516 | ||
| 503 | /** | 517 | /** |
| @@ -524,6 +538,8 @@ public: | |||
| 524 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached); | 538 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached); |
| 525 | 539 | ||
| 526 | private: | 540 | private: |
| 541 | Core::System& system; | ||
| 542 | |||
| 527 | struct Impl; | 543 | struct Impl; |
| 528 | std::unique_ptr<Impl> impl; | 544 | std::unique_ptr<Impl> impl; |
| 529 | }; | 545 | }; |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 8eec567ab..46a7e09b4 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "core/core_timing_util.h" | 11 | #include "core/core_timing_util.h" |
| 12 | #include "core/hardware_properties.h" | 12 | #include "core/hardware_properties.h" |
| 13 | #include "core/hle/kernel/k_page_table.h" | 13 | #include "core/hle/kernel/k_page_table.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/k_process.h" |
| 15 | #include "core/hle/service/hid/controllers/npad.h" | 15 | #include "core/hle/service/hid/controllers/npad.h" |
| 16 | #include "core/hle/service/hid/hid.h" | 16 | #include "core/hle/service/hid/hid.h" |
| 17 | #include "core/hle/service/sm/sm.h" | 17 | #include "core/hle/service/sm/sm.h" |
| @@ -37,8 +37,8 @@ std::string_view ExtractName(std::string_view data, std::size_t start_index, cha | |||
| 37 | } | 37 | } |
| 38 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 39 | 39 | ||
| 40 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) | 40 | StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_) |
| 41 | : metadata(metadata), system(system) {} | 41 | : metadata{metadata_}, system{system_} {} |
| 42 | 42 | ||
| 43 | StandardVmCallbacks::~StandardVmCallbacks() = default; | 43 | StandardVmCallbacks::~StandardVmCallbacks() = default; |
| 44 | 44 | ||
| @@ -174,11 +174,11 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const { | |||
| 174 | return out; | 174 | return out; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | CheatEngine::CheatEngine(Core::System& system, std::vector<CheatEntry> cheats, | 177 | CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_, |
| 178 | const std::array<u8, 0x20>& build_id) | 178 | const std::array<u8, 0x20>& build_id_) |
| 179 | : vm{std::make_unique<StandardVmCallbacks>(system, metadata)}, | 179 | : vm{std::make_unique<StandardVmCallbacks>(system_, metadata)}, |
| 180 | cheats(std::move(cheats)), core_timing{system.CoreTiming()}, system{system} { | 180 | cheats(std::move(cheats_)), core_timing{system_.CoreTiming()}, system{system_} { |
| 181 | metadata.main_nso_build_id = build_id; | 181 | metadata.main_nso_build_id = build_id_; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | CheatEngine::~CheatEngine() { | 184 | CheatEngine::~CheatEngine() { |
| @@ -222,8 +222,8 @@ void CheatEngine::SetMainMemoryParameters(VAddr main_region_begin, u64 main_regi | |||
| 222 | }; | 222 | }; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | 225 | void CheatEngine::Reload(std::vector<CheatEntry> reload_cheats) { |
| 226 | this->cheats = std::move(cheats); | 226 | cheats = std::move(reload_cheats); |
| 227 | is_pending_reload.exchange(true); | 227 | is_pending_reload.exchange(true); |
| 228 | } | 228 | } |
| 229 | 229 | ||
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index a31002346..a8e041d9d 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -25,7 +25,7 @@ namespace Core::Memory { | |||
| 25 | 25 | ||
| 26 | class StandardVmCallbacks : public DmntCheatVm::Callbacks { | 26 | class StandardVmCallbacks : public DmntCheatVm::Callbacks { |
| 27 | public: | 27 | public: |
| 28 | StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata); | 28 | StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_); |
| 29 | ~StandardVmCallbacks() override; | 29 | ~StandardVmCallbacks() override; |
| 30 | 30 | ||
| 31 | void MemoryRead(VAddr address, void* data, u64 size) override; | 31 | void MemoryRead(VAddr address, void* data, u64 size) override; |
| @@ -38,7 +38,7 @@ private: | |||
| 38 | VAddr SanitizeAddress(VAddr address) const; | 38 | VAddr SanitizeAddress(VAddr address) const; |
| 39 | 39 | ||
| 40 | const CheatProcessMetadata& metadata; | 40 | const CheatProcessMetadata& metadata; |
| 41 | Core::System& system; | 41 | System& system; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | // Intermediary class that parses a text file or other disk format for storing cheats into a | 44 | // Intermediary class that parses a text file or other disk format for storing cheats into a |
| @@ -61,14 +61,14 @@ public: | |||
| 61 | // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming | 61 | // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming |
| 62 | class CheatEngine final { | 62 | class CheatEngine final { |
| 63 | public: | 63 | public: |
| 64 | CheatEngine(Core::System& system_, std::vector<CheatEntry> cheats_, | 64 | CheatEngine(System& system_, std::vector<CheatEntry> cheats_, |
| 65 | const std::array<u8, 0x20>& build_id); | 65 | const std::array<u8, 0x20>& build_id_); |
| 66 | ~CheatEngine(); | 66 | ~CheatEngine(); |
| 67 | 67 | ||
| 68 | void Initialize(); | 68 | void Initialize(); |
| 69 | void SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size); | 69 | void SetMainMemoryParameters(VAddr main_region_begin, u64 main_region_size); |
| 70 | 70 | ||
| 71 | void Reload(std::vector<CheatEntry> cheats); | 71 | void Reload(std::vector<CheatEntry> reload_cheats); |
| 72 | 72 | ||
| 73 | private: | 73 | private: |
| 74 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 74 | void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index 48be80c12..dc04e37d2 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -29,7 +29,8 @@ | |||
| 29 | 29 | ||
| 30 | namespace Core::Memory { | 30 | namespace Core::Memory { |
| 31 | 31 | ||
| 32 | DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks) : callbacks(std::move(callbacks)) {} | 32 | DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks_) |
| 33 | : callbacks(std::move(callbacks_)) {} | ||
| 33 | 34 | ||
| 34 | DmntCheatVm::~DmntCheatVm() = default; | 35 | DmntCheatVm::~DmntCheatVm() = default; |
| 35 | 36 | ||
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h index 21b86b72c..707bee82b 100644 --- a/src/core/memory/dmnt_cheat_vm.h +++ b/src/core/memory/dmnt_cheat_vm.h | |||
| @@ -293,7 +293,7 @@ public: | |||
| 293 | static constexpr std::size_t NumStaticRegisters = | 293 | static constexpr std::size_t NumStaticRegisters = |
| 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; | 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; |
| 295 | 295 | ||
| 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); | 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks_); |
| 297 | ~DmntCheatVm(); | 297 | ~DmntCheatVm(); |
| 298 | 298 | ||
| 299 | std::size_t GetProgramSize() const { | 299 | std::size_t GetProgramSize() const { |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index c92337079..c42c437b7 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -27,7 +27,7 @@ constexpr std::size_t IgnoreFrames = 5; | |||
| 27 | 27 | ||
| 28 | namespace Core { | 28 | namespace Core { |
| 29 | 29 | ||
| 30 | PerfStats::PerfStats(u64 title_id) : title_id(title_id) {} | 30 | PerfStats::PerfStats(u64 title_id_) : title_id(title_id_) {} |
| 31 | 31 | ||
| 32 | PerfStats::~PerfStats() { | 32 | PerfStats::~PerfStats() { |
| 33 | if (!Settings::values.record_frame_times || title_id == 0) { | 33 | if (!Settings::values.record_frame_times || title_id == 0) { |
| @@ -69,9 +69,7 @@ void PerfStats::EndSystemFrame() { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void PerfStats::EndGameFrame() { | 71 | void PerfStats::EndGameFrame() { |
| 72 | std::lock_guard lock{object_mutex}; | 72 | game_frames.fetch_add(1, std::memory_order_relaxed); |
| 73 | |||
| 74 | game_frames += 1; | ||
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | double PerfStats::GetMeanFrametime() const { | 75 | double PerfStats::GetMeanFrametime() const { |
| @@ -94,10 +92,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 94 | const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); | 92 | const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); |
| 95 | 93 | ||
| 96 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; | 94 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; |
| 97 | 95 | const auto current_frames = static_cast<double>(game_frames.load(std::memory_order_relaxed)); | |
| 96 | const auto current_fps = current_frames / interval; | ||
| 98 | const PerfStatsResults results{ | 97 | const PerfStatsResults results{ |
| 99 | .system_fps = static_cast<double>(system_frames) / interval, | 98 | .system_fps = static_cast<double>(system_frames) / interval, |
| 100 | .game_fps = static_cast<double>(game_frames) / interval, | 99 | .average_game_fps = (current_fps + previous_fps) / 2.0, |
| 101 | .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / | 100 | .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / |
| 102 | static_cast<double>(system_frames), | 101 | static_cast<double>(system_frames), |
| 103 | .emulation_speed = system_us_per_second.count() / 1'000'000.0, | 102 | .emulation_speed = system_us_per_second.count() / 1'000'000.0, |
| @@ -108,7 +107,8 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 108 | reset_point_system_us = current_system_time_us; | 107 | reset_point_system_us = current_system_time_us; |
| 109 | accumulated_frametime = Clock::duration::zero(); | 108 | accumulated_frametime = Clock::duration::zero(); |
| 110 | system_frames = 0; | 109 | system_frames = 0; |
| 111 | game_frames = 0; | 110 | game_frames.store(0, std::memory_order_relaxed); |
| 111 | previous_fps = current_fps; | ||
| 112 | 112 | ||
| 113 | return results; | 113 | return results; |
| 114 | } | 114 | } |
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index 69256b960..e5d603717 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <atomic> | ||
| 8 | #include <chrono> | 9 | #include <chrono> |
| 9 | #include <cstddef> | 10 | #include <cstddef> |
| 10 | #include <mutex> | 11 | #include <mutex> |
| @@ -15,8 +16,8 @@ namespace Core { | |||
| 15 | struct PerfStatsResults { | 16 | struct PerfStatsResults { |
| 16 | /// System FPS (LCD VBlanks) in Hz | 17 | /// System FPS (LCD VBlanks) in Hz |
| 17 | double system_fps; | 18 | double system_fps; |
| 18 | /// Game FPS (GSP frame submissions) in Hz | 19 | /// Average game FPS (GPU frame renders) in Hz |
| 19 | double game_fps; | 20 | double average_game_fps; |
| 20 | /// Walltime per system frame, in seconds, excluding any waits | 21 | /// Walltime per system frame, in seconds, excluding any waits |
| 21 | double frametime; | 22 | double frametime; |
| 22 | /// Ratio of walltime / emulated time elapsed | 23 | /// Ratio of walltime / emulated time elapsed |
| @@ -29,7 +30,7 @@ struct PerfStatsResults { | |||
| 29 | */ | 30 | */ |
| 30 | class PerfStats { | 31 | class PerfStats { |
| 31 | public: | 32 | public: |
| 32 | explicit PerfStats(u64 title_id); | 33 | explicit PerfStats(u64 title_id_); |
| 33 | ~PerfStats(); | 34 | ~PerfStats(); |
| 34 | 35 | ||
| 35 | using Clock = std::chrono::high_resolution_clock; | 36 | using Clock = std::chrono::high_resolution_clock; |
| @@ -72,7 +73,7 @@ private: | |||
| 72 | /// Cumulative number of system frames (LCD VBlanks) presented since last reset | 73 | /// Cumulative number of system frames (LCD VBlanks) presented since last reset |
| 73 | u32 system_frames = 0; | 74 | u32 system_frames = 0; |
| 74 | /// Cumulative number of game frames (GSP frame submissions) since last reset | 75 | /// Cumulative number of game frames (GSP frame submissions) since last reset |
| 75 | u32 game_frames = 0; | 76 | std::atomic<u32> game_frames = 0; |
| 76 | 77 | ||
| 77 | /// Point when the previous system frame ended | 78 | /// Point when the previous system frame ended |
| 78 | Clock::time_point previous_frame_end = reset_point; | 79 | Clock::time_point previous_frame_end = reset_point; |
| @@ -80,6 +81,8 @@ private: | |||
| 80 | Clock::time_point frame_begin = reset_point; | 81 | Clock::time_point frame_begin = reset_point; |
| 81 | /// Total visible duration (including frame-limiting, etc.) of the previous system frame | 82 | /// Total visible duration (including frame-limiting, etc.) of the previous system frame |
| 82 | Clock::duration previous_frame_length = Clock::duration::zero(); | 83 | Clock::duration previous_frame_length = Clock::duration::zero(); |
| 84 | /// Previously computed fps | ||
| 85 | double previous_fps = 0; | ||
| 83 | }; | 86 | }; |
| 84 | 87 | ||
| 85 | class FrameLimiter { | 88 | class FrameLimiter { |
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 311d4dda8..d1e807dd4 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include "core/core.h" | 19 | #include "core/core.h" |
| 20 | #include "core/hle/kernel/hle_ipc.h" | 20 | #include "core/hle/kernel/hle_ipc.h" |
| 21 | #include "core/hle/kernel/k_page_table.h" | 21 | #include "core/hle/kernel/k_page_table.h" |
| 22 | #include "core/hle/kernel/process.h" | 22 | #include "core/hle/kernel/k_process.h" |
| 23 | #include "core/hle/result.h" | 23 | #include "core/hle/result.h" |
| 24 | #include "core/memory.h" | 24 | #include "core/memory.h" |
| 25 | #include "core/reporter.h" | 25 | #include "core/reporter.h" |
| @@ -192,7 +192,7 @@ json GetHLERequestContextData(Kernel::HLERequestContext& ctx, Core::Memory::Memo | |||
| 192 | 192 | ||
| 193 | namespace Core { | 193 | namespace Core { |
| 194 | 194 | ||
| 195 | Reporter::Reporter(System& system) : system(system) {} | 195 | Reporter::Reporter(System& system_) : system(system_) {} |
| 196 | 196 | ||
| 197 | Reporter::~Reporter() = default; | 197 | Reporter::~Reporter() = default; |
| 198 | 198 | ||
diff --git a/src/core/reporter.h b/src/core/reporter.h index b2c2d9a2e..6fb6ebffa 100644 --- a/src/core/reporter.h +++ b/src/core/reporter.h | |||
| @@ -30,7 +30,7 @@ class System; | |||
| 30 | 30 | ||
| 31 | class Reporter { | 31 | class Reporter { |
| 32 | public: | 32 | public: |
| 33 | explicit Reporter(System& system); | 33 | explicit Reporter(System& system_); |
| 34 | ~Reporter(); | 34 | ~Reporter(); |
| 35 | 35 | ||
| 36 | // Used by fatal services | 36 | // Used by fatal services |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 5c674a099..2e09faa6d 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -67,8 +67,8 @@ Freezer::~Freezer() { | |||
| 67 | core_timing.UnscheduleEvent(event, 0); | 67 | core_timing.UnscheduleEvent(event, 0); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | void Freezer::SetActive(bool active) { | 70 | void Freezer::SetActive(bool is_active) { |
| 71 | if (!this->active.exchange(active)) { | 71 | if (!active.exchange(is_active)) { |
| 72 | FillEntryReads(); | 72 | FillEntryReads(); |
| 73 | core_timing.ScheduleEvent(memory_freezer_ns, event); | 73 | core_timing.ScheduleEvent(memory_freezer_ns, event); |
| 74 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); | 74 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); |
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h index 0fdb701a7..067134e93 100644 --- a/src/core/tools/freezer.h +++ b/src/core/tools/freezer.h | |||
| @@ -43,7 +43,7 @@ public: | |||
| 43 | ~Freezer(); | 43 | ~Freezer(); |
| 44 | 44 | ||
| 45 | // Enables or disables the entire memory freezer. | 45 | // Enables or disables the entire memory freezer. |
| 46 | void SetActive(bool active); | 46 | void SetActive(bool is_active); |
| 47 | 47 | ||
| 48 | // Returns whether or not the freezer is active. | 48 | // Returns whether or not the freezer is active. |
| 49 | bool IsActive() const; | 49 | bool IsActive() const; |
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index ec3167bea..320f51ee6 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -155,8 +155,12 @@ void Adapter::UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_pa | |||
| 155 | for (const PadAxes axis : axes) { | 155 | for (const PadAxes axis : axes) { |
| 156 | const auto index = static_cast<std::size_t>(axis); | 156 | const auto index = static_cast<std::size_t>(axis); |
| 157 | const u8 axis_value = adapter_payload[offset + 3 + index]; | 157 | const u8 axis_value = adapter_payload[offset + 3 + index]; |
| 158 | if (pads[port].axis_origin[index] == 255) { | 158 | if (pads[port].reset_origin_counter <= 18) { |
| 159 | if (pads[port].axis_origin[index] != axis_value) { | ||
| 160 | pads[port].reset_origin_counter = 0; | ||
| 161 | } | ||
| 159 | pads[port].axis_origin[index] = axis_value; | 162 | pads[port].axis_origin[index] = axis_value; |
| 163 | pads[port].reset_origin_counter++; | ||
| 160 | } | 164 | } |
| 161 | pads[port].axis_values[index] = | 165 | pads[port].axis_values[index] = |
| 162 | static_cast<s16>(axis_value - pads[port].axis_origin[index]); | 166 | static_cast<s16>(axis_value - pads[port].axis_origin[index]); |
| @@ -375,7 +379,7 @@ void Adapter::ResetDevice(std::size_t port) { | |||
| 375 | pads[port].buttons = 0; | 379 | pads[port].buttons = 0; |
| 376 | pads[port].last_button = PadButton::Undefined; | 380 | pads[port].last_button = PadButton::Undefined; |
| 377 | pads[port].axis_values.fill(0); | 381 | pads[port].axis_values.fill(0); |
| 378 | pads[port].axis_origin.fill(255); | 382 | pads[port].reset_origin_counter = 0; |
| 379 | } | 383 | } |
| 380 | 384 | ||
| 381 | void Adapter::Reset() { | 385 | void Adapter::Reset() { |
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h index 7a6c545bd..e5de5e94f 100644 --- a/src/input_common/gcadapter/gc_adapter.h +++ b/src/input_common/gcadapter/gc_adapter.h | |||
| @@ -70,6 +70,7 @@ struct GCController { | |||
| 70 | PadButton last_button{}; | 70 | PadButton last_button{}; |
| 71 | std::array<s16, 6> axis_values{}; | 71 | std::array<s16, 6> axis_values{}; |
| 72 | std::array<u8, 6> axis_origin{}; | 72 | std::array<u8, 6> axis_origin{}; |
| 73 | u8 reset_origin_counter{}; | ||
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| 75 | class Adapter { | 76 | class Adapter { |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 7c4e7dd3b..7399c3648 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -153,6 +153,11 @@ struct InputSubsystem::Impl { | |||
| 153 | // TODO return the correct motion device | 153 | // TODO return the correct motion device |
| 154 | return {}; | 154 | return {}; |
| 155 | } | 155 | } |
| 156 | #ifdef HAVE_SDL2 | ||
| 157 | if (params.Get("class", "") == "sdl") { | ||
| 158 | return sdl->GetMotionMappingForDevice(params); | ||
| 159 | } | ||
| 160 | #endif | ||
| 156 | return {}; | 161 | return {}; |
| 157 | } | 162 | } |
| 158 | 163 | ||
diff --git a/src/input_common/motion_input.cpp b/src/input_common/motion_input.cpp index 6a65f175e..1c9d561c0 100644 --- a/src/input_common/motion_input.cpp +++ b/src/input_common/motion_input.cpp | |||
| @@ -195,7 +195,8 @@ Input::MotionStatus MotionInput::GetMotion() const { | |||
| 195 | const Common::Vec3f accelerometer = GetAcceleration(); | 195 | const Common::Vec3f accelerometer = GetAcceleration(); |
| 196 | const Common::Vec3f rotation = GetRotations(); | 196 | const Common::Vec3f rotation = GetRotations(); |
| 197 | const std::array<Common::Vec3f, 3> orientation = GetOrientation(); | 197 | const std::array<Common::Vec3f, 3> orientation = GetOrientation(); |
| 198 | return {accelerometer, gyroscope, rotation, orientation}; | 198 | const Common::Quaternion<f32> quaternion = GetQuaternion(); |
| 199 | return {accelerometer, gyroscope, rotation, orientation, quaternion}; | ||
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_magnitude) const { | 202 | Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_magnitude) const { |
| @@ -218,7 +219,12 @@ Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_m | |||
| 218 | Common::Vec3f{0.0f, 1.0f, 0.0f}, | 219 | Common::Vec3f{0.0f, 1.0f, 0.0f}, |
| 219 | Common::Vec3f{0.0f, 0.0f, 1.0f}, | 220 | Common::Vec3f{0.0f, 0.0f, 1.0f}, |
| 220 | }; | 221 | }; |
| 221 | return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation}; | 222 | constexpr Common::Quaternion<f32> quaternion{ |
| 223 | {0.0f, 0.0f, 0.0f}, | ||
| 224 | 1.0f, | ||
| 225 | }; | ||
| 226 | return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation, | ||
| 227 | quaternion}; | ||
| 222 | } | 228 | } |
| 223 | 229 | ||
| 224 | void MotionInput::ResetOrientation() { | 230 | void MotionInput::ResetOrientation() { |
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index fff1c6b45..a335e6da1 100644 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp | |||
| @@ -143,6 +143,15 @@ void Mouse::ReleaseButton(MouseButton button_) { | |||
| 143 | mouse_info[button_index].data.axis = {0, 0}; | 143 | mouse_info[button_index].data.axis = {0, 0}; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | void Mouse::ReleaseAllButtons() { | ||
| 147 | buttons = 0; | ||
| 148 | for (auto& info : mouse_info) { | ||
| 149 | info.tilt_speed = 0; | ||
| 150 | info.data.pressed = false; | ||
| 151 | info.data.axis = {0, 0}; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 146 | void Mouse::BeginConfiguration() { | 155 | void Mouse::BeginConfiguration() { |
| 147 | buttons = 0; | 156 | buttons = 0; |
| 148 | last_button = MouseButton::Undefined; | 157 | last_button = MouseButton::Undefined; |
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h index 750d9b011..5a971ad67 100644 --- a/src/input_common/mouse/mouse_input.h +++ b/src/input_common/mouse/mouse_input.h | |||
| @@ -65,10 +65,16 @@ public: | |||
| 65 | void MouseMove(int x, int y, int center_x, int center_y); | 65 | void MouseMove(int x, int y, int center_x, int center_y); |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * Signals that a motion sensor tilt has ended. | 68 | * Signals that a button is released. |
| 69 | * @param button_ the button pressed | ||
| 69 | */ | 70 | */ |
| 70 | void ReleaseButton(MouseButton button_); | 71 | void ReleaseButton(MouseButton button_); |
| 71 | 72 | ||
| 73 | /** | ||
| 74 | * Signals that all buttons are released | ||
| 75 | */ | ||
| 76 | void ReleaseAllButtons(); | ||
| 77 | |||
| 72 | [[nodiscard]] bool ToggleButton(std::size_t button_); | 78 | [[nodiscard]] bool ToggleButton(std::size_t button_); |
| 73 | [[nodiscard]] bool UnlockButton(std::size_t button_); | 79 | [[nodiscard]] bool UnlockButton(std::size_t button_); |
| 74 | 80 | ||
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 42bbf14d4..b5d41bba4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -37,6 +37,9 @@ public: | |||
| 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { | 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { |
| 38 | return {}; | 38 | return {}; |
| 39 | } | 39 | } |
| 40 | virtual MotionMapping GetMotionMappingForDevice(const Common::ParamPackage&) { | ||
| 41 | return {}; | ||
| 42 | } | ||
| 40 | }; | 43 | }; |
| 41 | 44 | ||
| 42 | class NullState : public State { | 45 | class NullState : public State { |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index f682a6db4..822d0b555 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #include "common/logging/log.h" | 31 | #include "common/logging/log.h" |
| 32 | #include "common/math_util.h" | ||
| 32 | #include "common/param_package.h" | 33 | #include "common/param_package.h" |
| 33 | #include "common/settings_input.h" | 34 | #include "common/settings_input.h" |
| 34 | #include "common/threadsafe_queue.h" | 35 | #include "common/threadsafe_queue.h" |
| @@ -68,13 +69,57 @@ public: | |||
| 68 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | 69 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |
| 69 | SDL_GameController* game_controller) | 70 | SDL_GameController* game_controller) |
| 70 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | 71 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, |
| 71 | sdl_controller{game_controller, &SDL_GameControllerClose} {} | 72 | sdl_controller{game_controller, &SDL_GameControllerClose} { |
| 73 | EnableMotion(); | ||
| 74 | } | ||
| 75 | |||
| 76 | void EnableMotion() { | ||
| 77 | if (sdl_controller) { | ||
| 78 | SDL_GameController* controller = sdl_controller.get(); | ||
| 79 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { | ||
| 80 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); | ||
| 81 | has_accel = true; | ||
| 82 | } | ||
| 83 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { | ||
| 84 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); | ||
| 85 | has_gyro = true; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 72 | 89 | ||
| 73 | void SetButton(int button, bool value) { | 90 | void SetButton(int button, bool value) { |
| 74 | std::lock_guard lock{mutex}; | 91 | std::lock_guard lock{mutex}; |
| 75 | state.buttons.insert_or_assign(button, value); | 92 | state.buttons.insert_or_assign(button, value); |
| 76 | } | 93 | } |
| 77 | 94 | ||
| 95 | void SetMotion(SDL_ControllerSensorEvent event) { | ||
| 96 | constexpr float gravity_constant = 9.80665f; | ||
| 97 | std::lock_guard lock{mutex}; | ||
| 98 | u64 time_difference = event.timestamp - last_motion_update; | ||
| 99 | last_motion_update = event.timestamp; | ||
| 100 | switch (event.sensor) { | ||
| 101 | case SDL_SENSOR_ACCEL: { | ||
| 102 | const Common::Vec3f acceleration = {-event.data[0], event.data[2], -event.data[1]}; | ||
| 103 | motion.SetAcceleration(acceleration / gravity_constant); | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | case SDL_SENSOR_GYRO: { | ||
| 107 | const Common::Vec3f gyroscope = {event.data[0], -event.data[2], event.data[1]}; | ||
| 108 | motion.SetGyroscope(gyroscope / (Common::PI * 2)); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | // Ignore duplicated timestamps | ||
| 114 | if (time_difference == 0) { | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | motion.SetGyroThreshold(0.0001f); | ||
| 119 | motion.UpdateRotation(time_difference * 1000); | ||
| 120 | motion.UpdateOrientation(time_difference * 1000); | ||
| 121 | } | ||
| 122 | |||
| 78 | bool GetButton(int button) const { | 123 | bool GetButton(int button) const { |
| 79 | std::lock_guard lock{mutex}; | 124 | std::lock_guard lock{mutex}; |
| 80 | return state.buttons.at(button); | 125 | return state.buttons.at(button); |
| @@ -121,6 +166,14 @@ public: | |||
| 121 | return std::make_tuple(x, y); | 166 | return std::make_tuple(x, y); |
| 122 | } | 167 | } |
| 123 | 168 | ||
| 169 | bool HasGyro() const { | ||
| 170 | return has_gyro; | ||
| 171 | } | ||
| 172 | |||
| 173 | bool HasAccel() const { | ||
| 174 | return has_accel; | ||
| 175 | } | ||
| 176 | |||
| 124 | const MotionInput& GetMotion() const { | 177 | const MotionInput& GetMotion() const { |
| 125 | return motion; | 178 | return motion; |
| 126 | } | 179 | } |
| @@ -173,8 +226,11 @@ private: | |||
| 173 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 226 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 174 | mutable std::mutex mutex; | 227 | mutable std::mutex mutex; |
| 175 | 228 | ||
| 176 | // Motion is initialized without PID values as motion input is not aviable for SDL2 | 229 | // Motion is initialized with the PID values |
| 177 | MotionInput motion{0.0f, 0.0f, 0.0f}; | 230 | MotionInput motion{0.3f, 0.005f, 0.0f}; |
| 231 | u64 last_motion_update{}; | ||
| 232 | bool has_gyro{false}; | ||
| 233 | bool has_accel{false}; | ||
| 178 | }; | 234 | }; |
| 179 | 235 | ||
| 180 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | 236 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { |
| @@ -296,6 +352,12 @@ void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 296 | } | 352 | } |
| 297 | break; | 353 | break; |
| 298 | } | 354 | } |
| 355 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 356 | if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 357 | joystick->SetMotion(event.csensor); | ||
| 358 | } | ||
| 359 | break; | ||
| 360 | } | ||
| 299 | case SDL_JOYDEVICEREMOVED: | 361 | case SDL_JOYDEVICEREMOVED: |
| 300 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); | 362 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); |
| 301 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); | 363 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); |
| @@ -449,6 +511,18 @@ private: | |||
| 449 | std::shared_ptr<SDLJoystick> joystick; | 511 | std::shared_ptr<SDLJoystick> joystick; |
| 450 | }; | 512 | }; |
| 451 | 513 | ||
| 514 | class SDLMotion final : public Input::MotionDevice { | ||
| 515 | public: | ||
| 516 | explicit SDLMotion(std::shared_ptr<SDLJoystick> joystick_) : joystick(std::move(joystick_)) {} | ||
| 517 | |||
| 518 | Input::MotionStatus GetStatus() const override { | ||
| 519 | return joystick->GetMotion().GetMotion(); | ||
| 520 | } | ||
| 521 | |||
| 522 | private: | ||
| 523 | std::shared_ptr<SDLJoystick> joystick; | ||
| 524 | }; | ||
| 525 | |||
| 452 | class SDLDirectionMotion final : public Input::MotionDevice { | 526 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 453 | public: | 527 | public: |
| 454 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 528 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -658,6 +732,10 @@ public: | |||
| 658 | 732 | ||
| 659 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 733 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 660 | 734 | ||
| 735 | if (params.Has("motion")) { | ||
| 736 | return std::make_unique<SDLMotion>(joystick); | ||
| 737 | } | ||
| 738 | |||
| 661 | if (params.Has("hat")) { | 739 | if (params.Has("hat")) { |
| 662 | const int hat = params.Get("hat", 0); | 740 | const int hat = params.Get("hat", 0); |
| 663 | const std::string direction_name = params.Get("direction", ""); | 741 | const std::string direction_name = params.Get("direction", ""); |
| @@ -717,6 +795,17 @@ SDLState::SDLState() { | |||
| 717 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | 795 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); |
| 718 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 796 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 719 | 797 | ||
| 798 | // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers | ||
| 799 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); | ||
| 800 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); | ||
| 801 | |||
| 802 | // Tell SDL2 to use the hidapi driver. This will allow joycons to be detected as a | ||
| 803 | // GameController and not a generic one | ||
| 804 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1"); | ||
| 805 | |||
| 806 | // Turn off Pro controller home led | ||
| 807 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0"); | ||
| 808 | |||
| 720 | // If the frontend is going to manage the event loop, then we don't start one here | 809 | // If the frontend is going to manage the event loop, then we don't start one here |
| 721 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; | 810 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; |
| 722 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { | 811 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { |
| @@ -853,6 +942,13 @@ Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s | |||
| 853 | return params; | 942 | return params; |
| 854 | } | 943 | } |
| 855 | 944 | ||
| 945 | Common::ParamPackage BuildMotionParam(int port, std::string guid) { | ||
| 946 | Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}}); | ||
| 947 | params.Set("port", port); | ||
| 948 | params.Set("guid", std::move(guid)); | ||
| 949 | return params; | ||
| 950 | } | ||
| 951 | |||
| 856 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | 952 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { |
| 857 | switch (event.type) { | 953 | switch (event.type) { |
| 858 | case SDL_JOYAXISMOTION: { | 954 | case SDL_JOYAXISMOTION: { |
| @@ -907,6 +1003,35 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve | |||
| 907 | } | 1003 | } |
| 908 | break; | 1004 | break; |
| 909 | } | 1005 | } |
| 1006 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 1007 | bool is_motion_shaking = false; | ||
| 1008 | constexpr float gyro_threshold = 5.0f; | ||
| 1009 | constexpr float accel_threshold = 11.0f; | ||
| 1010 | if (event.csensor.sensor == SDL_SENSOR_ACCEL) { | ||
| 1011 | const Common::Vec3f acceleration = {-event.csensor.data[0], event.csensor.data[2], | ||
| 1012 | -event.csensor.data[1]}; | ||
| 1013 | if (acceleration.Length() > accel_threshold) { | ||
| 1014 | is_motion_shaking = true; | ||
| 1015 | } | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | if (event.csensor.sensor == SDL_SENSOR_GYRO) { | ||
| 1019 | const Common::Vec3f gyroscope = {event.csensor.data[0], -event.csensor.data[2], | ||
| 1020 | event.csensor.data[1]}; | ||
| 1021 | if (gyroscope.Length() > gyro_threshold) { | ||
| 1022 | is_motion_shaking = true; | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | if (!is_motion_shaking) { | ||
| 1027 | break; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 1031 | return BuildMotionParam(joystick->GetPort(), joystick->GetGUID()); | ||
| 1032 | } | ||
| 1033 | break; | ||
| 1034 | } | ||
| 910 | } | 1035 | } |
| 911 | return {}; | 1036 | return {}; |
| 912 | } | 1037 | } |
| @@ -1036,6 +1161,27 @@ AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& pa | |||
| 1036 | return mapping; | 1161 | return mapping; |
| 1037 | } | 1162 | } |
| 1038 | 1163 | ||
| 1164 | MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& params) { | ||
| 1165 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 1166 | return {}; | ||
| 1167 | } | ||
| 1168 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 1169 | auto* controller = joystick->GetSDLGameController(); | ||
| 1170 | if (controller == nullptr) { | ||
| 1171 | return {}; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | joystick->EnableMotion(); | ||
| 1175 | |||
| 1176 | if (!joystick->HasGyro() && !joystick->HasAccel()) { | ||
| 1177 | return {}; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | MotionMapping mapping = {}; | ||
| 1181 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1182 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1183 | return mapping; | ||
| 1184 | } | ||
| 1039 | namespace Polling { | 1185 | namespace Polling { |
| 1040 | class SDLPoller : public InputCommon::Polling::DevicePoller { | 1186 | class SDLPoller : public InputCommon::Polling::DevicePoller { |
| 1041 | public: | 1187 | public: |
| @@ -1149,6 +1295,7 @@ public: | |||
| 1149 | [[fallthrough]]; | 1295 | [[fallthrough]]; |
| 1150 | case SDL_JOYBUTTONUP: | 1296 | case SDL_JOYBUTTONUP: |
| 1151 | case SDL_JOYHATMOTION: | 1297 | case SDL_JOYHATMOTION: |
| 1298 | case SDL_CONTROLLERSENSORUPDATE: | ||
| 1152 | return {SDLEventToMotionParamPackage(state, event)}; | 1299 | return {SDLEventToMotionParamPackage(state, event)}; |
| 1153 | } | 1300 | } |
| 1154 | return std::nullopt; | 1301 | return std::nullopt; |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 8b7363f56..121e01913 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -57,6 +57,7 @@ public: | |||
| 57 | 57 | ||
| 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; |
| 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; |
| 60 | MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; | ||
| 60 | 61 | ||
| 61 | private: | 62 | private: |
| 62 | void InitJoystick(int joystick_index); | 63 | void InitJoystick(int joystick_index); |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 8a38a380d..bc1dfab3d 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -86,6 +86,7 @@ private: | |||
| 86 | case Type::PadData: { | 86 | case Type::PadData: { |
| 87 | Response::PadData pad_data; | 87 | Response::PadData pad_data; |
| 88 | std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData)); | 88 | std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData)); |
| 89 | SanitizeMotion(pad_data); | ||
| 89 | callback.pad_data(std::move(pad_data)); | 90 | callback.pad_data(std::move(pad_data)); |
| 90 | break; | 91 | break; |
| 91 | } | 92 | } |
| @@ -114,6 +115,28 @@ private: | |||
| 114 | StartSend(timer.expiry()); | 115 | StartSend(timer.expiry()); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 118 | void SanitizeMotion(Response::PadData& data) { | ||
| 119 | // Zero out any non number value | ||
| 120 | if (!std::isnormal(data.gyro.pitch)) { | ||
| 121 | data.gyro.pitch = 0; | ||
| 122 | } | ||
| 123 | if (!std::isnormal(data.gyro.roll)) { | ||
| 124 | data.gyro.roll = 0; | ||
| 125 | } | ||
| 126 | if (!std::isnormal(data.gyro.yaw)) { | ||
| 127 | data.gyro.yaw = 0; | ||
| 128 | } | ||
| 129 | if (!std::isnormal(data.accel.x)) { | ||
| 130 | data.accel.x = 0; | ||
| 131 | } | ||
| 132 | if (!std::isnormal(data.accel.y)) { | ||
| 133 | data.accel.y = 0; | ||
| 134 | } | ||
| 135 | if (!std::isnormal(data.accel.z)) { | ||
| 136 | data.accel.z = 0; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 117 | SocketCallback callback; | 140 | SocketCallback callback; |
| 118 | boost::asio::io_service io_service; | 141 | boost::asio::io_service io_service; |
| 119 | boost::asio::basic_waitable_timer<clock> timer; | 142 | boost::asio::basic_waitable_timer<clock> timer; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 32dcbd693..de971041f 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -690,7 +690,10 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 690 | const VAddr cpu_addr = binding.cpu_addr; | 690 | const VAddr cpu_addr = binding.cpu_addr; |
| 691 | const u32 size = binding.size; | 691 | const u32 size = binding.size; |
| 692 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 692 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 693 | if (size <= uniform_buffer_skip_cache_size && !buffer.IsRegionGpuModified(cpu_addr, size)) { | 693 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && |
| 694 | size <= uniform_buffer_skip_cache_size && | ||
| 695 | !buffer.IsRegionGpuModified(cpu_addr, size); | ||
| 696 | if (use_fast_buffer) { | ||
| 694 | if constexpr (IS_OPENGL) { | 697 | if constexpr (IS_OPENGL) { |
| 695 | if (runtime.HasFastBufferSubData()) { | 698 | if (runtime.HasFastBufferSubData()) { |
| 696 | // Fast path for Nvidia | 699 | // Fast path for Nvidia |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index a38024242..37f7b24e1 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/frontend/emu_window.h" | 13 | #include "core/frontend/emu_window.h" |
| 14 | #include "core/hardware_interrupt_manager.h" | 14 | #include "core/hardware_interrupt_manager.h" |
| 15 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 16 | #include "core/perf_stats.h" | ||
| 16 | #include "video_core/engines/fermi_2d.h" | 17 | #include "video_core/engines/fermi_2d.h" |
| 17 | #include "video_core/engines/kepler_compute.h" | 18 | #include "video_core/engines/kepler_compute.h" |
| 18 | #include "video_core/engines/kepler_memory.h" | 19 | #include "video_core/engines/kepler_memory.h" |
| @@ -191,6 +192,10 @@ u64 GPU::GetTicks() const { | |||
| 191 | return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; | 192 | return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; |
| 192 | } | 193 | } |
| 193 | 194 | ||
| 195 | void GPU::RendererFrameEndNotify() { | ||
| 196 | system.GetPerfStats().EndGameFrame(); | ||
| 197 | } | ||
| 198 | |||
| 194 | void GPU::FlushCommands() { | 199 | void GPU::FlushCommands() { |
| 195 | rasterizer->FlushCommands(); | 200 | rasterizer->FlushCommands(); |
| 196 | } | 201 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 8669e9940..29a867863 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -247,6 +247,8 @@ public: | |||
| 247 | return use_nvdec; | 247 | return use_nvdec; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | void RendererFrameEndNotify(); | ||
| 251 | |||
| 250 | enum class FenceOperation : u32 { | 252 | enum class FenceOperation : u32 { |
| 251 | Acquire = 0, | 253 | Acquire = 0, |
| 252 | Increment = 1, | 254 | Increment = 1, |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 4eb71efbd..eb58ac6b6 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/k_page_table.h" | 9 | #include "core/hle/kernel/k_page_table.h" |
| 10 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/k_process.h" |
| 11 | #include "core/memory.h" | 11 | #include "core/memory.h" |
| 12 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |
| 13 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 0863904e9..a5dbb9adf 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include "common/scope_exit.h" | 19 | #include "common/scope_exit.h" |
| 20 | #include "common/settings.h" | 20 | #include "common/settings.h" |
| 21 | #include "core/core.h" | 21 | #include "core/core.h" |
| 22 | #include "core/hle/kernel/process.h" | 22 | #include "core/hle/kernel/k_process.h" |
| 23 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 24 | #include "video_core/engines/kepler_compute.h" | 24 | #include "video_core/engines/kepler_compute.h" |
| 25 | #include "video_core/engines/maxwell_3d.h" | 25 | #include "video_core/engines/maxwell_3d.h" |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 97fb11ac6..dbcb751cb 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 16 | #include "common/zstd_compression.h" | 16 | #include "common/zstd_compression.h" |
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/k_process.h" |
| 19 | #include "video_core/engines/shader_type.h" | 19 | #include "video_core/engines/shader_type.h" |
| 20 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 20 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 21 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 21 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 623b43d8a..ffe9edc1b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -543,8 +543,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, |
| 546 | const std::array<Offset2D, 2>& dst_region, | 546 | const Region2D& dst_region, const Region2D& src_region, |
| 547 | const std::array<Offset2D, 2>& src_region, | ||
| 548 | Tegra::Engines::Fermi2D::Filter filter, | 547 | Tegra::Engines::Fermi2D::Filter filter, |
| 549 | Tegra::Engines::Fermi2D::Operation operation) { | 548 | Tegra::Engines::Fermi2D::Operation operation) { |
| 550 | state_tracker.NotifyScissor0(); | 549 | state_tracker.NotifyScissor0(); |
| @@ -560,9 +559,9 @@ void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | |||
| 560 | const GLbitfield buffer_bits = dst->BufferBits(); | 559 | const GLbitfield buffer_bits = dst->BufferBits(); |
| 561 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; | 560 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; |
| 562 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 561 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| 563 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region[0].x, src_region[0].y, | 562 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region.start.x, src_region.start.y, |
| 564 | src_region[1].x, src_region[1].y, dst_region[0].x, dst_region[0].y, | 563 | src_region.end.x, src_region.end.y, dst_region.start.x, |
| 565 | dst_region[1].x, dst_region[1].y, buffer_bits, | 564 | dst_region.start.y, dst_region.end.x, dst_region.end.y, buffer_bits, |
| 566 | is_linear ? GL_LINEAR : GL_NEAREST); | 565 | is_linear ? GL_LINEAR : GL_NEAREST); |
| 567 | } | 566 | } |
| 568 | 567 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3c871541b..df8be12ff 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -28,7 +28,7 @@ using VideoCommon::ImageId; | |||
| 28 | using VideoCommon::ImageViewId; | 28 | using VideoCommon::ImageViewId; |
| 29 | using VideoCommon::ImageViewType; | 29 | using VideoCommon::ImageViewType; |
| 30 | using VideoCommon::NUM_RT; | 30 | using VideoCommon::NUM_RT; |
| 31 | using VideoCommon::Offset2D; | 31 | using VideoCommon::Region2D; |
| 32 | using VideoCommon::RenderTargets; | 32 | using VideoCommon::RenderTargets; |
| 33 | 33 | ||
| 34 | struct ImageBufferMap { | 34 | struct ImageBufferMap { |
| @@ -73,10 +73,8 @@ public: | |||
| 73 | 73 | ||
| 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 75 | 75 | ||
| 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, const Region2D& dst_region, |
| 77 | const std::array<Offset2D, 2>& dst_region, | 77 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 78 | const std::array<Offset2D, 2>& src_region, | ||
| 79 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 80 | Tegra::Engines::Fermi2D::Operation operation); | 78 | Tegra::Engines::Fermi2D::Operation operation); |
| 81 | 79 | ||
| 82 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, | 80 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index cc2e499f9..a718bff7a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -155,6 +155,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 155 | 155 | ||
| 156 | ++m_current_frame; | 156 | ++m_current_frame; |
| 157 | 157 | ||
| 158 | gpu.RendererFrameEndNotify(); | ||
| 158 | rasterizer.TickFrame(); | 159 | rasterizer.TickFrame(); |
| 159 | 160 | ||
| 160 | context->SwapBuffers(); | 161 | context->SwapBuffers(); |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 1f6a169ae..b7f5b8bc2 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -289,16 +289,15 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri | |||
| 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); | 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, |
| 293 | const std::array<Offset2D, 2>& dst_region, | 293 | const Region2D& src_region) { |
| 294 | const std::array<Offset2D, 2>& src_region) { | ||
| 295 | const VkOffset2D offset{ | 294 | const VkOffset2D offset{ |
| 296 | .x = std::min(dst_region[0].x, dst_region[1].x), | 295 | .x = std::min(dst_region.start.x, dst_region.end.x), |
| 297 | .y = std::min(dst_region[0].y, dst_region[1].y), | 296 | .y = std::min(dst_region.start.y, dst_region.end.y), |
| 298 | }; | 297 | }; |
| 299 | const VkExtent2D extent{ | 298 | const VkExtent2D extent{ |
| 300 | .width = static_cast<u32>(std::abs(dst_region[1].x - dst_region[0].x)), | 299 | .width = static_cast<u32>(std::abs(dst_region.end.x - dst_region.start.x)), |
| 301 | .height = static_cast<u32>(std::abs(dst_region[1].y - dst_region[0].y)), | 300 | .height = static_cast<u32>(std::abs(dst_region.end.y - dst_region.start.y)), |
| 302 | }; | 301 | }; |
| 303 | const VkViewport viewport{ | 302 | const VkViewport viewport{ |
| 304 | .x = static_cast<float>(offset.x), | 303 | .x = static_cast<float>(offset.x), |
| @@ -313,11 +312,12 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | |||
| 313 | .offset = offset, | 312 | .offset = offset, |
| 314 | .extent = extent, | 313 | .extent = extent, |
| 315 | }; | 314 | }; |
| 316 | const float scale_x = static_cast<float>(src_region[1].x - src_region[0].x); | 315 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x); |
| 317 | const float scale_y = static_cast<float>(src_region[1].y - src_region[0].y); | 316 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y); |
| 318 | const PushConstants push_constants{ | 317 | const PushConstants push_constants{ |
| 319 | .tex_scale = {scale_x, scale_y}, | 318 | .tex_scale = {scale_x, scale_y}, |
| 320 | .tex_offset = {static_cast<float>(src_region[0].x), static_cast<float>(src_region[0].y)}, | 319 | .tex_offset = {static_cast<float>(src_region.start.x), |
| 320 | static_cast<float>(src_region.start.y)}, | ||
| 321 | }; | 321 | }; |
| 322 | cmdbuf.SetViewport(0, viewport); | 322 | cmdbuf.SetViewport(0, viewport); |
| 323 | cmdbuf.SetScissor(0, scissor); | 323 | cmdbuf.SetScissor(0, scissor); |
| @@ -353,8 +353,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 353 | BlitImageHelper::~BlitImageHelper() = default; | 353 | BlitImageHelper::~BlitImageHelper() = default; |
| 354 | 354 | ||
| 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 356 | const std::array<Offset2D, 2>& dst_region, | 356 | const Region2D& dst_region, const Region2D& src_region, |
| 357 | const std::array<Offset2D, 2>& src_region, | ||
| 358 | Tegra::Engines::Fermi2D::Filter filter, | 357 | Tegra::Engines::Fermi2D::Filter filter, |
| 359 | Tegra::Engines::Fermi2D::Operation operation) { | 358 | Tegra::Engines::Fermi2D::Operation operation) { |
| 360 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 359 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| @@ -383,8 +382,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 383 | 382 | ||
| 384 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | 383 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, |
| 385 | VkImageView src_depth_view, VkImageView src_stencil_view, | 384 | VkImageView src_depth_view, VkImageView src_stencil_view, |
| 386 | const std::array<Offset2D, 2>& dst_region, | 385 | const Region2D& dst_region, const Region2D& src_region, |
| 387 | const std::array<Offset2D, 2>& src_region, | ||
| 388 | Tegra::Engines::Fermi2D::Filter filter, | 386 | Tegra::Engines::Fermi2D::Filter filter, |
| 389 | Tegra::Engines::Fermi2D::Operation operation) { | 387 | Tegra::Engines::Fermi2D::Operation operation) { |
| 390 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); | 388 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 43fd3d737..0d81a06ed 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Vulkan { | 14 | namespace Vulkan { |
| 15 | 15 | ||
| 16 | using VideoCommon::Offset2D; | 16 | using VideoCommon::Region2D; |
| 17 | 17 | ||
| 18 | class Device; | 18 | class Device; |
| 19 | class Framebuffer; | 19 | class Framebuffer; |
| @@ -35,15 +35,13 @@ public: | |||
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 38 | const std::array<Offset2D, 2>& dst_region, | 38 | const Region2D& dst_region, const Region2D& src_region, |
| 39 | const std::array<Offset2D, 2>& src_region, | ||
| 40 | Tegra::Engines::Fermi2D::Filter filter, | 39 | Tegra::Engines::Fermi2D::Filter filter, |
| 41 | Tegra::Engines::Fermi2D::Operation operation); | 40 | Tegra::Engines::Fermi2D::Operation operation); |
| 42 | 41 | ||
| 43 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, | 42 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, |
| 44 | VkImageView src_stencil_view, const std::array<Offset2D, 2>& dst_region, | 43 | VkImageView src_stencil_view, const Region2D& dst_region, |
| 45 | const std::array<Offset2D, 2>& src_region, | 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 46 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 47 | Tegra::Engines::Fermi2D::Operation operation); | 45 | Tegra::Engines::Fermi2D::Operation operation); |
| 48 | 46 | ||
| 49 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); | 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2e0cf4232..3986eb172 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -154,6 +154,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 154 | if (swapchain.Present(render_semaphore)) { | 154 | if (swapchain.Present(render_semaphore)) { |
| 155 | blit_screen.Recreate(); | 155 | blit_screen.Recreate(); |
| 156 | } | 156 | } |
| 157 | gpu.RendererFrameEndNotify(); | ||
| 157 | rasterizer.TickFrame(); | 158 | rasterizer.TickFrame(); |
| 158 | } | 159 | } |
| 159 | 160 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 017348e05..bdd0ce8bc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -490,8 +490,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 490 | write_barrier); | 490 | write_barrier); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const std::array<Offset2D, 2>& dst_region, | 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, |
| 494 | const std::array<Offset2D, 2>& src_region, | ||
| 495 | const VkImageSubresourceLayers& dst_layers, | 494 | const VkImageSubresourceLayers& dst_layers, |
| 496 | const VkImageSubresourceLayers& src_layers) { | 495 | const VkImageSubresourceLayers& src_layers) { |
| 497 | return VkImageBlit{ | 496 | return VkImageBlit{ |
| @@ -499,13 +498,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 499 | .srcOffsets = | 498 | .srcOffsets = |
| 500 | { | 499 | { |
| 501 | { | 500 | { |
| 502 | .x = src_region[0].x, | 501 | .x = src_region.start.x, |
| 503 | .y = src_region[0].y, | 502 | .y = src_region.start.y, |
| 504 | .z = 0, | 503 | .z = 0, |
| 505 | }, | 504 | }, |
| 506 | { | 505 | { |
| 507 | .x = src_region[1].x, | 506 | .x = src_region.end.x, |
| 508 | .y = src_region[1].y, | 507 | .y = src_region.end.y, |
| 509 | .z = 1, | 508 | .z = 1, |
| 510 | }, | 509 | }, |
| 511 | }, | 510 | }, |
| @@ -513,42 +512,42 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 513 | .dstOffsets = | 512 | .dstOffsets = |
| 514 | { | 513 | { |
| 515 | { | 514 | { |
| 516 | .x = dst_region[0].x, | 515 | .x = dst_region.start.x, |
| 517 | .y = dst_region[0].y, | 516 | .y = dst_region.start.y, |
| 518 | .z = 0, | 517 | .z = 0, |
| 519 | }, | 518 | }, |
| 520 | { | 519 | { |
| 521 | .x = dst_region[1].x, | 520 | .x = dst_region.end.x, |
| 522 | .y = dst_region[1].y, | 521 | .y = dst_region.end.y, |
| 523 | .z = 1, | 522 | .z = 1, |
| 524 | }, | 523 | }, |
| 525 | }, | 524 | }, |
| 526 | }; | 525 | }; |
| 527 | } | 526 | } |
| 528 | 527 | ||
| 529 | [[nodiscard]] VkImageResolve MakeImageResolve(const std::array<Offset2D, 2>& dst_region, | 528 | [[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, |
| 530 | const std::array<Offset2D, 2>& src_region, | 529 | const Region2D& src_region, |
| 531 | const VkImageSubresourceLayers& dst_layers, | 530 | const VkImageSubresourceLayers& dst_layers, |
| 532 | const VkImageSubresourceLayers& src_layers) { | 531 | const VkImageSubresourceLayers& src_layers) { |
| 533 | return VkImageResolve{ | 532 | return VkImageResolve{ |
| 534 | .srcSubresource = src_layers, | 533 | .srcSubresource = src_layers, |
| 535 | .srcOffset = | 534 | .srcOffset = |
| 536 | { | 535 | { |
| 537 | .x = src_region[0].x, | 536 | .x = src_region.start.x, |
| 538 | .y = src_region[0].y, | 537 | .y = src_region.start.y, |
| 539 | .z = 0, | 538 | .z = 0, |
| 540 | }, | 539 | }, |
| 541 | .dstSubresource = dst_layers, | 540 | .dstSubresource = dst_layers, |
| 542 | .dstOffset = | 541 | .dstOffset = |
| 543 | { | 542 | { |
| 544 | .x = dst_region[0].x, | 543 | .x = dst_region.start.x, |
| 545 | .y = dst_region[0].y, | 544 | .y = dst_region.start.y, |
| 546 | .z = 0, | 545 | .z = 0, |
| 547 | }, | 546 | }, |
| 548 | .extent = | 547 | .extent = |
| 549 | { | 548 | { |
| 550 | .width = static_cast<u32>(dst_region[1].x - dst_region[0].x), | 549 | .width = static_cast<u32>(dst_region.end.x - dst_region.start.x), |
| 551 | .height = static_cast<u32>(dst_region[1].y - dst_region[0].y), | 550 | .height = static_cast<u32>(dst_region.end.y - dst_region.start.y), |
| 552 | .depth = 1, | 551 | .depth = 1, |
| 553 | }, | 552 | }, |
| 554 | }; | 553 | }; |
| @@ -602,8 +601,7 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 602 | } | 601 | } |
| 603 | 602 | ||
| 604 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 603 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 605 | const std::array<Offset2D, 2>& dst_region, | 604 | const Region2D& dst_region, const Region2D& src_region, |
| 606 | const std::array<Offset2D, 2>& src_region, | ||
| 607 | Tegra::Engines::Fermi2D::Filter filter, | 605 | Tegra::Engines::Fermi2D::Filter filter, |
| 608 | Tegra::Engines::Fermi2D::Operation operation) { | 606 | Tegra::Engines::Fermi2D::Operation operation) { |
| 609 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); | 607 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 628785d5e..4a57d378b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -16,7 +16,7 @@ namespace Vulkan { | |||
| 16 | 16 | ||
| 17 | using VideoCommon::ImageId; | 17 | using VideoCommon::ImageId; |
| 18 | using VideoCommon::NUM_RT; | 18 | using VideoCommon::NUM_RT; |
| 19 | using VideoCommon::Offset2D; | 19 | using VideoCommon::Region2D; |
| 20 | using VideoCommon::RenderTargets; | 20 | using VideoCommon::RenderTargets; |
| 21 | using VideoCore::Surface::PixelFormat; | 21 | using VideoCore::Surface::PixelFormat; |
| 22 | 22 | ||
| @@ -71,8 +71,7 @@ struct TextureCacheRuntime { | |||
| 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); |
| 72 | 72 | ||
| 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 74 | const std::array<Offset2D, 2>& dst_region, | 74 | const Region2D& dst_region, const Region2D& src_region, |
| 75 | const std::array<Offset2D, 2>& src_region, | ||
| 76 | Tegra::Engines::Fermi2D::Filter filter, | 75 | Tegra::Engines::Fermi2D::Filter filter, |
| 77 | Tegra::Engines::Fermi2D::Operation operation); | 76 | Tegra::Engines::Fermi2D::Operation operation); |
| 78 | 77 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 98e33c3a0..59b7c678b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -148,7 +148,9 @@ public: | |||
| 148 | /// Blit an image with the given parameters | 148 | /// Blit an image with the given parameters |
| 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 150 | const Tegra::Engines::Fermi2D::Surface& src, | 150 | const Tegra::Engines::Fermi2D::Surface& src, |
| 151 | const Tegra::Engines::Fermi2D::Config& copy); | 151 | const Tegra::Engines::Fermi2D::Config& copy, |
| 152 | std::optional<Region2D> src_region_override = {}, | ||
| 153 | std::optional<Region2D> dst_region_override = {}); | ||
| 152 | 154 | ||
| 153 | /// Invalidate the contents of the color buffer index | 155 | /// Invalidate the contents of the color buffer index |
| 154 | /// These contents become unspecified, the cache can assume aggressive optimizations. | 156 | /// These contents become unspecified, the cache can assume aggressive optimizations. |
| @@ -615,7 +617,9 @@ void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | |||
| 615 | template <class P> | 617 | template <class P> |
| 616 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 618 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 617 | const Tegra::Engines::Fermi2D::Surface& src, | 619 | const Tegra::Engines::Fermi2D::Surface& src, |
| 618 | const Tegra::Engines::Fermi2D::Config& copy) { | 620 | const Tegra::Engines::Fermi2D::Config& copy, |
| 621 | std::optional<Region2D> src_override, | ||
| 622 | std::optional<Region2D> dst_override) { | ||
| 619 | const BlitImages images = GetBlitImages(dst, src); | 623 | const BlitImages images = GetBlitImages(dst, src); |
| 620 | const ImageId dst_id = images.dst_id; | 624 | const ImageId dst_id = images.dst_id; |
| 621 | const ImageId src_id = images.src_id; | 625 | const ImageId src_id = images.src_id; |
| @@ -631,20 +635,42 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 631 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); | 635 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); |
| 632 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); | 636 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); |
| 633 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); | 637 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); |
| 634 | const std::array src_region{ | 638 | |
| 635 | Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, | 639 | // out of bounds texture blit checking |
| 636 | Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, | 640 | const bool use_override = src_override.has_value(); |
| 641 | const s32 src_x0 = copy.src_x0 >> src_samples_x; | ||
| 642 | s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x; | ||
| 643 | const s32 src_y0 = copy.src_y0 >> src_samples_y; | ||
| 644 | const s32 src_y1 = copy.src_y1 >> src_samples_y; | ||
| 645 | |||
| 646 | const auto src_width = static_cast<s32>(src_image.info.size.width); | ||
| 647 | const bool width_oob = src_x1 > src_width; | ||
| 648 | const auto width_diff = width_oob ? src_x1 - src_width : 0; | ||
| 649 | if (width_oob) { | ||
| 650 | src_x1 = src_width; | ||
| 651 | } | ||
| 652 | |||
| 653 | const Region2D src_dimensions{ | ||
| 654 | Offset2D{.x = src_x0, .y = src_y0}, | ||
| 655 | Offset2D{.x = src_x1, .y = src_y1}, | ||
| 637 | }; | 656 | }; |
| 657 | const auto src_region = use_override ? *src_override : src_dimensions; | ||
| 638 | 658 | ||
| 639 | const std::optional src_base = src_image.TryFindBase(src.Address()); | 659 | const std::optional src_base = src_image.TryFindBase(src.Address()); |
| 640 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; | 660 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; |
| 641 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); | 661 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); |
| 642 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); | 662 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); |
| 643 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); | 663 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); |
| 644 | const std::array dst_region{ | 664 | |
| 645 | Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, | 665 | const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; |
| 646 | Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, | 666 | const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; |
| 667 | const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; | ||
| 668 | const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; | ||
| 669 | const Region2D dst_dimensions{ | ||
| 670 | Offset2D{.x = dst_x0, .y = dst_y0}, | ||
| 671 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, | ||
| 647 | }; | 672 | }; |
| 673 | const auto dst_region = use_override ? *dst_override : dst_dimensions; | ||
| 648 | 674 | ||
| 649 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. | 675 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. |
| 650 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; | 676 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; |
| @@ -661,6 +687,21 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 661 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, | 687 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, |
| 662 | copy.operation); | 688 | copy.operation); |
| 663 | } | 689 | } |
| 690 | |||
| 691 | if (width_oob) { | ||
| 692 | // Continue copy of the oob region of the texture on the next row | ||
| 693 | auto oob_src = src; | ||
| 694 | oob_src.height++; | ||
| 695 | const Region2D src_region_override{ | ||
| 696 | Offset2D{.x = 0, .y = src_y0 + 1}, | ||
| 697 | Offset2D{.x = width_diff, .y = src_y1 + 1}, | ||
| 698 | }; | ||
| 699 | const Region2D dst_region_override{ | ||
| 700 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y0}, | ||
| 701 | Offset2D{.x = dst_x1, .y = dst_y1}, | ||
| 702 | }; | ||
| 703 | BlitImage(dst, oob_src, copy, src_region_override, dst_region_override); | ||
| 704 | } | ||
| 664 | } | 705 | } |
| 665 | 706 | ||
| 666 | template <class P> | 707 | template <class P> |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 2ad2d72a6..c9571f7e4 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -64,6 +64,13 @@ struct Offset3D { | |||
| 64 | s32 z; | 64 | s32 z; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct Region2D { | ||
| 68 | constexpr auto operator<=>(const Region2D&) const noexcept = default; | ||
| 69 | |||
| 70 | Offset2D start; | ||
| 71 | Offset2D end; | ||
| 72 | }; | ||
| 73 | |||
| 67 | struct Extent2D { | 74 | struct Extent2D { |
| 68 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; | 75 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; |
| 69 | 76 | ||
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index 695b2ef5f..a2e0e6962 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp | |||
| @@ -9,17 +9,19 @@ | |||
| 9 | #include "yuzu/about_dialog.h" | 9 | #include "yuzu/about_dialog.h" |
| 10 | 10 | ||
| 11 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { | 11 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { |
| 12 | const auto branch_name = std::string(Common::g_scm_branch); | ||
| 13 | const auto description = std::string(Common::g_scm_desc); | ||
| 12 | const auto build_id = std::string(Common::g_build_id); | 14 | const auto build_id = std::string(Common::g_build_id); |
| 13 | const auto fmt = std::string(Common::g_title_bar_format_idle); | 15 | |
| 14 | const auto yuzu_build_version = | 16 | const auto yuzu_build = fmt::format("yuzu Development Build | {}-{}", branch_name, description); |
| 15 | fmt::format(fmt.empty() ? "yuzu Development Build" : fmt, std::string{}, std::string{}, | 17 | const auto override_build = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 16 | std::string{}, std::string{}, std::string{}, build_id); | 18 | const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; |
| 17 | 19 | ||
| 18 | ui->setupUi(this); | 20 | ui->setupUi(this); |
| 19 | ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200)); | 21 | ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200)); |
| 20 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( | 22 | ui->labelBuildInfo->setText( |
| 21 | QString::fromStdString(yuzu_build_version), QString::fromUtf8(Common::g_scm_branch), | 23 | ui->labelBuildInfo->text().arg(QString::fromStdString(yuzu_build_version), |
| 22 | QString::fromUtf8(Common::g_scm_desc), QString::fromUtf8(Common::g_build_date).left(10))); | 24 | QString::fromUtf8(Common::g_build_date).left(10))); |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | AboutDialog::~AboutDialog() = default; | 27 | AboutDialog::~AboutDialog() = default; |
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index 1b320630c..27d81cd13 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui | |||
| @@ -70,7 +70,7 @@ | |||
| 70 | </sizepolicy> | 70 | </sizepolicy> |
| 71 | </property> | 71 | </property> |
| 72 | <property name="text"> | 72 | <property name="text"> |
| 73 | <string><html><head/><body><p>%1 | %2-%3 (%4)</p></body></html></string> | 73 | <string><html><head/><body><p>%1 (%2)</p></body></html></string> |
| 74 | </property> | 74 | </property> |
| 75 | </widget> | 75 | </widget> |
| 76 | </item> | 76 | </item> |
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index fd3368479..b0f764994 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -404,12 +404,16 @@ void QtSoftwareKeyboardDialog::ShowTextCheckDialog( | |||
| 404 | 404 | ||
| 405 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | 405 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), |
| 406 | tr("Cancel"), tr("OK"), Qt::AlignCenter); | 406 | tr("Cancel"), tr("OK"), Qt::AlignCenter); |
| 407 | if (dialog.exec() == QDialog::Accepted) { | 407 | if (dialog.exec() != QDialog::Accepted) { |
| 408 | emit SubmitNormalText(SwkbdResult::Ok, current_text); | 408 | StartInputThread(); |
| 409 | break; | 409 | break; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | StartInputThread(); | 412 | auto text = ui->topOSK->currentIndex() == 1 |
| 413 | ? ui->text_edit_osk->toPlainText().toStdU16String() | ||
| 414 | : ui->line_edit_osk->text().toStdU16String(); | ||
| 415 | |||
| 416 | emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); | ||
| 413 | break; | 417 | break; |
| 414 | } | 418 | } |
| 415 | } | 419 | } |
| @@ -480,11 +484,7 @@ void QtSoftwareKeyboardDialog::open() { | |||
| 480 | void QtSoftwareKeyboardDialog::reject() { | 484 | void QtSoftwareKeyboardDialog::reject() { |
| 481 | // Pressing the ESC key in a dialog calls QDialog::reject(). | 485 | // Pressing the ESC key in a dialog calls QDialog::reject(). |
| 482 | // We will override this behavior to the "Cancel" action on the software keyboard. | 486 | // We will override this behavior to the "Cancel" action on the software keyboard. |
| 483 | if (is_inline) { | 487 | TranslateButtonPress(HIDButton::X); |
| 484 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | ||
| 485 | } else { | ||
| 486 | emit SubmitNormalText(SwkbdResult::Cancel, current_text); | ||
| 487 | } | ||
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { | 490 | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { |
| @@ -1027,10 +1027,8 @@ void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { | |||
| 1027 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); | 1027 | ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); |
| 1028 | 1028 | ||
| 1029 | ui->button_shift_shift->setStyleSheet( | 1029 | ui->button_shift_shift->setStyleSheet( |
| 1030 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" | 1030 | QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" |
| 1031 | "\nbackground-position: left top;" | 1031 | "\nimage-position: left;")); |
| 1032 | "\nbackground-repeat: no-repeat;" | ||
| 1033 | "\nbackground-origin: content;")); | ||
| 1034 | 1032 | ||
| 1035 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 1033 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); |
| 1036 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 1034 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); |
| @@ -1040,10 +1038,8 @@ void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { | |||
| 1040 | caps_lock_enabled = false; | 1038 | caps_lock_enabled = false; |
| 1041 | 1039 | ||
| 1042 | ui->button_shift_shift->setStyleSheet( | 1040 | ui->button_shift_shift->setStyleSheet( |
| 1043 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" | 1041 | QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" |
| 1044 | "\nbackground-position: left top;" | 1042 | "\nimage-position: left;")); |
| 1045 | "\nbackground-repeat: no-repeat;" | ||
| 1046 | "\nbackground-origin: content;")); | ||
| 1047 | 1043 | ||
| 1048 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 1044 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); |
| 1049 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 1045 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); |
| @@ -1056,10 +1052,8 @@ void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { | |||
| 1056 | caps_lock_enabled = true; | 1052 | caps_lock_enabled = true; |
| 1057 | 1053 | ||
| 1058 | ui->button_shift_shift->setStyleSheet( | 1054 | ui->button_shift_shift->setStyleSheet( |
| 1059 | QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_on.png);" | 1055 | QStringLiteral("image: url(:/overlay/osk_button_shift_lock_on.png);" |
| 1060 | "\nbackground-position: left top;" | 1056 | "\nimage-position: left;")); |
| 1061 | "\nbackground-repeat: no-repeat;" | ||
| 1062 | "\nbackground-origin: content;")); | ||
| 1063 | 1057 | ||
| 1064 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); | 1058 | ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); |
| 1065 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); | 1059 | ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); |
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp index e482ba029..93e3a4f6f 100644 --- a/src/yuzu/applets/web_browser.cpp +++ b/src/yuzu/applets/web_browser.cpp | |||
| @@ -102,8 +102,8 @@ QtNXWebEngineView::~QtNXWebEngineView() { | |||
| 102 | StopInputThread(); | 102 | StopInputThread(); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, | 105 | void QtNXWebEngineView::LoadLocalWebPage(const std::string& main_url, |
| 106 | std::string_view additional_args) { | 106 | const std::string& additional_args) { |
| 107 | is_local = true; | 107 | is_local = true; |
| 108 | 108 | ||
| 109 | LoadExtractedFonts(); | 109 | LoadExtractedFonts(); |
| @@ -113,12 +113,12 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, | |||
| 113 | SetLastURL("http://localhost/"); | 113 | SetLastURL("http://localhost/"); |
| 114 | StartInputThread(); | 114 | StartInputThread(); |
| 115 | 115 | ||
| 116 | load(QUrl(QUrl::fromLocalFile(QString::fromStdString(std::string(main_url))).toString() + | 116 | load(QUrl(QUrl::fromLocalFile(QString::fromStdString(main_url)).toString() + |
| 117 | QString::fromStdString(std::string(additional_args)))); | 117 | QString::fromStdString(additional_args))); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url, | 120 | void QtNXWebEngineView::LoadExternalWebPage(const std::string& main_url, |
| 121 | std::string_view additional_args) { | 121 | const std::string& additional_args) { |
| 122 | is_local = false; | 122 | is_local = false; |
| 123 | 123 | ||
| 124 | SetUserAgent(UserAgent::WebApplet); | 124 | SetUserAgent(UserAgent::WebApplet); |
| @@ -127,8 +127,7 @@ void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url, | |||
| 127 | SetLastURL("http://localhost/"); | 127 | SetLastURL("http://localhost/"); |
| 128 | StartInputThread(); | 128 | StartInputThread(); |
| 129 | 129 | ||
| 130 | load(QUrl(QString::fromStdString(std::string(main_url)) + | 130 | load(QUrl(QString::fromStdString(main_url) + QString::fromStdString(additional_args))); |
| 131 | QString::fromStdString(std::string(additional_args)))); | ||
| 132 | } | 131 | } |
| 133 | 132 | ||
| 134 | void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { | 133 | void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { |
| @@ -375,7 +374,7 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { | |||
| 375 | QtWebBrowser::~QtWebBrowser() = default; | 374 | QtWebBrowser::~QtWebBrowser() = default; |
| 376 | 375 | ||
| 377 | void QtWebBrowser::OpenLocalWebPage( | 376 | void QtWebBrowser::OpenLocalWebPage( |
| 378 | std::string_view local_url, std::function<void()> extract_romfs_callback_, | 377 | const std::string& local_url, std::function<void()> extract_romfs_callback_, |
| 379 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { | 378 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { |
| 380 | extract_romfs_callback = std::move(extract_romfs_callback_); | 379 | extract_romfs_callback = std::move(extract_romfs_callback_); |
| 381 | callback = std::move(callback_); | 380 | callback = std::move(callback_); |
| @@ -390,7 +389,7 @@ void QtWebBrowser::OpenLocalWebPage( | |||
| 390 | } | 389 | } |
| 391 | 390 | ||
| 392 | void QtWebBrowser::OpenExternalWebPage( | 391 | void QtWebBrowser::OpenExternalWebPage( |
| 393 | std::string_view external_url, | 392 | const std::string& external_url, |
| 394 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { | 393 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { |
| 395 | callback = std::move(callback_); | 394 | callback = std::move(callback_); |
| 396 | 395 | ||
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h index 47f960d69..7ad07409f 100644 --- a/src/yuzu/applets/web_browser.h +++ b/src/yuzu/applets/web_browser.h | |||
| @@ -58,7 +58,7 @@ public: | |||
| 58 | * @param main_url The url to the file. | 58 | * @param main_url The url to the file. |
| 59 | * @param additional_args Additional arguments appended to the main url. | 59 | * @param additional_args Additional arguments appended to the main url. |
| 60 | */ | 60 | */ |
| 61 | void LoadLocalWebPage(std::string_view main_url, std::string_view additional_args); | 61 | void LoadLocalWebPage(const std::string& main_url, const std::string& additional_args); |
| 62 | 62 | ||
| 63 | /** | 63 | /** |
| 64 | * Loads an external website. Cannot be used to load local urls. | 64 | * Loads an external website. Cannot be used to load local urls. |
| @@ -66,7 +66,7 @@ public: | |||
| 66 | * @param main_url The url to the website. | 66 | * @param main_url The url to the website. |
| 67 | * @param additional_args Additional arguments appended to the main url. | 67 | * @param additional_args Additional arguments appended to the main url. |
| 68 | */ | 68 | */ |
| 69 | void LoadExternalWebPage(std::string_view main_url, std::string_view additional_args); | 69 | void LoadExternalWebPage(const std::string& main_url, const std::string& additional_args); |
| 70 | 70 | ||
| 71 | /** | 71 | /** |
| 72 | * Sets the background color of the web page. | 72 | * Sets the background color of the web page. |
| @@ -193,16 +193,17 @@ public: | |||
| 193 | explicit QtWebBrowser(GMainWindow& parent); | 193 | explicit QtWebBrowser(GMainWindow& parent); |
| 194 | ~QtWebBrowser() override; | 194 | ~QtWebBrowser() override; |
| 195 | 195 | ||
| 196 | void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback_, | 196 | void OpenLocalWebPage(const std::string& local_url, |
| 197 | std::function<void()> extract_romfs_callback_, | ||
| 197 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 198 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> |
| 198 | callback_) const override; | 199 | callback_) const override; |
| 199 | 200 | ||
| 200 | void OpenExternalWebPage(std::string_view external_url, | 201 | void OpenExternalWebPage(const std::string& external_url, |
| 201 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 202 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> |
| 202 | callback_) const override; | 203 | callback_) const override; |
| 203 | 204 | ||
| 204 | signals: | 205 | signals: |
| 205 | void MainWindowOpenWebPage(std::string_view main_url, std::string_view additional_args, | 206 | void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, |
| 206 | bool is_local) const; | 207 | bool is_local) const; |
| 207 | 208 | ||
| 208 | private: | 209 | private: |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 9c7daeac7..86495803e 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include "common/settings.h" | 32 | #include "common/settings.h" |
| 33 | #include "core/core.h" | 33 | #include "core/core.h" |
| 34 | #include "core/frontend/framebuffer_layout.h" | 34 | #include "core/frontend/framebuffer_layout.h" |
| 35 | #include "core/hle/kernel/process.h" | 35 | #include "core/hle/kernel/k_process.h" |
| 36 | #include "input_common/keyboard.h" | 36 | #include "input_common/keyboard.h" |
| 37 | #include "input_common/main.h" | 37 | #include "input_common/main.h" |
| 38 | #include "input_common/mouse/mouse_input.h" | 38 | #include "input_common/mouse/mouse_input.h" |
| @@ -539,6 +539,8 @@ bool GRenderWindow::event(QEvent* event) { | |||
| 539 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { | 539 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { |
| 540 | QWidget::focusOutEvent(event); | 540 | QWidget::focusOutEvent(event); |
| 541 | input_subsystem->GetKeyboard()->ReleaseAllKeys(); | 541 | input_subsystem->GetKeyboard()->ReleaseAllKeys(); |
| 542 | input_subsystem->GetMouse()->ReleaseAllButtons(); | ||
| 543 | this->TouchReleased(0); | ||
| 542 | } | 544 | } |
| 543 | 545 | ||
| 544 | void GRenderWindow::resizeEvent(QResizeEvent* event) { | 546 | void GRenderWindow::resizeEvent(QResizeEvent* event) { |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d1b8c4fc9..125feb86b 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -736,10 +736,16 @@ void Config::ReadPathValues() { | |||
| 736 | void Config::ReadCpuValues() { | 736 | void Config::ReadCpuValues() { |
| 737 | qt_config->beginGroup(QStringLiteral("Cpu")); | 737 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 738 | 738 | ||
| 739 | if (global) { | 739 | ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0); |
| 740 | Settings::values.cpu_accuracy = static_cast<Settings::CPUAccuracy>( | 740 | |
| 741 | ReadSetting(QStringLiteral("cpu_accuracy"), 0).toInt()); | 741 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma, |
| 742 | QStringLiteral("cpuopt_unsafe_unfuse_fma"), true); | ||
| 743 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 744 | QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true); | ||
| 745 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 746 | QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true); | ||
| 742 | 747 | ||
| 748 | if (global) { | ||
| 743 | Settings::values.cpuopt_page_tables = | 749 | Settings::values.cpuopt_page_tables = |
| 744 | ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool(); | 750 | ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool(); |
| 745 | Settings::values.cpuopt_block_linking = | 751 | Settings::values.cpuopt_block_linking = |
| @@ -756,13 +762,6 @@ void Config::ReadCpuValues() { | |||
| 756 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); | 762 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); |
| 757 | Settings::values.cpuopt_reduce_misalign_checks = | 763 | Settings::values.cpuopt_reduce_misalign_checks = |
| 758 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); | 764 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); |
| 759 | |||
| 760 | Settings::values.cpuopt_unsafe_unfuse_fma = | ||
| 761 | ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool(); | ||
| 762 | Settings::values.cpuopt_unsafe_reduce_fp_error = | ||
| 763 | ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool(); | ||
| 764 | Settings::values.cpuopt_unsafe_inaccurate_nan = | ||
| 765 | ReadSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true).toBool(); | ||
| 766 | } | 765 | } |
| 767 | 766 | ||
| 768 | qt_config->endGroup(); | 767 | qt_config->endGroup(); |
| @@ -863,24 +862,20 @@ void Config::ReadSystemValues() { | |||
| 863 | Settings::values.rng_seed.SetGlobal(rng_seed_global); | 862 | Settings::values.rng_seed.SetGlobal(rng_seed_global); |
| 864 | if (global || !rng_seed_global) { | 863 | if (global || !rng_seed_global) { |
| 865 | if (rng_seed_enabled) { | 864 | if (rng_seed_enabled) { |
| 866 | Settings::values.rng_seed.SetValue( | 865 | Settings::values.rng_seed.SetValue(ReadSetting(QStringLiteral("rng_seed"), 0).toUInt()); |
| 867 | ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong()); | ||
| 868 | } else { | 866 | } else { |
| 869 | Settings::values.rng_seed.SetValue(std::nullopt); | 867 | Settings::values.rng_seed.SetValue(std::nullopt); |
| 870 | } | 868 | } |
| 871 | } | 869 | } |
| 872 | 870 | ||
| 873 | bool custom_rtc_enabled; | 871 | if (global) { |
| 874 | ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false); | 872 | const auto custom_rtc_enabled = |
| 875 | bool custom_rtc_global = | 873 | ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); |
| 876 | global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool(); | ||
| 877 | Settings::values.custom_rtc.SetGlobal(custom_rtc_global); | ||
| 878 | if (global || !custom_rtc_global) { | ||
| 879 | if (custom_rtc_enabled) { | 874 | if (custom_rtc_enabled) { |
| 880 | Settings::values.custom_rtc.SetValue( | 875 | Settings::values.custom_rtc = |
| 881 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong())); | 876 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()); |
| 882 | } else { | 877 | } else { |
| 883 | Settings::values.custom_rtc.SetValue(std::nullopt); | 878 | Settings::values.custom_rtc = std::nullopt; |
| 884 | } | 879 | } |
| 885 | } | 880 | } |
| 886 | 881 | ||
| @@ -1314,10 +1309,19 @@ void Config::SavePathValues() { | |||
| 1314 | void Config::SaveCpuValues() { | 1309 | void Config::SaveCpuValues() { |
| 1315 | qt_config->beginGroup(QStringLiteral("Cpu")); | 1310 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 1316 | 1311 | ||
| 1317 | if (global) { | 1312 | WriteSettingGlobal(QStringLiteral("cpu_accuracy"), |
| 1318 | WriteSetting(QStringLiteral("cpu_accuracy"), | 1313 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)), |
| 1319 | static_cast<int>(Settings::values.cpu_accuracy), 0); | 1314 | Settings::values.cpu_accuracy.UsingGlobal(), |
| 1315 | static_cast<u32>(Settings::CPUAccuracy::Accurate)); | ||
| 1320 | 1316 | ||
| 1317 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | ||
| 1318 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | ||
| 1319 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | ||
| 1320 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | ||
| 1321 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), | ||
| 1322 | Settings::values.cpuopt_unsafe_inaccurate_nan, true); | ||
| 1323 | |||
| 1324 | if (global) { | ||
| 1321 | WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, | 1325 | WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, |
| 1322 | true); | 1326 | true); |
| 1323 | WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking, | 1327 | WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking, |
| @@ -1332,13 +1336,6 @@ void Config::SaveCpuValues() { | |||
| 1332 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); | 1336 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); |
| 1333 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), | 1337 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), |
| 1334 | Settings::values.cpuopt_reduce_misalign_checks, true); | 1338 | Settings::values.cpuopt_reduce_misalign_checks, true); |
| 1335 | |||
| 1336 | WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | ||
| 1337 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | ||
| 1338 | WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | ||
| 1339 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | ||
| 1340 | WriteSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), | ||
| 1341 | Settings::values.cpuopt_unsafe_inaccurate_nan, true); | ||
| 1342 | } | 1339 | } |
| 1343 | 1340 | ||
| 1344 | qt_config->endGroup(); | 1341 | qt_config->endGroup(); |
| @@ -1433,14 +1430,14 @@ void Config::SaveSystemValues() { | |||
| 1433 | Settings::values.rng_seed.GetValue(global).value_or(0), | 1430 | Settings::values.rng_seed.GetValue(global).value_or(0), |
| 1434 | Settings::values.rng_seed.UsingGlobal(), 0); | 1431 | Settings::values.rng_seed.UsingGlobal(), 0); |
| 1435 | 1432 | ||
| 1436 | WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"), | 1433 | if (global) { |
| 1437 | Settings::values.custom_rtc.GetValue(global).has_value(), | 1434 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), |
| 1438 | Settings::values.custom_rtc.UsingGlobal(), false); | 1435 | false); |
| 1439 | WriteSettingGlobal( | 1436 | WriteSetting(QStringLiteral("custom_rtc"), |
| 1440 | QStringLiteral("custom_rtc"), | 1437 | QVariant::fromValue<long long>( |
| 1441 | QVariant::fromValue<long long>( | 1438 | Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), |
| 1442 | Settings::values.custom_rtc.GetValue(global).value_or(std::chrono::seconds{}).count()), | 1439 | 0); |
| 1443 | Settings::values.custom_rtc.UsingGlobal(), 0); | 1440 | } |
| 1444 | 1441 | ||
| 1445 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); | 1442 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); |
| 1446 | 1443 | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 5a2c026b3..ce3355588 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -132,5 +132,6 @@ private: | |||
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | 134 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT |
| 135 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); | ||
| 135 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 136 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 136 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 137 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); |
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index 89be4a62d..096e42e94 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -13,32 +13,29 @@ | |||
| 13 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, | 13 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, |
| 14 | const QCheckBox* checkbox, | 14 | const QCheckBox* checkbox, |
| 15 | const CheckState& tracker) { | 15 | const CheckState& tracker) { |
| 16 | if (tracker == CheckState::Global) { | 16 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { |
| 17 | setting->SetGlobal(true); | ||
| 18 | } else { | ||
| 19 | setting->SetGlobal(false); | ||
| 20 | setting->SetValue(checkbox->checkState()); | 17 | setting->SetValue(checkbox->checkState()); |
| 18 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 19 | if (tracker == CheckState::Global) { | ||
| 20 | setting->SetGlobal(true); | ||
| 21 | } else { | ||
| 22 | setting->SetGlobal(false); | ||
| 23 | setting->SetValue(checkbox->checkState()); | ||
| 24 | } | ||
| 21 | } | 25 | } |
| 22 | } | 26 | } |
| 23 | 27 | ||
| 24 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, | 28 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, |
| 25 | const QComboBox* combobox) { | 29 | const QComboBox* combobox) { |
| 26 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 30 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { |
| 27 | setting->SetGlobal(true); | 31 | setting->SetValue(combobox->currentIndex()); |
| 28 | } else { | 32 | } else if (!Settings::IsConfiguringGlobal()) { |
| 29 | setting->SetGlobal(false); | 33 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 30 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | 34 | setting->SetGlobal(true); |
| 31 | } | 35 | } else { |
| 32 | } | 36 | setting->SetGlobal(false); |
| 33 | 37 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | |
| 34 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | 38 | } |
| 35 | const QComboBox* combobox) { | ||
| 36 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 37 | setting->SetGlobal(true); | ||
| 38 | } else { | ||
| 39 | setting->SetGlobal(false); | ||
| 40 | setting->SetValue(static_cast<Settings::RendererBackend>( | ||
| 41 | combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 42 | } | 39 | } |
| 43 | } | 40 | } |
| 44 | 41 | ||
| @@ -51,27 +48,6 @@ void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | |||
| 51 | } | 48 | } |
| 52 | } | 49 | } |
| 53 | 50 | ||
| 54 | void ConfigurationShared::SetPerGameSetting(QComboBox* combobox, | ||
| 55 | const Settings::Setting<int>* setting) { | ||
| 56 | combobox->setCurrentIndex(setting->UsingGlobal() | ||
| 57 | ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 58 | : setting->GetValue() + ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 59 | } | ||
| 60 | |||
| 61 | void ConfigurationShared::SetPerGameSetting( | ||
| 62 | QComboBox* combobox, const Settings::Setting<Settings::RendererBackend>* setting) { | ||
| 63 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 64 | : static_cast<int>(setting->GetValue()) + | ||
| 65 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 66 | } | ||
| 67 | |||
| 68 | void ConfigurationShared::SetPerGameSetting( | ||
| 69 | QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting) { | ||
| 70 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 71 | : static_cast<int>(setting->GetValue()) + | ||
| 72 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 73 | } | ||
| 74 | |||
| 75 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { | 51 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { |
| 76 | if (highlighted) { | 52 | if (highlighted) { |
| 77 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") | 53 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") |
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 5b344cdbd..1e0ef01ca 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -15,37 +15,45 @@ constexpr int USE_GLOBAL_INDEX = 0; | |||
| 15 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; | 15 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; |
| 16 | constexpr int USE_GLOBAL_OFFSET = 2; | 16 | constexpr int USE_GLOBAL_OFFSET = 2; |
| 17 | 17 | ||
| 18 | // CheckBoxes require a tracker for their state since we emulate a tristate CheckBox | ||
| 18 | enum class CheckState { | 19 | enum class CheckState { |
| 19 | Off, | 20 | Off, // Checkbox overrides to off/false |
| 20 | On, | 21 | On, // Checkbox overrides to on/true |
| 21 | Global, | 22 | Global, // Checkbox defers to the global state |
| 22 | Count, | 23 | Count, // Simply the number of states, not a valid checkbox state |
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | // Global-aware apply and set functions | 26 | // Global-aware apply and set functions |
| 26 | 27 | ||
| 28 | // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting | ||
| 27 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, | 29 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, |
| 28 | const CheckState& tracker); | 30 | const CheckState& tracker); |
| 29 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); | 31 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); |
| 30 | void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | ||
| 31 | const QComboBox* combobox); | ||
| 32 | void ApplyPerGameSetting(Settings::Setting<Settings::GPUAccuracy>* setting, | ||
| 33 | const QComboBox* combobox); | ||
| 34 | 32 | ||
| 33 | // Sets a Qt UI element given a Settings::Setting | ||
| 35 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); | 34 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); |
| 36 | void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting); | ||
| 37 | void SetPerGameSetting(QComboBox* combobox, | ||
| 38 | const Settings::Setting<Settings::RendererBackend>* setting); | ||
| 39 | void SetPerGameSetting(QComboBox* combobox, | ||
| 40 | const Settings::Setting<Settings::GPUAccuracy>* setting); | ||
| 41 | 35 | ||
| 36 | template <typename Type> | ||
| 37 | void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<Type>* setting) { | ||
| 38 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 39 | : static_cast<int>(setting->GetValue()) + | ||
| 40 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 41 | } | ||
| 42 | |||
| 43 | // (Un)highlights a Qt UI element | ||
| 42 | void SetHighlight(QWidget* widget, bool highlighted); | 44 | void SetHighlight(QWidget* widget, bool highlighted); |
| 45 | |||
| 46 | // Sets up a QCheckBox like a tristate one, given a Setting | ||
| 43 | void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting, | 47 | void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting, |
| 44 | CheckState& tracker); | 48 | CheckState& tracker); |
| 45 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, | 49 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, |
| 46 | CheckState& tracker); | 50 | CheckState& tracker); |
| 51 | |||
| 52 | // Sets up coloring of a QWidget `target` based on the state of a QComboBox, and calls | ||
| 53 | // InsertGlobalItem | ||
| 47 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); | 54 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); |
| 48 | 55 | ||
| 56 | // Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox | ||
| 49 | void InsertGlobalItem(QComboBox* combobox, int global_index); | 57 | void InsertGlobalItem(QComboBox* combobox, int global_index); |
| 50 | 58 | ||
| 51 | } // namespace ConfigurationShared | 59 | } // namespace ConfigurationShared |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index f9507e228..fc0191432 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -99,6 +99,9 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | |||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void ConfigureAudio::ApplyConfiguration() { | 101 | void ConfigureAudio::ApplyConfiguration() { |
| 102 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||
| 103 | ui->toggle_audio_stretching, enable_audio_stretching); | ||
| 104 | |||
| 102 | if (Settings::IsConfiguringGlobal()) { | 105 | if (Settings::IsConfiguringGlobal()) { |
| 103 | Settings::values.sink_id = | 106 | Settings::values.sink_id = |
| 104 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | 107 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) |
| @@ -108,19 +111,12 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 108 | .toStdString(); | 111 | .toStdString(); |
| 109 | 112 | ||
| 110 | // Guard if during game and set to game-specific value | 113 | // Guard if during game and set to game-specific value |
| 111 | if (Settings::values.enable_audio_stretching.UsingGlobal()) { | ||
| 112 | Settings::values.enable_audio_stretching.SetValue( | ||
| 113 | ui->toggle_audio_stretching->isChecked()); | ||
| 114 | } | ||
| 115 | if (Settings::values.volume.UsingGlobal()) { | 114 | if (Settings::values.volume.UsingGlobal()) { |
| 116 | Settings::values.volume.SetValue( | 115 | Settings::values.volume.SetValue( |
| 117 | static_cast<float>(ui->volume_slider->sliderPosition()) / | 116 | static_cast<float>(ui->volume_slider->sliderPosition()) / |
| 118 | ui->volume_slider->maximum()); | 117 | ui->volume_slider->maximum()); |
| 119 | } | 118 | } |
| 120 | } else { | 119 | } else { |
| 121 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||
| 122 | ui->toggle_audio_stretching, | ||
| 123 | enable_audio_stretching); | ||
| 124 | if (ui->volume_combo_box->currentIndex() == 0) { | 120 | if (ui->volume_combo_box->currentIndex() == 0) { |
| 125 | Settings::values.volume.SetGlobal(true); | 121 | Settings::values.volume.SetGlobal(true); |
| 126 | } else { | 122 | } else { |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 4f99bc80f..525c42ff0 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -10,11 +10,14 @@ | |||
| 10 | #include "common/settings.h" | 10 | #include "common/settings.h" |
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "ui_configure_cpu.h" | 12 | #include "ui_configure_cpu.h" |
| 13 | #include "yuzu/configuration/configuration_shared.h" | ||
| 13 | #include "yuzu/configuration/configure_cpu.h" | 14 | #include "yuzu/configuration/configure_cpu.h" |
| 14 | 15 | ||
| 15 | ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) { | 16 | ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) { |
| 16 | ui->setupUi(this); | 17 | ui->setupUi(this); |
| 17 | 18 | ||
| 19 | SetupPerGameUI(); | ||
| 20 | |||
| 18 | SetConfiguration(); | 21 | SetConfiguration(); |
| 19 | 22 | ||
| 20 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, | 23 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, |
| @@ -29,19 +32,29 @@ void ConfigureCpu::SetConfiguration() { | |||
| 29 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 32 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 30 | 33 | ||
| 31 | ui->accuracy->setEnabled(runtime_lock); | 34 | ui->accuracy->setEnabled(runtime_lock); |
| 32 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy)); | ||
| 33 | UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy)); | ||
| 34 | |||
| 35 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); | 35 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); |
| 36 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 37 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); | 36 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); |
| 38 | ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 39 | ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); | 37 | ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); |
| 40 | ui->cpuopt_unsafe_inaccurate_nan->setChecked(Settings::values.cpuopt_unsafe_inaccurate_nan); | 38 | |
| 39 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()); | ||
| 40 | ui->cpuopt_unsafe_reduce_fp_error->setChecked( | ||
| 41 | Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()); | ||
| 42 | ui->cpuopt_unsafe_inaccurate_nan->setChecked( | ||
| 43 | Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()); | ||
| 44 | |||
| 45 | if (Settings::IsConfiguringGlobal()) { | ||
| 46 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue())); | ||
| 47 | } else { | ||
| 48 | ConfigurationShared::SetPerGameSetting(ui->accuracy, &Settings::values.cpu_accuracy); | ||
| 49 | ConfigurationShared::SetHighlight(ui->widget_accuracy, | ||
| 50 | !Settings::values.cpu_accuracy.UsingGlobal()); | ||
| 51 | } | ||
| 52 | UpdateGroup(ui->accuracy->currentIndex()); | ||
| 41 | } | 53 | } |
| 42 | 54 | ||
| 43 | void ConfigureCpu::AccuracyUpdated(int index) { | 55 | void ConfigureCpu::AccuracyUpdated(int index) { |
| 44 | if (static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) { | 56 | if (Settings::IsConfiguringGlobal() && |
| 57 | static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) { | ||
| 45 | const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"), | 58 | const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"), |
| 46 | tr("CPU Debug Mode is only intended for developer " | 59 | tr("CPU Debug Mode is only intended for developer " |
| 47 | "use. Are you sure you want to enable this?"), | 60 | "use. Are you sure you want to enable this?"), |
| @@ -54,16 +67,39 @@ void ConfigureCpu::AccuracyUpdated(int index) { | |||
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | void ConfigureCpu::UpdateGroup(int index) { | 69 | void ConfigureCpu::UpdateGroup(int index) { |
| 57 | ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) == | 70 | if (!Settings::IsConfiguringGlobal()) { |
| 58 | Settings::CPUAccuracy::Unsafe); | 71 | index -= ConfigurationShared::USE_GLOBAL_OFFSET; |
| 72 | } | ||
| 73 | const auto accuracy = static_cast<Settings::CPUAccuracy>(index); | ||
| 74 | ui->unsafe_group->setVisible(accuracy == Settings::CPUAccuracy::Unsafe); | ||
| 59 | } | 75 | } |
| 60 | 76 | ||
| 61 | void ConfigureCpu::ApplyConfiguration() { | 77 | void ConfigureCpu::ApplyConfiguration() { |
| 62 | Settings::values.cpu_accuracy = | 78 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma, |
| 63 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()); | 79 | ui->cpuopt_unsafe_unfuse_fma, |
| 64 | Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked(); | 80 | cpuopt_unsafe_unfuse_fma); |
| 65 | Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked(); | 81 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error, |
| 66 | Settings::values.cpuopt_unsafe_inaccurate_nan = ui->cpuopt_unsafe_inaccurate_nan->isChecked(); | 82 | ui->cpuopt_unsafe_reduce_fp_error, |
| 83 | cpuopt_unsafe_reduce_fp_error); | ||
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 85 | ui->cpuopt_unsafe_inaccurate_nan, | ||
| 86 | cpuopt_unsafe_inaccurate_nan); | ||
| 87 | |||
| 88 | if (Settings::IsConfiguringGlobal()) { | ||
| 89 | // Guard if during game and set to game-specific value | ||
| 90 | if (Settings::values.cpu_accuracy.UsingGlobal()) { | ||
| 91 | Settings::values.cpu_accuracy.SetValue( | ||
| 92 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex())); | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | if (ui->accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 96 | Settings::values.cpu_accuracy.SetGlobal(true); | ||
| 97 | } else { | ||
| 98 | Settings::values.cpu_accuracy.SetGlobal(false); | ||
| 99 | Settings::values.cpu_accuracy.SetValue(static_cast<Settings::CPUAccuracy>( | ||
| 100 | ui->accuracy->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 101 | } | ||
| 102 | } | ||
| 67 | } | 103 | } |
| 68 | 104 | ||
| 69 | void ConfigureCpu::changeEvent(QEvent* event) { | 105 | void ConfigureCpu::changeEvent(QEvent* event) { |
| @@ -77,3 +113,25 @@ void ConfigureCpu::changeEvent(QEvent* event) { | |||
| 77 | void ConfigureCpu::RetranslateUI() { | 113 | void ConfigureCpu::RetranslateUI() { |
| 78 | ui->retranslateUi(this); | 114 | ui->retranslateUi(this); |
| 79 | } | 115 | } |
| 116 | |||
| 117 | void ConfigureCpu::SetupPerGameUI() { | ||
| 118 | if (Settings::IsConfiguringGlobal()) { | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | ConfigurationShared::SetColoredComboBox( | ||
| 123 | ui->accuracy, ui->widget_accuracy, | ||
| 124 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true))); | ||
| 125 | ui->accuracy->removeItem(static_cast<u32>(Settings::CPUAccuracy::DebugMode) + | ||
| 126 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 127 | |||
| 128 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma, | ||
| 129 | Settings::values.cpuopt_unsafe_unfuse_fma, | ||
| 130 | cpuopt_unsafe_unfuse_fma); | ||
| 131 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error, | ||
| 132 | Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 133 | cpuopt_unsafe_reduce_fp_error); | ||
| 134 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan, | ||
| 135 | Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 136 | cpuopt_unsafe_inaccurate_nan); | ||
| 137 | } | ||
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index ef77b2e7e..8e2eeb7a6 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | 10 | ||
| 11 | namespace ConfigurationShared { | ||
| 12 | enum class CheckState; | ||
| 13 | } | ||
| 14 | |||
| 11 | namespace Ui { | 15 | namespace Ui { |
| 12 | class ConfigureCpu; | 16 | class ConfigureCpu; |
| 13 | } | 17 | } |
| @@ -30,5 +34,11 @@ private: | |||
| 30 | 34 | ||
| 31 | void SetConfiguration(); | 35 | void SetConfiguration(); |
| 32 | 36 | ||
| 37 | void SetupPerGameUI(); | ||
| 38 | |||
| 33 | std::unique_ptr<Ui::ConfigureCpu> ui; | 39 | std::unique_ptr<Ui::ConfigureCpu> ui; |
| 40 | |||
| 41 | ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma; | ||
| 42 | ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error; | ||
| 43 | ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan; | ||
| 34 | }; | 44 | }; |
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index bcd0962e9..d0e7e7bfe 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui | |||
| @@ -23,42 +23,44 @@ | |||
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout"> | 24 | <layout class="QVBoxLayout"> |
| 25 | <item> | 25 | <item> |
| 26 | <layout class="QHBoxLayout"> | 26 | <widget class="QWidget" name="widget_accuracy" native="true"> |
| 27 | <item> | 27 | <layout class="QHBoxLayout" name="layout_accuracy"> |
| 28 | <widget class="QLabel"> | 28 | <item> |
| 29 | <property name="text"> | 29 | <widget class="QLabel" name="label"> |
| 30 | <string>Accuracy:</string> | ||
| 31 | </property> | ||
| 32 | </widget> | ||
| 33 | </item> | ||
| 34 | <item> | ||
| 35 | <widget class="QComboBox" name="accuracy"> | ||
| 36 | <item> | ||
| 37 | <property name="text"> | 30 | <property name="text"> |
| 38 | <string>Accurate</string> | 31 | <string>Accuracy:</string> |
| 39 | </property> | 32 | </property> |
| 40 | </item> | 33 | </widget> |
| 41 | <item> | 34 | </item> |
| 42 | <property name="text"> | 35 | <item> |
| 43 | <string>Unsafe</string> | 36 | <widget class="QComboBox" name="accuracy"> |
| 44 | </property> | 37 | <item> |
| 45 | </item> | 38 | <property name="text"> |
| 46 | <item> | 39 | <string>Accurate</string> |
| 47 | <property name="text"> | 40 | </property> |
| 48 | <string>Enable Debug Mode</string> | 41 | </item> |
| 49 | </property> | 42 | <item> |
| 50 | </item> | 43 | <property name="text"> |
| 51 | </widget> | 44 | <string>Unsafe</string> |
| 52 | </item> | 45 | </property> |
| 53 | </layout> | 46 | </item> |
| 47 | <item> | ||
| 48 | <property name="text"> | ||
| 49 | <string>Enable Debug Mode</string> | ||
| 50 | </property> | ||
| 51 | </item> | ||
| 52 | </widget> | ||
| 53 | </item> | ||
| 54 | </layout> | ||
| 55 | </widget> | ||
| 54 | </item> | 56 | </item> |
| 55 | <item> | 57 | <item> |
| 56 | <widget class="QLabel"> | 58 | <widget class="QLabel" name="label"> |
| 57 | <property name="wordWrap"> | ||
| 58 | <bool>1</bool> | ||
| 59 | </property> | ||
| 60 | <property name="text"> | 59 | <property name="text"> |
| 61 | <string>We recommend setting accuracy to "Accurate".</string> | 60 | <string>We recommend setting accuracy to "Accurate".</string> |
| 61 | </property> | ||
| 62 | <property name="wordWrap"> | ||
| 63 | <bool>false</bool> | ||
| 62 | </property> | 64 | </property> |
| 63 | </widget> | 65 | </widget> |
| 64 | </item> | 66 | </item> |
| @@ -76,49 +78,49 @@ | |||
| 76 | </property> | 78 | </property> |
| 77 | <layout class="QVBoxLayout"> | 79 | <layout class="QVBoxLayout"> |
| 78 | <item> | 80 | <item> |
| 79 | <widget class="QLabel"> | 81 | <widget class="QLabel" name="label"> |
| 80 | <property name="wordWrap"> | ||
| 81 | <bool>1</bool> | ||
| 82 | </property> | ||
| 83 | <property name="text"> | 82 | <property name="text"> |
| 84 | <string>These settings reduce accuracy for speed.</string> | 83 | <string>These settings reduce accuracy for speed.</string> |
| 85 | </property> | 84 | </property> |
| 85 | <property name="wordWrap"> | ||
| 86 | <bool>false</bool> | ||
| 87 | </property> | ||
| 86 | </widget> | 88 | </widget> |
| 87 | </item> | 89 | </item> |
| 88 | <item> | 90 | <item> |
| 89 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> | 91 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> |
| 90 | <property name="text"> | ||
| 91 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | ||
| 92 | </property> | ||
| 93 | <property name="toolTip"> | 92 | <property name="toolTip"> |
| 94 | <string> | 93 | <string> |
| 95 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> | 94 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> |
| 96 | </string> | 95 | </string> |
| 97 | </property> | 96 | </property> |
| 97 | <property name="text"> | ||
| 98 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | ||
| 99 | </property> | ||
| 98 | </widget> | 100 | </widget> |
| 99 | </item> | 101 | </item> |
| 100 | <item> | 102 | <item> |
| 101 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> | 103 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> |
| 102 | <property name="text"> | ||
| 103 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 104 | </property> | ||
| 105 | <property name="toolTip"> | 104 | <property name="toolTip"> |
| 106 | <string> | 105 | <string> |
| 107 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> | 106 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> |
| 108 | </string> | 107 | </string> |
| 109 | </property> | 108 | </property> |
| 109 | <property name="text"> | ||
| 110 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 111 | </property> | ||
| 110 | </widget> | 112 | </widget> |
| 111 | </item> | 113 | </item> |
| 112 | <item> | 114 | <item> |
| 113 | <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> | 115 | <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> |
| 114 | <property name="text"> | ||
| 115 | <string>Inaccurate NaN handling</string> | ||
| 116 | </property> | ||
| 117 | <property name="toolTip"> | 116 | <property name="toolTip"> |
| 118 | <string> | 117 | <string> |
| 119 | <div>This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.</div> | 118 | <div>This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.</div> |
| 120 | </string> | 119 | </string> |
| 121 | </property> | 120 | </property> |
| 121 | <property name="text"> | ||
| 122 | <string>Inaccurate NaN handling</string> | ||
| 123 | </property> | ||
| 122 | </widget> | 124 | </widget> |
| 123 | </item> | 125 | </item> |
| 124 | </layout> | 126 | </layout> |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index d812858b6..c9e60ee08 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | <item> | 23 | <item> |
| 24 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 24 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel" name="label_2"> | 26 | <widget class="QLabel" name="label_1"> |
| 27 | <property name="text"> | 27 | <property name="text"> |
| 28 | <string>Global Log Filter</string> | 28 | <string>Global Log Filter</string> |
| 29 | </property> | 29 | </property> |
| @@ -66,7 +66,7 @@ | |||
| 66 | </widget> | 66 | </widget> |
| 67 | </item> | 67 | </item> |
| 68 | <item> | 68 | <item> |
| 69 | <widget class="QLabel" name="label_3"> | 69 | <widget class="QLabel" name="label_2"> |
| 70 | <property name="font"> | 70 | <property name="font"> |
| 71 | <font> | 71 | <font> |
| 72 | <italic>true</italic> | 72 | <italic>true</italic> |
| @@ -92,7 +92,7 @@ | |||
| 92 | <item> | 92 | <item> |
| 93 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | 93 | <layout class="QHBoxLayout" name="horizontalLayout_4"> |
| 94 | <item> | 94 | <item> |
| 95 | <widget class="QLabel" name="label_4"> | 95 | <widget class="QLabel" name="label_3"> |
| 96 | <property name="text"> | 96 | <property name="text"> |
| 97 | <string>Arguments String</string> | 97 | <string>Arguments String</string> |
| 98 | </property> | 98 | </property> |
| @@ -155,7 +155,7 @@ | |||
| 155 | </widget> | 155 | </widget> |
| 156 | </item> | 156 | </item> |
| 157 | <item> | 157 | <item> |
| 158 | <widget class="QLabel" name="label_5"> | 158 | <widget class="QLabel" name="label_4"> |
| 159 | <property name="font"> | 159 | <property name="font"> |
| 160 | <font> | 160 | <font> |
| 161 | <italic>true</italic> | 161 | <italic>true</italic> |
| @@ -200,7 +200,7 @@ | |||
| 200 | </widget> | 200 | </widget> |
| 201 | </item> | 201 | </item> |
| 202 | <item> | 202 | <item> |
| 203 | <widget class="QLabel" name="label_3"> | 203 | <widget class="QLabel" name="label_5"> |
| 204 | <property name="font"> | 204 | <property name="font"> |
| 205 | <font> | 205 | <font> |
| 206 | <italic>true</italic> | 206 | <italic>true</italic> |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 2fa88dcec..55a6a37bd 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -50,6 +50,9 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void ConfigureGeneral::ApplyConfiguration() { | 52 | void ConfigureGeneral::ApplyConfiguration() { |
| 53 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, | ||
| 54 | use_multi_core); | ||
| 55 | |||
| 53 | if (Settings::IsConfiguringGlobal()) { | 56 | if (Settings::IsConfiguringGlobal()) { |
| 54 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | 57 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); |
| 55 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); | 58 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); |
| @@ -62,13 +65,7 @@ void ConfigureGeneral::ApplyConfiguration() { | |||
| 62 | Qt::Checked); | 65 | Qt::Checked); |
| 63 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | 66 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); |
| 64 | } | 67 | } |
| 65 | if (Settings::values.use_multi_core.UsingGlobal()) { | ||
| 66 | Settings::values.use_multi_core.SetValue(ui->use_multi_core->isChecked()); | ||
| 67 | } | ||
| 68 | } else { | 68 | } else { |
| 69 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, | ||
| 70 | ui->use_multi_core, use_multi_core); | ||
| 71 | |||
| 72 | bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; | 69 | bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; |
| 73 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); | 70 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); |
| 74 | Settings::values.frame_limit.SetGlobal(global_frame_limit); | 71 | Settings::values.frame_limit.SetGlobal(global_frame_limit); |
| @@ -94,6 +91,9 @@ void ConfigureGeneral::RetranslateUI() { | |||
| 94 | 91 | ||
| 95 | void ConfigureGeneral::SetupPerGameUI() { | 92 | void ConfigureGeneral::SetupPerGameUI() { |
| 96 | if (Settings::IsConfiguringGlobal()) { | 93 | if (Settings::IsConfiguringGlobal()) { |
| 94 | // Disables each setting if: | ||
| 95 | // - A game is running (thus settings in use), and | ||
| 96 | // - A non-global setting is applied. | ||
| 97 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); | 97 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); |
| 98 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); | 98 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); |
| 99 | 99 | ||
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 0a7536617..fb9ec093c 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -106,6 +106,19 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ConfigureGraphics::ApplyConfiguration() { | 108 | void ConfigureGraphics::ApplyConfiguration() { |
| 109 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 110 | ui->fullscreen_mode_combobox); | ||
| 111 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 112 | ui->aspect_ratio_combobox); | ||
| 113 | |||
| 114 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 115 | ui->use_disk_shader_cache, use_disk_shader_cache); | ||
| 116 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 117 | ui->use_asynchronous_gpu_emulation, | ||
| 118 | use_asynchronous_gpu_emulation); | ||
| 119 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation, | ||
| 120 | ui->use_nvdec_emulation, use_nvdec_emulation); | ||
| 121 | |||
| 109 | if (Settings::IsConfiguringGlobal()) { | 122 | if (Settings::IsConfiguringGlobal()) { |
| 110 | // Guard if during game and set to game-specific value | 123 | // Guard if during game and set to game-specific value |
| 111 | if (Settings::values.renderer_backend.UsingGlobal()) { | 124 | if (Settings::values.renderer_backend.UsingGlobal()) { |
| @@ -114,22 +127,6 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 114 | if (Settings::values.vulkan_device.UsingGlobal()) { | 127 | if (Settings::values.vulkan_device.UsingGlobal()) { |
| 115 | Settings::values.vulkan_device.SetValue(vulkan_device); | 128 | Settings::values.vulkan_device.SetValue(vulkan_device); |
| 116 | } | 129 | } |
| 117 | if (Settings::values.fullscreen_mode.UsingGlobal()) { | ||
| 118 | Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex()); | ||
| 119 | } | ||
| 120 | if (Settings::values.aspect_ratio.UsingGlobal()) { | ||
| 121 | Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); | ||
| 122 | } | ||
| 123 | if (Settings::values.use_disk_shader_cache.UsingGlobal()) { | ||
| 124 | Settings::values.use_disk_shader_cache.SetValue(ui->use_disk_shader_cache->isChecked()); | ||
| 125 | } | ||
| 126 | if (Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()) { | ||
| 127 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | ||
| 128 | ui->use_asynchronous_gpu_emulation->isChecked()); | ||
| 129 | } | ||
| 130 | if (Settings::values.use_nvdec_emulation.UsingGlobal()) { | ||
| 131 | Settings::values.use_nvdec_emulation.SetValue(ui->use_nvdec_emulation->isChecked()); | ||
| 132 | } | ||
| 133 | if (Settings::values.bg_red.UsingGlobal()) { | 130 | if (Settings::values.bg_red.UsingGlobal()) { |
| 134 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); | 131 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); |
| 135 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); | 132 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); |
| @@ -150,19 +147,6 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 150 | } | 147 | } |
| 151 | } | 148 | } |
| 152 | 149 | ||
| 153 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 154 | ui->fullscreen_mode_combobox); | ||
| 155 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 156 | ui->aspect_ratio_combobox); | ||
| 157 | |||
| 158 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 159 | ui->use_disk_shader_cache, use_disk_shader_cache); | ||
| 160 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 161 | ui->use_asynchronous_gpu_emulation, | ||
| 162 | use_asynchronous_gpu_emulation); | ||
| 163 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation, | ||
| 164 | ui->use_nvdec_emulation, use_nvdec_emulation); | ||
| 165 | |||
| 166 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 150 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 167 | Settings::values.bg_red.SetGlobal(true); | 151 | Settings::values.bg_red.SetGlobal(true); |
| 168 | Settings::values.bg_green.SetGlobal(true); | 152 | Settings::values.bg_green.SetGlobal(true); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index c67609b0e..35bf9c6be 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -54,47 +54,23 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 54 | ui->gpu_accuracy->currentIndex() - | 54 | ui->gpu_accuracy->currentIndex() - |
| 55 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | 55 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); |
| 56 | 56 | ||
| 57 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 58 | ui->anisotropic_filtering_combobox); | ||
| 59 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); | ||
| 60 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | ||
| 61 | ui->use_assembly_shaders, use_assembly_shaders); | ||
| 62 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 63 | ui->use_asynchronous_shaders, | ||
| 64 | use_asynchronous_shaders); | ||
| 65 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 66 | ui->use_fast_gpu_time, use_fast_gpu_time); | ||
| 67 | |||
| 57 | if (Settings::IsConfiguringGlobal()) { | 68 | if (Settings::IsConfiguringGlobal()) { |
| 58 | // Must guard in case of a during-game configuration when set to be game-specific. | 69 | // Must guard in case of a during-game configuration when set to be game-specific. |
| 59 | if (Settings::values.gpu_accuracy.UsingGlobal()) { | 70 | if (Settings::values.gpu_accuracy.UsingGlobal()) { |
| 60 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | 71 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); |
| 61 | } | 72 | } |
| 62 | if (Settings::values.use_vsync.UsingGlobal()) { | ||
| 63 | Settings::values.use_vsync.SetValue(ui->use_vsync->isChecked()); | ||
| 64 | } | ||
| 65 | if (Settings::values.use_assembly_shaders.UsingGlobal()) { | ||
| 66 | Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); | ||
| 67 | } | ||
| 68 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 69 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 70 | ui->use_asynchronous_shaders->isChecked()); | ||
| 71 | } | ||
| 72 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 73 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 74 | ui->use_asynchronous_shaders->isChecked()); | ||
| 75 | } | ||
| 76 | if (Settings::values.use_fast_gpu_time.UsingGlobal()) { | ||
| 77 | Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); | ||
| 78 | } | ||
| 79 | if (Settings::values.max_anisotropy.UsingGlobal()) { | ||
| 80 | Settings::values.max_anisotropy.SetValue( | ||
| 81 | ui->anisotropic_filtering_combobox->currentIndex()); | ||
| 82 | } | ||
| 83 | } else { | 73 | } else { |
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 85 | ui->anisotropic_filtering_combobox); | ||
| 86 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, | ||
| 87 | use_vsync); | ||
| 88 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | ||
| 89 | ui->use_assembly_shaders, use_assembly_shaders); | ||
| 90 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 91 | ui->use_asynchronous_shaders, | ||
| 92 | use_asynchronous_shaders); | ||
| 93 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 94 | ui->use_fast_gpu_time, use_fast_gpu_time); | ||
| 95 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 96 | ui->anisotropic_filtering_combobox); | ||
| 97 | |||
| 98 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 74 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 99 | Settings::values.gpu_accuracy.SetGlobal(true); | 75 | Settings::values.gpu_accuracy.SetGlobal(true); |
| 100 | } else { | 76 | } else { |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index c9318c562..ab3512810 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -153,6 +153,10 @@ QString ButtonToText(const Common::ParamPackage& param) { | |||
| 153 | return QObject::tr("Button %1").arg(button_str); | 153 | return QObject::tr("Button %1").arg(button_str); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | if (param.Has("motion")) { | ||
| 157 | return QObject::tr("SDL Motion"); | ||
| 158 | } | ||
| 159 | |||
| 156 | return {}; | 160 | return {}; |
| 157 | } | 161 | } |
| 158 | 162 | ||
| @@ -1245,12 +1249,16 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { | |||
| 1245 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 1249 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; |
| 1246 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 1250 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); |
| 1247 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 1251 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); |
| 1252 | auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); | ||
| 1248 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { | 1253 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { |
| 1249 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | 1254 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; |
| 1250 | } | 1255 | } |
| 1251 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { | 1256 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { |
| 1252 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | 1257 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; |
| 1253 | } | 1258 | } |
| 1259 | for (std::size_t i = 0; i < motions_param.size(); ++i) { | ||
| 1260 | motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]; | ||
| 1261 | } | ||
| 1254 | 1262 | ||
| 1255 | UpdateUI(); | 1263 | UpdateUI(); |
| 1256 | } | 1264 | } |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index bd91ebc42..f550567e2 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -52,6 +52,7 @@ ConfigurePerGame::~ConfigurePerGame() = default; | |||
| 52 | void ConfigurePerGame::ApplyConfiguration() { | 52 | void ConfigurePerGame::ApplyConfiguration() { |
| 53 | ui->addonsTab->ApplyConfiguration(); | 53 | ui->addonsTab->ApplyConfiguration(); |
| 54 | ui->generalTab->ApplyConfiguration(); | 54 | ui->generalTab->ApplyConfiguration(); |
| 55 | ui->cpuTab->ApplyConfiguration(); | ||
| 55 | ui->systemTab->ApplyConfiguration(); | 56 | ui->systemTab->ApplyConfiguration(); |
| 56 | ui->graphicsTab->ApplyConfiguration(); | 57 | ui->graphicsTab->ApplyConfiguration(); |
| 57 | ui->graphicsAdvancedTab->ApplyConfiguration(); | 58 | ui->graphicsAdvancedTab->ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index 25975b3b9..adf6d0b39 100644 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -235,6 +235,11 @@ | |||
| 235 | <string>System</string> | 235 | <string>System</string> |
| 236 | </attribute> | 236 | </attribute> |
| 237 | </widget> | 237 | </widget> |
| 238 | <widget class="ConfigureCpu" name="cpuTab"> | ||
| 239 | <attribute name="title"> | ||
| 240 | <string>CPU</string> | ||
| 241 | </attribute> | ||
| 242 | </widget> | ||
| 238 | <widget class="ConfigureGraphics" name="graphicsTab"> | 243 | <widget class="ConfigureGraphics" name="graphicsTab"> |
| 239 | <attribute name="title"> | 244 | <attribute name="title"> |
| 240 | <string>Graphics</string> | 245 | <string>Graphics</string> |
| @@ -311,6 +316,12 @@ | |||
| 311 | <header>configuration/configure_per_game_addons.h</header> | 316 | <header>configuration/configure_per_game_addons.h</header> |
| 312 | <container>1</container> | 317 | <container>1</container> |
| 313 | </customwidget> | 318 | </customwidget> |
| 319 | <customwidget> | ||
| 320 | <class>ConfigureCpu</class> | ||
| 321 | <extends>QWidget</extends> | ||
| 322 | <header>configuration/configure_cpu.h</header> | ||
| 323 | <container>1</container> | ||
| 324 | </customwidget> | ||
| 314 | </customwidgets> | 325 | </customwidgets> |
| 315 | <resources/> | 326 | <resources/> |
| 316 | <connections> | 327 | <connections> |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 268ed44c3..85418f969 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -65,7 +65,7 @@ void ConfigureSystem::SetConfiguration() { | |||
| 65 | QStringLiteral("%1") | 65 | QStringLiteral("%1") |
| 66 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) | 66 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) |
| 67 | .toUpper(); | 67 | .toUpper(); |
| 68 | const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( | 68 | const auto rtc_time = Settings::values.custom_rtc.value_or( |
| 69 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); | 69 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); |
| 70 | 70 | ||
| 71 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); | 71 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); |
| @@ -73,9 +73,8 @@ void ConfigureSystem::SetConfiguration() { | |||
| 73 | Settings::values.rng_seed.UsingGlobal()); | 73 | Settings::values.rng_seed.UsingGlobal()); |
| 74 | ui->rng_seed_edit->setText(rng_seed); | 74 | ui->rng_seed_edit->setText(rng_seed); |
| 75 | 75 | ||
| 76 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value()); | 76 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value()); |
| 77 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() && | 77 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.has_value()); |
| 78 | Settings::values.rng_seed.UsingGlobal()); | ||
| 79 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); | 78 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); |
| 80 | 79 | ||
| 81 | if (Settings::IsConfiguringGlobal()) { | 80 | if (Settings::IsConfiguringGlobal()) { |
| @@ -109,17 +108,17 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 109 | 108 | ||
| 110 | // Allow setting custom RTC even if system is powered on, | 109 | // Allow setting custom RTC even if system is powered on, |
| 111 | // to allow in-game time to be fast forwarded | 110 | // to allow in-game time to be fast forwarded |
| 112 | if (Settings::values.custom_rtc.UsingGlobal()) { | 111 | if (Settings::IsConfiguringGlobal()) { |
| 113 | if (ui->custom_rtc_checkbox->isChecked()) { | 112 | if (ui->custom_rtc_checkbox->isChecked()) { |
| 114 | Settings::values.custom_rtc.SetValue( | 113 | Settings::values.custom_rtc = |
| 115 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | 114 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()); |
| 116 | if (system.IsPoweredOn()) { | 115 | if (system.IsPoweredOn()) { |
| 117 | const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() + | 116 | const s64 posix_time{Settings::values.custom_rtc->count() + |
| 118 | Service::Time::TimeManager::GetExternalTimeZoneOffset()}; | 117 | Service::Time::TimeManager::GetExternalTimeZoneOffset()}; |
| 119 | system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); | 118 | system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); |
| 120 | } | 119 | } |
| 121 | } else { | 120 | } else { |
| 122 | Settings::values.custom_rtc.SetValue(std::nullopt); | 121 | Settings::values.custom_rtc = std::nullopt; |
| 123 | } | 122 | } |
| 124 | } | 123 | } |
| 125 | 124 | ||
| @@ -127,21 +126,14 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 127 | return; | 126 | return; |
| 128 | } | 127 | } |
| 129 | 128 | ||
| 129 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, ui->combo_language); | ||
| 130 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | ||
| 131 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 132 | ui->combo_time_zone); | ||
| 133 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | ||
| 134 | |||
| 130 | if (Settings::IsConfiguringGlobal()) { | 135 | if (Settings::IsConfiguringGlobal()) { |
| 131 | // Guard if during game and set to game-specific value | 136 | // Guard if during game and set to game-specific value |
| 132 | if (Settings::values.language_index.UsingGlobal()) { | ||
| 133 | Settings::values.language_index.SetValue(ui->combo_language->currentIndex()); | ||
| 134 | } | ||
| 135 | if (Settings::values.region_index.UsingGlobal()) { | ||
| 136 | Settings::values.region_index.SetValue(ui->combo_region->currentIndex()); | ||
| 137 | } | ||
| 138 | if (Settings::values.time_zone_index.UsingGlobal()) { | ||
| 139 | Settings::values.time_zone_index.SetValue(ui->combo_time_zone->currentIndex()); | ||
| 140 | } | ||
| 141 | if (Settings::values.sound_index.UsingGlobal()) { | ||
| 142 | Settings::values.sound_index.SetValue(ui->combo_sound->currentIndex()); | ||
| 143 | } | ||
| 144 | |||
| 145 | if (Settings::values.rng_seed.UsingGlobal()) { | 137 | if (Settings::values.rng_seed.UsingGlobal()) { |
| 146 | if (ui->rng_seed_checkbox->isChecked()) { | 138 | if (ui->rng_seed_checkbox->isChecked()) { |
| 147 | Settings::values.rng_seed.SetValue( | 139 | Settings::values.rng_seed.SetValue( |
| @@ -151,13 +143,6 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 151 | } | 143 | } |
| 152 | } | 144 | } |
| 153 | } else { | 145 | } else { |
| 154 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, | ||
| 155 | ui->combo_language); | ||
| 156 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | ||
| 157 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 158 | ui->combo_time_zone); | ||
| 159 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | ||
| 160 | |||
| 161 | switch (use_rng_seed) { | 146 | switch (use_rng_seed) { |
| 162 | case ConfigurationShared::CheckState::On: | 147 | case ConfigurationShared::CheckState::On: |
| 163 | case ConfigurationShared::CheckState::Off: | 148 | case ConfigurationShared::CheckState::Off: |
| @@ -177,26 +162,6 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 177 | case ConfigurationShared::CheckState::Count: | 162 | case ConfigurationShared::CheckState::Count: |
| 178 | break; | 163 | break; |
| 179 | } | 164 | } |
| 180 | |||
| 181 | switch (use_custom_rtc) { | ||
| 182 | case ConfigurationShared::CheckState::On: | ||
| 183 | case ConfigurationShared::CheckState::Off: | ||
| 184 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 185 | if (ui->custom_rtc_checkbox->isChecked()) { | ||
| 186 | Settings::values.custom_rtc.SetValue( | ||
| 187 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | ||
| 188 | } else { | ||
| 189 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 190 | } | ||
| 191 | break; | ||
| 192 | case ConfigurationShared::CheckState::Global: | ||
| 193 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 194 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 195 | Settings::values.custom_rtc.SetGlobal(true); | ||
| 196 | break; | ||
| 197 | case ConfigurationShared::CheckState::Count: | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | 165 | } |
| 201 | 166 | ||
| 202 | system.ApplySettings(); | 167 | system.ApplySettings(); |
| @@ -227,8 +192,6 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 227 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); | 192 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); |
| 228 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); | 193 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); |
| 229 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); | 194 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); |
| 230 | ui->custom_rtc_checkbox->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 231 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 232 | 195 | ||
| 233 | return; | 196 | return; |
| 234 | } | 197 | } |
| @@ -246,8 +209,7 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 246 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), | 209 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), |
| 247 | Settings::values.rng_seed.GetValue().has_value(), | 210 | Settings::values.rng_seed.GetValue().has_value(), |
| 248 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); | 211 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); |
| 249 | ConfigurationShared::SetColoredTristate( | 212 | |
| 250 | ui->custom_rtc_checkbox, Settings::values.custom_rtc.UsingGlobal(), | 213 | ui->custom_rtc_checkbox->setVisible(false); |
| 251 | Settings::values.custom_rtc.GetValue().has_value(), | 214 | ui->custom_rtc_edit->setVisible(false); |
| 252 | Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc); | ||
| 253 | } | 215 | } |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index f35c89e04..0cdaea8a4 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -46,6 +46,7 @@ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::Configur | |||
| 46 | SetConfiguration(); | 46 | SetConfiguration(); |
| 47 | 47 | ||
| 48 | // Force game list reload if any of the relevant settings are changed. | 48 | // Force game list reload if any of the relevant settings are changed. |
| 49 | connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); | ||
| 49 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 50 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
| 50 | &ConfigureUi::RequestGameListUpdate); | 51 | &ConfigureUi::RequestGameListUpdate); |
| 51 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 52 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 3bca6277b..bdfda6c54 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -12,12 +12,13 @@ | |||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "core/arm/arm_interface.h" | 13 | #include "core/arm/arm_interface.h" |
| 14 | #include "core/core.h" | 14 | #include "core/core.h" |
| 15 | #include "core/hle/kernel/handle_table.h" | 15 | #include "core/hle/kernel/k_class_token.h" |
| 16 | #include "core/hle/kernel/k_handle_table.h" | ||
| 17 | #include "core/hle/kernel/k_process.h" | ||
| 16 | #include "core/hle/kernel/k_readable_event.h" | 18 | #include "core/hle/kernel/k_readable_event.h" |
| 17 | #include "core/hle/kernel/k_scheduler.h" | 19 | #include "core/hle/kernel/k_scheduler.h" |
| 18 | #include "core/hle/kernel/k_synchronization_object.h" | 20 | #include "core/hle/kernel/k_synchronization_object.h" |
| 19 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 20 | #include "core/hle/kernel/process.h" | ||
| 21 | #include "core/hle/kernel/svc_common.h" | 22 | #include "core/hle/kernel/svc_common.h" |
| 22 | #include "core/hle/kernel/svc_types.h" | 23 | #include "core/hle/kernel/svc_types.h" |
| 23 | #include "core/memory.h" | 24 | #include "core/memory.h" |
| @@ -91,7 +92,7 @@ std::size_t WaitTreeItem::Row() const { | |||
| 91 | std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() { | 92 | std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() { |
| 92 | std::vector<std::unique_ptr<WaitTreeThread>> item_list; | 93 | std::vector<std::unique_ptr<WaitTreeThread>> item_list; |
| 93 | std::size_t row = 0; | 94 | std::size_t row = 0; |
| 94 | auto add_threads = [&](const std::vector<std::shared_ptr<Kernel::KThread>>& threads) { | 95 | auto add_threads = [&](const std::vector<Kernel::KThread*>& threads) { |
| 95 | for (std::size_t i = 0; i < threads.size(); ++i) { | 96 | for (std::size_t i = 0; i < threads.size(); ++i) { |
| 96 | if (threads[i]->GetThreadTypeForDebugging() == Kernel::ThreadType::User) { | 97 | if (threads[i]->GetThreadTypeForDebugging() == Kernel::ThreadType::User) { |
| 97 | item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i])); | 98 | item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i])); |
| @@ -114,11 +115,11 @@ QString WaitTreeText::GetText() const { | |||
| 114 | return text; | 115 | return text; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table) | 118 | WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table) |
| 118 | : mutex_address(mutex_address) { | 119 | : mutex_address(mutex_address) { |
| 119 | mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); | 120 | mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); |
| 120 | owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); | 121 | owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); |
| 121 | owner = handle_table.Get<Kernel::KThread>(owner_handle); | 122 | owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe(); |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 124 | WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; | 125 | WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; |
| @@ -183,18 +184,20 @@ bool WaitTreeExpandableItem::IsExpandable() const { | |||
| 183 | } | 184 | } |
| 184 | 185 | ||
| 185 | QString WaitTreeSynchronizationObject::GetText() const { | 186 | QString WaitTreeSynchronizationObject::GetText() const { |
| 186 | return tr("[%1]%2 %3") | 187 | return tr("[%1] %2 %3") |
| 187 | .arg(object.GetObjectId()) | 188 | .arg(object.GetId()) |
| 188 | .arg(QString::fromStdString(object.GetTypeName()), | 189 | .arg(QString::fromStdString(object.GetTypeObj().GetName()), |
| 189 | QString::fromStdString(object.GetName())); | 190 | QString::fromStdString(object.GetName())); |
| 190 | } | 191 | } |
| 191 | 192 | ||
| 192 | std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make( | 193 | std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make( |
| 193 | const Kernel::KSynchronizationObject& object) { | 194 | const Kernel::KSynchronizationObject& object) { |
| 194 | switch (object.GetHandleType()) { | 195 | const auto type = |
| 195 | case Kernel::HandleType::ReadableEvent: | 196 | static_cast<Kernel::KClassTokenGenerator::ObjectType>(object.GetTypeObj().GetClassToken()); |
| 197 | switch (type) { | ||
| 198 | case Kernel::KClassTokenGenerator::ObjectType::KReadableEvent: | ||
| 196 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object)); | 199 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object)); |
| 197 | case Kernel::HandleType::Thread: | 200 | case Kernel::KClassTokenGenerator::ObjectType::KThread: |
| 198 | return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object)); | 201 | return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object)); |
| 199 | default: | 202 | default: |
| 200 | return std::make_unique<WaitTreeSynchronizationObject>(object); | 203 | return std::make_unique<WaitTreeSynchronizationObject>(object); |
| @@ -204,12 +207,13 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma | |||
| 204 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const { | 207 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const { |
| 205 | std::vector<std::unique_ptr<WaitTreeItem>> list; | 208 | std::vector<std::unique_ptr<WaitTreeItem>> list; |
| 206 | 209 | ||
| 207 | const auto& threads = object.GetWaitingThreadsForDebugging(); | 210 | auto threads = object.GetWaitingThreadsForDebugging(); |
| 208 | if (threads.empty()) { | 211 | if (threads.empty()) { |
| 209 | list.push_back(std::make_unique<WaitTreeText>(tr("waited by no thread"))); | 212 | list.push_back(std::make_unique<WaitTreeText>(tr("waited by no thread"))); |
| 210 | } else { | 213 | } else { |
| 211 | list.push_back(std::make_unique<WaitTreeThreadList>(threads)); | 214 | list.push_back(std::make_unique<WaitTreeThreadList>(std::move(threads))); |
| 212 | } | 215 | } |
| 216 | |||
| 213 | return list; | 217 | return list; |
| 214 | } | 218 | } |
| 215 | 219 | ||
| @@ -377,8 +381,8 @@ WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object) | |||
| 377 | : WaitTreeSynchronizationObject(object) {} | 381 | : WaitTreeSynchronizationObject(object) {} |
| 378 | WaitTreeEvent::~WaitTreeEvent() = default; | 382 | WaitTreeEvent::~WaitTreeEvent() = default; |
| 379 | 383 | ||
| 380 | WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::KThread*>& list) | 384 | WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list) |
| 381 | : thread_list(list) {} | 385 | : thread_list(std::move(list)) {} |
| 382 | WaitTreeThreadList::~WaitTreeThreadList() = default; | 386 | WaitTreeThreadList::~WaitTreeThreadList() = default; |
| 383 | 387 | ||
| 384 | QString WaitTreeThreadList::GetText() const { | 388 | QString WaitTreeThreadList::GetText() const { |
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 3da2fdfd2..d450345df 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h | |||
| @@ -11,13 +11,15 @@ | |||
| 11 | #include <QAbstractItemModel> | 11 | #include <QAbstractItemModel> |
| 12 | #include <QDockWidget> | 12 | #include <QDockWidget> |
| 13 | #include <QTreeView> | 13 | #include <QTreeView> |
| 14 | |||
| 14 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 15 | #include "core/hle/kernel/object.h" | 16 | #include "core/hle/kernel/k_auto_object.h" |
| 17 | #include "core/hle/kernel/svc_common.h" | ||
| 16 | 18 | ||
| 17 | class EmuThread; | 19 | class EmuThread; |
| 18 | 20 | ||
| 19 | namespace Kernel { | 21 | namespace Kernel { |
| 20 | class HandleTable; | 22 | class KHandleTable; |
| 21 | class KReadableEvent; | 23 | class KReadableEvent; |
| 22 | class KSynchronizationObject; | 24 | class KSynchronizationObject; |
| 23 | class KThread; | 25 | class KThread; |
| @@ -73,17 +75,17 @@ public: | |||
| 73 | class WaitTreeMutexInfo : public WaitTreeExpandableItem { | 75 | class WaitTreeMutexInfo : public WaitTreeExpandableItem { |
| 74 | Q_OBJECT | 76 | Q_OBJECT |
| 75 | public: | 77 | public: |
| 76 | explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table); | 78 | explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table); |
| 77 | ~WaitTreeMutexInfo() override; | 79 | ~WaitTreeMutexInfo() override; |
| 78 | 80 | ||
| 79 | QString GetText() const override; | 81 | QString GetText() const override; |
| 80 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 82 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
| 81 | 83 | ||
| 82 | private: | 84 | private: |
| 83 | VAddr mutex_address; | 85 | VAddr mutex_address{}; |
| 84 | u32 mutex_value; | 86 | u32 mutex_value{}; |
| 85 | Kernel::Handle owner_handle; | 87 | Kernel::Handle owner_handle{}; |
| 86 | std::shared_ptr<Kernel::KThread> owner; | 88 | Kernel::KThread* owner{}; |
| 87 | }; | 89 | }; |
| 88 | 90 | ||
| 89 | class WaitTreeCallstack : public WaitTreeExpandableItem { | 91 | class WaitTreeCallstack : public WaitTreeExpandableItem { |
| @@ -149,14 +151,14 @@ public: | |||
| 149 | class WaitTreeThreadList : public WaitTreeExpandableItem { | 151 | class WaitTreeThreadList : public WaitTreeExpandableItem { |
| 150 | Q_OBJECT | 152 | Q_OBJECT |
| 151 | public: | 153 | public: |
| 152 | explicit WaitTreeThreadList(const std::vector<Kernel::KThread*>& list); | 154 | explicit WaitTreeThreadList(std::vector<Kernel::KThread*>&& list); |
| 153 | ~WaitTreeThreadList() override; | 155 | ~WaitTreeThreadList() override; |
| 154 | 156 | ||
| 155 | QString GetText() const override; | 157 | QString GetText() const override; |
| 156 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 158 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
| 157 | 159 | ||
| 158 | private: | 160 | private: |
| 159 | const std::vector<Kernel::KThread*>& thread_list; | 161 | std::vector<Kernel::KThread*> thread_list; |
| 160 | }; | 162 | }; |
| 161 | 163 | ||
| 162 | class WaitTreeModel : public QAbstractItemModel { | 164 | class WaitTreeModel : public QAbstractItemModel { |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 48b78d65f..63cf82f7d 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -85,8 +85,8 @@ void GameListSearchField::setFilterResult(int visible, int total) { | |||
| 85 | label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); | 85 | label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | bool GameListSearchField::isEmpty() const { | 88 | QString GameListSearchField::filterText() const { |
| 89 | return edit_filter->text().isEmpty(); | 89 | return edit_filter->text(); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | QString GameList::GetLastFilterResultItem() const { | 92 | QString GameList::GetLastFilterResultItem() const { |
| @@ -236,9 +236,9 @@ void GameList::OnTextChanged(const QString& new_text) { | |||
| 236 | } else { | 236 | } else { |
| 237 | tree_view->setRowHidden(j, folder_index, true); | 237 | tree_view->setRowHidden(j, folder_index, true); |
| 238 | } | 238 | } |
| 239 | search_field->setFilterResult(result_count, children_total); | ||
| 240 | } | 239 | } |
| 241 | } | 240 | } |
| 241 | search_field->setFilterResult(result_count, children_total); | ||
| 242 | } | 242 | } |
| 243 | } | 243 | } |
| 244 | 244 | ||
| @@ -595,6 +595,7 @@ void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 595 | connect(delete_dir, &QAction::triggered, [this, &game_dir, selected] { | 595 | connect(delete_dir, &QAction::triggered, [this, &game_dir, selected] { |
| 596 | UISettings::values.game_dirs.removeOne(game_dir); | 596 | UISettings::values.game_dirs.removeOne(game_dir); |
| 597 | item_model->invisibleRootItem()->removeRow(selected.row()); | 597 | item_model->invisibleRootItem()->removeRow(selected.row()); |
| 598 | OnTextChanged(search_field->filterText()); | ||
| 598 | }); | 599 | }); |
| 599 | } | 600 | } |
| 600 | 601 | ||
| @@ -622,7 +623,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 622 | // move the treeview items | 623 | // move the treeview items |
| 623 | QList<QStandardItem*> item = item_model->takeRow(row); | 624 | QList<QStandardItem*> item = item_model->takeRow(row); |
| 624 | item_model->invisibleRootItem()->insertRow(row - 1, item); | 625 | item_model->invisibleRootItem()->insertRow(row - 1, item); |
| 625 | tree_view->setExpanded(selected, UISettings::values.game_dirs[game_dir_index].expanded); | 626 | tree_view->setExpanded(selected.sibling(row - 1, 0), |
| 627 | UISettings::values.game_dirs[other_index].expanded); | ||
| 626 | }); | 628 | }); |
| 627 | 629 | ||
| 628 | connect(move_down, &QAction::triggered, [this, selected, row, game_dir_index] { | 630 | connect(move_down, &QAction::triggered, [this, selected, row, game_dir_index] { |
| @@ -637,7 +639,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 637 | // move the treeview items | 639 | // move the treeview items |
| 638 | const QList<QStandardItem*> item = item_model->takeRow(row); | 640 | const QList<QStandardItem*> item = item_model->takeRow(row); |
| 639 | item_model->invisibleRootItem()->insertRow(row + 1, item); | 641 | item_model->invisibleRootItem()->insertRow(row + 1, item); |
| 640 | tree_view->setExpanded(selected, UISettings::values.game_dirs[game_dir_index].expanded); | 642 | tree_view->setExpanded(selected.sibling(row + 1, 0), |
| 643 | UISettings::values.game_dirs[other_index].expanded); | ||
| 641 | }); | 644 | }); |
| 642 | 645 | ||
| 643 | connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { | 646 | connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { |
| @@ -774,7 +777,7 @@ void GameList::RefreshGameDirectory() { | |||
| 774 | void GameList::ToggleFavorite(u64 program_id) { | 777 | void GameList::ToggleFavorite(u64 program_id) { |
| 775 | if (!UISettings::values.favorited_ids.contains(program_id)) { | 778 | if (!UISettings::values.favorited_ids.contains(program_id)) { |
| 776 | tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), | 779 | tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), |
| 777 | !search_field->isEmpty()); | 780 | !search_field->filterText().isEmpty()); |
| 778 | UISettings::values.favorited_ids.append(program_id); | 781 | UISettings::values.favorited_ids.append(program_id); |
| 779 | AddFavorite(program_id); | 782 | AddFavorite(program_id); |
| 780 | item_model->sort(tree_view->header()->sortIndicatorSection(), | 783 | item_model->sort(tree_view->header()->sortIndicatorSection(), |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 7ca8ece23..978d27325 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -346,8 +346,8 @@ class GameListSearchField : public QWidget { | |||
| 346 | public: | 346 | public: |
| 347 | explicit GameListSearchField(GameList* parent = nullptr); | 347 | explicit GameListSearchField(GameList* parent = nullptr); |
| 348 | 348 | ||
| 349 | QString filterText() const; | ||
| 349 | void setFilterResult(int visible, int total); | 350 | void setFilterResult(int visible, int total); |
| 350 | bool isEmpty() const; | ||
| 351 | 351 | ||
| 352 | void clear(); | 352 | void clear(); |
| 353 | void setFocus(); | 353 | void setFocus(); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 5f6cdc0c6..9275cba53 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -92,7 +92,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 92 | #include "core/file_sys/romfs.h" | 92 | #include "core/file_sys/romfs.h" |
| 93 | #include "core/file_sys/savedata_factory.h" | 93 | #include "core/file_sys/savedata_factory.h" |
| 94 | #include "core/file_sys/submission_package.h" | 94 | #include "core/file_sys/submission_package.h" |
| 95 | #include "core/hle/kernel/process.h" | 95 | #include "core/hle/kernel/k_process.h" |
| 96 | #include "core/hle/service/am/am.h" | 96 | #include "core/hle/service/am/am.h" |
| 97 | #include "core/hle/service/filesystem/filesystem.h" | 97 | #include "core/hle/service/filesystem/filesystem.h" |
| 98 | #include "core/hle/service/nfp/nfp.h" | 98 | #include "core/hle/service/nfp/nfp.h" |
| @@ -241,14 +241,15 @@ GMainWindow::GMainWindow() | |||
| 241 | ConnectMenuEvents(); | 241 | ConnectMenuEvents(); |
| 242 | ConnectWidgetEvents(); | 242 | ConnectWidgetEvents(); |
| 243 | 243 | ||
| 244 | const auto branch_name = std::string(Common::g_scm_branch); | ||
| 245 | const auto description = std::string(Common::g_scm_desc); | ||
| 244 | const auto build_id = std::string(Common::g_build_id); | 246 | const auto build_id = std::string(Common::g_build_id); |
| 245 | const auto fmt = std::string(Common::g_title_bar_format_idle); | ||
| 246 | const auto yuzu_build_version = | ||
| 247 | fmt::format(fmt.empty() ? "yuzu Development Build" : fmt, std::string{}, std::string{}, | ||
| 248 | std::string{}, std::string{}, std::string{}, build_id); | ||
| 249 | 247 | ||
| 250 | LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", yuzu_build_version, Common::g_scm_branch, | 248 | const auto yuzu_build = fmt::format("yuzu Development Build | {}-{}", branch_name, description); |
| 251 | Common::g_scm_desc); | 249 | const auto override_build = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 250 | const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; | ||
| 251 | |||
| 252 | LOG_INFO(Frontend, "yuzu Version: {}", yuzu_build_version); | ||
| 252 | #ifdef ARCHITECTURE_x86_64 | 253 | #ifdef ARCHITECTURE_x86_64 |
| 253 | const auto& caps = Common::GetCPUCaps(); | 254 | const auto& caps = Common::GetCPUCaps(); |
| 254 | std::string cpu_string = caps.cpu_string; | 255 | std::string cpu_string = caps.cpu_string; |
| @@ -349,7 +350,7 @@ GMainWindow::GMainWindow() | |||
| 349 | continue; | 350 | continue; |
| 350 | } | 351 | } |
| 351 | 352 | ||
| 352 | Settings::values.current_user = selected_user; | 353 | Settings::values.current_user = static_cast<s32>(selected_user); |
| 353 | continue; | 354 | continue; |
| 354 | } | 355 | } |
| 355 | 356 | ||
| @@ -574,8 +575,8 @@ void GMainWindow::SoftwareKeyboardExit() { | |||
| 574 | software_keyboard = nullptr; | 575 | software_keyboard = nullptr; |
| 575 | } | 576 | } |
| 576 | 577 | ||
| 577 | void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 578 | void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, |
| 578 | bool is_local) { | 579 | const std::string& additional_args, bool is_local) { |
| 579 | #ifdef YUZU_USE_QT_WEB_ENGINE | 580 | #ifdef YUZU_USE_QT_WEB_ENGINE |
| 580 | 581 | ||
| 581 | if (disable_web_applet) { | 582 | if (disable_web_applet) { |
| @@ -596,13 +597,15 @@ void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_v | |||
| 596 | loading_progress.setRange(0, 3); | 597 | loading_progress.setRange(0, 3); |
| 597 | loading_progress.setValue(0); | 598 | loading_progress.setValue(0); |
| 598 | 599 | ||
| 599 | if (is_local && !Common::FS::Exists(std::string(main_url))) { | 600 | if (is_local && !Common::FS::Exists(main_url)) { |
| 600 | loading_progress.show(); | 601 | loading_progress.show(); |
| 601 | 602 | ||
| 602 | auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); }); | 603 | auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); }); |
| 603 | 604 | ||
| 604 | while (!future.isFinished()) { | 605 | while (!future.isFinished()) { |
| 605 | QCoreApplication::processEvents(); | 606 | QCoreApplication::processEvents(); |
| 607 | |||
| 608 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||
| 606 | } | 609 | } |
| 607 | } | 610 | } |
| 608 | 611 | ||
| @@ -1375,7 +1378,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { | |||
| 1375 | game_list->hide(); | 1378 | game_list->hide(); |
| 1376 | game_list_placeholder->hide(); | 1379 | game_list_placeholder->hide(); |
| 1377 | } | 1380 | } |
| 1378 | status_bar_update_timer.start(2000); | 1381 | status_bar_update_timer.start(500); |
| 1379 | async_status_button->setDisabled(true); | 1382 | async_status_button->setDisabled(true); |
| 1380 | multicore_status_button->setDisabled(true); | 1383 | multicore_status_button->setDisabled(true); |
| 1381 | renderer_status_button->setDisabled(true); | 1384 | renderer_status_button->setDisabled(true); |
| @@ -2099,6 +2102,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2099 | QStringList new_files{}; // Newly installed files that do not yet exist in the NAND | 2102 | QStringList new_files{}; // Newly installed files that do not yet exist in the NAND |
| 2100 | QStringList overwritten_files{}; // Files that overwrote those existing in the NAND | 2103 | QStringList overwritten_files{}; // Files that overwrote those existing in the NAND |
| 2101 | QStringList failed_files{}; // Files that failed to install due to errors | 2104 | QStringList failed_files{}; // Files that failed to install due to errors |
| 2105 | bool detected_base_install{}; // Whether a base game was attempted to be installed | ||
| 2102 | 2106 | ||
| 2103 | ui.action_Install_File_NAND->setEnabled(false); | 2107 | ui.action_Install_File_NAND->setEnabled(false); |
| 2104 | 2108 | ||
| @@ -2124,6 +2128,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2124 | 2128 | ||
| 2125 | while (!future.isFinished()) { | 2129 | while (!future.isFinished()) { |
| 2126 | QCoreApplication::processEvents(); | 2130 | QCoreApplication::processEvents(); |
| 2131 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||
| 2127 | } | 2132 | } |
| 2128 | 2133 | ||
| 2129 | result = future.result(); | 2134 | result = future.result(); |
| @@ -2144,6 +2149,10 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2144 | case InstallResult::Failure: | 2149 | case InstallResult::Failure: |
| 2145 | failed_files.append(QFileInfo(file).fileName()); | 2150 | failed_files.append(QFileInfo(file).fileName()); |
| 2146 | break; | 2151 | break; |
| 2152 | case InstallResult::BaseInstallAttempted: | ||
| 2153 | failed_files.append(QFileInfo(file).fileName()); | ||
| 2154 | detected_base_install = true; | ||
| 2155 | break; | ||
| 2147 | } | 2156 | } |
| 2148 | 2157 | ||
| 2149 | --remaining; | 2158 | --remaining; |
| @@ -2151,6 +2160,13 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2151 | 2160 | ||
| 2152 | install_progress->close(); | 2161 | install_progress->close(); |
| 2153 | 2162 | ||
| 2163 | if (detected_base_install) { | ||
| 2164 | QMessageBox::warning( | ||
| 2165 | this, tr("Install Results"), | ||
| 2166 | tr("To avoid possible conflicts, we discourage users from installing base games to the " | ||
| 2167 | "NAND.\nPlease, only use this feature to install updates and DLC.")); | ||
| 2168 | } | ||
| 2169 | |||
| 2154 | const QString install_results = | 2170 | const QString install_results = |
| 2155 | (new_files.isEmpty() ? QString{} | 2171 | (new_files.isEmpty() ? QString{} |
| 2156 | : tr("%n file(s) were newly installed\n", "", new_files.size())) + | 2172 | : tr("%n file(s) were newly installed\n", "", new_files.size())) + |
| @@ -2212,11 +2228,14 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { | |||
| 2212 | const auto res = | 2228 | const auto res = |
| 2213 | Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( | 2229 | Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( |
| 2214 | *nsp, true, qt_raw_copy); | 2230 | *nsp, true, qt_raw_copy); |
| 2215 | if (res == FileSys::InstallResult::Success) { | 2231 | switch (res) { |
| 2232 | case FileSys::InstallResult::Success: | ||
| 2216 | return InstallResult::Success; | 2233 | return InstallResult::Success; |
| 2217 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | 2234 | case FileSys::InstallResult::OverwriteExisting: |
| 2218 | return InstallResult::Overwrite; | 2235 | return InstallResult::Overwrite; |
| 2219 | } else { | 2236 | case FileSys::InstallResult::ErrorBaseInstall: |
| 2237 | return InstallResult::BaseInstallAttempted; | ||
| 2238 | default: | ||
| 2220 | return InstallResult::Failure; | 2239 | return InstallResult::Failure; |
| 2221 | } | 2240 | } |
| 2222 | } | 2241 | } |
| @@ -2749,24 +2768,19 @@ void GMainWindow::MigrateConfigFiles() { | |||
| 2749 | 2768 | ||
| 2750 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, | 2769 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, |
| 2751 | const std::string& title_version) { | 2770 | const std::string& title_version) { |
| 2752 | const auto full_name = std::string(Common::g_build_fullname); | ||
| 2753 | const auto branch_name = std::string(Common::g_scm_branch); | 2771 | const auto branch_name = std::string(Common::g_scm_branch); |
| 2754 | const auto description = std::string(Common::g_scm_desc); | 2772 | const auto description = std::string(Common::g_scm_desc); |
| 2755 | const auto build_id = std::string(Common::g_build_id); | 2773 | const auto build_id = std::string(Common::g_build_id); |
| 2756 | 2774 | ||
| 2757 | const auto date = | 2775 | const auto yuzu_title = fmt::format("yuzu | {}-{}", branch_name, description); |
| 2758 | QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd")).toStdString(); | 2776 | const auto override_title = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 2777 | const auto window_title = override_title.empty() ? yuzu_title : override_title; | ||
| 2759 | 2778 | ||
| 2760 | if (title_name.empty()) { | 2779 | if (title_name.empty()) { |
| 2761 | const auto fmt = std::string(Common::g_title_bar_format_idle); | 2780 | setWindowTitle(QString::fromStdString(window_title)); |
| 2762 | setWindowTitle(QString::fromStdString(fmt::format(fmt.empty() ? "yuzu {0}| {1}-{2}" : fmt, | ||
| 2763 | full_name, branch_name, description, | ||
| 2764 | std::string{}, date, build_id))); | ||
| 2765 | } else { | 2781 | } else { |
| 2766 | const auto fmt = std::string(Common::g_title_bar_format_running); | 2782 | const auto run_title = fmt::format("{} | {} | {}", window_title, title_name, title_version); |
| 2767 | setWindowTitle(QString::fromStdString( | 2783 | setWindowTitle(QString::fromStdString(run_title)); |
| 2768 | fmt::format(fmt.empty() ? "yuzu {0}| {3} | {6} | {1}-{2}" : fmt, full_name, branch_name, | ||
| 2769 | description, title_name, date, build_id, title_version))); | ||
| 2770 | } | 2784 | } |
| 2771 | } | 2785 | } |
| 2772 | 2786 | ||
| @@ -2795,7 +2809,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2795 | } else { | 2809 | } else { |
| 2796 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | 2810 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |
| 2797 | } | 2811 | } |
| 2798 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); | 2812 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); |
| 2799 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); | 2813 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); |
| 2800 | 2814 | ||
| 2801 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); | 2815 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 7f1e50a5b..b3a5033ce 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -76,6 +76,7 @@ enum class InstallResult { | |||
| 76 | Success, | 76 | Success, |
| 77 | Overwrite, | 77 | Overwrite, |
| 78 | Failure, | 78 | Failure, |
| 79 | BaseInstallAttempted, | ||
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 81 | enum class ReinitializeKeyBehavior { | 82 | enum class ReinitializeKeyBehavior { |
| @@ -159,7 +160,7 @@ public slots: | |||
| 159 | void SoftwareKeyboardExit(); | 160 | void SoftwareKeyboardExit(); |
| 160 | void ErrorDisplayDisplayError(QString error_code, QString error_text); | 161 | void ErrorDisplayDisplayError(QString error_code, QString error_text); |
| 161 | void ProfileSelectorSelectProfile(); | 162 | void ProfileSelectorSelectProfile(); |
| 162 | void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 163 | void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args, |
| 163 | bool is_local); | 164 | bool is_local); |
| 164 | void OnAppFocusStateChanged(Qt::ApplicationState state); | 165 | void OnAppFocusStateChanged(Qt::ApplicationState state); |
| 165 | 166 | ||
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 7e1d5f379..38d896d65 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -361,10 +361,10 @@ void Config::ReadValues() { | |||
| 361 | 361 | ||
| 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); | 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); |
| 363 | if (custom_rtc_enabled) { | 363 | if (custom_rtc_enabled) { |
| 364 | Settings::values.custom_rtc.SetValue( | 364 | Settings::values.custom_rtc = |
| 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0))); | 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0)); |
| 366 | } else { | 366 | } else { |
| 367 | Settings::values.custom_rtc.SetValue(std::nullopt); | 367 | Settings::values.custom_rtc = std::nullopt; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | Settings::values.language_index.SetValue( | 370 | Settings::values.language_index.SetValue( |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index d64f81106..06b20c975 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -215,7 +215,7 @@ void EmuWindow_SDL2::WaitEvent() { | |||
| 215 | const auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 215 | const auto results = Core::System::GetInstance().GetAndResetPerfStats(); |
| 216 | const auto title = | 216 | const auto title = |
| 217 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, | 217 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, |
| 218 | Common::g_scm_branch, Common::g_scm_desc, results.game_fps, | 218 | Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, |
| 219 | results.emulation_speed * 100.0); | 219 | results.emulation_speed * 100.0); |
| 220 | SDL_SetWindowTitle(render_window, title.c_str()); | 220 | SDL_SetWindowTitle(render_window, title.c_str()); |
| 221 | last_time = current_time; | 221 | last_time = current_time; |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 4871ac3bb..e2812ca61 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include "core/crypto/key_manager.h" | 27 | #include "core/crypto/key_manager.h" |
| 28 | #include "core/file_sys/registered_cache.h" | 28 | #include "core/file_sys/registered_cache.h" |
| 29 | #include "core/file_sys/vfs_real.h" | 29 | #include "core/file_sys/vfs_real.h" |
| 30 | #include "core/hle/kernel/process.h" | 30 | #include "core/hle/kernel/k_process.h" |
| 31 | #include "core/hle/service/filesystem/filesystem.h" | 31 | #include "core/hle/service/filesystem/filesystem.h" |
| 32 | #include "core/loader/loader.h" | 32 | #include "core/loader/loader.h" |
| 33 | #include "core/telemetry_session.h" | 33 | #include "core/telemetry_session.h" |