Compare commits
280 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
610378faa6 | ||
|
|
39cd6306e6 | ||
|
|
403fc86c11 | ||
|
|
c317504b5f | ||
|
|
5aae61775f | ||
|
|
bea7824bd1 | ||
|
|
7bb2dd75cd | ||
|
|
899fdb9c44 | ||
|
|
f84328934f | ||
|
|
8fad7dc248 | ||
|
|
5b2fa8dd41 | ||
|
|
b869439969 | ||
|
|
158a693111 | ||
|
|
1d829150ee | ||
|
|
01f79d638f | ||
|
|
d418af157a | ||
|
|
e209fff374 | ||
|
|
4a77ceb151 | ||
|
|
71e19153ef | ||
|
|
6c0d902373 | ||
|
|
427bf76e62 | ||
|
|
b848cc5c3f | ||
|
|
afee2bc8fa | ||
|
|
21ed944ff9 | ||
|
|
ae3e51c795 | ||
|
|
2f5808b7ff | ||
|
|
282bdfd1bf | ||
|
|
d8467ca6c0 | ||
|
|
fadcee14f8 | ||
|
|
219d0ba978 | ||
|
|
3a33519598 | ||
|
|
579f4ea4bd | ||
|
|
5daf3abe65 | ||
|
|
36d45b4a7f | ||
|
|
6f1c6e6ba9 | ||
|
|
c3784b2a08 | ||
|
|
596323f89f | ||
|
|
8bd5742349 | ||
|
|
b9251155f8 | ||
|
|
4ce0a650d1 | ||
|
|
91341b421d | ||
|
|
9ad6c26821 | ||
|
|
3fc7aceea7 | ||
|
|
e29f3b87f1 | ||
|
|
839547dc90 | ||
|
|
8af9f3216e | ||
|
|
673d37a7c2 | ||
|
|
4acec5283e | ||
|
|
d09e618bd2 | ||
|
|
e55affe264 | ||
|
|
5f6cd32c9e | ||
|
|
616d0236f5 | ||
|
|
781c1d8df8 | ||
|
|
5fbfc4c19e | ||
|
|
fba301155b | ||
|
|
6f35fb8d26 | ||
|
|
24c0dde958 | ||
|
|
90014ada8f | ||
|
|
bc4b4e3f56 | ||
|
|
d780eab357 | ||
|
|
b0e83f949e | ||
|
|
321c64a122 | ||
|
|
d103e2daf9 | ||
|
|
e401c77351 | ||
|
|
4b5f0af3fd | ||
|
|
f5b41068e6 | ||
|
|
5114819b6b | ||
|
|
7cd43b139a | ||
|
|
4f9d58621c | ||
|
|
7dd7c54add | ||
|
|
db9b80399b | ||
|
|
06f22c3d28 | ||
|
|
9a53173e4d | ||
|
|
9266bad229 | ||
|
|
73666fb262 | ||
|
|
31c0f6ca33 | ||
|
|
c8512839d7 | ||
|
|
4baef7905e | ||
|
|
ab63a193d7 | ||
|
|
1e1ecca691 | ||
|
|
326a449ef0 | ||
|
|
3e07655b1b | ||
|
|
17bf40f405 | ||
|
|
091e141142 | ||
|
|
40314cc586 | ||
|
|
2b3c9c61db | ||
|
|
77e327dd1a | ||
|
|
7b22d61fb1 | ||
|
|
cd973d6037 | ||
|
|
24049591f6 | ||
|
|
1ea8073783 | ||
|
|
a9c3619d26 | ||
|
|
ad85689417 | ||
|
|
6e376c27a3 | ||
|
|
75d8ec1e9f | ||
|
|
5401cf6eb5 | ||
|
|
33a1d790e8 | ||
|
|
e6c4bf52f0 | ||
|
|
9bb6580d89 | ||
|
|
f078b15565 | ||
|
|
c01a872c8e | ||
|
|
4297d2fea2 | ||
|
|
3a7b37238b | ||
|
|
f25d6ebc45 | ||
|
|
b42c3ce21d | ||
|
|
35f46fc079 | ||
|
|
25cd0342c4 | ||
|
|
738cd1896b | ||
|
|
b54bf126f7 | ||
|
|
6d7801deb7 | ||
|
|
d4ee94165f | ||
|
|
ff54d9615f | ||
|
|
22162f906b | ||
|
|
ab808fe7cf | ||
|
|
a606b1448b | ||
|
|
e3c153efa4 | ||
|
|
5601e1cb00 | ||
|
|
f6d5444293 | ||
|
|
371feaa635 | ||
|
|
7f737b022a | ||
|
|
09ab819040 | ||
|
|
44135b011f | ||
|
|
84f7e7e91c | ||
|
|
877cd60b00 | ||
|
|
c2ddda2f51 | ||
|
|
e4d9814ec4 | ||
|
|
7bc07195c5 | ||
|
|
17b0955f9a | ||
|
|
8984abfc76 | ||
|
|
b34b3efbb2 | ||
|
|
2df2b3719a | ||
|
|
8d63ebcb64 | ||
|
|
081ccc6441 | ||
|
|
67f7a6c398 | ||
|
|
db1c4b125f | ||
|
|
d86a9b9a4b | ||
|
|
7a712da2b3 | ||
|
|
62e88d0e74 | ||
|
|
edf3da346f | ||
|
|
fde9b84b21 | ||
|
|
e7c8a0bb23 | ||
|
|
1bb28dfe2c | ||
|
|
e7ca37b1e5 | ||
|
|
3512cae623 | ||
|
|
d180fd7c36 | ||
|
|
35e5a67a83 | ||
|
|
e4318d2207 | ||
|
|
678f73069f | ||
|
|
8e289ade15 | ||
|
|
727f607e00 | ||
|
|
9248442bb2 | ||
|
|
4ab549e62a | ||
|
|
f0f416e85c | ||
|
|
9907302465 | ||
|
|
3428232bca | ||
|
|
74030eb427 | ||
|
|
47b6f522bd | ||
|
|
188cf1aed2 | ||
|
|
e67463df24 | ||
|
|
63b4c8f9f7 | ||
|
|
76abf55f25 | ||
|
|
554c46d186 | ||
|
|
6f307f1521 | ||
|
|
4a6a73e887 | ||
|
|
ae028ddf22 | ||
|
|
eb1e3f19bb | ||
|
|
290afc00d3 | ||
|
|
be4e192903 | ||
|
|
82c867164b | ||
|
|
ec6490f5ad | ||
|
|
472aad69db | ||
|
|
55854c807d | ||
|
|
9bddcdac69 | ||
|
|
a7bbd37f81 | ||
|
|
5798537ce4 | ||
|
|
c9710f6c78 | ||
|
|
7e9163779d | ||
|
|
005b0e68db | ||
|
|
543081e4a1 | ||
|
|
89958e27aa | ||
|
|
6b16f7807e | ||
|
|
eb1ba45c39 | ||
|
|
b1e655f898 | ||
|
|
bbc1800c1b | ||
|
|
e5ca733722 | ||
|
|
9cdf2383e9 | ||
|
|
4bc3c788f5 | ||
|
|
9e2bf49677 | ||
|
|
ab73787d8f | ||
|
|
743428e025 | ||
|
|
0292374807 | ||
|
|
bdd153bc0d | ||
|
|
296fa4e06e | ||
|
|
9141816b10 | ||
|
|
4e2aa50cef | ||
|
|
51ccc29cdd | ||
|
|
0b891c9245 | ||
|
|
1de9e4e121 | ||
|
|
d994466a08 | ||
|
|
e05bfd2f54 | ||
|
|
d9ce179ec2 | ||
|
|
fb3e9314b9 | ||
|
|
25a97e0139 | ||
|
|
a7bbaa4897 | ||
|
|
cf26f375ff | ||
|
|
7d854fbdb0 | ||
|
|
1e2a89d306 | ||
|
|
b2572a56d3 | ||
|
|
25444041d0 | ||
|
|
c57e0b3b24 | ||
|
|
d956fb3c7c | ||
|
|
5b45dfe971 | ||
|
|
a5d9dcf3d9 | ||
|
|
95213270ef | ||
|
|
956171f024 | ||
|
|
73b11f390e | ||
|
|
122eb3cbd0 | ||
|
|
ec19d9594f | ||
|
|
907dfbea71 | ||
|
|
4fda7f1c82 | ||
|
|
fe0acec539 | ||
|
|
ff48f06fb9 | ||
|
|
5f19b66189 | ||
|
|
27f8f3333f | ||
|
|
3c65c8580f | ||
|
|
4e88989435 | ||
|
|
7d2265b6a8 | ||
|
|
ba82bb359b | ||
|
|
d540d284b5 | ||
|
|
862dc2b2b3 | ||
|
|
f134a5e56c | ||
|
|
c20ea89390 | ||
|
|
790a09bc93 | ||
|
|
c1e2063c0d | ||
|
|
878d0225c5 | ||
|
|
871e1c6315 | ||
|
|
a32a7dacf4 | ||
|
|
6e407c02d8 | ||
|
|
d10d480642 | ||
|
|
98c2f0e576 | ||
|
|
0c8594b225 | ||
|
|
eb2624ed65 | ||
|
|
3de38c9a70 | ||
|
|
3843995ceb | ||
|
|
de71a4d70d | ||
|
|
4654fb96b0 | ||
|
|
4d535799eb | ||
|
|
84b4ac5729 | ||
|
|
bed0c3c92a | ||
|
|
7eb4542c1d | ||
|
|
f65f8b9097 | ||
|
|
6fef91ce4c | ||
|
|
a428a843cb | ||
|
|
c4a1d3cbf4 | ||
|
|
e0397f00d0 | ||
|
|
bde6b899a1 | ||
|
|
455e28790a | ||
|
|
519978ce70 | ||
|
|
0821d95399 | ||
|
|
155b99ee55 | ||
|
|
ef2066b272 | ||
|
|
d82fc52cea | ||
|
|
151ab86204 | ||
|
|
4fd655cb46 | ||
|
|
9cb376f8c2 | ||
|
|
beb7305b73 | ||
|
|
b384129c63 | ||
|
|
cd016d3cb5 | ||
|
|
a832aa699f | ||
|
|
bc3efb79cc | ||
|
|
92bc51b66a | ||
|
|
537c6ac8fe | ||
|
|
14e93f133a | ||
|
|
af6290ed12 | ||
|
|
1770503185 | ||
|
|
81ed54d13e | ||
|
|
001675dced | ||
|
|
356e10898f | ||
|
|
0be4e402e2 | ||
|
|
659039ca6d |
@@ -7,7 +7,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
|
||||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=clang-format-10
|
||||
CLANG_FORMAT=clang-format-12
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
stages:
|
||||
- stage: merge
|
||||
displayName: 'merge'
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
stages:
|
||||
- stage: merge
|
||||
displayName: 'merge'
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -28,9 +28,6 @@
|
||||
[submodule "mbedtls"]
|
||||
path = externals/mbedtls
|
||||
url = https://github.com/yuzu-emu/mbedtls
|
||||
[submodule "libzip"]
|
||||
path = externals/libzip/libzip
|
||||
url = https://github.com/nih-at/libzip.git
|
||||
[submodule "xbyak"]
|
||||
path = externals/xbyak
|
||||
url = https://github.com/herumi/xbyak.git
|
||||
|
||||
115
CMakeLists.txt
115
CMakeLists.txt
@@ -29,16 +29,10 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
||||
|
||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||
|
||||
option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON)
|
||||
|
||||
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
|
||||
|
||||
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
|
||||
|
||||
if (NOT ENABLE_WEB_SERVICE)
|
||||
set(YUZU_ENABLE_BOXCAT OFF)
|
||||
endif()
|
||||
|
||||
# Default to a Release build
|
||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
|
||||
@@ -135,7 +129,7 @@ endif()
|
||||
# boost asio's concept usage doesn't play nicely with some compilers yet.
|
||||
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
|
||||
if (MSVC)
|
||||
add_compile_options(/std:c++latest)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++latest>)
|
||||
|
||||
# cubeb and boost still make use of deprecated result_of.
|
||||
add_definitions(-D_HAS_DEPRECATED_RESULT_OF)
|
||||
@@ -243,7 +237,7 @@ yuzu_find_packages()
|
||||
|
||||
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
|
||||
if(ENABLE_QT)
|
||||
set(QT_VERSION 5.12)
|
||||
set(QT_VERSION 5.15)
|
||||
# We want to load the generated conan qt config so that we get the QT_ROOT var so that we can use the official
|
||||
# Qt5Config inside the root folder instead of the conan generated one.
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/qtConfig.cmake)
|
||||
@@ -345,8 +339,8 @@ if(ENABLE_QT)
|
||||
set(QT_PREFIX_HINT)
|
||||
|
||||
if(YUZU_USE_BUNDLED_QT)
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
|
||||
set(QT_BUILD qt-5.12.8-msvc2017_64)
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
||||
set(QT_BUILD qt-5.15.2-msvc2019_64)
|
||||
elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64)
|
||||
set(QT_BUILD qt5_5_15_2)
|
||||
else()
|
||||
@@ -375,7 +369,7 @@ endif()
|
||||
if (ENABLE_SDL2)
|
||||
if (YUZU_USE_BUNDLED_SDL2)
|
||||
# Detect toolchain and platform
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
||||
set(SDL2_VER "SDL2-2.0.16")
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
|
||||
@@ -422,11 +416,6 @@ if (CONAN_REQUIRED_LIBS)
|
||||
endif()
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
|
||||
set(CONAN_LIB_OPTIONS
|
||||
libzip:with_openssl=False
|
||||
libzip:enable_windows_crypto=False
|
||||
)
|
||||
|
||||
conan_check(VERSION 1.24.0 REQUIRED)
|
||||
|
||||
# Manually add iconv to fix a dep conflict between qt and sdl2
|
||||
@@ -473,7 +462,7 @@ if (CONAN_REQUIRED_LIBS)
|
||||
if(ENABLE_QT)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt5 5.15 REQUIRED COMPONENTS Widgets)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
@@ -518,6 +507,10 @@ set(FFmpeg_COMPONENTS
|
||||
avutil
|
||||
swscale)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
Include(FindPkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBVA libva)
|
||||
endif()
|
||||
if (NOT YUZU_USE_BUNDLED_FFMPEG)
|
||||
# Use system installed FFmpeg
|
||||
find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
@@ -540,6 +533,9 @@ endif()
|
||||
|
||||
if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
if (NOT WIN32)
|
||||
# TODO(lat9nq): Move this to externals/ffmpeg/CMakeLists.txt (and move externals/ffmpeg to
|
||||
# externals/ffmpeg/ffmpeg)
|
||||
|
||||
# Build FFmpeg from externals
|
||||
message(STATUS "Using FFmpeg from externals")
|
||||
|
||||
@@ -579,20 +575,23 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
CACHE PATH "Paths to FFmpeg libraries" FORCE)
|
||||
endforeach()
|
||||
|
||||
set(FFmpeg_INCLUDE_DIR
|
||||
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR}"
|
||||
CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
Include(FindPkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBVA libva)
|
||||
pkg_check_modules(CUDA cuda)
|
||||
pkg_check_modules(FFNVCODEC ffnvcodec)
|
||||
pkg_check_modules(VDPAU vdpau)
|
||||
|
||||
set(FFmpeg_HWACCEL_LIBRARIES)
|
||||
set(FFmpeg_HWACCEL_FLAGS)
|
||||
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
|
||||
set(FFmpeg_HWACCEL_LDFLAGS)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
Include(FindPkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBVA libva)
|
||||
endif()
|
||||
if(LIBVA_FOUND)
|
||||
pkg_check_modules(LIBDRM libdrm REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
|
||||
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
|
||||
set(FFmpeg_LIBVA_LIBRARIES
|
||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||
${LIBDRM_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
${LIBVA-DRM_LIBRARIES}
|
||||
@@ -602,11 +601,56 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
--enable-hwaccel=h264_vaapi
|
||||
--enable-hwaccel=vp9_vaapi
|
||||
--enable-libdrm)
|
||||
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
|
||||
${LIBDRM_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIRS}
|
||||
${LIBVA-DRM_INCLUDE_DIRS}
|
||||
${LIBVA-X11_INCLUDE_DIRS}
|
||||
${LIBVA_INCLUDE_DIRS}
|
||||
)
|
||||
message(STATUS "VA-API found")
|
||||
else()
|
||||
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
|
||||
endif()
|
||||
|
||||
if (FFNVCODEC_FOUND AND CUDA_FOUND)
|
||||
list(APPEND FFmpeg_HWACCEL_FLAGS
|
||||
--enable-cuvid
|
||||
--enable-ffnvcodec
|
||||
--enable-nvdec
|
||||
--enable-hwaccel=h264_nvdec
|
||||
--enable-hwaccel=vp9_nvdec
|
||||
--extra-cflags=-I${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||
${FFNVCODEC_LIBRARIES}
|
||||
${CUDA_LIBRARIES}
|
||||
)
|
||||
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
|
||||
${FFNVCODEC_INCLUDE_DIRS}
|
||||
${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND FFmpeg_HWACCEL_LDFLAGS
|
||||
${FFNVCODEC_LDFLAGS}
|
||||
${CUDA_LDFLAGS}
|
||||
)
|
||||
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
|
||||
endif()
|
||||
|
||||
if (VDPAU_FOUND)
|
||||
list(APPEND FFmpeg_HWACCEL_FLAGS
|
||||
--enable-vdpau
|
||||
--enable-hwaccel=h264_vdpau
|
||||
--enable-hwaccel=vp9_vdpau
|
||||
)
|
||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
|
||||
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
|
||||
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
|
||||
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
|
||||
else()
|
||||
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
|
||||
endif()
|
||||
|
||||
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
|
||||
# `--disable-vdpau` is needed to avoid linking issues
|
||||
add_custom_command(
|
||||
@@ -624,7 +668,6 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
--disable-network
|
||||
--disable-postproc
|
||||
--disable-swresample
|
||||
--disable-vdpau
|
||||
--enable-decoder=h264
|
||||
--enable-decoder=vp9
|
||||
--cc="${CMAKE_C_COMPILER}"
|
||||
@@ -653,15 +696,26 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
${FFmpeg_BUILD_DIR}
|
||||
)
|
||||
|
||||
set(FFmpeg_INCLUDE_DIR
|
||||
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
|
||||
CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
|
||||
set(FFmpeg_LDFLAGS
|
||||
"${FFmpeg_HWACCEL_LDFLAGS}"
|
||||
CACHE STRING "FFmpeg linker flags" FORCE)
|
||||
|
||||
# ALL makes this custom target build every time
|
||||
# but it won't actually build if the DEPENDS parameter is up to date
|
||||
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
|
||||
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
|
||||
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
|
||||
set(FFmpeg_LIBRARIES ${FFmpeg_LIBVA_LIBRARIES} ${FFmpeg_BUILD_LIBRARIES}
|
||||
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
|
||||
CACHE PATH "Paths to FFmpeg libraries" FORCE)
|
||||
unset(FFmpeg_BUILD_LIBRARIES)
|
||||
unset(FFmpeg_LIBVA_LIBRARIES)
|
||||
unset(FFmpeg_HWACCEL_FLAGS)
|
||||
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
|
||||
unset(FFmpeg_HWACCEL_LDFLAGS)
|
||||
unset(FFmpeg_HWACCEL_LIBRARIES)
|
||||
|
||||
if (FFmpeg_FOUND)
|
||||
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
|
||||
@@ -670,12 +724,13 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
endif()
|
||||
else() # WIN32
|
||||
# Use yuzu FFmpeg binaries
|
||||
set(FFmpeg_EXT_NAME "ffmpeg-4.3.1")
|
||||
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
|
||||
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
|
||||
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
|
||||
set(FFmpeg_FOUND YES)
|
||||
set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
|
||||
set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
|
||||
set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
|
||||
set(FFmpeg_LIBRARIES
|
||||
${FFmpeg_LIBRARY_DIR}/swscale.lib
|
||||
@@ -714,7 +769,7 @@ endif()
|
||||
# against all the src files. This should be used before making a pull request.
|
||||
# =======================================================================
|
||||
|
||||
set(CLANG_FORMAT_POSTFIX "-10")
|
||||
set(CLANG_FORMAT_POSTFIX "-12")
|
||||
find_program(CLANG_FORMAT
|
||||
NAMES clang-format${CLANG_FORMAT_POSTFIX}
|
||||
clang-format
|
||||
|
||||
@@ -33,6 +33,7 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
Qt5Positioning$<$<CONFIG:Debug>:d>.*
|
||||
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Qml$<$<CONFIG:Debug>:d>.*
|
||||
Qt5QmlModels$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Quick$<$<CONFIG:Debug>:d>.*
|
||||
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
|
||||
|
||||
12
externals/CMakeLists.txt
vendored
12
externals/CMakeLists.txt
vendored
@@ -7,7 +7,9 @@ include(DownloadExternals)
|
||||
# xbyak
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
add_library(xbyak INTERFACE)
|
||||
target_include_directories(xbyak SYSTEM INTERFACE ./xbyak/xbyak)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/xbyak/xbyak DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
target_include_directories(xbyak SYSTEM INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES)
|
||||
endif()
|
||||
|
||||
@@ -19,6 +21,7 @@ target_include_directories(catch-single-include INTERFACE catch/single_include)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
set(DYNARMIC_TESTS OFF)
|
||||
set(DYNARMIC_NO_BUNDLED_FMT ON)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(dynarmic)
|
||||
endif()
|
||||
|
||||
@@ -90,13 +93,6 @@ endif()
|
||||
# Sirit
|
||||
add_subdirectory(sirit)
|
||||
|
||||
# libzip
|
||||
find_package(libzip 1.5)
|
||||
if (NOT libzip_FOUND)
|
||||
message(STATUS "libzip 1.5 or newer not found, falling back to externals")
|
||||
add_subdirectory(libzip EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(OpenSSL 1.1)
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 7946868af4...517e35f845
72
externals/find-modules/Findlibzip.cmake
vendored
72
externals/find-modules/Findlibzip.cmake
vendored
@@ -1,72 +0,0 @@
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_libzip QUIET libzip)
|
||||
|
||||
find_path(libzip_INCLUDE_DIR
|
||||
NAMES zip.h
|
||||
PATHS ${PC_libzip_INCLUDE_DIRS}
|
||||
"$ENV{LIB_DIR}/include"
|
||||
"$ENV{INCLUDE}"
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
find_path(libzip_INCLUDE_DIR_ZIPCONF
|
||||
NAMES zipconf.h
|
||||
HINTS ${PC_libzip_INCLUDE_DIRS}
|
||||
"$ENV{LIB_DIR}/include"
|
||||
"$ENV{LIB_DIR}/lib/libzip/include"
|
||||
"$ENV{LIB}/lib/libzip/include"
|
||||
/usr/local/lib/libzip/include
|
||||
/usr/lib/libzip/include
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
"$ENV{INCLUDE}"
|
||||
)
|
||||
find_library(libzip_LIBRARY
|
||||
NAMES zip
|
||||
PATHS ${PC_libzip_LIBRARY_DIRS}
|
||||
"$ENV{LIB_DIR}/lib" "$ENV{LIB}" /usr/local/lib /usr/lib
|
||||
)
|
||||
|
||||
if (libzip_INCLUDE_DIR_ZIPCONF)
|
||||
FILE(READ "${libzip_INCLUDE_DIR_ZIPCONF}/zipconf.h" _libzip_VERSION_CONTENTS)
|
||||
if (_libzip_VERSION_CONTENTS)
|
||||
STRING(REGEX REPLACE ".*#define LIBZIP_VERSION \"([0-9.]+)\".*" "\\1" libzip_VERSION "${_libzip_VERSION_CONTENTS}")
|
||||
endif()
|
||||
unset(_libzip_VERSION_CONTENTS)
|
||||
endif()
|
||||
|
||||
set(libzip_VERSION ${libzip_VERSION} CACHE STRING "Version number of libzip")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libzip
|
||||
FOUND_VAR libzip_FOUND
|
||||
REQUIRED_VARS
|
||||
libzip_LIBRARY
|
||||
libzip_INCLUDE_DIR
|
||||
libzip_INCLUDE_DIR_ZIPCONF
|
||||
libzip_VERSION
|
||||
VERSION_VAR libzip_VERSION
|
||||
)
|
||||
|
||||
if(libzip_FOUND)
|
||||
set(libzip_LIBRARIES ${libzip_LIBRARY})
|
||||
set(libzip_INCLUDE_DIRS ${libzip_INCLUDE_DIR})
|
||||
set(libzip_DEFINITIONS ${PC_libzip_CFLAGS_OTHER})
|
||||
endif()
|
||||
|
||||
if(libzip_FOUND AND NOT TARGET libzip::libzip)
|
||||
add_library(libzip::libzip UNKNOWN IMPORTED)
|
||||
set_target_properties(libzip::libzip PROPERTIES
|
||||
IMPORTED_LOCATION "${libzip_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_libzip_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${libzip_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
libzip_INCLUDE_DIR
|
||||
libzip_INCLUDE_DIR_ZIPCONF
|
||||
libzip_LIBRARY
|
||||
libzip_VERSION
|
||||
)
|
||||
564
externals/libzip/CMakeLists.txt
vendored
564
externals/libzip/CMakeLists.txt
vendored
@@ -1,564 +0,0 @@
|
||||
# TODO:
|
||||
# create usable libtool .la file
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
|
||||
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libzip")
|
||||
|
||||
PROJECT(libzip C)
|
||||
|
||||
OPTION(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" ON)
|
||||
OPTION(ENABLE_GNUTLS "Enable use of GnuTLS" ON)
|
||||
OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" ON)
|
||||
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
|
||||
OPTION(ENABLE_WINDOWS_CRYPTO "Enable use of Windows cryptography libraries" ON)
|
||||
|
||||
OPTION(ENABLE_BZIP2 "Enable use of BZip2" OFF)
|
||||
OPTION(ENABLE_LZMA "Enable use of LZMA" OFF)
|
||||
|
||||
INCLUDE(CheckFunctionExists)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckTypeSize)
|
||||
INCLUDE(CheckCSourceRuns)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
INCLUDE(CheckStructHasMember)
|
||||
INCLUDE(TestBigEndian)
|
||||
INCLUDE(GNUInstallDirs)
|
||||
IF(ENABLE_COMMONCRYPTO)
|
||||
CHECK_INCLUDE_FILES(CommonCrypto/CommonCrypto.h COMMONCRYPTO_FOUND)
|
||||
ELSE()
|
||||
SET(COMMONCRYPTO_FOUND FALSE)
|
||||
ENDIF()
|
||||
IF(ENABLE_GNUTLS)
|
||||
INCLUDE(FindNettle)
|
||||
INCLUDE(FindGnuTLS)
|
||||
ELSE()
|
||||
SET(GNUTLS_FOUND FALSE)
|
||||
ENDIF()
|
||||
IF(ENABLE_MBEDTLS)
|
||||
FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/aes.h)
|
||||
FIND_LIBRARY(MBEDTLS_LIBRARIES NAMES mbedcrypto)
|
||||
ELSE()
|
||||
SET(MBEDTLS_LIBRARIES FALSE)
|
||||
ENDIF()
|
||||
IF(ENABLE_OPENSSL)
|
||||
INCLUDE(FindOpenSSL)
|
||||
ELSE()
|
||||
SET(OPENSSL_FOUND FALSE)
|
||||
ENDIF()
|
||||
IF(WIN32)
|
||||
IF(ENABLE_WINDOWS_CRYPTO)
|
||||
SET(WINDOWS_CRYPTO_FOUND TRUE)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(WINDOWS_CRYPTO_FOUND FALSE)
|
||||
ENDIF()
|
||||
|
||||
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
OPTION(SHARED_LIB_VERSIONNING "Add SO version in .so build" ON)
|
||||
|
||||
SET(PACKAGE "libzip")
|
||||
SET(PACKAGE_NAME ${PACKAGE})
|
||||
SET(PACKAGE_VERSION_MAJOR "1")
|
||||
SET(PACKAGE_VERSION_MINOR "5")
|
||||
SET(PACKAGE_VERSION_MICRO "2a")
|
||||
#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
|
||||
SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_MICRO}")
|
||||
SET(PACKAGE_VERSION ${VERSION})
|
||||
SET(LIBZIP_VERSION ${PACKAGE_VERSION})
|
||||
SET(LIBZIP_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR})
|
||||
SET(LIBZIP_VERSION_MINOR ${PACKAGE_VERSION_MINOR})
|
||||
SET(LIBZIP_VERSION_MICRO ${PACKAGE_VERSION_MICRO})
|
||||
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
|
||||
SET(ARCHIVE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
|
||||
IF(NOT TARGET dist)
|
||||
ADD_CUSTOM_TARGET(dist
|
||||
COMMAND git config tar.tar.xz.command "xz -c"
|
||||
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.gz HEAD
|
||||
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.xz HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
ADD_CUSTOM_TARGET(distcheck
|
||||
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest 2>/dev/null || true
|
||||
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
|
||||
COMMAND cmake -E tar xf ${ARCHIVE_NAME}.tar.gz
|
||||
COMMAND chmod -R u-w ${ARCHIVE_NAME}
|
||||
COMMAND mkdir ${ARCHIVE_NAME}-build
|
||||
COMMAND mkdir ${ARCHIVE_NAME}-dest
|
||||
COMMAND cd ${ARCHIVE_NAME}-build && cmake -DCMAKE_INSTALL_PREFIX=../${ARCHIVE_NAME}-dest ../${ARCHIVE_NAME}
|
||||
COMMAND cd ${ARCHIVE_NAME}-build && make -j4
|
||||
COMMAND cd ${ARCHIVE_NAME}-build && make test
|
||||
COMMAND cd ${ARCHIVE_NAME}-build && make install
|
||||
# COMMAND cd ${ARCHIVE_NAME}-build && make uninstall
|
||||
# COMMAND if [ `find ${ARCHIVE_NAME}-dest ! -type d | wc -l` -ne 0 ]; then echo leftover files in ${ARCHIVE_NAME}-dest; false; fi
|
||||
COMMAND cd ${ARCHIVE_NAME}-build && make clean
|
||||
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
|
||||
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
|
||||
COMMAND echo "${ARCHIVE_NAME}.tar.gz is ready for distribution."
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
ADD_DEPENDENCIES(distcheck dist)
|
||||
ENDIF(NOT TARGET dist)
|
||||
|
||||
IF(BUILD_SHARED_LIBS)
|
||||
SET(HAVE_SHARED TRUE)
|
||||
ELSE()
|
||||
SET(ZIP_STATIC TRUE)
|
||||
ENDIF()
|
||||
|
||||
# Checks
|
||||
|
||||
CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD)
|
||||
CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE)
|
||||
CHECK_FUNCTION_EXISTS(_dup HAVE__DUP)
|
||||
CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN)
|
||||
CHECK_FUNCTION_EXISTS(_fileno HAVE__FILENO)
|
||||
CHECK_FUNCTION_EXISTS(_open HAVE__OPEN)
|
||||
CHECK_FUNCTION_EXISTS(_setmode HAVE__SETMODE)
|
||||
CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
|
||||
CHECK_FUNCTION_EXISTS(_strdup HAVE__STRDUP)
|
||||
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
|
||||
CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64)
|
||||
CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64)
|
||||
CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK)
|
||||
CHECK_FUNCTION_EXISTS(arc4random HAVE_ARC4RANDOM)
|
||||
CHECK_FUNCTION_EXISTS(clonefile HAVE_CLONEFILE)
|
||||
CHECK_FUNCTION_EXISTS(explicit_bzero HAVE_EXPLICIT_BZERO)
|
||||
CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET)
|
||||
CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO)
|
||||
CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
|
||||
CHECK_FUNCTION_EXISTS(ftello HAVE_FTELLO)
|
||||
CHECK_FUNCTION_EXISTS(getprogname HAVE_GETPROGNAME)
|
||||
CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
|
||||
CHECK_FUNCTION_EXISTS(open HAVE_OPEN)
|
||||
CHECK_FUNCTION_EXISTS(setmode HAVE_SETMODE)
|
||||
CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
|
||||
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
|
||||
CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP)
|
||||
CHECK_FUNCTION_EXISTS(stricmp HAVE_STRICMP)
|
||||
CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL)
|
||||
CHECK_FUNCTION_EXISTS(strtoull HAVE_STRTOULL)
|
||||
|
||||
CHECK_INCLUDE_FILES("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H)
|
||||
CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
|
||||
CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)
|
||||
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
|
||||
|
||||
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H_LIBZIP)
|
||||
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H_LIBZIP)
|
||||
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H_LIBZIP)
|
||||
|
||||
# TODO: fix test
|
||||
# this test does not find __progname even when it exists
|
||||
#CHECK_SYMBOL_EXISTS(__progname stdlib.h HAVE___PROGNAME)
|
||||
|
||||
CHECK_TYPE_SIZE(__int8 __INT8_LIBZIP)
|
||||
CHECK_TYPE_SIZE(int8_t INT8_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(uint8_t UINT8_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(__int16 __INT16_LIBZIP)
|
||||
CHECK_TYPE_SIZE(int16_t INT16_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(uint16_t UINT16_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(__int32 __INT32_LIBZIP)
|
||||
CHECK_TYPE_SIZE(int32_t INT32_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(uint32_t UINT32_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(__int64 __INT64_LIBZIP)
|
||||
CHECK_TYPE_SIZE(int64_t INT64_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE(uint64_t UINT64_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE("short" SHORT_LIBZIP)
|
||||
CHECK_TYPE_SIZE("int" INT_LIBZIP)
|
||||
CHECK_TYPE_SIZE("long" LONG_LIBZIP)
|
||||
CHECK_TYPE_SIZE("long long" LONG_LONG_LIBZIP)
|
||||
CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T)
|
||||
CHECK_TYPE_SIZE("size_t" SIZE_T_LIBZIP)
|
||||
CHECK_TYPE_SIZE("ssize_t" SSIZE_T_LIBZIP)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
int foo(char * _Nullable bar);
|
||||
int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
|
||||
|
||||
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
|
||||
|
||||
#FIND_PACKAGE(ZLIB 1.1.2 REQUIRED)
|
||||
INCLUDE_DIRECTORIES(../zlib/zlib)
|
||||
SET(CMAKE_REQUIRED_INCLUDES ../zlib/zlib)
|
||||
|
||||
IF(ENABLE_BZIP2)
|
||||
FIND_PACKAGE(BZip2)
|
||||
IF(BZIP2_FOUND)
|
||||
SET (HAVE_LIBBZ2 1)
|
||||
|
||||
INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${BZIP2_LIBRARIES})
|
||||
ELSE()
|
||||
MESSAGE(WARNING "-- bzip2 library not found; bzip2 support disabled")
|
||||
ENDIF(BZIP2_FOUND)
|
||||
ENDIF(ENABLE_BZIP2)
|
||||
|
||||
IF(ENABLE_LZMA)
|
||||
FIND_PACKAGE(LibLZMA)
|
||||
IF(LIBLZMA_FOUND)
|
||||
SET (HAVE_LIBLZMA 1)
|
||||
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIR})
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${LIBLZMA_LIBRARY})
|
||||
ELSE()
|
||||
MESSAGE(WARNING "-- lzma library not found; lzma support disabled")
|
||||
ENDIF(LIBLZMA_FOUND)
|
||||
ENDIF(ENABLE_LZMA)
|
||||
|
||||
|
||||
IF (COMMONCRYPTO_FOUND)
|
||||
SET (HAVE_CRYPTO 1)
|
||||
SET (HAVE_COMMONCRYPTO 1)
|
||||
ELSEIF (WINDOWS_CRYPTO_FOUND)
|
||||
SET (HAVE_CRYPTO 1)
|
||||
SET (HAVE_WINDOWS_CRYPTO 1)
|
||||
ELSEIF (GNUTLS_FOUND AND NETTLE_FOUND)
|
||||
SET (HAVE_CRYPTO 1)
|
||||
SET (HAVE_GNUTLS 1)
|
||||
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR} ${NETTLE_INCLUDE_DIR})
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${GNUTLS_LIBRARY} ${NETTLE_LIBRARY})
|
||||
ELSEIF (OPENSSL_FOUND)
|
||||
SET (HAVE_CRYPTO 1)
|
||||
SET (HAVE_OPENSSL 1)
|
||||
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${OPENSSL_LIBRARIES})
|
||||
ELSEIF (MBEDTLS_LIBRARIES)
|
||||
SET (HAVE_CRYPTO 1)
|
||||
SET (HAVE_MBEDTLS 1)
|
||||
INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${MBEDTLS_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
IF (NOT HAVE_CRYPTO)
|
||||
MESSAGE(WARNING "-- neither Common Crypto, GnuTLS, mbed TLS, OpenSSL, nor Windows Cryptography found; AES support disabled")
|
||||
ENDIF()
|
||||
|
||||
IF(MSVC)
|
||||
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS")
|
||||
ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE")
|
||||
ENDIF(MSVC)
|
||||
|
||||
if(WIN32)
|
||||
if(HAVE_WINDOWS_CRYPTO)
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} bcrypt)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
ADD_DEFINITIONS(-DMS_UWP)
|
||||
else(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} advapi32)
|
||||
endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
endif(WIN32)
|
||||
|
||||
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
|
||||
|
||||
# rpath handling: use rpath in installed binaries
|
||||
IF(NOT CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
ENDIF()
|
||||
|
||||
# fixed size integral types
|
||||
|
||||
IF(HAVE_INTTYPES_H_LIBZIP)
|
||||
SET(LIBZIP_TYPES_INCLUDE "#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>")
|
||||
ELSEIF(HAVE_STDINT_H_LIBZIP)
|
||||
SET(LIBZIP_TYPES_INCLUDE "#include <stdint.h>")
|
||||
ELSEIF(HAVE_SYS_TYPES_H_LIBZIP)
|
||||
SET(LIBZIP_TYPES_INCLUDE "#include <sys/types.h>")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_INT8_T_LIBZIP)
|
||||
SET(ZIP_INT8_T int8_t)
|
||||
ELSEIF(HAVE___INT8_LIBZIP)
|
||||
SET(ZIP_INT8_T __int8)
|
||||
ELSE()
|
||||
SET(ZIP_INT8_T "signed char")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_UINT8_T_LIBZIP)
|
||||
SET(ZIP_UINT8_T uint8_t)
|
||||
ELSEIF(HAVE___INT8_LIBZIP)
|
||||
SET(ZIP_UINT8_T "unsigned __int8")
|
||||
ELSE()
|
||||
SET(ZIP_UINT8_T "unsigned char")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_INT16_T_LIBZIP)
|
||||
SET(ZIP_INT16_T int16_t)
|
||||
ELSEIF(HAVE___INT16_LIBZIP)
|
||||
SET(INT16_T_LIBZIP __int16)
|
||||
ELSEIF(SHORT_LIBZIP EQUAL 2)
|
||||
SET(INT16_T_LIBZIP short)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_UINT16_T_LIBZIP)
|
||||
SET(ZIP_UINT16_T uint16_t)
|
||||
ELSEIF(HAVE___INT16_LIBZIP)
|
||||
SET(UINT16_T_LIBZIP "unsigned __int16")
|
||||
ELSEIF(SHORT_LIBZIP EQUAL 2)
|
||||
SET(UINT16_T_LIBZIP "unsigned short")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_INT32_T_LIBZIP)
|
||||
SET(ZIP_INT32_T int32_t)
|
||||
ELSEIF(HAVE___INT32_LIBZIP)
|
||||
SET(ZIP_INT32_T __int32)
|
||||
ELSEIF(INT_LIBZIP EQUAL 4)
|
||||
SET(ZIP_INT32_T int)
|
||||
ELSEIF(LONG_LIBZIP EQUAL 4)
|
||||
SET(ZIP_INT32_T long)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_UINT32_T_LIBZIP)
|
||||
SET(ZIP_UINT32_T uint32_t)
|
||||
ELSEIF(HAVE___INT32_LIBZIP)
|
||||
SET(ZIP_UINT32_T "unsigned __int32")
|
||||
ELSEIF(INT_LIBZIP EQUAL 4)
|
||||
SET(ZIP_UINT32_T "unsigned int")
|
||||
ELSEIF(LONG_LIBZIP EQUAL 4)
|
||||
SET(ZIP_UINT32_T "unsigned long")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_INT64_T_LIBZIP)
|
||||
SET(ZIP_INT64_T int64_t)
|
||||
ELSEIF(HAVE___INT64_LIBZIP)
|
||||
SET(ZIP_INT64_T __int64)
|
||||
ELSEIF(LONG_LIBZIP EQUAL 8)
|
||||
SET(ZIP_INT64_T long)
|
||||
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
|
||||
SET(ZIP_INT64_T "long long")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_UINT64_T_LIBZIP)
|
||||
SET(ZIP_UINT64_T uint64_t)
|
||||
ELSEIF(HAVE___INT64_LIBZIP)
|
||||
SET(ZIP_UINT64_T "unsigned __int64")
|
||||
ELSEIF(LONG_LIBZIP EQUAL 8)
|
||||
SET(ZIP_UINT64_T "unsigned long")
|
||||
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
|
||||
SET(ZIP_UINT64_T "unsigned long long")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_NULLABLE)
|
||||
SET(ZIP_NULLABLE_DEFINES)
|
||||
ELSE()
|
||||
SET(ZIP_NULLABLE_DEFINES "#define _Nullable
|
||||
#define _Nonnull")
|
||||
ENDIF()
|
||||
|
||||
# write out config file
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/config.h)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-zipconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h)
|
||||
|
||||
# installation
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
INSTALL(FILES libzip/lib/zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
SET(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
|
||||
ADD_LIBRARY(zip
|
||||
libzip/lib/zip_add.c
|
||||
libzip/lib/zip_add_dir.c
|
||||
libzip/lib/zip_add_entry.c
|
||||
libzip/lib/zip_algorithm_deflate.c
|
||||
libzip/lib/zip_buffer.c
|
||||
libzip/lib/zip_close.c
|
||||
libzip/lib/zip_delete.c
|
||||
libzip/lib/zip_dir_add.c
|
||||
libzip/lib/zip_dirent.c
|
||||
libzip/lib/zip_discard.c
|
||||
libzip/lib/zip_entry.c
|
||||
libzip/lib/zip_err_str.c
|
||||
libzip/lib/zip_error.c
|
||||
libzip/lib/zip_error_clear.c
|
||||
libzip/lib/zip_error_get.c
|
||||
libzip/lib/zip_error_get_sys_type.c
|
||||
libzip/lib/zip_error_strerror.c
|
||||
libzip/lib/zip_error_to_str.c
|
||||
libzip/lib/zip_extra_field.c
|
||||
libzip/lib/zip_extra_field_api.c
|
||||
libzip/lib/zip_fclose.c
|
||||
libzip/lib/zip_fdopen.c
|
||||
libzip/lib/zip_file_add.c
|
||||
libzip/lib/zip_file_error_clear.c
|
||||
libzip/lib/zip_file_error_get.c
|
||||
libzip/lib/zip_file_get_comment.c
|
||||
libzip/lib/zip_file_get_external_attributes.c
|
||||
libzip/lib/zip_file_get_offset.c
|
||||
libzip/lib/zip_file_rename.c
|
||||
libzip/lib/zip_file_replace.c
|
||||
libzip/lib/zip_file_set_comment.c
|
||||
libzip/lib/zip_file_set_encryption.c
|
||||
libzip/lib/zip_file_set_external_attributes.c
|
||||
libzip/lib/zip_file_set_mtime.c
|
||||
libzip/lib/zip_file_strerror.c
|
||||
libzip/lib/zip_filerange_crc.c
|
||||
libzip/lib/zip_fopen.c
|
||||
libzip/lib/zip_fopen_encrypted.c
|
||||
libzip/lib/zip_fopen_index.c
|
||||
libzip/lib/zip_fopen_index_encrypted.c
|
||||
libzip/lib/zip_fread.c
|
||||
libzip/lib/zip_fseek.c
|
||||
libzip/lib/zip_ftell.c
|
||||
libzip/lib/zip_get_archive_comment.c
|
||||
libzip/lib/zip_get_archive_flag.c
|
||||
libzip/lib/zip_get_encryption_implementation.c
|
||||
libzip/lib/zip_get_file_comment.c
|
||||
libzip/lib/zip_get_name.c
|
||||
libzip/lib/zip_get_num_entries.c
|
||||
libzip/lib/zip_get_num_files.c
|
||||
libzip/lib/zip_hash.c
|
||||
libzip/lib/zip_io_util.c
|
||||
libzip/lib/zip_libzip_version.c
|
||||
libzip/lib/zip_memdup.c
|
||||
libzip/lib/zip_name_locate.c
|
||||
libzip/lib/zip_new.c
|
||||
libzip/lib/zip_open.c
|
||||
libzip/lib/zip_progress.c
|
||||
libzip/lib/zip_rename.c
|
||||
libzip/lib/zip_replace.c
|
||||
libzip/lib/zip_set_archive_comment.c
|
||||
libzip/lib/zip_set_archive_flag.c
|
||||
libzip/lib/zip_set_default_password.c
|
||||
libzip/lib/zip_set_file_comment.c
|
||||
libzip/lib/zip_set_file_compression.c
|
||||
libzip/lib/zip_set_name.c
|
||||
libzip/lib/zip_source_accept_empty.c
|
||||
libzip/lib/zip_source_begin_write.c
|
||||
libzip/lib/zip_source_begin_write_cloning.c
|
||||
libzip/lib/zip_source_buffer.c
|
||||
libzip/lib/zip_source_call.c
|
||||
libzip/lib/zip_source_close.c
|
||||
libzip/lib/zip_source_commit_write.c
|
||||
libzip/lib/zip_source_compress.c
|
||||
libzip/lib/zip_source_crc.c
|
||||
libzip/lib/zip_source_error.c
|
||||
libzip/lib/zip_source_filep.c
|
||||
libzip/lib/zip_source_free.c
|
||||
libzip/lib/zip_source_function.c
|
||||
libzip/lib/zip_source_get_compression_flags.c
|
||||
libzip/lib/zip_source_is_deleted.c
|
||||
libzip/lib/zip_source_layered.c
|
||||
libzip/lib/zip_source_open.c
|
||||
libzip/lib/zip_source_pkware.c
|
||||
libzip/lib/zip_source_read.c
|
||||
libzip/lib/zip_source_remove.c
|
||||
libzip/lib/zip_source_rollback_write.c
|
||||
libzip/lib/zip_source_seek.c
|
||||
libzip/lib/zip_source_seek_write.c
|
||||
libzip/lib/zip_source_stat.c
|
||||
libzip/lib/zip_source_supports.c
|
||||
libzip/lib/zip_source_tell.c
|
||||
libzip/lib/zip_source_tell_write.c
|
||||
libzip/lib/zip_source_window.c
|
||||
libzip/lib/zip_source_write.c
|
||||
libzip/lib/zip_source_zip.c
|
||||
libzip/lib/zip_source_zip_new.c
|
||||
libzip/lib/zip_stat.c
|
||||
libzip/lib/zip_stat_index.c
|
||||
libzip/lib/zip_stat_init.c
|
||||
libzip/lib/zip_strerror.c
|
||||
libzip/lib/zip_string.c
|
||||
libzip/lib/zip_unchange.c
|
||||
libzip/lib/zip_unchange_all.c
|
||||
libzip/lib/zip_unchange_archive.c
|
||||
libzip/lib/zip_unchange_data.c
|
||||
libzip/lib/zip_utf-8.c
|
||||
)
|
||||
|
||||
IF(WIN32)
|
||||
target_sources(zip PRIVATE
|
||||
libzip/lib/zip_source_win32handle.c
|
||||
libzip/lib/zip_source_win32utf8.c
|
||||
libzip/lib/zip_source_win32w.c
|
||||
)
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
ELSE()
|
||||
target_sources(zip PRIVATE libzip/lib/zip_source_win32a.c)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
target_sources(zip PRIVATE
|
||||
libzip/lib/zip_mkstempm.c
|
||||
libzip/lib/zip_source_file.c
|
||||
libzip/lib/zip_random_unix.c
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_LIBBZ2)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_algorithm_bzip2.c)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_LIBLZMA)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_algorithm_xz.c)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_COMMONCRYPTO)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_crypto_commoncrypto.c)
|
||||
ELSEIF(HAVE_WINDOWS_CRYPTO)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_crypto_win.c)
|
||||
ELSEIF(HAVE_GNUTLS)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_crypto_gnutls.c)
|
||||
ELSEIF(HAVE_OPENSSL)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_crypto_openssl.c)
|
||||
ELSEIF(HAVE_MBEDTLS)
|
||||
target_sources(zip PRIVATE libzip/lib/zip_crypto_mbedtls.c)
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_CRYPTO)
|
||||
target_sources(zip PRIVATE
|
||||
libzip/lib/zip_winzip_aes.c
|
||||
libzip/lib/zip_source_winzip_aes_decode.c
|
||||
libzip/lib/zip_source_winzip_aes_encode.c
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
target_include_directories(zip
|
||||
PUBLIC
|
||||
libzip/lib
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libzip
|
||||
)
|
||||
|
||||
# pkgconfig file
|
||||
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(exec_prefix \${prefix})
|
||||
SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
|
||||
SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
|
||||
SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES BSD)
|
||||
SET(PKG_CONFIG_RPATH "-Wl,-R\${libdir}")
|
||||
ENDIF(CMAKE_SYSTEM_NAME MATCHES BSD)
|
||||
get_target_property(LIBS_PRIVATE zip LINK_LIBRARIES)
|
||||
foreach(LIB ${LIBS_PRIVATE})
|
||||
if(LIB MATCHES "^/")
|
||||
get_filename_component(LIB ${LIB} NAME_WE)
|
||||
string(REGEX REPLACE "^lib" "" LIB ${LIB})
|
||||
endif()
|
||||
set(LIBS "${LIBS} -l${LIB}")
|
||||
endforeach()
|
||||
CONFIGURE_FILE(libzip/libzip.pc.in libzip/libzip.pc @ONLY)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
ADD_CUSTOM_TARGET(update_zip_err_str
|
||||
COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip_err_str.c
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh
|
||||
)
|
||||
|
||||
IF(SHARED_LIB_VERSIONNING)
|
||||
SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 5.0 SOVERSION 5)
|
||||
ENDIF()
|
||||
|
||||
TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARIES} ${OPTIONAL_LIBRARY})
|
||||
INSTALL(TARGETS zip
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
1
externals/libzip/libzip
vendored
1
externals/libzip/libzip
vendored
Submodule externals/libzip/libzip deleted from 89bd6d63bd
@@ -2,13 +2,16 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <numbers>
|
||||
|
||||
#include "audio_core/algorithm/interpolate.h"
|
||||
#include "audio_core/command_generator.h"
|
||||
#include "audio_core/effect_context.h"
|
||||
#include "audio_core/mix_context.h"
|
||||
#include "audio_core/voice_context.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "audio_core/behavior_info.h"
|
||||
#include "audio_core/common.h"
|
||||
#include "audio_core/effect_context.h"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "audio_core/behavior_info.h"
|
||||
#include "audio_core/voice_context.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
@@ -53,6 +53,8 @@ add_library(common STATIC
|
||||
div_ceil.h
|
||||
dynamic_library.cpp
|
||||
dynamic_library.h
|
||||
error.cpp
|
||||
error.h
|
||||
fiber.cpp
|
||||
fiber.h
|
||||
fs/file.cpp
|
||||
@@ -77,6 +79,7 @@ add_library(common STATIC
|
||||
logging/filter.cpp
|
||||
logging/filter.h
|
||||
logging/log.h
|
||||
logging/log_entry.h
|
||||
logging/text_formatter.cpp
|
||||
logging/text_formatter.h
|
||||
logging/types.h
|
||||
@@ -88,7 +91,6 @@ add_library(common STATIC
|
||||
microprofile.cpp
|
||||
microprofile.h
|
||||
microprofileui.h
|
||||
misc.cpp
|
||||
nvidia_flags.cpp
|
||||
nvidia_flags.h
|
||||
page_table.cpp
|
||||
|
||||
@@ -9,41 +9,48 @@
|
||||
namespace Common {
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>[[nodiscard]] constexpr T AlignUp(T value, size_t size) {
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignUp(T value, size_t size) {
|
||||
auto mod{static_cast<T>(value % size)};
|
||||
value -= mod;
|
||||
return static_cast<T>(mod == T{0} ? value : value + size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>[[nodiscard]] constexpr T AlignUpLog2(T value, size_t align_log2) {
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignUpLog2(T value, size_t align_log2) {
|
||||
return static_cast<T>((value + ((1ULL << align_log2) - 1)) >> align_log2 << align_log2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>[[nodiscard]] constexpr T AlignDown(T value, size_t size) {
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignDown(T value, size_t size) {
|
||||
return static_cast<T>(value - value % size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>[[nodiscard]] constexpr bool Is4KBAligned(T value) {
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool Is4KBAligned(T value) {
|
||||
return (value & 0xFFF) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>[[nodiscard]] constexpr bool IsWordAligned(T value) {
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool IsWordAligned(T value) {
|
||||
return (value & 0b11) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_integral_v<T>[[nodiscard]] constexpr bool IsAligned(T value, size_t alignment) {
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] constexpr bool IsAligned(T value, size_t alignment) {
|
||||
using U = typename std::make_unsigned_t<T>;
|
||||
const U mask = static_cast<U>(alignment - 1);
|
||||
return (value & mask) == 0;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
requires std::is_integral_v<T>[[nodiscard]] constexpr T DivideUp(T x, U y) {
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] constexpr T DivideUp(T x, U y) {
|
||||
return (x + (y - 1)) / y;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
|
||||
#if !defined(ARCHITECTURE_x86_64)
|
||||
#include <cstdlib> // for exit
|
||||
@@ -49,16 +48,6 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
|
||||
#endif // _MSC_VER ndef
|
||||
|
||||
// Generic function to get last error message.
|
||||
// Call directly after the command or use the error num.
|
||||
// This function might change the error code.
|
||||
// Defined in misc.cpp.
|
||||
[[nodiscard]] std::string GetLastErrorMsg();
|
||||
|
||||
// Like GetLastErrorMsg(), but passing an explicit error code.
|
||||
// Defined in misc.cpp.
|
||||
[[nodiscard]] std::string NativeErrorToString(int e);
|
||||
|
||||
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
|
||||
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
@@ -72,6 +61,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) ^ static_cast<T>(b)); \
|
||||
} \
|
||||
[[nodiscard]] constexpr type operator<<(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) << static_cast<T>(b)); \
|
||||
} \
|
||||
[[nodiscard]] constexpr type operator>>(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) >> static_cast<T>(b)); \
|
||||
} \
|
||||
constexpr type& operator|=(type& a, type b) noexcept { \
|
||||
a = a | b; \
|
||||
return a; \
|
||||
@@ -84,6 +81,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
a = a ^ b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator<<=(type& a, type b) noexcept { \
|
||||
a = a << b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator>>=(type& a, type b) noexcept { \
|
||||
a = a >> b; \
|
||||
return a; \
|
||||
} \
|
||||
[[nodiscard]] constexpr type operator~(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(~static_cast<T>(key)); \
|
||||
|
||||
@@ -11,15 +11,15 @@ namespace Common {
|
||||
|
||||
/// Ceiled integer division.
|
||||
template <typename N, typename D>
|
||||
requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeil(N number,
|
||||
D divisor) {
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
[[nodiscard]] constexpr N DivCeil(N number, D divisor) {
|
||||
return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor);
|
||||
}
|
||||
|
||||
/// Ceiled integer division with logarithmic divisor in base 2
|
||||
template <typename N, typename D>
|
||||
requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeilLog2(
|
||||
N value, D alignment_log2) {
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
[[nodiscard]] constexpr N DivCeilLog2(N value, D alignment_log2) {
|
||||
return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/error.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
std::string NativeErrorToString(int e) {
|
||||
#ifdef _WIN32
|
||||
@@ -50,3 +52,5 @@ std::string GetLastErrorMsg() {
|
||||
return NativeErrorToString(errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
21
src/common/error.h
Normal file
21
src/common/error.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
// Generic function to get last error message.
|
||||
// Call directly after the command or use the error num.
|
||||
// This function might change the error code.
|
||||
// Defined in error.cpp.
|
||||
[[nodiscard]] std::string GetLastErrorMsg();
|
||||
|
||||
// Like GetLastErrorMsg(), but passing an explicit error code.
|
||||
// Defined in error.cpp.
|
||||
[[nodiscard]] std::string NativeErrorToString(int e);
|
||||
|
||||
} // namespace Common
|
||||
@@ -21,6 +21,7 @@
|
||||
#define SCREENSHOTS_DIR "screenshots"
|
||||
#define SDMC_DIR "sdmc"
|
||||
#define SHADER_DIR "shader"
|
||||
#define TAS_DIR "tas"
|
||||
|
||||
// yuzu-specific files
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ private:
|
||||
GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR);
|
||||
GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR);
|
||||
}
|
||||
|
||||
~PathManagerImpl() = default;
|
||||
|
||||
@@ -23,6 +23,7 @@ enum class YuzuPath {
|
||||
ScreenshotsDir, // Where yuzu screenshots are stored.
|
||||
SDMCDir, // Where the emulated SDMC is stored.
|
||||
ShaderDir, // Where shaders are stored.
|
||||
TASDir, // Where TAS scripts are stored.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -314,8 +314,8 @@ private:
|
||||
}
|
||||
|
||||
void UntrackPlaceholder(boost::icl::separate_interval_set<size_t>::iterator it) {
|
||||
placeholders.erase(it);
|
||||
placeholder_host_pointers.erase(it->lower());
|
||||
placeholders.erase(it);
|
||||
}
|
||||
|
||||
/// Return true when a given memory region is a "nieche" and the placeholders don't have to be
|
||||
|
||||
@@ -235,20 +235,19 @@ public:
|
||||
|
||||
template <typename T>
|
||||
concept HasLightCompareType = requires {
|
||||
{ std::is_same<typename T::LightCompareType, void>::value }
|
||||
->std::convertible_to<bool>;
|
||||
{ std::is_same<typename T::LightCompareType, void>::value } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <typename T, typename Default>
|
||||
consteval auto* GetLightCompareType() {
|
||||
if constexpr (HasLightCompareType<T>) {
|
||||
return static_cast<typename T::LightCompareType*>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default*>(nullptr);
|
||||
template <typename T, typename Default>
|
||||
consteval auto* GetLightCompareType() {
|
||||
if constexpr (HasLightCompareType<T>) {
|
||||
return static_cast<typename T::LightCompareType*>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default*>(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
|
||||
@@ -2,42 +2,188 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> // For OutputDebugStringW
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/fs_paths.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/literals.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/log_entry.h"
|
||||
#include "common/logging/text_formatter.h"
|
||||
#include "common/settings.h"
|
||||
#ifdef _WIN32
|
||||
#include "common/string_util.h"
|
||||
#endif
|
||||
#include "common/threadsafe_queue.h"
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Interface for logging backends.
|
||||
*/
|
||||
class Backend {
|
||||
public:
|
||||
virtual ~Backend() = default;
|
||||
|
||||
virtual void Write(const Entry& entry) = 0;
|
||||
|
||||
virtual void EnableForStacktrace() = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr and with color
|
||||
*/
|
||||
class ColorConsoleBackend final : public Backend {
|
||||
public:
|
||||
explicit ColorConsoleBackend() = default;
|
||||
|
||||
~ColorConsoleBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
if (enabled.load(std::memory_order_relaxed)) {
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() override {
|
||||
// stderr shouldn't be buffered
|
||||
}
|
||||
|
||||
void EnableForStacktrace() override {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
void SetEnabled(bool enabled_) {
|
||||
enabled = enabled_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_bool enabled{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to a file passed into the constructor
|
||||
*/
|
||||
class FileBackend final : public Backend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename) {
|
||||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
static_cast<void>(FS::RemoveFile(old_filename));
|
||||
static_cast<void>(FS::RenameFile(filename, old_filename));
|
||||
|
||||
file = std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write,
|
||||
FS::FileType::TextFile);
|
||||
}
|
||||
|
||||
~FileBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB;
|
||||
const bool write_limit_exceeded = bytes_written > write_limit;
|
||||
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
||||
if (write_limit_exceeded) {
|
||||
// Stop writing after the write limit is exceeded.
|
||||
// Don't close the file so we can print a stacktrace if necessary
|
||||
enabled = false;
|
||||
}
|
||||
file->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() override {
|
||||
file->Flush();
|
||||
}
|
||||
|
||||
void EnableForStacktrace() override {
|
||||
enabled = true;
|
||||
bytes_written = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<FS::IOFile> file;
|
||||
bool enabled = true;
|
||||
std::size_t bytes_written = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to Visual Studio's output window
|
||||
*/
|
||||
class DebuggerBackend final : public Backend {
|
||||
public:
|
||||
explicit DebuggerBackend() = default;
|
||||
|
||||
~DebuggerBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
#ifdef _WIN32
|
||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
void EnableForStacktrace() override {}
|
||||
};
|
||||
|
||||
bool initialization_in_progress_suppress_logging = true;
|
||||
|
||||
/**
|
||||
* Static state as a singleton.
|
||||
*/
|
||||
class Impl {
|
||||
public:
|
||||
static Impl& Instance() {
|
||||
static Impl backend;
|
||||
return backend;
|
||||
if (!instance) {
|
||||
throw std::runtime_error("Using Logging instance before its initialization");
|
||||
}
|
||||
return *instance;
|
||||
}
|
||||
|
||||
static void Initialize() {
|
||||
if (instance) {
|
||||
LOG_WARNING(Log, "Reinitializing logging backend");
|
||||
return;
|
||||
}
|
||||
using namespace Common::FS;
|
||||
const auto& log_dir = GetYuzuPath(YuzuPath::LogDir);
|
||||
void(CreateDir(log_dir));
|
||||
Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter),
|
||||
Deleter);
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
Impl(const Impl&) = delete;
|
||||
@@ -46,74 +192,54 @@ public:
|
||||
Impl(Impl&&) = delete;
|
||||
Impl& operator=(Impl&&) = delete;
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string message) {
|
||||
message_queue.Push(
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
|
||||
}
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
backends.push_back(std::move(backend));
|
||||
}
|
||||
|
||||
void RemoveBackend(std::string_view backend_name) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
|
||||
std::erase_if(backends, [&backend_name](const auto& backend) {
|
||||
return backend_name == backend->GetName();
|
||||
});
|
||||
}
|
||||
|
||||
const Filter& GetGlobalFilter() const {
|
||||
return filter;
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& f) {
|
||||
filter = f;
|
||||
}
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name) {
|
||||
const auto it =
|
||||
std::find_if(backends.begin(), backends.end(),
|
||||
[&backend_name](const auto& i) { return backend_name == i->GetName(); });
|
||||
if (it == backends.end())
|
||||
return nullptr;
|
||||
return it->get();
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
color_console_backend.SetEnabled(enabled);
|
||||
}
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string message) {
|
||||
if (!filter.CheckMessage(log_class, log_level))
|
||||
return;
|
||||
const Entry& entry =
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
|
||||
message_queue.Push(entry);
|
||||
}
|
||||
|
||||
private:
|
||||
Impl() {
|
||||
backend_thread = std::thread([&] {
|
||||
Entry entry;
|
||||
auto write_logs = [&](Entry& e) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
for (const auto& backend : backends) {
|
||||
backend->Write(e);
|
||||
}
|
||||
};
|
||||
while (true) {
|
||||
entry = message_queue.PopWait();
|
||||
if (entry.final_entry) {
|
||||
break;
|
||||
}
|
||||
write_logs(entry);
|
||||
}
|
||||
|
||||
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
|
||||
// case where a system is repeatedly spamming logs even on close.
|
||||
const int MAX_LOGS_TO_WRITE = filter.IsDebug() ? INT_MAX : 100;
|
||||
int logs_written = 0;
|
||||
while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) {
|
||||
write_logs(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
||||
: filter{filter_}, file_backend{file_backend_filename}, backend_thread{std::thread([this] {
|
||||
Common::SetCurrentThreadName("yuzu:Log");
|
||||
Entry entry;
|
||||
const auto write_logs = [this, &entry]() {
|
||||
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
|
||||
};
|
||||
while (true) {
|
||||
entry = message_queue.PopWait();
|
||||
if (entry.final_entry) {
|
||||
break;
|
||||
}
|
||||
write_logs();
|
||||
}
|
||||
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
|
||||
// case where a system is repeatedly spamming logs even on close.
|
||||
int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
|
||||
while (max_logs_to_write-- && message_queue.Pop(entry)) {
|
||||
write_logs();
|
||||
}
|
||||
})} {}
|
||||
|
||||
~Impl() {
|
||||
Entry entry;
|
||||
entry.final_entry = true;
|
||||
message_queue.Push(entry);
|
||||
StopBackendThread();
|
||||
}
|
||||
|
||||
void StopBackendThread() {
|
||||
Entry stop_entry{};
|
||||
stop_entry.final_entry = true;
|
||||
message_queue.Push(stop_entry);
|
||||
backend_thread.join();
|
||||
}
|
||||
|
||||
@@ -135,100 +261,51 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
std::mutex writing_mutex;
|
||||
std::thread backend_thread;
|
||||
std::vector<std::unique_ptr<Backend>> backends;
|
||||
MPSCQueue<Entry> message_queue;
|
||||
void ForEachBackend(auto lambda) {
|
||||
lambda(static_cast<Backend&>(debugger_backend));
|
||||
lambda(static_cast<Backend&>(color_console_backend));
|
||||
lambda(static_cast<Backend&>(file_backend));
|
||||
}
|
||||
|
||||
static void Deleter(Impl* ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||
|
||||
Filter filter;
|
||||
DebuggerBackend debugger_backend{};
|
||||
ColorConsoleBackend color_console_backend{};
|
||||
FileBackend file_backend;
|
||||
|
||||
std::thread backend_thread;
|
||||
MPSCQueue<Entry> message_queue{};
|
||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ConsoleBackend::~ConsoleBackend() = default;
|
||||
|
||||
void ConsoleBackend::Write(const Entry& entry) {
|
||||
PrintMessage(entry);
|
||||
void Initialize() {
|
||||
Impl::Initialize();
|
||||
}
|
||||
|
||||
ColorConsoleBackend::~ColorConsoleBackend() = default;
|
||||
|
||||
void ColorConsoleBackend::Write(const Entry& entry) {
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
|
||||
FileBackend::FileBackend(const std::filesystem::path& filename) {
|
||||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
FS::RemoveFile(old_filename);
|
||||
void(FS::RenameFile(filename, old_filename));
|
||||
|
||||
file =
|
||||
std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
|
||||
}
|
||||
|
||||
FileBackend::~FileBackend() = default;
|
||||
|
||||
void FileBackend::Write(const Entry& entry) {
|
||||
if (!file->IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
constexpr std::size_t MAX_BYTES_WRITTEN = 100_MiB;
|
||||
constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1_GiB;
|
||||
|
||||
const bool write_limit_exceeded =
|
||||
bytes_written > MAX_BYTES_WRITTEN_EXTENDED ||
|
||||
(bytes_written > MAX_BYTES_WRITTEN && !Settings::values.extended_logging);
|
||||
|
||||
// Close the file after the write limit is exceeded.
|
||||
if (write_limit_exceeded) {
|
||||
file->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
|
||||
if (entry.log_level >= Level::Error) {
|
||||
file->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
DebuggerBackend::~DebuggerBackend() = default;
|
||||
|
||||
void DebuggerBackend::Write(const Entry& entry) {
|
||||
#ifdef _WIN32
|
||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||
#endif
|
||||
void DisableLoggingInTests() {
|
||||
initialization_in_progress_suppress_logging = true;
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& filter) {
|
||||
Impl::Instance().SetGlobalFilter(filter);
|
||||
}
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend) {
|
||||
Impl::Instance().AddBackend(std::move(backend));
|
||||
}
|
||||
|
||||
void RemoveBackend(std::string_view backend_name) {
|
||||
Impl::Instance().RemoveBackend(backend_name);
|
||||
}
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name) {
|
||||
return Impl::Instance().GetBackend(backend_name);
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||
}
|
||||
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, const char* format,
|
||||
const fmt::format_args& args) {
|
||||
auto& instance = Impl::Instance();
|
||||
const auto& filter = instance.GetGlobalFilter();
|
||||
if (!filter.CheckMessage(log_class, log_level))
|
||||
return;
|
||||
|
||||
instance.PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, args));
|
||||
if (!initialization_in_progress_suppress_logging) {
|
||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, args));
|
||||
}
|
||||
}
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -5,120 +5,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace Common::FS {
|
||||
class IOFile;
|
||||
}
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
class Filter;
|
||||
|
||||
/**
|
||||
* Interface for logging backends. As loggers can be created and removed at runtime, this can be
|
||||
* used by a frontend for adding a custom logging backend as needed
|
||||
*/
|
||||
class Backend {
|
||||
public:
|
||||
virtual ~Backend() = default;
|
||||
/// Initializes the logging system. This should be the first thing called in main.
|
||||
void Initialize();
|
||||
|
||||
virtual void SetFilter(const Filter& new_filter) {
|
||||
filter = new_filter;
|
||||
}
|
||||
virtual const char* GetName() const = 0;
|
||||
virtual void Write(const Entry& entry) = 0;
|
||||
|
||||
private:
|
||||
Filter filter;
|
||||
};
|
||||
void DisableLoggingInTests();
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr without any color commands
|
||||
*/
|
||||
class ConsoleBackend : public Backend {
|
||||
public:
|
||||
~ConsoleBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "console";
|
||||
}
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr and with color
|
||||
*/
|
||||
class ColorConsoleBackend : public Backend {
|
||||
public:
|
||||
~ColorConsoleBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "color_console";
|
||||
}
|
||||
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to a file passed into the constructor
|
||||
*/
|
||||
class FileBackend : public Backend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename);
|
||||
~FileBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "file";
|
||||
}
|
||||
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
|
||||
void Write(const Entry& entry) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<FS::IOFile> file;
|
||||
std::size_t bytes_written = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to Visual Studio's output window
|
||||
*/
|
||||
class DebuggerBackend : public Backend {
|
||||
public:
|
||||
~DebuggerBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "debugger";
|
||||
}
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend);
|
||||
|
||||
void RemoveBackend(std::string_view backend_name);
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name);
|
||||
|
||||
/**
|
||||
* The global filter will prevent any messages from even being processed if they are filtered. Each
|
||||
* backend can have a filter, but if the level is lower than the global filter, the backend will
|
||||
* never get the message
|
||||
* The global filter will prevent any messages from even being processed if they are filtered.
|
||||
*/
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
} // namespace Common::Log
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -111,6 +111,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Service, NCM) \
|
||||
SUB(Service, NFC) \
|
||||
SUB(Service, NFP) \
|
||||
SUB(Service, NGCT) \
|
||||
SUB(Service, NIFM) \
|
||||
SUB(Service, NIM) \
|
||||
SUB(Service, NPNS) \
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "common/logging/types.h"
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
28
src/common/logging/log_entry.h
Normal file
28
src/common/logging/log_entry.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "common/logging/types.h"
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
/**
|
||||
* A log entry. Log entries are store in a structured format to permit more varied output
|
||||
* formatting on different frontends, as well as facilitating filtering and aggregation.
|
||||
*/
|
||||
struct Entry {
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class{};
|
||||
Level log_level{};
|
||||
const char* filename = nullptr;
|
||||
unsigned int line_num = 0;
|
||||
std::string function;
|
||||
std::string message;
|
||||
bool final_entry = false;
|
||||
};
|
||||
|
||||
} // namespace Common::Log
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/log_entry.h"
|
||||
#include "common/logging/text_formatter.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common::Log {
|
||||
@@ -81,6 +79,7 @@ enum class Class : u8 {
|
||||
Service_NCM, ///< The NCM service
|
||||
Service_NFC, ///< The NFC (Near-field communication) service
|
||||
Service_NFP, ///< The NFP service
|
||||
Service_NGCT, ///< The NGCT (No Good Content for Terra) service
|
||||
Service_NIFM, ///< The NIFM (Network interface) service
|
||||
Service_NIM, ///< The NIM service
|
||||
Service_NPNS, ///< The NPNS service
|
||||
@@ -130,19 +129,4 @@ enum class Class : u8 {
|
||||
Count ///< Total number of logging classes
|
||||
};
|
||||
|
||||
/**
|
||||
* A log entry. Log entries are store in a structured format to permit more varied output
|
||||
* formatting on different frontends, as well as facilitating filtering and aggregation.
|
||||
*/
|
||||
struct Entry {
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class{};
|
||||
Level log_level{};
|
||||
const char* filename = nullptr;
|
||||
unsigned int line_num = 0;
|
||||
std::string function;
|
||||
std::string message;
|
||||
bool final_entry = false;
|
||||
};
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
140
src/common/lru_cache.h
Normal file
140
src/common/lru_cache.h
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2+ or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <class Traits>
|
||||
class LeastRecentlyUsedCache {
|
||||
using ObjectType = typename Traits::ObjectType;
|
||||
using TickType = typename Traits::TickType;
|
||||
|
||||
struct Item {
|
||||
ObjectType obj;
|
||||
TickType tick;
|
||||
Item* next{};
|
||||
Item* prev{};
|
||||
};
|
||||
|
||||
public:
|
||||
LeastRecentlyUsedCache() : first_item{}, last_item{} {}
|
||||
~LeastRecentlyUsedCache() = default;
|
||||
|
||||
size_t Insert(ObjectType obj, TickType tick) {
|
||||
const auto new_id = Build();
|
||||
auto& item = item_pool[new_id];
|
||||
item.obj = obj;
|
||||
item.tick = tick;
|
||||
Attach(item);
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void Touch(size_t id, TickType tick) {
|
||||
auto& item = item_pool[id];
|
||||
if (item.tick >= tick) {
|
||||
return;
|
||||
}
|
||||
item.tick = tick;
|
||||
if (&item == last_item) {
|
||||
return;
|
||||
}
|
||||
Detach(item);
|
||||
Attach(item);
|
||||
}
|
||||
|
||||
void Free(size_t id) {
|
||||
auto& item = item_pool[id];
|
||||
Detach(item);
|
||||
item.prev = nullptr;
|
||||
item.next = nullptr;
|
||||
free_items.push_back(id);
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void ForEachItemBelow(TickType tick, Func&& func) {
|
||||
static constexpr bool RETURNS_BOOL =
|
||||
std::is_same_v<std::invoke_result<Func, ObjectType>, bool>;
|
||||
Item* iterator = first_item;
|
||||
while (iterator) {
|
||||
if (static_cast<s64>(tick) - static_cast<s64>(iterator->tick) < 0) {
|
||||
return;
|
||||
}
|
||||
Item* next = iterator->next;
|
||||
if constexpr (RETURNS_BOOL) {
|
||||
if (func(iterator->obj)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
func(iterator->obj);
|
||||
}
|
||||
iterator = next;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
size_t Build() {
|
||||
if (free_items.empty()) {
|
||||
const size_t item_id = item_pool.size();
|
||||
auto& item = item_pool.emplace_back();
|
||||
item.next = nullptr;
|
||||
item.prev = nullptr;
|
||||
return item_id;
|
||||
}
|
||||
const size_t item_id = free_items.front();
|
||||
free_items.pop_front();
|
||||
auto& item = item_pool[item_id];
|
||||
item.next = nullptr;
|
||||
item.prev = nullptr;
|
||||
return item_id;
|
||||
}
|
||||
|
||||
void Attach(Item& item) {
|
||||
if (!first_item) {
|
||||
first_item = &item;
|
||||
}
|
||||
if (!last_item) {
|
||||
last_item = &item;
|
||||
} else {
|
||||
item.prev = last_item;
|
||||
last_item->next = &item;
|
||||
item.next = nullptr;
|
||||
last_item = &item;
|
||||
}
|
||||
}
|
||||
|
||||
void Detach(Item& item) {
|
||||
if (item.prev) {
|
||||
item.prev->next = item.next;
|
||||
}
|
||||
if (item.next) {
|
||||
item.next->prev = item.prev;
|
||||
}
|
||||
if (&item == first_item) {
|
||||
first_item = item.next;
|
||||
if (first_item) {
|
||||
first_item->prev = nullptr;
|
||||
}
|
||||
}
|
||||
if (&item == last_item) {
|
||||
last_item = item.prev;
|
||||
if (last_item) {
|
||||
last_item->next = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::deque<Item> item_pool;
|
||||
std::deque<size_t> free_items;
|
||||
Item* first_item{};
|
||||
Item* last_item{};
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -54,15 +54,13 @@ void LogSettings() {
|
||||
log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousGpuEmulation",
|
||||
values.use_asynchronous_gpu_emulation.GetValue());
|
||||
log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue());
|
||||
log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue());
|
||||
log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue());
|
||||
log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
|
||||
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
|
||||
log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue());
|
||||
log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
|
||||
log_setting("Audio_OutputEngine", values.sink_id.GetValue());
|
||||
log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
|
||||
log_setting("Audio_OutputDevice", values.audio_device_id.GetValue());
|
||||
log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue());
|
||||
log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir));
|
||||
@@ -71,8 +69,9 @@ void LogSettings() {
|
||||
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
||||
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
|
||||
log_setting("Debugging_ProgramArgs", values.program_args.GetValue());
|
||||
log_setting("Services_BCATBackend", values.bcat_backend.GetValue());
|
||||
log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local.GetValue());
|
||||
log_setting("Input_EnableMotion", values.motion_enabled.GetValue());
|
||||
log_setting("Input_EnableVibration", values.vibration_enabled.GetValue());
|
||||
log_setting("Input_EnableRawInput", values.enable_raw_input.GetValue());
|
||||
}
|
||||
|
||||
bool IsConfiguringGlobal() {
|
||||
@@ -113,7 +112,6 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
}
|
||||
|
||||
// Audio
|
||||
values.enable_audio_stretching.SetGlobal(true);
|
||||
values.volume.SetGlobal(true);
|
||||
|
||||
// Core
|
||||
@@ -137,13 +135,12 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
values.use_disk_shader_cache.SetGlobal(true);
|
||||
values.gpu_accuracy.SetGlobal(true);
|
||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||
values.use_nvdec_emulation.SetGlobal(true);
|
||||
values.nvdec_emulation.SetGlobal(true);
|
||||
values.accelerate_astc.SetGlobal(true);
|
||||
values.use_vsync.SetGlobal(true);
|
||||
values.shader_backend.SetGlobal(true);
|
||||
values.use_asynchronous_shaders.SetGlobal(true);
|
||||
values.use_fast_gpu_time.SetGlobal(true);
|
||||
values.use_caches_gc.SetGlobal(true);
|
||||
values.bg_red.SetGlobal(true);
|
||||
values.bg_green.SetGlobal(true);
|
||||
values.bg_blue.SetGlobal(true);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings_input.h"
|
||||
#include "input_common/udp/client.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
@@ -48,6 +47,12 @@ enum class FullscreenMode : u32 {
|
||||
Exclusive = 1,
|
||||
};
|
||||
|
||||
enum class NvdecEmulation : u32 {
|
||||
Off = 0,
|
||||
CPU = 1,
|
||||
GPU = 2,
|
||||
};
|
||||
|
||||
/** The BasicSetting class is a simple resource manager. It defines a label and default value
|
||||
* alongside the actual value of the setting for simpler and less-error prone use with frontend
|
||||
* configurations. Setting a default value and label is required, though subclasses may deviate from
|
||||
@@ -409,7 +414,6 @@ struct Values {
|
||||
BasicSetting<std::string> audio_device_id{"auto", "output_device"};
|
||||
BasicSetting<std::string> sink_id{"auto", "output_engine"};
|
||||
BasicSetting<bool> audio_muted{false, "audio_muted"};
|
||||
Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"};
|
||||
RangedSetting<u8> volume{100, 0, 100, "volume"};
|
||||
|
||||
// Core
|
||||
@@ -466,7 +470,7 @@ struct Values {
|
||||
RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||
Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||
Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"};
|
||||
Setting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||
Setting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||
Setting<bool> use_vsync{true, "use_vsync"};
|
||||
BasicRangedSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"};
|
||||
@@ -475,7 +479,6 @@ struct Values {
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
|
||||
Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
|
||||
Setting<bool> use_caches_gc{false, "use_caches_gc"};
|
||||
|
||||
Setting<u8> bg_red{0, "bg_red"};
|
||||
Setting<u8> bg_green{0, "bg_green"};
|
||||
@@ -489,7 +492,7 @@ struct Values {
|
||||
std::chrono::seconds custom_rtc_differential;
|
||||
|
||||
BasicSetting<s32> current_user{0, "current_user"};
|
||||
RangedSetting<s32> language_index{1, 0, 16, "language_index"};
|
||||
RangedSetting<s32> language_index{1, 0, 17, "language_index"};
|
||||
RangedSetting<s32> region_index{1, 0, 6, "region_index"};
|
||||
RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"};
|
||||
RangedSetting<s32> sound_index{1, 0, 2, "sound_index"};
|
||||
@@ -499,14 +502,20 @@ struct Values {
|
||||
|
||||
Setting<bool> use_docked_mode{true, "use_docked_mode"};
|
||||
|
||||
BasicSetting<bool> enable_raw_input{false, "enable_raw_input"};
|
||||
|
||||
Setting<bool> vibration_enabled{true, "vibration_enabled"};
|
||||
Setting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};
|
||||
|
||||
Setting<bool> motion_enabled{true, "motion_enabled"};
|
||||
BasicSetting<std::string> motion_device{"engine:motion_emu,update_period:100,sensitivity:0.01",
|
||||
"motion_device"};
|
||||
BasicSetting<std::string> udp_input_servers{InputCommon::CemuhookUDP::DEFAULT_SRV,
|
||||
"udp_input_servers"};
|
||||
BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
|
||||
|
||||
BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
|
||||
BasicSetting<bool> tas_enable{false, "tas_enable"};
|
||||
BasicSetting<bool> tas_loop{false, "tas_loop"};
|
||||
BasicSetting<bool> tas_swap_controllers{true, "tas_swap_controllers"};
|
||||
|
||||
BasicSetting<bool> mouse_panning{false, "mouse_panning"};
|
||||
BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
|
||||
@@ -559,8 +568,6 @@ struct Values {
|
||||
BasicSetting<bool> use_dev_keys{false, "use_dev_keys"};
|
||||
|
||||
// Network
|
||||
BasicSetting<std::string> bcat_backend{"none", "bcat_backend"};
|
||||
BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"};
|
||||
BasicSetting<std::string> network_interface{std::string(), "network_interface"};
|
||||
|
||||
// WebService
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include <string>
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/thread.h"
|
||||
#ifdef __APPLE__
|
||||
@@ -21,8 +23,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define cpu_set_t cpuset_t
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <utility>
|
||||
|
||||
namespace Common {
|
||||
template <typename T>
|
||||
template <typename T, bool with_stop_token = false>
|
||||
class SPSCQueue {
|
||||
public:
|
||||
SPSCQueue() {
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
void Wait() {
|
||||
if (Empty()) {
|
||||
std::unique_lock lock{cv_mutex};
|
||||
cv.wait(lock, [this]() { return !Empty(); });
|
||||
cv.wait(lock, [this] { return !Empty(); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,19 @@ public:
|
||||
return t;
|
||||
}
|
||||
|
||||
T PopWait(std::stop_token stop_token) {
|
||||
if (Empty()) {
|
||||
std::unique_lock lock{cv_mutex};
|
||||
cv.wait(lock, stop_token, [this] { return !Empty(); });
|
||||
}
|
||||
if (stop_token.stop_requested()) {
|
||||
return T{};
|
||||
}
|
||||
T t;
|
||||
Pop(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
// not thread-safe
|
||||
void Clear() {
|
||||
size.store(0);
|
||||
@@ -123,13 +136,13 @@ private:
|
||||
ElementPtr* read_ptr;
|
||||
std::atomic_size_t size{0};
|
||||
std::mutex cv_mutex;
|
||||
std::condition_variable cv;
|
||||
std::conditional_t<with_stop_token, std::condition_variable_any, std::condition_variable> cv;
|
||||
};
|
||||
|
||||
// a simple thread-safe,
|
||||
// single reader, multiple writer queue
|
||||
|
||||
template <typename T>
|
||||
template <typename T, bool with_stop_token = false>
|
||||
class MPSCQueue {
|
||||
public:
|
||||
[[nodiscard]] std::size_t Size() const {
|
||||
@@ -166,13 +179,17 @@ public:
|
||||
return spsc_queue.PopWait();
|
||||
}
|
||||
|
||||
T PopWait(std::stop_token stop_token) {
|
||||
return spsc_queue.PopWait(stop_token);
|
||||
}
|
||||
|
||||
// not thread-safe
|
||||
void Clear() {
|
||||
spsc_queue.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
SPSCQueue<T> spsc_queue;
|
||||
SPSCQueue<T, with_stop_token> spsc_queue;
|
||||
std::mutex write_lock;
|
||||
};
|
||||
} // namespace Common
|
||||
|
||||
@@ -58,6 +58,13 @@ struct UUID {
|
||||
uuid = INVALID_UUID;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsInvalid() const {
|
||||
return uuid == INVALID_UUID;
|
||||
}
|
||||
[[nodiscard]] constexpr bool IsValid() const {
|
||||
return !IsInvalid();
|
||||
}
|
||||
|
||||
// TODO(ogniK): Properly generate a Nintendo ID
|
||||
[[nodiscard]] constexpr u64 GetNintendoID() const {
|
||||
return uuid[0];
|
||||
|
||||
@@ -667,8 +667,8 @@ template <typename T>
|
||||
|
||||
// linear interpolation via float: 0.0=begin, 1.0=end
|
||||
template <typename X>
|
||||
[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
|
||||
const float t) {
|
||||
[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{})
|
||||
Lerp(const X& begin, const X& end, const float t) {
|
||||
return begin * (1.f - t) + end * t;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
#include <xbyak.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <xbyak.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include "common/x64/xbyak_abi.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
@@ -106,8 +106,6 @@ add_library(core STATIC
|
||||
file_sys/vfs_concat.h
|
||||
file_sys/vfs_layered.cpp
|
||||
file_sys/vfs_layered.h
|
||||
file_sys/vfs_libzip.cpp
|
||||
file_sys/vfs_libzip.h
|
||||
file_sys/vfs_offset.cpp
|
||||
file_sys/vfs_offset.h
|
||||
file_sys/vfs_real.cpp
|
||||
@@ -218,6 +216,7 @@ add_library(core STATIC
|
||||
hle/kernel/k_session.h
|
||||
hle/kernel/k_shared_memory.cpp
|
||||
hle/kernel/k_shared_memory.h
|
||||
hle/kernel/k_shared_memory_info.h
|
||||
hle/kernel/k_slab_heap.h
|
||||
hle/kernel/k_spin_lock.cpp
|
||||
hle/kernel/k_spin_lock.h
|
||||
@@ -263,6 +262,8 @@ add_library(core STATIC
|
||||
hle/service/acc/acc_u0.h
|
||||
hle/service/acc/acc_u1.cpp
|
||||
hle/service/acc/acc_u1.h
|
||||
hle/service/acc/async_context.cpp
|
||||
hle/service/acc/async_context.h
|
||||
hle/service/acc/errors.h
|
||||
hle/service/acc/profile_manager.cpp
|
||||
hle/service/acc/profile_manager.h
|
||||
@@ -452,6 +453,8 @@ add_library(core STATIC
|
||||
hle/service/nfp/nfp.h
|
||||
hle/service/nfp/nfp_user.cpp
|
||||
hle/service/nfp/nfp_user.h
|
||||
hle/service/ngct/ngct.cpp
|
||||
hle/service/ngct/ngct.h
|
||||
hle/service/nifm/nifm.cpp
|
||||
hle/service/nifm/nifm.h
|
||||
hle/service/nim/nim.cpp
|
||||
@@ -649,13 +652,6 @@ add_library(core STATIC
|
||||
tools/freezer.h
|
||||
)
|
||||
|
||||
if (YUZU_ENABLE_BOXCAT)
|
||||
target_sources(core PRIVATE
|
||||
hle/service/bcat/backend/boxcat.cpp
|
||||
hle/service/bcat/backend/boxcat.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
@@ -686,12 +682,7 @@ endif()
|
||||
create_target_directory_groups(core)
|
||||
|
||||
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus zip)
|
||||
|
||||
if (YUZU_ENABLE_BOXCAT)
|
||||
target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT)
|
||||
target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus)
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -82,9 +83,13 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
void KProcessDeleter(Kernel::KProcess* process) {
|
||||
process->Destroy();
|
||||
}
|
||||
|
||||
/*static*/ System System::s_instance;
|
||||
using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
const std::string& path) {
|
||||
@@ -234,8 +239,8 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||
auto main_process = Kernel::KProcess::Create(system.Kernel());
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
|
||||
main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
|
||||
Kernel::KProcess::ProcessType::Userland)
|
||||
.IsSuccess());
|
||||
main_process->Open();
|
||||
@@ -248,7 +253,7 @@ struct System::Impl {
|
||||
static_cast<u32>(load_result));
|
||||
}
|
||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||
kernel.MakeCurrentProcess(main_process);
|
||||
kernel.MakeCurrentProcess(main_process.get());
|
||||
kernel.InitializeCores();
|
||||
|
||||
// Initialize cheat engine
|
||||
@@ -300,10 +305,6 @@ struct System::Impl {
|
||||
is_powered_on = false;
|
||||
exit_lock = false;
|
||||
|
||||
if (gpu_core) {
|
||||
gpu_core->ShutDown();
|
||||
}
|
||||
|
||||
services.reset();
|
||||
service_manager.reset();
|
||||
cheat_engine.reset();
|
||||
@@ -312,11 +313,13 @@ struct System::Impl {
|
||||
time_manager.Shutdown();
|
||||
core_timing.Shutdown();
|
||||
app_loader.reset();
|
||||
gpu_core.reset();
|
||||
perf_stats.reset();
|
||||
gpu_core.reset();
|
||||
kernel.Shutdown();
|
||||
memory.Reset();
|
||||
applet_manager.ClearAll();
|
||||
// TODO: The main process should be freed based on KAutoObject ref counting.
|
||||
main_process.reset();
|
||||
|
||||
LOG_DEBUG(Core, "Shutdown OK");
|
||||
}
|
||||
@@ -375,6 +378,7 @@ struct System::Impl {
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
|
||||
std::unique_ptr<Core::DeviceMemory> device_memory;
|
||||
KProcessPtr main_process{nullptr, KProcessDeleter};
|
||||
Core::Memory::Memory memory;
|
||||
CpuManager cpu_manager;
|
||||
std::atomic_bool is_powered_on{};
|
||||
@@ -417,6 +421,7 @@ struct System::Impl {
|
||||
bool is_async_gpu{};
|
||||
|
||||
ExecuteProgramCallback execute_program_callback;
|
||||
ExitCallback exit_callback;
|
||||
|
||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
||||
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
|
||||
@@ -425,6 +430,20 @@ struct System::Impl {
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
System::~System() = default;
|
||||
|
||||
System& System::GetInstance() {
|
||||
if (!s_instance) {
|
||||
throw std::runtime_error("Using System instance before its initialization");
|
||||
}
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void System::InitializeGlobalInstance() {
|
||||
if (s_instance) {
|
||||
throw std::runtime_error("Reinitializing Global System instance.");
|
||||
}
|
||||
s_instance = std::unique_ptr<System>(new System);
|
||||
}
|
||||
|
||||
CpuManager& System::GetCpuManager() {
|
||||
return impl->cpu_manager;
|
||||
}
|
||||
@@ -494,6 +513,12 @@ const ARM_Interface& System::CurrentArmInterface() const {
|
||||
return impl->kernel.CurrentPhysicalCore().ArmInterface();
|
||||
}
|
||||
|
||||
std::size_t System::CurrentCoreIndex() const {
|
||||
std::size_t core = impl->kernel.GetCurrentHostThreadID();
|
||||
ASSERT(core < Core::Hardware::NUM_CPU_CORES);
|
||||
return core;
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& System::CurrentPhysicalCore() {
|
||||
return impl->kernel.CurrentPhysicalCore();
|
||||
}
|
||||
@@ -774,6 +799,18 @@ void System::ExecuteProgram(std::size_t program_index) {
|
||||
}
|
||||
}
|
||||
|
||||
void System::RegisterExitCallback(ExitCallback&& callback) {
|
||||
impl->exit_callback = std::move(callback);
|
||||
}
|
||||
|
||||
void System::Exit() {
|
||||
if (impl->exit_callback) {
|
||||
impl->exit_callback();
|
||||
} else {
|
||||
LOG_CRITICAL(Core, "exit_callback must be initialized by the frontend");
|
||||
}
|
||||
}
|
||||
|
||||
void System::ApplySettings() {
|
||||
if (IsPoweredOn()) {
|
||||
Renderer().RefreshBaseSettings();
|
||||
|
||||
@@ -120,9 +120,9 @@ public:
|
||||
* Gets the instance of the System singleton class.
|
||||
* @returns Reference to the instance of the System singleton class.
|
||||
*/
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance();
|
||||
|
||||
static void InitializeGlobalInstance();
|
||||
|
||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||
enum class ResultStatus : u32 {
|
||||
@@ -205,6 +205,9 @@ public:
|
||||
/// Gets an ARM interface to the CPU core that is currently running
|
||||
[[nodiscard]] const ARM_Interface& CurrentArmInterface() const;
|
||||
|
||||
/// Gets the index of the currently running CPU core
|
||||
[[nodiscard]] std::size_t CurrentCoreIndex() const;
|
||||
|
||||
/// Gets the physical core for the CPU core that is currently running
|
||||
[[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore();
|
||||
|
||||
@@ -384,6 +387,18 @@ public:
|
||||
*/
|
||||
void ExecuteProgram(std::size_t program_index);
|
||||
|
||||
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||
using ExitCallback = std::function<void()>;
|
||||
|
||||
/**
|
||||
* Registers a callback from the frontend for System to exit the application.
|
||||
* @param callback Callback from the frontend to exit the application.
|
||||
*/
|
||||
void RegisterExitCallback(ExitCallback&& callback);
|
||||
|
||||
/// Instructs the frontend to exit the application.
|
||||
void Exit();
|
||||
|
||||
/// Applies any changes to settings to this core instance.
|
||||
void ApplySettings();
|
||||
|
||||
@@ -393,7 +408,7 @@ private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
static System s_instance;
|
||||
inline static std::unique_ptr<System> s_instance{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -118,18 +118,17 @@ void CpuManager::MultiCoreRunGuestLoop() {
|
||||
physical_core = &kernel.CurrentPhysicalCore();
|
||||
}
|
||||
system.ExitDynarmicProfile();
|
||||
{
|
||||
Kernel::KScopedDisableDispatch dd(kernel);
|
||||
physical_core->ArmInterface().ClearExclusiveState();
|
||||
}
|
||||
physical_core->ArmInterface().ClearExclusiveState();
|
||||
kernel.CurrentScheduler()->RescheduleCurrentCore();
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::MultiCoreRunIdleThread() {
|
||||
auto& kernel = system.Kernel();
|
||||
while (true) {
|
||||
Kernel::KScopedDisableDispatch dd(kernel);
|
||||
kernel.CurrentPhysicalCore().Idle();
|
||||
auto& physical_core = kernel.CurrentPhysicalCore();
|
||||
physical_core.Idle();
|
||||
kernel.CurrentScheduler()->RescheduleCurrentCore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,12 +136,12 @@ void CpuManager::MultiCoreRunSuspendThread() {
|
||||
auto& kernel = system.Kernel();
|
||||
kernel.CurrentScheduler()->OnThreadStart();
|
||||
while (true) {
|
||||
auto core = kernel.CurrentPhysicalCoreIndex();
|
||||
auto core = kernel.GetCurrentHostThreadID();
|
||||
auto& scheduler = *kernel.CurrentScheduler();
|
||||
Kernel::KThread* current_thread = scheduler.GetCurrentThread();
|
||||
Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
|
||||
ASSERT(scheduler.ContextSwitchPending());
|
||||
ASSERT(core == kernel.CurrentPhysicalCoreIndex());
|
||||
ASSERT(core == kernel.GetCurrentHostThreadID());
|
||||
scheduler.RescheduleCurrentCore();
|
||||
}
|
||||
}
|
||||
@@ -348,11 +347,15 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
|
||||
sc_sync_first_use = false;
|
||||
}
|
||||
|
||||
// Emulation was stopped
|
||||
if (stop_token.stop_requested()) {
|
||||
// Abort if emulation was killed before the session really starts
|
||||
if (!system.IsPoweredOn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stop_token.stop_requested()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
|
||||
data.is_running = true;
|
||||
Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
|
||||
@@ -77,7 +77,7 @@ void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address
|
||||
aci_header.title_id = title_id;
|
||||
aci_file_access.permissions = filesystem_permissions;
|
||||
npdm_header.system_resource_size = system_resource_size;
|
||||
aci_kernel_capabilities = std ::move(capabilities);
|
||||
aci_kernel_capabilities = std::move(capabilities);
|
||||
}
|
||||
|
||||
bool ProgramMetadata::Is64BitProgram() const {
|
||||
|
||||
@@ -273,6 +273,10 @@ VirtualFile VfsDirectory::GetFile(std::string_view name) const {
|
||||
return iter == files.end() ? nullptr : *iter;
|
||||
}
|
||||
|
||||
FileTimeStampRaw VfsDirectory::GetFileTimeStamp([[maybe_unused]] std::string_view path) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
VirtualDir VfsDirectory::GetSubdirectory(std::string_view name) const {
|
||||
const auto& subs = GetSubdirectories();
|
||||
const auto iter = std::find_if(subs.begin(), subs.end(),
|
||||
|
||||
@@ -199,6 +199,9 @@ public:
|
||||
// file with name.
|
||||
virtual VirtualFile GetFile(std::string_view name) const;
|
||||
|
||||
// Returns a struct containing the file's timestamp.
|
||||
virtual FileTimeStampRaw GetFileTimeStamp(std::string_view path) const;
|
||||
|
||||
// Returns a vector containing all of the subdirectories in this directory.
|
||||
virtual std::vector<VirtualDir> GetSubdirectories() const = 0;
|
||||
// Returns the directory with name matching name. Returns nullptr if directory dosen't have a
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#include <zip.h>
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "common/fs/path_util.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_libzip.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
VirtualDir ExtractZIP(VirtualFile file) {
|
||||
zip_error_t error{};
|
||||
|
||||
const auto data = file->ReadAllBytes();
|
||||
std::unique_ptr<zip_source_t, decltype(&zip_source_close)> src{
|
||||
zip_source_buffer_create(data.data(), data.size(), 0, &error), zip_source_close};
|
||||
if (src == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<zip_t, decltype(&zip_close)> zip{zip_open_from_source(src.get(), 0, &error),
|
||||
zip_close};
|
||||
if (zip == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::shared_ptr<VectorVfsDirectory> out = std::make_shared<VectorVfsDirectory>();
|
||||
|
||||
const auto num_entries = static_cast<std::size_t>(zip_get_num_entries(zip.get(), 0));
|
||||
|
||||
zip_stat_t stat{};
|
||||
zip_stat_init(&stat);
|
||||
|
||||
for (std::size_t i = 0; i < num_entries; ++i) {
|
||||
const auto stat_res = zip_stat_index(zip.get(), i, 0, &stat);
|
||||
if (stat_res == -1)
|
||||
return nullptr;
|
||||
|
||||
const std::string name(stat.name);
|
||||
if (name.empty())
|
||||
continue;
|
||||
|
||||
if (name.back() != '/') {
|
||||
std::unique_ptr<zip_file_t, decltype(&zip_fclose)> file2{
|
||||
zip_fopen_index(zip.get(), i, 0), zip_fclose};
|
||||
|
||||
std::vector<u8> buf(stat.size);
|
||||
if (zip_fread(file2.get(), buf.data(), buf.size()) != s64(buf.size()))
|
||||
return nullptr;
|
||||
|
||||
const auto parts = Common::FS::SplitPathComponents(stat.name);
|
||||
const auto new_file = std::make_shared<VectorVfsFile>(buf, parts.back());
|
||||
|
||||
std::shared_ptr<VectorVfsDirectory> dtrv = out;
|
||||
for (std::size_t j = 0; j < parts.size() - 1; ++j) {
|
||||
if (dtrv == nullptr)
|
||||
return nullptr;
|
||||
const auto subdir = dtrv->GetSubdirectory(parts[j]);
|
||||
if (subdir == nullptr) {
|
||||
const auto temp = std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parts[j]);
|
||||
dtrv->AddDirectory(temp);
|
||||
dtrv = temp;
|
||||
} else {
|
||||
dtrv = std::dynamic_pointer_cast<VectorVfsDirectory>(subdir);
|
||||
}
|
||||
}
|
||||
|
||||
if (dtrv == nullptr)
|
||||
return nullptr;
|
||||
dtrv->AddFile(new_file);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
VirtualDir ExtractZIP(VirtualFile zip);
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -13,6 +13,13 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
|
||||
// For FileTimeStampRaw
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define stat _stat64
|
||||
#endif
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
namespace FS = Common::FS;
|
||||
@@ -392,6 +399,28 @@ std::vector<VirtualFile> RealVfsDirectory::GetFiles() const {
|
||||
return IterateEntries<RealVfsFile, VfsFile>();
|
||||
}
|
||||
|
||||
FileTimeStampRaw RealVfsDirectory::GetFileTimeStamp(std::string_view path_) const {
|
||||
const auto full_path = FS::SanitizePath(path + '/' + std::string(path_));
|
||||
const auto fs_path = std::filesystem::path{FS::ToU8String(full_path)};
|
||||
struct stat file_status;
|
||||
|
||||
#ifdef _WIN32
|
||||
const auto stat_result = _wstat64(fs_path.c_str(), &file_status);
|
||||
#else
|
||||
const auto stat_result = stat(fs_path.c_str(), &file_status);
|
||||
#endif
|
||||
|
||||
if (stat_result != 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
.created{static_cast<u64>(file_status.st_ctime)},
|
||||
.accessed{static_cast<u64>(file_status.st_atime)},
|
||||
.modified{static_cast<u64>(file_status.st_mtime)},
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<VirtualDir> RealVfsDirectory::GetSubdirectories() const {
|
||||
return IterateEntries<RealVfsDirectory, VfsDirectory>();
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
VirtualDir CreateDirectoryRelative(std::string_view relative_path) override;
|
||||
bool DeleteSubdirectoryRecursive(std::string_view name) override;
|
||||
std::vector<VirtualFile> GetFiles() const override;
|
||||
FileTimeStampRaw GetFileTimeStamp(std::string_view path) const override;
|
||||
std::vector<VirtualDir> GetSubdirectories() const override;
|
||||
bool IsWritable() const override;
|
||||
bool IsReadable() const override;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
class VfsDirectory;
|
||||
@@ -18,4 +20,11 @@ using VirtualDir = std::shared_ptr<VfsDirectory>;
|
||||
using VirtualFile = std::shared_ptr<VfsFile>;
|
||||
using VirtualFilesystem = std::shared_ptr<VfsFilesystem>;
|
||||
|
||||
struct FileTimeStampRaw {
|
||||
u64 created{};
|
||||
u64 accessed{};
|
||||
u64 modified{};
|
||||
u64 padding{};
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
@@ -13,7 +13,8 @@ ProfileSelectApplet::~ProfileSelectApplet() = default;
|
||||
void DefaultProfileSelectApplet::SelectProfile(
|
||||
std::function<void(std::optional<Common::UUID>)> callback) const {
|
||||
Service::Account::ProfileManager manager;
|
||||
callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{}));
|
||||
callback(manager.GetUser(Settings::values.current_user.GetValue())
|
||||
.value_or(Common::UUID{Common::INVALID_UUID}));
|
||||
LOG_INFO(Service_ACC, "called, selecting current user instead of prompting...");
|
||||
}
|
||||
|
||||
|
||||
@@ -28,13 +28,20 @@ constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0";
|
||||
|
||||
// Atmosphere version constants.
|
||||
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 5;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0;
|
||||
|
||||
constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) {
|
||||
return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev};
|
||||
}
|
||||
|
||||
constexpr u32 AtmosphereTargetFirmware(u8 major, u8 minor, u8 micro) {
|
||||
return AtmosphereTargetFirmwareWithRevision(major, minor, micro, 0);
|
||||
}
|
||||
|
||||
constexpr u32 GetTargetFirmware() {
|
||||
return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
|
||||
u32{HOS_VERSION_MICRO} << 8 | 0U;
|
||||
return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO);
|
||||
}
|
||||
|
||||
} // namespace HLE::ApiVersion
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
#include "core/hle/kernel/k_session.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/k_handle_table.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "common/concepts.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/svc_common.h"
|
||||
|
||||
union ResultCode;
|
||||
@@ -38,6 +37,7 @@ namespace Kernel {
|
||||
|
||||
class Domain;
|
||||
class HLERequestContext;
|
||||
class KAutoObject;
|
||||
class KernelCore;
|
||||
class KHandleTable;
|
||||
class KProcess;
|
||||
|
||||
@@ -28,7 +28,7 @@ bool ReadFromUser(Core::System& system, s32* out, VAddr address) {
|
||||
|
||||
bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 value) {
|
||||
auto& monitor = system.Monitor();
|
||||
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
|
||||
const auto current_core = system.CurrentCoreIndex();
|
||||
|
||||
// TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable.
|
||||
// TODO(bunnei): We should call CanAccessAtomic(..) here.
|
||||
@@ -58,7 +58,7 @@ bool DecrementIfLessThan(Core::System& system, s32* out, VAddr address, s32 valu
|
||||
|
||||
bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 new_value) {
|
||||
auto& monitor = system.Monitor();
|
||||
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
|
||||
const auto current_core = system.CurrentCoreIndex();
|
||||
|
||||
// TODO(bunnei): We should disable interrupts here via KScopedInterruptDisable.
|
||||
// TODO(bunnei): We should call CanAccessAtomic(..) here.
|
||||
|
||||
@@ -170,10 +170,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
private:
|
||||
void RegisterWithKernel();
|
||||
void UnregisterWithKernel();
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "core/hle/kernel/k_auto_object_container.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -35,7 +35,7 @@ bool WriteToUser(Core::System& system, VAddr address, const u32* p) {
|
||||
bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero,
|
||||
u32 new_orr_mask) {
|
||||
auto& monitor = system.Monitor();
|
||||
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
|
||||
const auto current_core = system.CurrentCoreIndex();
|
||||
|
||||
// Load the value from the address.
|
||||
const auto expected = monitor.ExclusiveRead32(current_core, address);
|
||||
|
||||
@@ -7,13 +7,12 @@
|
||||
namespace Kernel {
|
||||
|
||||
KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
|
||||
KHandleTable ::~KHandleTable() = default;
|
||||
KHandleTable::~KHandleTable() = default;
|
||||
|
||||
ResultCode KHandleTable::Finalize() {
|
||||
// Get the table and clear our record of it.
|
||||
u16 saved_table_size = 0;
|
||||
{
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
std::swap(m_table_size, saved_table_size);
|
||||
@@ -44,7 +43,6 @@ bool KHandleTable::Remove(Handle handle) {
|
||||
// Find the object and free the entry.
|
||||
KAutoObject* obj = nullptr;
|
||||
{
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
if (this->IsValidHandle(handle)) {
|
||||
@@ -63,7 +61,6 @@ bool KHandleTable::Remove(Handle handle) {
|
||||
}
|
||||
|
||||
ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
// Never exceed our capacity.
|
||||
@@ -86,7 +83,6 @@ ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
|
||||
}
|
||||
|
||||
ResultCode KHandleTable::Reserve(Handle* out_handle) {
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
// Never exceed our capacity.
|
||||
@@ -97,7 +93,6 @@ ResultCode KHandleTable::Reserve(Handle* out_handle) {
|
||||
}
|
||||
|
||||
void KHandleTable::Unreserve(Handle handle) {
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
// Unpack the handle.
|
||||
@@ -116,7 +111,6 @@ void KHandleTable::Unreserve(Handle handle) {
|
||||
}
|
||||
|
||||
void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) {
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
// Unpack the handle.
|
||||
|
||||
@@ -69,7 +69,6 @@ public:
|
||||
template <typename T = KAutoObject>
|
||||
KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const {
|
||||
// Lock and look up in table.
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
if constexpr (std::is_same_v<T, KAutoObject>) {
|
||||
@@ -124,7 +123,6 @@ public:
|
||||
size_t num_opened;
|
||||
{
|
||||
// Lock the table.
|
||||
KScopedDisableDispatch dd(kernel);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
for (num_opened = 0; num_opened < num_handles; num_opened++) {
|
||||
// Get the current handle.
|
||||
|
||||
@@ -22,12 +22,10 @@ class KThread;
|
||||
|
||||
template <typename T>
|
||||
concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) {
|
||||
{ t.GetAffinityMask() }
|
||||
->Common::ConvertibleTo<u64>;
|
||||
{ t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
|
||||
{t.SetAffinityMask(0)};
|
||||
|
||||
{ t.GetAffinity(0) }
|
||||
->std::same_as<bool>;
|
||||
{ t.GetAffinity(0) } -> std::same_as<bool>;
|
||||
{t.SetAffinity(0, false)};
|
||||
{t.SetAll()};
|
||||
};
|
||||
@@ -38,25 +36,20 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
|
||||
{(typename T::QueueEntry()).Initialize()};
|
||||
{(typename T::QueueEntry()).SetPrev(std::addressof(t))};
|
||||
{(typename T::QueueEntry()).SetNext(std::addressof(t))};
|
||||
{ (typename T::QueueEntry()).GetNext() }
|
||||
->std::same_as<T*>;
|
||||
{ (typename T::QueueEntry()).GetPrev() }
|
||||
->std::same_as<T*>;
|
||||
{ t.GetPriorityQueueEntry(0) }
|
||||
->std::same_as<typename T::QueueEntry&>;
|
||||
{ (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
|
||||
{ (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
|
||||
{ t.GetPriorityQueueEntry(0) } -> std::same_as<typename T::QueueEntry&>;
|
||||
|
||||
{t.GetAffinityMask()};
|
||||
{ std::remove_cvref_t<decltype(t.GetAffinityMask())>() }
|
||||
->KPriorityQueueAffinityMask;
|
||||
{ std::remove_cvref_t<decltype(t.GetAffinityMask())>() } -> KPriorityQueueAffinityMask;
|
||||
|
||||
{ t.GetActiveCore() }
|
||||
->Common::ConvertibleTo<s32>;
|
||||
{ t.GetPriority() }
|
||||
->Common::ConvertibleTo<s32>;
|
||||
{ t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
|
||||
{ t.GetPriority() } -> Common::ConvertibleTo<s32>;
|
||||
};
|
||||
|
||||
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
|
||||
requires KPriorityQueueMember<Member> class KPriorityQueue {
|
||||
requires KPriorityQueueMember<Member>
|
||||
class KPriorityQueue {
|
||||
public:
|
||||
using AffinityMaskType = std::remove_cv_t<
|
||||
std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_shared_memory_info.h"
|
||||
#include "core/hle/kernel/k_slab_heap.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@@ -59,7 +60,6 @@ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority
|
||||
thread->GetContext64().cpu_registers[0] = 0;
|
||||
thread->GetContext32().cpu_registers[1] = thread_handle;
|
||||
thread->GetContext64().cpu_registers[1] = thread_handle;
|
||||
thread->DisableDispatch();
|
||||
|
||||
auto& kernel = system.Kernel();
|
||||
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
|
||||
@@ -255,10 +255,26 @@ ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAdd
|
||||
// Lock ourselves, to prevent concurrent access.
|
||||
KScopedLightLock lk(state_lock);
|
||||
|
||||
// TODO(bunnei): Manage KSharedMemoryInfo list here.
|
||||
// Try to find an existing info for the memory.
|
||||
KSharedMemoryInfo* shemen_info = nullptr;
|
||||
const auto iter = std::find_if(
|
||||
shared_memory_list.begin(), shared_memory_list.end(),
|
||||
[shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
|
||||
if (iter != shared_memory_list.end()) {
|
||||
shemen_info = *iter;
|
||||
}
|
||||
|
||||
// Open a reference to the shared memory.
|
||||
if (shemen_info == nullptr) {
|
||||
shemen_info = KSharedMemoryInfo::Allocate(kernel);
|
||||
R_UNLESS(shemen_info != nullptr, ResultOutOfMemory);
|
||||
|
||||
shemen_info->Initialize(shmem);
|
||||
shared_memory_list.push_back(shemen_info);
|
||||
}
|
||||
|
||||
// Open a reference to the shared memory and its info.
|
||||
shmem->Open();
|
||||
shemen_info->Open();
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
@@ -268,7 +284,20 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
|
||||
// Lock ourselves, to prevent concurrent access.
|
||||
KScopedLightLock lk(state_lock);
|
||||
|
||||
// TODO(bunnei): Manage KSharedMemoryInfo list here.
|
||||
KSharedMemoryInfo* shemen_info = nullptr;
|
||||
const auto iter = std::find_if(
|
||||
shared_memory_list.begin(), shared_memory_list.end(),
|
||||
[shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
|
||||
if (iter != shared_memory_list.end()) {
|
||||
shemen_info = *iter;
|
||||
}
|
||||
|
||||
ASSERT(shemen_info != nullptr);
|
||||
|
||||
if (shemen_info->Close()) {
|
||||
shared_memory_list.erase(iter);
|
||||
KSharedMemoryInfo::Free(kernel, shemen_info);
|
||||
}
|
||||
|
||||
// Close a reference to the shared memory.
|
||||
shmem->Close();
|
||||
@@ -413,6 +442,24 @@ void KProcess::Finalize() {
|
||||
// Finalize the handle table and close any open handles.
|
||||
handle_table.Finalize();
|
||||
|
||||
// Free all shared memory infos.
|
||||
{
|
||||
auto it = shared_memory_list.begin();
|
||||
while (it != shared_memory_list.end()) {
|
||||
KSharedMemoryInfo* info = *it;
|
||||
KSharedMemory* shmem = info->GetSharedMemory();
|
||||
|
||||
while (!info->Close()) {
|
||||
shmem->Close();
|
||||
}
|
||||
|
||||
shmem->Close();
|
||||
|
||||
it = shared_memory_list.erase(it);
|
||||
KSharedMemoryInfo::Free(kernel, info);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform inherited finalization.
|
||||
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class KernelCore;
|
||||
class KPageTable;
|
||||
class KResourceLimit;
|
||||
class KThread;
|
||||
class KSharedMemoryInfo;
|
||||
class TLSPage;
|
||||
|
||||
struct CodeSet;
|
||||
@@ -448,6 +449,9 @@ private:
|
||||
/// List of threads that are running with this process as their owner.
|
||||
std::list<const KThread*> thread_list;
|
||||
|
||||
/// List of shared memory that are running with this process as their owner.
|
||||
std::list<KSharedMemoryInfo*> shared_memory_list;
|
||||
|
||||
/// Address of the top of the main thread's stack
|
||||
VAddr main_thread_stack_top{};
|
||||
|
||||
|
||||
@@ -376,18 +376,20 @@ void KScheduler::ClearSchedulerUpdateNeeded(KernelCore& kernel) {
|
||||
}
|
||||
|
||||
void KScheduler::DisableScheduling(KernelCore& kernel) {
|
||||
ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 0);
|
||||
GetCurrentThreadPointer(kernel)->DisableDispatch();
|
||||
if (auto* scheduler = kernel.CurrentScheduler(); scheduler) {
|
||||
ASSERT(scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 0);
|
||||
scheduler->GetCurrentThread()->DisableDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) {
|
||||
ASSERT(GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() >= 1);
|
||||
|
||||
if (GetCurrentThreadPointer(kernel)->GetDisableDispatchCount() > 1) {
|
||||
GetCurrentThreadPointer(kernel)->EnableDispatch();
|
||||
} else {
|
||||
RescheduleCores(kernel, cores_needing_scheduling);
|
||||
if (auto* scheduler = kernel.CurrentScheduler(); scheduler) {
|
||||
ASSERT(scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 1);
|
||||
if (scheduler->GetCurrentThread()->GetDisableDispatchCount() >= 1) {
|
||||
scheduler->GetCurrentThread()->EnableDispatch();
|
||||
}
|
||||
}
|
||||
RescheduleCores(kernel, cores_needing_scheduling);
|
||||
}
|
||||
|
||||
u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) {
|
||||
@@ -615,17 +617,13 @@ KScheduler::KScheduler(Core::System& system_, s32 core_id_) : system{system_}, c
|
||||
state.highest_priority_thread = nullptr;
|
||||
}
|
||||
|
||||
void KScheduler::Finalize() {
|
||||
KScheduler::~KScheduler() {
|
||||
if (idle_thread) {
|
||||
idle_thread->Close();
|
||||
idle_thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
KScheduler::~KScheduler() {
|
||||
ASSERT(!idle_thread);
|
||||
}
|
||||
|
||||
KThread* KScheduler::GetCurrentThread() const {
|
||||
if (auto result = current_thread.load(); result) {
|
||||
return result;
|
||||
@@ -644,12 +642,10 @@ void KScheduler::RescheduleCurrentCore() {
|
||||
if (phys_core.IsInterrupted()) {
|
||||
phys_core.ClearInterrupt();
|
||||
}
|
||||
|
||||
guard.Lock();
|
||||
if (state.needs_scheduling.load()) {
|
||||
Schedule();
|
||||
} else {
|
||||
GetCurrentThread()->EnableDispatch();
|
||||
guard.Unlock();
|
||||
}
|
||||
}
|
||||
@@ -659,33 +655,26 @@ void KScheduler::OnThreadStart() {
|
||||
}
|
||||
|
||||
void KScheduler::Unload(KThread* thread) {
|
||||
ASSERT(thread);
|
||||
|
||||
LOG_TRACE(Kernel, "core {}, unload thread {}", core_id, thread ? thread->GetName() : "nullptr");
|
||||
|
||||
if (thread->IsCallingSvc()) {
|
||||
thread->ClearIsCallingSvc();
|
||||
if (thread) {
|
||||
if (thread->IsCallingSvc()) {
|
||||
thread->ClearIsCallingSvc();
|
||||
}
|
||||
if (!thread->IsTerminationRequested()) {
|
||||
prev_thread = thread;
|
||||
|
||||
Core::ARM_Interface& cpu_core = system.ArmInterface(core_id);
|
||||
cpu_core.SaveContext(thread->GetContext32());
|
||||
cpu_core.SaveContext(thread->GetContext64());
|
||||
// Save the TPIDR_EL0 system register in case it was modified.
|
||||
thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
|
||||
cpu_core.ClearExclusiveState();
|
||||
} else {
|
||||
prev_thread = nullptr;
|
||||
}
|
||||
thread->context_guard.Unlock();
|
||||
}
|
||||
|
||||
auto& physical_core = system.Kernel().PhysicalCore(core_id);
|
||||
if (!physical_core.IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Core::ARM_Interface& cpu_core = physical_core.ArmInterface();
|
||||
cpu_core.SaveContext(thread->GetContext32());
|
||||
cpu_core.SaveContext(thread->GetContext64());
|
||||
// Save the TPIDR_EL0 system register in case it was modified.
|
||||
thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
|
||||
cpu_core.ClearExclusiveState();
|
||||
|
||||
if (!thread->IsTerminationRequested() && thread->GetActiveCore() == core_id) {
|
||||
prev_thread = thread;
|
||||
} else {
|
||||
prev_thread = nullptr;
|
||||
}
|
||||
|
||||
thread->context_guard.Unlock();
|
||||
}
|
||||
|
||||
void KScheduler::Reload(KThread* thread) {
|
||||
@@ -694,6 +683,11 @@ void KScheduler::Reload(KThread* thread) {
|
||||
if (thread) {
|
||||
ASSERT_MSG(thread->GetState() == ThreadState::Runnable, "Thread must be runnable.");
|
||||
|
||||
auto* const thread_owner_process = thread->GetOwnerProcess();
|
||||
if (thread_owner_process != nullptr) {
|
||||
system.Kernel().MakeCurrentProcess(thread_owner_process);
|
||||
}
|
||||
|
||||
Core::ARM_Interface& cpu_core = system.ArmInterface(core_id);
|
||||
cpu_core.LoadContext(thread->GetContext32());
|
||||
cpu_core.LoadContext(thread->GetContext64());
|
||||
@@ -711,7 +705,7 @@ void KScheduler::SwitchContextStep2() {
|
||||
}
|
||||
|
||||
void KScheduler::ScheduleImpl() {
|
||||
KThread* previous_thread = GetCurrentThread();
|
||||
KThread* previous_thread = current_thread.load();
|
||||
KThread* next_thread = state.highest_priority_thread;
|
||||
|
||||
state.needs_scheduling = false;
|
||||
@@ -723,15 +717,10 @@ void KScheduler::ScheduleImpl() {
|
||||
|
||||
// If we're not actually switching thread, there's nothing to do.
|
||||
if (next_thread == current_thread.load()) {
|
||||
previous_thread->EnableDispatch();
|
||||
guard.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (next_thread->GetCurrentCore() != core_id) {
|
||||
next_thread->SetCurrentCore(core_id);
|
||||
}
|
||||
|
||||
current_thread.store(next_thread);
|
||||
|
||||
KProcess* const previous_process = system.Kernel().CurrentProcess();
|
||||
@@ -742,7 +731,11 @@ void KScheduler::ScheduleImpl() {
|
||||
Unload(previous_thread);
|
||||
|
||||
std::shared_ptr<Common::Fiber>* old_context;
|
||||
old_context = &previous_thread->GetHostContext();
|
||||
if (previous_thread != nullptr) {
|
||||
old_context = &previous_thread->GetHostContext();
|
||||
} else {
|
||||
old_context = &idle_thread->GetHostContext();
|
||||
}
|
||||
guard.Unlock();
|
||||
|
||||
Common::Fiber::YieldTo(*old_context, *switch_fiber);
|
||||
|
||||
@@ -33,8 +33,6 @@ public:
|
||||
explicit KScheduler(Core::System& system_, s32 core_id_);
|
||||
~KScheduler();
|
||||
|
||||
void Finalize();
|
||||
|
||||
/// Reschedules to the next available thread (call after current thread is suspended)
|
||||
void RescheduleCurrentCore();
|
||||
|
||||
@@ -199,7 +197,7 @@ private:
|
||||
|
||||
class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> {
|
||||
public:
|
||||
explicit KScopedSchedulerLock(KernelCore & kernel);
|
||||
explicit KScopedSchedulerLock(KernelCore& kernel);
|
||||
~KScopedSchedulerLock();
|
||||
};
|
||||
|
||||
|
||||
@@ -13,19 +13,18 @@ namespace Kernel {
|
||||
|
||||
template <typename T>
|
||||
concept KLockable = !std::is_reference_v<T> && requires(T & t) {
|
||||
{ t.Lock() }
|
||||
->std::same_as<void>;
|
||||
{ t.Unlock() }
|
||||
->std::same_as<void>;
|
||||
{ t.Lock() } -> std::same_as<void>;
|
||||
{ t.Unlock() } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires KLockable<T> class [[nodiscard]] KScopedLock {
|
||||
requires KLockable<T>
|
||||
class [[nodiscard]] KScopedLock {
|
||||
public:
|
||||
explicit KScopedLock(T * l) : lock_ptr(l) {
|
||||
explicit KScopedLock(T* l) : lock_ptr(l) {
|
||||
this->lock_ptr->Lock();
|
||||
}
|
||||
explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {}
|
||||
explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) {}
|
||||
|
||||
~KScopedLock() {
|
||||
this->lock_ptr->Unlock();
|
||||
@@ -34,7 +33,7 @@ public:
|
||||
KScopedLock(const KScopedLock&) = delete;
|
||||
KScopedLock& operator=(const KScopedLock&) = delete;
|
||||
|
||||
KScopedLock(KScopedLock &&) = delete;
|
||||
KScopedLock(KScopedLock&&) = delete;
|
||||
KScopedLock& operator=(KScopedLock&&) = delete;
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Kernel {
|
||||
|
||||
class [[nodiscard]] KScopedSchedulerLockAndSleep {
|
||||
public:
|
||||
explicit KScopedSchedulerLockAndSleep(KernelCore & kernel_, KThread * t, s64 timeout)
|
||||
explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout)
|
||||
: kernel(kernel_), thread(t), timeout_tick(timeout) {
|
||||
// Lock the scheduler.
|
||||
kernel.GlobalSchedulerContext().scheduler_lock.Lock();
|
||||
|
||||
46
src/core/hle/kernel/k_shared_memory_info.h
Normal file
46
src/core/hle/kernel/k_shared_memory_info.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/hle/kernel/slab_helpers.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KSharedMemory;
|
||||
|
||||
class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>,
|
||||
public boost::intrusive::list_base_hook<> {
|
||||
|
||||
public:
|
||||
explicit KSharedMemoryInfo() = default;
|
||||
|
||||
constexpr void Initialize(KSharedMemory* shmem) {
|
||||
shared_memory = shmem;
|
||||
}
|
||||
|
||||
constexpr KSharedMemory* GetSharedMemory() const {
|
||||
return shared_memory;
|
||||
}
|
||||
|
||||
constexpr void Open() {
|
||||
++reference_count;
|
||||
}
|
||||
|
||||
constexpr bool Close() {
|
||||
return (--reference_count) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
KSharedMemory* shared_memory{};
|
||||
size_t reference_count{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "common/fiber.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/thread_queue_list.h"
|
||||
#include "core/core.h"
|
||||
#include "core/cpu_manager.h"
|
||||
@@ -189,7 +188,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
|
||||
// Setup the stack parameters.
|
||||
StackParameters& sp = GetStackParameters();
|
||||
sp.cur_thread = this;
|
||||
sp.disable_count = 0;
|
||||
sp.disable_count = 1;
|
||||
SetInExceptionHandler();
|
||||
|
||||
// Set thread ID.
|
||||
@@ -216,10 +215,9 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint
|
||||
// Initialize the thread.
|
||||
R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type));
|
||||
|
||||
// Initialize emulation parameters.
|
||||
// Initialize host context.
|
||||
thread->host_context =
|
||||
std::make_shared<Common::Fiber>(std::move(init_func), init_func_parameter);
|
||||
thread->is_single_core = !Settings::values.use_multi_core.GetValue();
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
@@ -972,9 +970,6 @@ ResultCode KThread::Run() {
|
||||
|
||||
// Set our state and finish.
|
||||
SetState(ThreadState::Runnable);
|
||||
|
||||
DisableDispatch();
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
@@ -1059,16 +1054,4 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
|
||||
return GetCurrentThread(kernel).GetCurrentCore();
|
||||
}
|
||||
|
||||
KScopedDisableDispatch::~KScopedDisableDispatch() {
|
||||
if (GetCurrentThread(kernel).GetDisableDispatchCount() <= 1) {
|
||||
auto scheduler = kernel.CurrentScheduler();
|
||||
|
||||
if (scheduler) {
|
||||
scheduler->RescheduleCurrentCore();
|
||||
}
|
||||
} else {
|
||||
GetCurrentThread(kernel).EnableDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -450,39 +450,16 @@ public:
|
||||
sleeping_queue = q;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsKernelThread() const {
|
||||
return GetActiveCore() == 3;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsDispatchTrackingDisabled() const {
|
||||
return is_single_core || IsKernelThread();
|
||||
}
|
||||
|
||||
[[nodiscard]] s32 GetDisableDispatchCount() const {
|
||||
if (IsDispatchTrackingDisabled()) {
|
||||
// TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
|
||||
return 1;
|
||||
}
|
||||
|
||||
return this->GetStackParameters().disable_count;
|
||||
}
|
||||
|
||||
void DisableDispatch() {
|
||||
if (IsDispatchTrackingDisabled()) {
|
||||
// TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0);
|
||||
this->GetStackParameters().disable_count++;
|
||||
}
|
||||
|
||||
void EnableDispatch() {
|
||||
if (IsDispatchTrackingDisabled()) {
|
||||
// TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0);
|
||||
this->GetStackParameters().disable_count--;
|
||||
}
|
||||
@@ -731,7 +708,6 @@ private:
|
||||
|
||||
// For emulation
|
||||
std::shared_ptr<Common::Fiber> host_context{};
|
||||
bool is_single_core{};
|
||||
|
||||
// For debugging
|
||||
std::vector<KSynchronizationObject*> wait_objects_for_debugging;
|
||||
@@ -776,16 +752,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class KScopedDisableDispatch {
|
||||
public:
|
||||
[[nodiscard]] explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} {
|
||||
GetCurrentThread(kernel).DisableDispatch();
|
||||
}
|
||||
|
||||
~KScopedDisableDispatch();
|
||||
|
||||
private:
|
||||
KernelCore& kernel;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -85,9 +85,8 @@ struct KernelCore::Impl {
|
||||
}
|
||||
|
||||
void InitializeCores() {
|
||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||
cores[core_id].Initialize(current_process->Is64BitProcess());
|
||||
system.Memory().SetCurrentPageTable(*current_process, core_id);
|
||||
for (auto& core : cores) {
|
||||
core.Initialize(current_process->Is64BitProcess());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +131,15 @@ struct KernelCore::Impl {
|
||||
next_user_process_id = KProcess::ProcessIDMin;
|
||||
next_thread_id = 1;
|
||||
|
||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||
if (suspend_threads[core_id]) {
|
||||
suspend_threads[core_id]->Close();
|
||||
suspend_threads[core_id] = nullptr;
|
||||
}
|
||||
|
||||
schedulers[core_id].reset();
|
||||
}
|
||||
|
||||
cores.clear();
|
||||
|
||||
global_handle_table->Finalize();
|
||||
@@ -159,16 +167,6 @@ struct KernelCore::Impl {
|
||||
CleanupObject(time_shared_mem);
|
||||
CleanupObject(system_resource_limit);
|
||||
|
||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||
if (suspend_threads[core_id]) {
|
||||
suspend_threads[core_id]->Close();
|
||||
suspend_threads[core_id] = nullptr;
|
||||
}
|
||||
|
||||
schedulers[core_id]->Finalize();
|
||||
schedulers[core_id].reset();
|
||||
}
|
||||
|
||||
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
|
||||
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
|
||||
|
||||
@@ -259,22 +257,33 @@ struct KernelCore::Impl {
|
||||
|
||||
void MakeCurrentProcess(KProcess* process) {
|
||||
current_process = process;
|
||||
}
|
||||
if (process == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Creates a new host thread ID, should only be called by GetHostThreadId
|
||||
u32 AllocateHostThreadId(std::optional<std::size_t> core_id) {
|
||||
if (core_id) {
|
||||
// The first for slots are reserved for CPU core threads
|
||||
ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
return static_cast<u32>(*core_id);
|
||||
} else {
|
||||
return next_host_thread_id++;
|
||||
const u32 core_id = GetCurrentHostThreadID();
|
||||
if (core_id < Core::Hardware::NUM_CPU_CORES) {
|
||||
system.Memory().SetCurrentPageTable(*process, core_id);
|
||||
}
|
||||
}
|
||||
|
||||
static inline thread_local u32 host_thread_id = UINT32_MAX;
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) {
|
||||
const thread_local auto host_thread_id{AllocateHostThreadId(core_id)};
|
||||
u32 GetHostThreadId(std::size_t core_id) {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
// The first four slots are reserved for CPU core threads
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
host_thread_id = static_cast<u32>(core_id);
|
||||
}
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId() {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
host_thread_id = next_host_thread_id++;
|
||||
}
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
@@ -818,20 +827,16 @@ const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
|
||||
return impl->cores[id];
|
||||
}
|
||||
|
||||
size_t KernelCore::CurrentPhysicalCoreIndex() const {
|
||||
const u32 core_id = impl->GetCurrentHostThreadID();
|
||||
if (core_id >= Core::Hardware::NUM_CPU_CORES) {
|
||||
return Core::Hardware::NUM_CPU_CORES - 1;
|
||||
}
|
||||
return core_id;
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
|
||||
return impl->cores[CurrentPhysicalCoreIndex()];
|
||||
u32 core_id = impl->GetCurrentHostThreadID();
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
return impl->cores[core_id];
|
||||
}
|
||||
|
||||
const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
|
||||
return impl->cores[CurrentPhysicalCoreIndex()];
|
||||
u32 core_id = impl->GetCurrentHostThreadID();
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
return impl->cores[core_id];
|
||||
}
|
||||
|
||||
Kernel::KScheduler* KernelCore::CurrentScheduler() {
|
||||
@@ -1024,9 +1029,6 @@ void KernelCore::Suspend(bool in_suspention) {
|
||||
impl->suspend_threads[core_id]->SetState(state);
|
||||
impl->suspend_threads[core_id]->SetWaitReasonForDebugging(
|
||||
ThreadWaitReasonForDebugging::Suspended);
|
||||
if (!should_suspend) {
|
||||
impl->suspend_threads[core_id]->DisableDispatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1041,11 +1043,13 @@ void KernelCore::ExceptionalExit() {
|
||||
}
|
||||
|
||||
void KernelCore::EnterSVCProfile() {
|
||||
impl->svc_ticks[CurrentPhysicalCoreIndex()] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
|
||||
std::size_t core = impl->GetCurrentHostThreadID();
|
||||
impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
|
||||
}
|
||||
|
||||
void KernelCore::ExitSVCProfile() {
|
||||
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
|
||||
std::size_t core = impl->GetCurrentHostThreadID();
|
||||
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
|
||||
}
|
||||
|
||||
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -48,6 +49,7 @@ class KScheduler;
|
||||
class KServerSession;
|
||||
class KSession;
|
||||
class KSharedMemory;
|
||||
class KSharedMemoryInfo;
|
||||
class KThread;
|
||||
class KTransferMemory;
|
||||
class KWritableEvent;
|
||||
@@ -146,9 +148,6 @@ public:
|
||||
/// Gets the an instance of the respective physical CPU core.
|
||||
const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;
|
||||
|
||||
/// Gets the current physical core index for the running host thread.
|
||||
std::size_t CurrentPhysicalCoreIndex() const;
|
||||
|
||||
/// Gets the sole instance of the Scheduler at the current running core.
|
||||
Kernel::KScheduler* CurrentScheduler();
|
||||
|
||||
@@ -311,6 +310,8 @@ public:
|
||||
return slab_heap_container->session;
|
||||
} else if constexpr (std::is_same_v<T, KSharedMemory>) {
|
||||
return slab_heap_container->shared_memory;
|
||||
} else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) {
|
||||
return slab_heap_container->shared_memory_info;
|
||||
} else if constexpr (std::is_same_v<T, KThread>) {
|
||||
return slab_heap_container->thread;
|
||||
} else if constexpr (std::is_same_v<T, KTransferMemory>) {
|
||||
@@ -364,6 +365,7 @@ private:
|
||||
KSlabHeap<KResourceLimit> resource_limit;
|
||||
KSlabHeap<KSession> session;
|
||||
KSlabHeap<KSharedMemory> shared_memory;
|
||||
KSlabHeap<KSharedMemoryInfo> shared_memory_info;
|
||||
KSlabHeap<KThread> thread;
|
||||
KSlabHeap<KTransferMemory> transfer_memory;
|
||||
KSlabHeap<KWritableEvent> writeable_event;
|
||||
|
||||
@@ -320,17 +320,19 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
|
||||
auto& kernel = system.Kernel();
|
||||
|
||||
KScopedAutoObject session =
|
||||
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
|
||||
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
|
||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
||||
|
||||
auto thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
{
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
thread->SetState(ThreadState::Waiting);
|
||||
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
|
||||
session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
|
||||
|
||||
{
|
||||
KScopedAutoObject session =
|
||||
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
|
||||
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
|
||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
||||
session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
|
||||
}
|
||||
}
|
||||
|
||||
KSynchronizationObject* dummy{};
|
||||
@@ -877,7 +879,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
|
||||
const u64 thread_ticks = current_thread->GetCpuTime();
|
||||
|
||||
out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
|
||||
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
|
||||
} else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
|
||||
out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "core/hle/service/acc/acc_su.h"
|
||||
#include "core/hle/service/acc/acc_u0.h"
|
||||
#include "core/hle/service/acc/acc_u1.h"
|
||||
#include "core/hle/service/acc/async_context.h"
|
||||
#include "core/hle/service/acc/errors.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/glue/arp.h"
|
||||
@@ -454,22 +455,6 @@ public:
|
||||
: IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {}
|
||||
};
|
||||
|
||||
class IAsyncContext final : public ServiceFramework<IAsyncContext> {
|
||||
public:
|
||||
explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSystemEvent"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "HasDone"},
|
||||
{3, nullptr, "GetResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ISessionObject final : public ServiceFramework<ISessionObject> {
|
||||
public:
|
||||
explicit ISessionObject(Core::System& system_, Common::UUID)
|
||||
@@ -504,16 +489,44 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class EnsureTokenIdCacheAsyncInterface final : public IAsyncContext {
|
||||
public:
|
||||
explicit EnsureTokenIdCacheAsyncInterface(Core::System& system_) : IAsyncContext{system_} {
|
||||
MarkComplete();
|
||||
}
|
||||
~EnsureTokenIdCacheAsyncInterface() = default;
|
||||
|
||||
void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool IsComplete() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cancel() override {}
|
||||
|
||||
ResultCode GetResult() const override {
|
||||
return ResultSuccess;
|
||||
}
|
||||
};
|
||||
|
||||
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
|
||||
public:
|
||||
explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_)
|
||||
: ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} {
|
||||
: ServiceFramework{system_, "IManagerForApplication"},
|
||||
ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
|
||||
user_id{user_id_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
|
||||
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
|
||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
{3, nullptr, "LoadIdTokenCache"},
|
||||
{2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"},
|
||||
{3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"},
|
||||
{130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"},
|
||||
{150, nullptr, "CreateAuthorizationRequest"},
|
||||
{160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
|
||||
@@ -540,6 +553,20 @@ private:
|
||||
rb.PushRaw<u64>(user_id.GetNintendoID());
|
||||
}
|
||||
|
||||
void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface(ensure_token_id);
|
||||
}
|
||||
|
||||
void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
ensure_token_id->LoadIdTokenCache(ctx);
|
||||
}
|
||||
|
||||
void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
@@ -562,6 +589,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
|
||||
Common::UUID user_id{Common::INVALID_UUID};
|
||||
};
|
||||
|
||||
@@ -901,8 +929,7 @@ void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContex
|
||||
}
|
||||
|
||||
const auto user_list = profile_manager->GetAllUsers();
|
||||
if (std::all_of(user_list.begin(), user_list.end(),
|
||||
[](const auto& user) { return user.uuid == Common::INVALID_UUID; })) {
|
||||
if (std::ranges::all_of(user_list, [](const auto& user) { return user.IsInvalid(); })) {
|
||||
rb.Push(ResultUnknown); // TODO(ogniK): Find the correct error code
|
||||
rb.PushRaw<u128>(Common::INVALID_UUID);
|
||||
return;
|
||||
|
||||
71
src/core/hle/service/acc/async_context.cpp
Normal file
71
src/core/hle/service/acc/async_context.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/acc/async_context.h"
|
||||
|
||||
namespace Service::Account {
|
||||
IAsyncContext::IAsyncContext(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAsyncContext"}, service_context{system_, "IAsyncContext"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"},
|
||||
{1, &IAsyncContext::Cancel, "Cancel"},
|
||||
{2, &IAsyncContext::HasDone, "HasDone"},
|
||||
{3, &IAsyncContext::GetResult, "GetResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
completion_event = service_context.CreateEvent("IAsyncContext:CompletionEvent");
|
||||
}
|
||||
|
||||
IAsyncContext::~IAsyncContext() {
|
||||
service_context.CloseEvent(completion_event);
|
||||
}
|
||||
|
||||
void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(completion_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
|
||||
Cancel();
|
||||
MarkComplete();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
|
||||
is_complete.store(IsComplete());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_complete.load());
|
||||
}
|
||||
|
||||
void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(GetResult());
|
||||
}
|
||||
|
||||
void IAsyncContext::MarkComplete() {
|
||||
is_complete.store(true);
|
||||
completion_event->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
} // namespace Service::Account
|
||||
40
src/core/hle/service/acc/async_context.h
Normal file
40
src/core/hle/service/acc/async_context.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2021 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Account {
|
||||
|
||||
class IAsyncContext : public ServiceFramework<IAsyncContext> {
|
||||
public:
|
||||
explicit IAsyncContext(Core::System& system_);
|
||||
~IAsyncContext() override;
|
||||
|
||||
void GetSystemEvent(Kernel::HLERequestContext& ctx);
|
||||
void Cancel(Kernel::HLERequestContext& ctx);
|
||||
void HasDone(Kernel::HLERequestContext& ctx);
|
||||
void GetResult(Kernel::HLERequestContext& ctx);
|
||||
|
||||
protected:
|
||||
virtual bool IsComplete() const = 0;
|
||||
virtual void Cancel() = 0;
|
||||
virtual ResultCode GetResult() const = 0;
|
||||
|
||||
void MarkComplete();
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
std::atomic<bool> is_complete{false};
|
||||
Kernel::KEvent* completion_event;
|
||||
};
|
||||
|
||||
} // namespace Service::Account
|
||||
@@ -208,9 +208,10 @@ bool ProfileManager::UserExists(UUID uuid) const {
|
||||
}
|
||||
|
||||
bool ProfileManager::UserExistsIndex(std::size_t index) const {
|
||||
if (index >= MAX_USERS)
|
||||
if (index >= MAX_USERS) {
|
||||
return false;
|
||||
return profiles[index].user_uuid.uuid != Common::INVALID_UUID;
|
||||
}
|
||||
return profiles[index].user_uuid.IsValid();
|
||||
}
|
||||
|
||||
/// Opens a specific user
|
||||
@@ -304,7 +305,7 @@ bool ProfileManager::RemoveUser(UUID uuid) {
|
||||
|
||||
bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
|
||||
const auto index = GetUserIndex(uuid);
|
||||
if (!index || profile_new.user_uuid == UUID(Common::INVALID_UUID)) {
|
||||
if (!index || profile_new.user_uuid.IsInvalid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ void ProfileManager::ParseUserSaveFile() {
|
||||
}
|
||||
|
||||
for (const auto& user : data.users) {
|
||||
if (user.uuid == UUID(Common::INVALID_UUID)) {
|
||||
if (user.uuid.IsInvalid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
@@ -254,8 +252,9 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
|
||||
IDebugFunctions::~IDebugFunctions() = default;
|
||||
|
||||
ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_)
|
||||
: ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_},
|
||||
launchable_event{system.Kernel()}, accumulated_suspended_tick_changed_event{system.Kernel()} {
|
||||
: ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_}, service_context{
|
||||
system,
|
||||
"ISelfController"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ISelfController::Exit, "Exit"},
|
||||
@@ -275,12 +274,14 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
|
||||
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
|
||||
{19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
|
||||
{20, nullptr, "SetDesirableKeyboardLayout"},
|
||||
{21, nullptr, "GetScreenShotProgramId"},
|
||||
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
|
||||
{41, nullptr, "IsSystemBufferSharingEnabled"},
|
||||
{42, nullptr, "GetSystemSharedLayerHandle"},
|
||||
{43, nullptr, "GetSystemSharedBufferHandle"},
|
||||
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
|
||||
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
|
||||
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
|
||||
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
|
||||
{51, nullptr, "ApproveToDisplay"},
|
||||
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
|
||||
@@ -302,15 +303,14 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
|
||||
{100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
|
||||
{110, nullptr, "SetApplicationAlbumUserData"},
|
||||
{120, nullptr, "SaveCurrentScreenshot"},
|
||||
{130, nullptr, "SetRecordVolumeMuted"},
|
||||
{1000, nullptr, "GetDebugStorageChannel"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(launchable_event));
|
||||
|
||||
launchable_event.Initialize("ISelfController:LaunchableEvent");
|
||||
launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
|
||||
|
||||
// This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
|
||||
// called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
|
||||
@@ -318,21 +318,23 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
|
||||
// suspended if the event has previously been created by a call to
|
||||
// GetAccumulatedSuspendedTickChangedEvent.
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(accumulated_suspended_tick_changed_event));
|
||||
accumulated_suspended_tick_changed_event.Initialize(
|
||||
"ISelfController:AccumulatedSuspendedTickChangedEvent");
|
||||
accumulated_suspended_tick_changed_event.GetWritableEvent().Signal();
|
||||
accumulated_suspended_tick_changed_event =
|
||||
service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
|
||||
accumulated_suspended_tick_changed_event->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
ISelfController::~ISelfController() = default;
|
||||
ISelfController::~ISelfController() {
|
||||
service_context.CloseEvent(launchable_event);
|
||||
service_context.CloseEvent(accumulated_suspended_tick_changed_event);
|
||||
}
|
||||
|
||||
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
system.Shutdown();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
||||
system.Exit();
|
||||
}
|
||||
|
||||
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
|
||||
@@ -380,11 +382,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
|
||||
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
launchable_event.GetWritableEvent().Signal();
|
||||
launchable_event->GetWritableEvent().Signal();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(launchable_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(launchable_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
|
||||
@@ -563,7 +565,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(accumulated_suspended_tick_changed_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) {
|
||||
@@ -581,40 +583,39 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestCo
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel)
|
||||
: on_new_message{kernel}, on_operation_mode_changed{kernel} {
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(on_new_message));
|
||||
Kernel::KAutoObject::Create(std::addressof(on_operation_mode_changed));
|
||||
|
||||
on_new_message.Initialize("AMMessageQueue:OnMessageReceived");
|
||||
on_operation_mode_changed.Initialize("AMMessageQueue:OperationModeChanged");
|
||||
AppletMessageQueue::AppletMessageQueue(Core::System& system)
|
||||
: service_context{system, "AppletMessageQueue"} {
|
||||
on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
|
||||
on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
|
||||
}
|
||||
|
||||
AppletMessageQueue::~AppletMessageQueue() = default;
|
||||
AppletMessageQueue::~AppletMessageQueue() {
|
||||
service_context.CloseEvent(on_new_message);
|
||||
service_context.CloseEvent(on_operation_mode_changed);
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
|
||||
return on_new_message.GetReadableEvent();
|
||||
return on_new_message->GetReadableEvent();
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
|
||||
return on_operation_mode_changed.GetReadableEvent();
|
||||
return on_operation_mode_changed->GetReadableEvent();
|
||||
}
|
||||
|
||||
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
||||
messages.push(msg);
|
||||
on_new_message.GetWritableEvent().Signal();
|
||||
on_new_message->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
||||
if (messages.empty()) {
|
||||
on_new_message.GetWritableEvent().Clear();
|
||||
on_new_message->GetWritableEvent().Clear();
|
||||
return AppletMessage::NoMessage;
|
||||
}
|
||||
auto msg = messages.front();
|
||||
messages.pop();
|
||||
if (messages.empty()) {
|
||||
on_new_message.GetWritableEvent().Clear();
|
||||
on_new_message->GetWritableEvent().Clear();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
@@ -634,7 +635,7 @@ void AppletMessageQueue::FocusStateChanged() {
|
||||
void AppletMessageQueue::OperationModeChanged() {
|
||||
PushMessage(AppletMessage::OperationModeChanged);
|
||||
PushMessage(AppletMessage::PerformanceModeChanged);
|
||||
on_operation_mode_changed.GetWritableEvent().Signal();
|
||||
on_operation_mode_changed->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||
@@ -683,6 +684,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||
{91, nullptr, "GetCurrentPerformanceConfiguration"},
|
||||
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
|
||||
{110, nullptr, "OpenMyGpuErrorHandler"},
|
||||
{120, nullptr, "GetAppletLaunchedHistory"},
|
||||
{200, nullptr, "GetOperationModeSystemInfo"},
|
||||
{300, nullptr, "GetSettingsPlatformRegion"},
|
||||
{400, nullptr, "ActivateMigrationService"},
|
||||
@@ -1268,9 +1270,8 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
|
||||
}
|
||||
|
||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()},
|
||||
friend_invitation_storage_channel_event{system.Kernel()},
|
||||
health_warning_disappeared_system_event{system.Kernel()} {
|
||||
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
||||
"IApplicationFunctions"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
||||
@@ -1322,7 +1323,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
|
||||
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
|
||||
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
|
||||
{150, nullptr, "GetNotificationStorageChannelEvent"},
|
||||
{150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
|
||||
{151, nullptr, "TryPopFromNotificationStorageChannel"},
|
||||
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
|
||||
{170, nullptr, "SetHdcpAuthenticationActivated"},
|
||||
@@ -1338,18 +1339,22 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event));
|
||||
|
||||
gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent");
|
||||
friend_invitation_storage_channel_event.Initialize(
|
||||
"IApplicationFunctions:FriendInvitationStorageChannelEvent");
|
||||
health_warning_disappeared_system_event.Initialize(
|
||||
"IApplicationFunctions:HealthWarningDisappearedSystemEvent");
|
||||
gpu_error_detected_event =
|
||||
service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
|
||||
friend_invitation_storage_channel_event =
|
||||
service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
|
||||
notification_storage_channel_event =
|
||||
service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
|
||||
health_warning_disappeared_system_event =
|
||||
service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
|
||||
}
|
||||
|
||||
IApplicationFunctions::~IApplicationFunctions() = default;
|
||||
IApplicationFunctions::~IApplicationFunctions() {
|
||||
service_context.CloseEvent(gpu_error_detected_event);
|
||||
service_context.CloseEvent(friend_invitation_storage_channel_event);
|
||||
service_context.CloseEvent(notification_storage_channel_event);
|
||||
service_context.CloseEvent(health_warning_disappeared_system_event);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
@@ -1743,7 +1748,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(gpu_error_detected_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
|
||||
@@ -1751,7 +1756,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(friend_invitation_storage_channel_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
|
||||
@@ -1762,17 +1767,25 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
|
||||
rb.Push(ERR_NO_DATA_IN_CHANNEL);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(health_warning_disappeared_system_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
|
||||
Core::System& system) {
|
||||
auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
|
||||
auto message_queue = std::make_shared<AppletMessageQueue>(system);
|
||||
// Needed on game boot
|
||||
message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
|
||||
@@ -1785,8 +1798,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
|
||||
}
|
||||
|
||||
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IHomeMenuFunctions"}, pop_from_general_channel_event{
|
||||
system.Kernel()} {
|
||||
: ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
|
||||
"IHomeMenuFunctions"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
|
||||
@@ -1807,11 +1820,13 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(pop_from_general_channel_event));
|
||||
pop_from_general_channel_event.Initialize("IHomeMenuFunctions:PopFromGeneralChannelEvent");
|
||||
pop_from_general_channel_event =
|
||||
service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
|
||||
}
|
||||
|
||||
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
||||
IHomeMenuFunctions::~IHomeMenuFunctions() {
|
||||
service_context.CloseEvent(pop_from_general_channel_event);
|
||||
}
|
||||
|
||||
void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
@@ -1825,7 +1840,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(pop_from_general_channel_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
IGlobalStateController::IGlobalStateController(Core::System& system_)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
PerformanceModeChanged = 31,
|
||||
};
|
||||
|
||||
explicit AppletMessageQueue(Kernel::KernelCore& kernel);
|
||||
explicit AppletMessageQueue(Core::System& system);
|
||||
~AppletMessageQueue();
|
||||
|
||||
Kernel::KReadableEvent& GetMessageReceiveEvent();
|
||||
@@ -66,9 +66,12 @@ public:
|
||||
void OperationModeChanged();
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* on_new_message;
|
||||
Kernel::KEvent* on_operation_mode_changed;
|
||||
|
||||
std::queue<AppletMessage> messages;
|
||||
Kernel::KEvent on_new_message;
|
||||
Kernel::KEvent on_operation_mode_changed;
|
||||
};
|
||||
|
||||
class IWindowController final : public ServiceFramework<IWindowController> {
|
||||
@@ -156,8 +159,11 @@ private:
|
||||
};
|
||||
|
||||
NVFlinger::NVFlinger& nvflinger;
|
||||
Kernel::KEvent launchable_event;
|
||||
Kernel::KEvent accumulated_suspended_tick_changed_event;
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* launchable_event;
|
||||
Kernel::KEvent* accumulated_suspended_tick_changed_event;
|
||||
|
||||
u32 idle_time_detection_extension = 0;
|
||||
u64 num_fatal_sections_entered = 0;
|
||||
@@ -295,14 +301,18 @@ private:
|
||||
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
|
||||
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
|
||||
void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
|
||||
void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx);
|
||||
void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
bool launch_popped_application_specific = false;
|
||||
bool launch_popped_account_preselect = false;
|
||||
s32 previous_program_index{-1};
|
||||
Kernel::KEvent gpu_error_detected_event;
|
||||
Kernel::KEvent friend_invitation_storage_channel_event;
|
||||
Kernel::KEvent health_warning_disappeared_system_event;
|
||||
Kernel::KEvent* gpu_error_detected_event;
|
||||
Kernel::KEvent* friend_invitation_storage_channel_event;
|
||||
Kernel::KEvent* notification_storage_channel_event;
|
||||
Kernel::KEvent* health_warning_disappeared_system_event;
|
||||
};
|
||||
|
||||
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
||||
@@ -314,7 +324,9 @@ private:
|
||||
void RequestToGetForeground(Kernel::HLERequestContext& ctx);
|
||||
void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
Kernel::KEvent pop_from_general_channel_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* pop_from_general_channel_event;
|
||||
};
|
||||
|
||||
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service {
|
||||
|
||||
@@ -16,6 +16,30 @@
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
struct ErrorCode {
|
||||
u32 error_category{};
|
||||
u32 error_number{};
|
||||
|
||||
static constexpr ErrorCode FromU64(u64 error_code) {
|
||||
return {
|
||||
.error_category{static_cast<u32>(error_code >> 32)},
|
||||
.error_number{static_cast<u32>(error_code & 0xFFFFFFFF)},
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr ErrorCode FromResultCode(ResultCode result) {
|
||||
return {
|
||||
.error_category{2000 + static_cast<u32>(result.module.Value())},
|
||||
.error_number{result.description.Value()},
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ResultCode ToResultCode() const {
|
||||
return ResultCode{static_cast<ErrorModule>(error_category - 2000), error_number};
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct ShowError {
|
||||
u8 mode;
|
||||
@@ -76,12 +100,7 @@ void CopyArgumentData(const std::vector<u8>& data, T& variable) {
|
||||
}
|
||||
|
||||
ResultCode Decode64BitError(u64 error) {
|
||||
const auto description = (error >> 32) & 0x1FFF;
|
||||
auto module = error & 0x3FF;
|
||||
if (module >= 2000)
|
||||
module -= 2000;
|
||||
module &= 0x1FF;
|
||||
return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
|
||||
return ErrorCode::FromU64(error).ToResultCode();
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
@@ -60,7 +60,7 @@ void ProfileSelect::Execute() {
|
||||
void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
|
||||
UserSelectionOutput output{};
|
||||
|
||||
if (uuid.has_value() && uuid->uuid != Common::INVALID_UUID) {
|
||||
if (uuid.has_value() && uuid->IsValid()) {
|
||||
output.result = 0;
|
||||
output.uuid_selected = uuid->uuid;
|
||||
} else {
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
#include "core/frontend/applets/profile_select.h"
|
||||
#include "core/frontend/applets/software_keyboard.h"
|
||||
#include "core/frontend/applets/web_browser.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
@@ -29,19 +28,19 @@
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
|
||||
: system{system_}, applet_mode{applet_mode_}, state_changed_event{system.Kernel()},
|
||||
pop_out_data_event{system.Kernel()}, pop_interactive_out_data_event{system.Kernel()} {
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(state_changed_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(pop_out_data_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(pop_interactive_out_data_event));
|
||||
|
||||
state_changed_event.Initialize("ILibraryAppletAccessor:StateChangedEvent");
|
||||
pop_out_data_event.Initialize("ILibraryAppletAccessor:PopDataOutEvent");
|
||||
pop_interactive_out_data_event.Initialize("ILibraryAppletAccessor:PopInteractiveDataOutEvent");
|
||||
: system{system_}, applet_mode{applet_mode_}, service_context{system,
|
||||
"ILibraryAppletAccessor"} {
|
||||
state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent");
|
||||
pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent");
|
||||
pop_interactive_out_data_event =
|
||||
service_context.CreateEvent("ILibraryAppletAccessor:PopInteractiveDataOutEvent");
|
||||
}
|
||||
|
||||
AppletDataBroker::~AppletDataBroker() = default;
|
||||
AppletDataBroker::~AppletDataBroker() {
|
||||
service_context.CloseEvent(state_changed_event);
|
||||
service_context.CloseEvent(pop_out_data_event);
|
||||
service_context.CloseEvent(pop_interactive_out_data_event);
|
||||
}
|
||||
|
||||
AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const {
|
||||
std::vector<std::vector<u8>> out_normal;
|
||||
@@ -65,7 +64,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
|
||||
|
||||
auto out = std::move(out_channel.front());
|
||||
out_channel.pop_front();
|
||||
pop_out_data_event.GetWritableEvent().Clear();
|
||||
pop_out_data_event->GetWritableEvent().Clear();
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -84,7 +83,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
|
||||
|
||||
auto out = std::move(out_interactive_channel.front());
|
||||
out_interactive_channel.pop_front();
|
||||
pop_interactive_out_data_event.GetWritableEvent().Clear();
|
||||
pop_interactive_out_data_event->GetWritableEvent().Clear();
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -103,7 +102,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag
|
||||
|
||||
void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
|
||||
out_channel.emplace_back(std::move(storage));
|
||||
pop_out_data_event.GetWritableEvent().Signal();
|
||||
pop_out_data_event->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
|
||||
@@ -112,11 +111,11 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s
|
||||
|
||||
void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
|
||||
out_interactive_channel.emplace_back(std::move(storage));
|
||||
pop_interactive_out_data_event.GetWritableEvent().Signal();
|
||||
pop_interactive_out_data_event->GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
void AppletDataBroker::SignalStateChanged() {
|
||||
state_changed_event.GetWritableEvent().Signal();
|
||||
state_changed_event->GetWritableEvent().Signal();
|
||||
|
||||
switch (applet_mode) {
|
||||
case LibraryAppletMode::AllForeground:
|
||||
@@ -141,15 +140,15 @@ void AppletDataBroker::SignalStateChanged() {
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& AppletDataBroker::GetNormalDataEvent() {
|
||||
return pop_out_data_event.GetReadableEvent();
|
||||
return pop_out_data_event->GetReadableEvent();
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& AppletDataBroker::GetInteractiveDataEvent() {
|
||||
return pop_interactive_out_data_event.GetReadableEvent();
|
||||
return pop_interactive_out_data_event->GetReadableEvent();
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& AppletDataBroker::GetStateChangedEvent() {
|
||||
return state_changed_event.GetReadableEvent();
|
||||
return state_changed_event->GetReadableEvent();
|
||||
}
|
||||
|
||||
Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <queue>
|
||||
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
|
||||
union ResultCode;
|
||||
|
||||
@@ -105,6 +105,8 @@ private:
|
||||
Core::System& system;
|
||||
LibraryAppletMode applet_mode;
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
// Queues are named from applet's perspective
|
||||
|
||||
// PopNormalDataToApplet and PushNormalDataFromGame
|
||||
@@ -119,13 +121,13 @@ private:
|
||||
// PopInteractiveDataToGame and PushInteractiveDataFromApplet
|
||||
std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
|
||||
|
||||
Kernel::KEvent state_changed_event;
|
||||
Kernel::KEvent* state_changed_event;
|
||||
|
||||
// Signaled on PushNormalDataFromApplet
|
||||
Kernel::KEvent pop_out_data_event;
|
||||
Kernel::KEvent* pop_out_data_event;
|
||||
|
||||
// Signaled on PushInteractiveDataFromApplet
|
||||
Kernel::KEvent pop_interactive_out_data_event;
|
||||
Kernel::KEvent* pop_interactive_out_data_event;
|
||||
};
|
||||
|
||||
class Applet {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/aoc/aoc_u.h"
|
||||
#include "core/loader/loader.h"
|
||||
@@ -49,7 +49,8 @@ static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
|
||||
class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> {
|
||||
public:
|
||||
explicit IPurchaseEventManager(Core::System& system_)
|
||||
: ServiceFramework{system_, "IPurchaseEventManager"}, purchased_event{system.Kernel()} {
|
||||
: ServiceFramework{system_, "IPurchaseEventManager"}, service_context{
|
||||
system, "IPurchaseEventManager"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"},
|
||||
@@ -62,8 +63,11 @@ public:
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(purchased_event));
|
||||
purchased_event.Initialize("IPurchaseEventManager:PurchasedEvent");
|
||||
purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent");
|
||||
}
|
||||
|
||||
~IPurchaseEventManager() override {
|
||||
service_context.CloseEvent(purchased_event);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -96,15 +100,17 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(purchased_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(purchased_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
Kernel::KEvent purchased_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* purchased_event;
|
||||
};
|
||||
|
||||
AOC_U::AOC_U(Core::System& system_)
|
||||
: ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)},
|
||||
aoc_change_event{system.Kernel()} {
|
||||
service_context{system_, "aoc:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CountAddOnContentByApplicationId"},
|
||||
@@ -126,11 +132,12 @@ AOC_U::AOC_U(Core::System& system_)
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(aoc_change_event));
|
||||
aoc_change_event.Initialize("GetAddOnContentListChanged:Event");
|
||||
aoc_change_event = service_context.CreateEvent("GetAddOnContentListChanged:Event");
|
||||
}
|
||||
|
||||
AOC_U::~AOC_U() = default;
|
||||
AOC_U::~AOC_U() {
|
||||
service_context.CloseEvent(aoc_change_event);
|
||||
}
|
||||
|
||||
void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
|
||||
struct Parameters {
|
||||
@@ -254,7 +261,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(aoc_change_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void AOC_U::GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestContext& ctx) {
|
||||
@@ -262,7 +269,7 @@ void AOC_U::GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestConte
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(aoc_change_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -33,7 +33,9 @@ private:
|
||||
void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
|
||||
|
||||
std::vector<u64> add_on_content;
|
||||
Kernel::KEvent aoc_change_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* aoc_change_event;
|
||||
};
|
||||
|
||||
/// Registers all AOC services with the specified service manager.
|
||||
|
||||
@@ -41,6 +41,14 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
|
||||
{27, nullptr, "SetVolumeMappingTableForDev"},
|
||||
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{30, nullptr, "Unknown30"},
|
||||
{31, nullptr, "Unknown31"},
|
||||
{32, nullptr, "Unknown32"},
|
||||
{33, nullptr, "Unknown33"},
|
||||
{34, nullptr, "Unknown34"},
|
||||
{10000, nullptr, "Unknown10000"},
|
||||
{10001, nullptr, "Unknown10001"},
|
||||
{10002, nullptr, "Unknown10002"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -3,38 +3,65 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/audio/audin_u.h"
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
class IAudioIn final : public ServiceFramework<IAudioIn> {
|
||||
public:
|
||||
explicit IAudioIn(Core::System& system_) : ServiceFramework{system_, "IAudioIn"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetAudioInState"},
|
||||
{1, nullptr, "Start"},
|
||||
{2, nullptr, "Stop"},
|
||||
{3, nullptr, "AppendAudioInBuffer"},
|
||||
{4, nullptr, "RegisterBufferEvent"},
|
||||
{5, nullptr, "GetReleasedAudioInBuffer"},
|
||||
{6, nullptr, "ContainsAudioInBuffer"},
|
||||
{7, nullptr, "AppendUacInBuffer"},
|
||||
{8, nullptr, "AppendAudioInBufferAuto"},
|
||||
{9, nullptr, "GetReleasedAudioInBuffersAuto"},
|
||||
{10, nullptr, "AppendUacInBufferAuto"},
|
||||
{11, nullptr, "GetAudioInBufferCount"},
|
||||
{12, nullptr, "SetDeviceGain"},
|
||||
{13, nullptr, "GetDeviceGain"},
|
||||
{14, nullptr, "FlushAudioInBuffers"},
|
||||
};
|
||||
// clang-format on
|
||||
IAudioIn::IAudioIn(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAudioIn"}, service_context{system_, "IAudioIn"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetAudioInState"},
|
||||
{1, &IAudioIn::Start, "Start"},
|
||||
{2, nullptr, "Stop"},
|
||||
{3, nullptr, "AppendAudioInBuffer"},
|
||||
{4, &IAudioIn::RegisterBufferEvent, "RegisterBufferEvent"},
|
||||
{5, nullptr, "GetReleasedAudioInBuffer"},
|
||||
{6, nullptr, "ContainsAudioInBuffer"},
|
||||
{7, nullptr, "AppendUacInBuffer"},
|
||||
{8, &IAudioIn::AppendAudioInBufferAuto, "AppendAudioInBufferAuto"},
|
||||
{9, nullptr, "GetReleasedAudioInBuffersAuto"},
|
||||
{10, nullptr, "AppendUacInBufferAuto"},
|
||||
{11, nullptr, "GetAudioInBufferCount"},
|
||||
{12, nullptr, "SetDeviceGain"},
|
||||
{13, nullptr, "GetDeviceGain"},
|
||||
{14, nullptr, "FlushAudioInBuffers"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
buffer_event = service_context.CreateEvent("IAudioIn:BufferEvent");
|
||||
}
|
||||
|
||||
IAudioIn::~IAudioIn() {
|
||||
service_context.CloseEvent(buffer_event);
|
||||
}
|
||||
|
||||
void IAudioIn::Start(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IAudioIn::RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(buffer_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IAudioIn::AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
AudInU::AudInU(Core::System& system_) : ServiceFramework{system_, "audin:u"} {
|
||||
// clang-format off
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -16,6 +17,21 @@ class HLERequestContext;
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
class IAudioIn final : public ServiceFramework<IAudioIn> {
|
||||
public:
|
||||
explicit IAudioIn(Core::System& system_);
|
||||
~IAudioIn() override;
|
||||
|
||||
private:
|
||||
void Start(Kernel::HLERequestContext& ctx);
|
||||
void RegisterBufferEvent(Kernel::HLERequestContext& ctx);
|
||||
void AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* buffer_event;
|
||||
};
|
||||
|
||||
class AudInU final : public ServiceFramework<AudInU> {
|
||||
public:
|
||||
explicit AudInU(Core::System& system_);
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/audio/audout_u.h"
|
||||
#include "core/hle/service/audio/errors.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Service::Audio {
|
||||
@@ -41,11 +39,12 @@ enum class AudioState : u32 {
|
||||
|
||||
class IAudioOut final : public ServiceFramework<IAudioOut> {
|
||||
public:
|
||||
IAudioOut(Core::System& system_, AudoutParams audio_params_, AudioCore::AudioOut& audio_core_,
|
||||
std::string&& device_name_, std::string&& unique_name)
|
||||
: ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, device_name{std::move(
|
||||
device_name_)},
|
||||
audio_params{audio_params_}, buffer_event{system.Kernel()}, main_memory{system.Memory()} {
|
||||
explicit IAudioOut(Core::System& system_, AudoutParams audio_params_,
|
||||
AudioCore::AudioOut& audio_core_, std::string&& device_name_,
|
||||
std::string&& unique_name)
|
||||
: ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_},
|
||||
device_name{std::move(device_name_)}, audio_params{audio_params_},
|
||||
main_memory{system.Memory()}, service_context{system_, "IAudioOut"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
|
||||
@@ -67,16 +66,19 @@ public:
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// This is the event handle used to check if the audio buffer was released
|
||||
Kernel::KAutoObject::Create(std::addressof(buffer_event));
|
||||
buffer_event.Initialize("IAudioOutBufferReleased");
|
||||
buffer_event = service_context.CreateEvent("IAudioOutBufferReleased");
|
||||
|
||||
stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
|
||||
audio_params.channel_count, std::move(unique_name), [this] {
|
||||
const auto guard = LockService();
|
||||
buffer_event.GetWritableEvent().Signal();
|
||||
buffer_event->GetWritableEvent().Signal();
|
||||
});
|
||||
}
|
||||
|
||||
~IAudioOut() override {
|
||||
service_context.CloseEvent(buffer_event);
|
||||
}
|
||||
|
||||
private:
|
||||
struct AudioBuffer {
|
||||
u64_le next;
|
||||
@@ -126,7 +128,7 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(buffer_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(buffer_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
|
||||
@@ -227,9 +229,12 @@ private:
|
||||
|
||||
[[maybe_unused]] AudoutParams audio_params{};
|
||||
|
||||
/// This is the event handle used to check if the audio buffer was released
|
||||
Kernel::KEvent buffer_event;
|
||||
Core::Memory::Memory& main_memory;
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
/// This is the event handle used to check if the audio buffer was released
|
||||
Kernel::KEvent* buffer_event;
|
||||
};
|
||||
|
||||
AudOutU::AudOutU(Core::System& system_) : ServiceFramework{system_, "audout:u"} {
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/audio/audren_u.h"
|
||||
#include "core/hle/service/audio/errors.h"
|
||||
@@ -30,7 +27,7 @@ public:
|
||||
explicit IAudioRenderer(Core::System& system_,
|
||||
const AudioCommon::AudioRendererParameter& audren_params,
|
||||
const std::size_t instance_number)
|
||||
: ServiceFramework{system_, "IAudioRenderer"}, system_event{system.Kernel()} {
|
||||
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
|
||||
@@ -49,17 +46,20 @@ public:
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(system_event));
|
||||
system_event.Initialize("IAudioRenderer:SystemEvent");
|
||||
system_event = service_context.CreateEvent("IAudioRenderer:SystemEvent");
|
||||
renderer = std::make_unique<AudioCore::AudioRenderer>(
|
||||
system.CoreTiming(), system.Memory(), audren_params,
|
||||
[this]() {
|
||||
const auto guard = LockService();
|
||||
system_event.GetWritableEvent().Signal();
|
||||
system_event->GetWritableEvent().Signal();
|
||||
},
|
||||
instance_number);
|
||||
}
|
||||
|
||||
~IAudioRenderer() override {
|
||||
service_context.CloseEvent(system_event);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetSampleRate(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
@@ -130,7 +130,7 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(system_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(system_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
|
||||
@@ -164,14 +164,16 @@ private:
|
||||
rb.Push(ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
Kernel::KEvent system_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* system_event;
|
||||
std::unique_ptr<AudioCore::AudioRenderer> renderer;
|
||||
u32 rendering_time_limit_percent = 100;
|
||||
};
|
||||
|
||||
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
|
||||
public:
|
||||
explicit IAudioDevice(Core::System& system_, Kernel::KEvent& buffer_event_, u32_le revision_)
|
||||
explicit IAudioDevice(Core::System& system_, Kernel::KEvent* buffer_event_, u32_le revision_)
|
||||
: ServiceFramework{system_, "IAudioDevice"}, buffer_event{buffer_event_}, revision{
|
||||
revision_} {
|
||||
static const FunctionInfo functions[] = {
|
||||
@@ -187,7 +189,8 @@ public:
|
||||
{10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
|
||||
{11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
|
||||
{12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
|
||||
{13, nullptr, "GetAudioSystemMasterVolumeSetting"},
|
||||
{13, nullptr, "GetActiveAudioOutputDeviceName"},
|
||||
{14, nullptr, "ListAudioOutputDeviceName"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
@@ -278,11 +281,11 @@ private:
|
||||
void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Audio, "(STUBBED) called");
|
||||
|
||||
buffer_event.GetWritableEvent().Signal();
|
||||
buffer_event->GetWritableEvent().Signal();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(buffer_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(buffer_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
|
||||
@@ -299,7 +302,7 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(buffer_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(buffer_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) {
|
||||
@@ -307,16 +310,15 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(buffer_event.GetReadableEvent());
|
||||
rb.PushCopyObjects(buffer_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
Kernel::KEvent& buffer_event;
|
||||
Kernel::KEvent* buffer_event;
|
||||
u32_le revision = 0;
|
||||
};
|
||||
|
||||
AudRenU::AudRenU(Core::System& system_)
|
||||
: ServiceFramework{system_, "audren:u"}, buffer_event{system.Kernel()} {
|
||||
|
||||
: ServiceFramework{system_, "audren:u"}, service_context{system_, "audren:u"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
|
||||
@@ -329,11 +331,12 @@ AudRenU::AudRenU(Core::System& system_)
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(buffer_event));
|
||||
buffer_event.Initialize("IAudioOutBufferReleasedEvent");
|
||||
buffer_event = service_context.CreateEvent("IAudioOutBufferReleasedEvent");
|
||||
}
|
||||
|
||||
AudRenU::~AudRenU() = default;
|
||||
AudRenU::~AudRenU() {
|
||||
service_context.CloseEvent(buffer_event);
|
||||
}
|
||||
|
||||
void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Audio, "called");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -31,8 +31,10 @@ private:
|
||||
|
||||
void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
std::size_t audren_instance_count = 0;
|
||||
Kernel::KEvent buffer_event;
|
||||
Kernel::KEvent* buffer_event;
|
||||
};
|
||||
|
||||
// Describes a particular audio feature that may be supported in a particular revision.
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/service/audio/hwopus.h"
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user