Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48bf837d27 |
No files matched your search
@@ -18,8 +18,7 @@ cmake .. \
|
||||
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||
-DENABLE_QT_TRANSLATION=ON \
|
||||
-DUSE_DISCORD_PRESENCE=ON \
|
||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||
-DYUZU_USE_BUNDLED_FFMPEG=ON
|
||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"}
|
||||
|
||||
make -j$(nproc)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ stages:
|
||||
displayName: 'build'
|
||||
jobs:
|
||||
- job: build
|
||||
timeoutInMinutes: 120
|
||||
displayName: 'standard'
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
@@ -44,7 +43,6 @@ stages:
|
||||
displayName: 'build-windows'
|
||||
jobs:
|
||||
- job: build
|
||||
timeoutInMinutes: 120
|
||||
displayName: 'msvc'
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
@@ -67,4 +65,4 @@ stages:
|
||||
- job: github
|
||||
displayName: 'github'
|
||||
steps:
|
||||
- template: ./templates/release-github.yml
|
||||
- template: ./templates/release-github.yml
|
||||
+33
-132
@@ -13,7 +13,7 @@ project(yuzu)
|
||||
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
|
||||
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
|
||||
option(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" OFF)
|
||||
|
||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
||||
@@ -25,7 +25,7 @@ option(YUZU_USE_BUNDLED_BOOST "Download bundled Boost" OFF)
|
||||
|
||||
option(YUZU_USE_BUNDLED_LIBUSB "Compile bundled libusb" OFF)
|
||||
|
||||
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ON "WIN32" OFF)
|
||||
|
||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||
|
||||
@@ -254,9 +254,7 @@ if(ENABLE_QT)
|
||||
|
||||
# Check for system Qt on Linux, fallback to bundled Qt
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
if (NOT YUZU_USE_BUNDLED_QT)
|
||||
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets)
|
||||
endif()
|
||||
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets)
|
||||
if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)
|
||||
# Check for dependencies, then enable bundled Qt download
|
||||
|
||||
@@ -339,8 +337,6 @@ if(ENABLE_QT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH)
|
||||
|
||||
# Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries
|
||||
set(QT_PREFIX_HINT)
|
||||
|
||||
@@ -358,10 +354,8 @@ if(ENABLE_QT)
|
||||
endif()
|
||||
|
||||
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
|
||||
|
||||
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
|
||||
endif()
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} NO_CMAKE_SYSTEM_PATH)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
@@ -376,7 +370,7 @@ 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)
|
||||
set(SDL2_VER "SDL2-2.0.16")
|
||||
set(SDL2_VER "SDL2-2.0.15-prerelease")
|
||||
else()
|
||||
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
|
||||
endif()
|
||||
@@ -393,20 +387,26 @@ if (ENABLE_SDL2)
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
|
||||
target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
|
||||
elseif (YUZU_USE_EXTERNAL_SDL2)
|
||||
message(STATUS "Using SDL2 from externals.")
|
||||
else()
|
||||
find_package(SDL2 2.0.16 REQUIRED)
|
||||
if (YUZU_ALLOW_SYSTEM_SDL2)
|
||||
find_package(SDL2 2.0.15 QUIET)
|
||||
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
if (SDL2_FOUND)
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
else()
|
||||
message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using SDL2 from externals.")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -496,7 +496,7 @@ endif()
|
||||
# Ensure libusb is properly configured (based on dolphin libusb include)
|
||||
if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB)
|
||||
include(FindPkgConfig)
|
||||
if (PKG_CONFIG_FOUND AND NOT CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24)
|
||||
else()
|
||||
find_package(LibUSB)
|
||||
@@ -518,10 +518,6 @@ 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})
|
||||
@@ -544,9 +540,6 @@ 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")
|
||||
|
||||
@@ -586,84 +579,12 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
CACHE PATH "Paths to FFmpeg libraries" FORCE)
|
||||
endforeach()
|
||||
|
||||
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(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)
|
||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||
${LIBDRM_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
${LIBVA-DRM_LIBRARIES}
|
||||
${LIBVA-X11_LIBRARIES}
|
||||
${LIBVA_LIBRARIES})
|
||||
set(FFmpeg_HWACCEL_FLAGS
|
||||
--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()
|
||||
set(FFmpeg_INCLUDE_DIR
|
||||
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR}"
|
||||
CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
|
||||
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
|
||||
# `--disable-vdpau` is needed to avoid linking issues
|
||||
# `--disable-{vaapi,vdpau}` is needed to avoid linking issues
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${FFmpeg_MAKEFILE}
|
||||
@@ -679,15 +600,13 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
--disable-network
|
||||
--disable-postproc
|
||||
--disable-swresample
|
||||
--disable-vaapi
|
||||
--disable-vdpau
|
||||
--enable-decoder=h264
|
||||
--enable-decoder=vp9
|
||||
--cc="${CMAKE_C_COMPILER}"
|
||||
--cxx="${CMAKE_CXX_COMPILER}"
|
||||
${FFmpeg_HWACCEL_FLAGS}
|
||||
WORKING_DIRECTORY
|
||||
${FFmpeg_BUILD_DIR}
|
||||
)
|
||||
unset(FFmpeg_HWACCEL_FLAGS)
|
||||
|
||||
# Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
|
||||
# with context of the jobserver. Also helps ninja users.
|
||||
@@ -697,36 +616,19 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
OUTPUT_VARIABLE
|
||||
SYSTEM_THREADS)
|
||||
|
||||
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${FFmpeg_BUILD_LIBRARIES}
|
||||
${FFmpeg_LIBRARIES}
|
||||
COMMAND
|
||||
make -j${SYSTEM_THREADS}
|
||||
WORKING_DIRECTORY
|
||||
${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_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
|
||||
CACHE PATH "Paths to FFmpeg libraries" FORCE)
|
||||
unset(FFmpeg_BUILD_LIBRARIES)
|
||||
unset(FFmpeg_HWACCEL_FLAGS)
|
||||
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
|
||||
unset(FFmpeg_HWACCEL_LDFLAGS)
|
||||
unset(FFmpeg_HWACCEL_LIBRARIES)
|
||||
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES} ffmpeg-configure)
|
||||
|
||||
if (FFmpeg_FOUND)
|
||||
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
|
||||
@@ -735,13 +637,12 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
endif()
|
||||
else() # WIN32
|
||||
# Use yuzu FFmpeg binaries
|
||||
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
|
||||
set(FFmpeg_EXT_NAME "ffmpeg-4.3.1")
|
||||
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
|
||||
@@ -767,7 +668,7 @@ if (APPLE)
|
||||
elseif (WIN32)
|
||||
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600)
|
||||
set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi)
|
||||
set(PLATFORM_LIBRARIES winmm ws2_32)
|
||||
if (MINGW)
|
||||
# PSAPI is the Process Status API
|
||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
|
||||
|
||||
@@ -48,6 +48,69 @@ if (BUILD_REPOSITORY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The variable SRC_DIR must be passed into the script
|
||||
# (since it uses the current build directory for all values of CMAKE_*_DIR)
|
||||
# The variable SRC_DIR must be passed into the script (since it uses the current build directory for all values of CMAKE_*_DIR)
|
||||
set(VIDEO_CORE "${SRC_DIR}/src/video_core")
|
||||
set(HASH_FILES
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_integer.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_integer_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/bfe.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/bfi.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/conversion.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/ffma.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/float_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/float_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/half_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/half_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/hfma2.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/image.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/integer_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/memory.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/texture.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/other.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/predicate_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/predicate_set_register.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/register_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/shift.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/video.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/warp.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/xmad.cpp"
|
||||
"${VIDEO_CORE}/shader/ast.cpp"
|
||||
"${VIDEO_CORE}/shader/ast.h"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.cpp"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.h"
|
||||
"${VIDEO_CORE}/shader/control_flow.cpp"
|
||||
"${VIDEO_CORE}/shader/control_flow.h"
|
||||
"${VIDEO_CORE}/shader/decode.cpp"
|
||||
"${VIDEO_CORE}/shader/expr.cpp"
|
||||
"${VIDEO_CORE}/shader/expr.h"
|
||||
"${VIDEO_CORE}/shader/node.h"
|
||||
"${VIDEO_CORE}/shader/node_helper.cpp"
|
||||
"${VIDEO_CORE}/shader/node_helper.h"
|
||||
"${VIDEO_CORE}/shader/registry.cpp"
|
||||
"${VIDEO_CORE}/shader/registry.h"
|
||||
"${VIDEO_CORE}/shader/shader_ir.cpp"
|
||||
"${VIDEO_CORE}/shader/shader_ir.h"
|
||||
"${VIDEO_CORE}/shader/track.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.h"
|
||||
)
|
||||
set(COMBINED "")
|
||||
foreach (F IN LISTS HASH_FILES)
|
||||
file(READ ${F} TMP)
|
||||
set(COMBINED "${COMBINED}${TMP}")
|
||||
endforeach()
|
||||
string(MD5 SHADER_CACHE_VERSION "${COMBINED}")
|
||||
configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY)
|
||||
@@ -35,7 +35,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f
|
||||
|
||||
The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements).
|
||||
|
||||
For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/)
|
||||
For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/)
|
||||
|
||||
Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more!
|
||||
|
||||
@@ -43,7 +43,7 @@ Check out our [website](https://yuzu-emu.org/) for the latest news on exciting f
|
||||
|
||||
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted. For development discussion, please join us on [Discord](https://discord.com/invite/u77vRWY).
|
||||
|
||||
If you want to contribute, please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information).
|
||||
If you want to contribute, please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information).
|
||||
You can also contact any of the developers on Discord in order to know about the current state of the emulator.
|
||||
|
||||
If you want to contribute to the user interface translation project, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations.
|
||||
@@ -78,5 +78,3 @@ If you wish to support us a different way, please join our [Discord](https://dis
|
||||
## License
|
||||
|
||||
yuzu is licensed under the GPLv2 (or any later version). Refer to the [license.txt](https://github.com/yuzu-emu/yuzu/blob/master/license.txt) file.
|
||||
|
||||
The [Skyline-Emulator Team](https://github.com/skyline-emu/skyline) is exempt from GPLv2 for the contributions from all these contributors [FernandoS27](https://github.com/FernandoS27), [lioncash](https://github.com/lioncash), [bunnei](https://github.com/bunnei), [ReinUsesLisp](https://github.com/ReinUsesLisp), [Morph1984](https://github.com/Morph1984), [ogniK5377](https://github.com/ogniK5377), [german77](https://github.com/german77), [ameerj](https://github.com/ameerj), [Kelebek1](https://github.com/Kelebek1) and [lat9nq](https://github.com/lat9nq). They may only use the code from these contributors under Mozilla Public License, version 2.0.
|
||||
Vendored
-20
@@ -38,26 +38,6 @@ QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #0066ff;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton {
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:checked {
|
||||
color: #b06020;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:!checked {
|
||||
color: #109010;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 21px;
|
||||
min-height: 21px;
|
||||
|
||||
Vendored
-21
@@ -1283,27 +1283,6 @@ QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #00ccdd;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:checked {
|
||||
color: #ff8040;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:!checked {
|
||||
color: #40dd40;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 23px;
|
||||
min-height: 23px;
|
||||
|
||||
@@ -2186,27 +2186,6 @@ QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #00ccdd;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:checked {
|
||||
color: #ff8040;
|
||||
}
|
||||
|
||||
QPushButton#GPUStatusBarButton:!checked {
|
||||
color: #40dd40;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 19px;
|
||||
min-height: 19px;
|
||||
|
||||
Vendored
+2
-5
@@ -7,9 +7,7 @@ include(DownloadExternals)
|
||||
# xbyak
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
add_library(xbyak INTERFACE)
|
||||
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_include_directories(xbyak SYSTEM INTERFACE ./xbyak/xbyak)
|
||||
target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES)
|
||||
endif()
|
||||
|
||||
@@ -21,7 +19,6 @@ 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()
|
||||
|
||||
@@ -54,7 +51,7 @@ if (NOT LIBUSB_FOUND OR YUZU_USE_BUNDLED_LIBUSB)
|
||||
endif()
|
||||
|
||||
# SDL2
|
||||
if (YUZU_USE_EXTERNAL_SDL2)
|
||||
if (NOT SDL2_FOUND AND ENABLE_SDL2)
|
||||
if (NOT WIN32)
|
||||
# Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio
|
||||
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
|
||||
|
||||
Vendored
+1
-1
Submodule externals/SDL updated: 25f9ed87ff...2f248a2a31.
Vendored
+1
-1
Submodule externals/Vulkan-Headers updated: 07c4a37bcf...8188e3fbbc.
Vendored
+1
-1
Submodule externals/dynarmic updated: 517e35f845...7946868af4.
Vendored
-2
@@ -67,8 +67,6 @@ if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)
|
||||
"${LIBUSB_MAKEFILE}"
|
||||
COMMAND
|
||||
env
|
||||
CC="${CMAKE_C_COMPILER}"
|
||||
CXX="${CMAKE_CXX_COMPILER}"
|
||||
CFLAGS="${LIBUSB_CFLAGS}"
|
||||
sh "${LIBUSB_CONFIGURE}"
|
||||
${LIBUSB_CONFIGURE_ARGS}
|
||||
|
||||
Vendored
+1
-1
Submodule externals/sirit updated: a39596358a...eefca56afd.
@@ -142,7 +142,6 @@ add_subdirectory(core)
|
||||
add_subdirectory(audio_core)
|
||||
add_subdirectory(video_core)
|
||||
add_subdirectory(input_common)
|
||||
add_subdirectory(shader_recompiler)
|
||||
add_subdirectory(tests)
|
||||
|
||||
if (ENABLE_SDL2)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Add a custom command to generate a new shader_cache_version hash when any of the following files change
|
||||
# NOTE: This is an approximation of what files affect shader generation, its possible something else
|
||||
# could affect the result, but much more unlikely than the following files. Keeping a list of files
|
||||
# like this allows for much better caching since it doesn't force the user to recompile binary shaders every update
|
||||
set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core")
|
||||
if (DEFINED ENV{AZURECIREPO})
|
||||
set(BUILD_REPOSITORY $ENV{AZURECIREPO})
|
||||
endif()
|
||||
@@ -25,7 +30,64 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
|
||||
-P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
|
||||
DEPENDS
|
||||
# Check that the scm_rev files haven't changed
|
||||
# WARNING! It was too much work to try and make a common location for this list,
|
||||
# so if you need to change it, please update CMakeModules/GenerateSCMRev.cmake as well
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
|
||||
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_integer.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/arithmetic_integer_immediate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/bfe.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/bfi.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/conversion.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/ffma.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/float_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/float_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/half_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/half_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/hfma2.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/image.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/integer_set.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/memory.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/texture.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/other.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/predicate_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/predicate_set_register.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/register_set_predicate.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/shift.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/video.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/warp.cpp"
|
||||
"${VIDEO_CORE}/shader/decode/xmad.cpp"
|
||||
"${VIDEO_CORE}/shader/ast.cpp"
|
||||
"${VIDEO_CORE}/shader/ast.h"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.cpp"
|
||||
"${VIDEO_CORE}/shader/compiler_settings.h"
|
||||
"${VIDEO_CORE}/shader/control_flow.cpp"
|
||||
"${VIDEO_CORE}/shader/control_flow.h"
|
||||
"${VIDEO_CORE}/shader/decode.cpp"
|
||||
"${VIDEO_CORE}/shader/expr.cpp"
|
||||
"${VIDEO_CORE}/shader/expr.h"
|
||||
"${VIDEO_CORE}/shader/node.h"
|
||||
"${VIDEO_CORE}/shader/node_helper.cpp"
|
||||
"${VIDEO_CORE}/shader/node_helper.h"
|
||||
"${VIDEO_CORE}/shader/registry.cpp"
|
||||
"${VIDEO_CORE}/shader/registry.h"
|
||||
"${VIDEO_CORE}/shader/shader_ir.cpp"
|
||||
"${VIDEO_CORE}/shader/shader_ir.h"
|
||||
"${VIDEO_CORE}/shader/track.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.cpp"
|
||||
"${VIDEO_CORE}/shader/transform_feedback.h"
|
||||
# and also check that the scm_rev files haven't changed
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h"
|
||||
# technically we should regenerate if the git version changed, but its not worth the effort imo
|
||||
@@ -53,8 +115,6 @@ add_library(common STATIC
|
||||
div_ceil.h
|
||||
dynamic_library.cpp
|
||||
dynamic_library.h
|
||||
error.cpp
|
||||
error.h
|
||||
fiber.cpp
|
||||
fiber.h
|
||||
fs/file.cpp
|
||||
@@ -90,6 +150,7 @@ add_library(common STATIC
|
||||
microprofile.cpp
|
||||
microprofile.h
|
||||
microprofileui.h
|
||||
misc.cpp
|
||||
nvidia_flags.cpp
|
||||
nvidia_flags.h
|
||||
page_table.cpp
|
||||
@@ -170,7 +231,7 @@ endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 xbyak)
|
||||
if (MSVC)
|
||||
target_link_libraries(common PRIVATE zstd::zstd)
|
||||
|
||||
+2
-6
@@ -52,12 +52,8 @@ assert_noinline_call(const Fn& fn) {
|
||||
#define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__)
|
||||
#else // not debug
|
||||
#define DEBUG_ASSERT(_a_) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUG_ASSERT(_a_)
|
||||
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
|
||||
#endif
|
||||
|
||||
#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")
|
||||
|
||||
+12
-17
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
#if !defined(ARCHITECTURE_x86_64)
|
||||
#include <cstdlib> // for exit
|
||||
@@ -48,6 +49,16 @@ __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>; \
|
||||
@@ -61,14 +72,6 @@ __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; \
|
||||
@@ -81,14 +84,6 @@ __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)); \
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// 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,7 +21,6 @@
|
||||
#define SCREENSHOTS_DIR "screenshots"
|
||||
#define SDMC_DIR "sdmc"
|
||||
#define SHADER_DIR "shader"
|
||||
#define TAS_DIR "tas"
|
||||
|
||||
// yuzu-specific files
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ std::string ToUTF8String(std::u8string_view u8_string) {
|
||||
return std::string{u8_string.begin(), u8_string.end()};
|
||||
}
|
||||
|
||||
std::string BufferToUTF8String(std::span<const u8> buffer) {
|
||||
return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})};
|
||||
}
|
||||
|
||||
std::string PathToUTF8String(const std::filesystem::path& path) {
|
||||
return ToUTF8String(path.u8string());
|
||||
}
|
||||
|
||||
@@ -46,17 +46,6 @@ concept IsChar = std::same_as<T, char>;
|
||||
*/
|
||||
[[nodiscard]] std::string ToUTF8String(std::u8string_view u8_string);
|
||||
|
||||
/**
|
||||
* Converts a buffer of bytes to a UTF8-encoded std::string.
|
||||
* This converts from the start of the buffer until the first encountered null-terminator.
|
||||
* If no null-terminator is found, this converts the entire buffer instead.
|
||||
*
|
||||
* @param buffer Buffer of bytes
|
||||
*
|
||||
* @returns UTF-8 encoded std::string.
|
||||
*/
|
||||
[[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer);
|
||||
|
||||
/**
|
||||
* Converts a filesystem path to a UTF-8 encoded std::string.
|
||||
*
|
||||
|
||||
@@ -116,7 +116,6 @@ 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,7 +23,6 @@ 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.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ template <typename ContiguousContainer>
|
||||
return out;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::array<u8, 16> AsArray(const char (&data)[33]) {
|
||||
[[nodiscard]] constexpr std::array<u8, 16> AsArray(const char (&data)[17]) {
|
||||
return HexStringToArray<16>(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <windows.h>
|
||||
#include "common/dynamic_library.h"
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||
#elif defined(__linux__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
@@ -343,7 +343,7 @@ private:
|
||||
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
|
||||
};
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||
#elif defined(__linux__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||
|
||||
class HostMemory::Impl {
|
||||
public:
|
||||
@@ -357,12 +357,7 @@ public:
|
||||
});
|
||||
|
||||
// Backing memory initialization
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ < 13
|
||||
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
|
||||
fd = shm_open(SHM_ANON, O_RDWR, 0600);
|
||||
#else
|
||||
fd = memfd_create("HostMemory", 0);
|
||||
#endif
|
||||
if (fd == -1) {
|
||||
LOG_CRITICAL(HW_Memory, "memfd_create failed: {}", strerror(errno));
|
||||
throw std::bad_alloc{};
|
||||
|
||||
+143
-217
@@ -2,10 +2,13 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <exception>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -13,174 +16,28 @@
|
||||
#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/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() {
|
||||
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;
|
||||
static Impl backend;
|
||||
return backend;
|
||||
}
|
||||
|
||||
Impl(const Impl&) = delete;
|
||||
@@ -189,54 +46,74 @@ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
private:
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
|
||||
~Impl() {
|
||||
StopBackendThread();
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void StopBackendThread() {
|
||||
Entry stop_entry{};
|
||||
stop_entry.final_entry = true;
|
||||
message_queue.Push(stop_entry);
|
||||
~Impl() {
|
||||
Entry entry;
|
||||
entry.final_entry = true;
|
||||
message_queue.Push(entry);
|
||||
backend_thread.join();
|
||||
}
|
||||
|
||||
@@ -258,51 +135,100 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
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::mutex writing_mutex;
|
||||
std::thread backend_thread;
|
||||
MPSCQueue<Entry> message_queue{};
|
||||
std::vector<std::unique_ptr<Backend>> backends;
|
||||
MPSCQueue<Entry> message_queue;
|
||||
Filter filter;
|
||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void Initialize() {
|
||||
Impl::Initialize();
|
||||
ConsoleBackend::~ConsoleBackend() = default;
|
||||
|
||||
void ConsoleBackend::Write(const Entry& entry) {
|
||||
PrintMessage(entry);
|
||||
}
|
||||
|
||||
void DisableLoggingInTests() {
|
||||
initialization_in_progress_suppress_logging = true;
|
||||
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 SetGlobalFilter(const Filter& filter) {
|
||||
Impl::Instance().SetGlobalFilter(filter);
|
||||
}
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||
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 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) {
|
||||
if (!initialization_in_progress_suppress_logging) {
|
||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, 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));
|
||||
}
|
||||
} // namespace Common::Log
|
||||
@@ -5,21 +5,120 @@
|
||||
#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;
|
||||
|
||||
/// Initializes the logging system. This should be the first thing called in main.
|
||||
void Initialize();
|
||||
/**
|
||||
* 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;
|
||||
|
||||
void DisableLoggingInTests();
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* The global filter will prevent any messages from even being processed if they are filtered.
|
||||
* 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
|
||||
*/
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
} // namespace Common::Log
|
||||
} // namespace Common::Log
|
||||
@@ -111,7 +111,6 @@ 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) \
|
||||
@@ -145,10 +144,6 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Render, Software) \
|
||||
SUB(Render, OpenGL) \
|
||||
SUB(Render, Vulkan) \
|
||||
CLS(Shader) \
|
||||
SUB(Shader, SPIRV) \
|
||||
SUB(Shader, GLASM) \
|
||||
SUB(Shader, GLSL) \
|
||||
CLS(Audio) \
|
||||
SUB(Audio, DSP) \
|
||||
SUB(Audio, Sink) \
|
||||
|
||||
@@ -81,7 +81,6 @@ 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
|
||||
@@ -115,10 +114,6 @@ enum class Class : u8 {
|
||||
Render_Software, ///< Software renderer backend
|
||||
Render_OpenGL, ///< OpenGL backend
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
Shader, ///< Shader recompiler
|
||||
Shader_SPIRV, ///< Shader SPIR-V code generation
|
||||
Shader_GLASM, ///< Shader GLASM code generation
|
||||
Shader_GLSL, ///< Shader GLSL code generation
|
||||
Audio, ///< Audio emulation
|
||||
Audio_DSP, ///< The HLE implementation of the DSP
|
||||
Audio_Sink, ///< Emulator audio output backend
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
// 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
|
||||
@@ -10,9 +10,7 @@
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#include "common/error.h"
|
||||
|
||||
namespace Common {
|
||||
#include "common/common_funcs.h"
|
||||
|
||||
std::string NativeErrorToString(int e) {
|
||||
#ifdef _WIN32
|
||||
@@ -52,5 +50,3 @@ std::string GetLastErrorMsg() {
|
||||
return NativeErrorToString(errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
@@ -14,6 +14,7 @@
|
||||
#define BUILD_ID "@BUILD_ID@"
|
||||
#define TITLE_BAR_FORMAT_IDLE "@TITLE_BAR_FORMAT_IDLE@"
|
||||
#define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@"
|
||||
#define SHADER_CACHE_VERSION "@SHADER_CACHE_VERSION@"
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -27,6 +28,7 @@ const char g_build_version[] = BUILD_VERSION;
|
||||
const char g_build_id[] = BUILD_ID;
|
||||
const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE;
|
||||
const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING;
|
||||
const char g_shader_cache_version[] = SHADER_CACHE_VERSION;
|
||||
|
||||
} // namespace
|
||||
|
||||
+13
-12
@@ -48,19 +48,21 @@ void LogSettings() {
|
||||
log_setting("Core_UseMultiCore", values.use_multi_core.GetValue());
|
||||
log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue());
|
||||
log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue());
|
||||
log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue());
|
||||
log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue());
|
||||
log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue());
|
||||
log_setting("Renderer_FrameLimit", values.frame_limit.GetValue());
|
||||
log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
|
||||
log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
|
||||
log_setting("Renderer_UseAsynchronousGpuEmulation",
|
||||
values.use_asynchronous_gpu_emulation.GetValue());
|
||||
log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue());
|
||||
log_setting("Renderer_UseNvdecEmulation", values.use_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_UseAssemblyShaders", values.use_assembly_shaders.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,9 +73,6 @@ void LogSettings() {
|
||||
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() {
|
||||
@@ -104,7 +103,7 @@ float Volume() {
|
||||
if (values.audio_muted) {
|
||||
return 0.0f;
|
||||
}
|
||||
return values.volume.GetValue() / 100.0f;
|
||||
return values.volume.GetValue();
|
||||
}
|
||||
|
||||
void RestoreGlobalState(bool is_powered_on) {
|
||||
@@ -114,6 +113,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
}
|
||||
|
||||
// Audio
|
||||
values.enable_audio_stretching.SetGlobal(true);
|
||||
values.volume.SetGlobal(true);
|
||||
|
||||
// Core
|
||||
@@ -132,17 +132,18 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
values.vulkan_device.SetGlobal(true);
|
||||
values.aspect_ratio.SetGlobal(true);
|
||||
values.max_anisotropy.SetGlobal(true);
|
||||
values.use_speed_limit.SetGlobal(true);
|
||||
values.speed_limit.SetGlobal(true);
|
||||
values.use_frame_limit.SetGlobal(true);
|
||||
values.frame_limit.SetGlobal(true);
|
||||
values.use_disk_shader_cache.SetGlobal(true);
|
||||
values.gpu_accuracy.SetGlobal(true);
|
||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||
values.nvdec_emulation.SetGlobal(true);
|
||||
values.use_nvdec_emulation.SetGlobal(true);
|
||||
values.accelerate_astc.SetGlobal(true);
|
||||
values.use_vsync.SetGlobal(true);
|
||||
values.shader_backend.SetGlobal(true);
|
||||
values.use_assembly_shaders.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);
|
||||
|
||||
+40
-191
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
@@ -16,6 +15,7 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings_input.h"
|
||||
#include "input_common/udp/client.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
@@ -24,12 +24,6 @@ enum class RendererBackend : u32 {
|
||||
Vulkan = 1,
|
||||
};
|
||||
|
||||
enum class ShaderBackend : u32 {
|
||||
GLSL = 0,
|
||||
GLASM = 1,
|
||||
SPIRV = 2,
|
||||
};
|
||||
|
||||
enum class GPUAccuracy : u32 {
|
||||
Normal = 0,
|
||||
High = 1,
|
||||
@@ -42,17 +36,6 @@ enum class CPUAccuracy : u32 {
|
||||
Unsafe = 2,
|
||||
};
|
||||
|
||||
enum class FullscreenMode : u32 {
|
||||
Borderless = 0,
|
||||
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
|
||||
@@ -80,14 +63,14 @@ public:
|
||||
*/
|
||||
explicit BasicSetting(const Type& default_val, const std::string& name)
|
||||
: default_value{default_val}, global{default_val}, label{name} {}
|
||||
virtual ~BasicSetting() = default;
|
||||
~BasicSetting() = default;
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting's value.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const {
|
||||
[[nodiscard]] const Type& GetValue() const {
|
||||
return global;
|
||||
}
|
||||
|
||||
@@ -96,7 +79,7 @@ public:
|
||||
*
|
||||
* @param value The desired value
|
||||
*/
|
||||
virtual void SetValue(const Type& value) {
|
||||
void SetValue(const Type& value) {
|
||||
Type temp{value};
|
||||
std::swap(global, temp);
|
||||
}
|
||||
@@ -126,7 +109,7 @@ public:
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
virtual const Type& operator=(const Type& value) {
|
||||
const Type& operator=(const Type& value) {
|
||||
Type temp{value};
|
||||
std::swap(global, temp);
|
||||
return global;
|
||||
@@ -137,7 +120,7 @@ public:
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
explicit virtual operator const Type&() const {
|
||||
explicit operator const Type&() const {
|
||||
return global;
|
||||
}
|
||||
|
||||
@@ -147,51 +130,6 @@ protected:
|
||||
const std::string label{}; ///< The setting's label
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicRangedSetting class is intended for use with quantifiable settings that need a more
|
||||
* restrictive range than implicitly defined by its type. Implements a minimum and maximum that is
|
||||
* simply used to sanitize SetValue and the assignment overload.
|
||||
*/
|
||||
template <typename Type>
|
||||
class BasicRangedSetting : virtual public BasicSetting<Type> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param default_val Intial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit BasicRangedSetting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
: BasicSetting<Type>{default_val, name}, minimum{min_val}, maximum{max_val} {}
|
||||
virtual ~BasicRangedSetting() = default;
|
||||
|
||||
/**
|
||||
* Like BasicSetting's SetValue, except value is clamped to the range of the setting.
|
||||
*
|
||||
* @param value The desired value
|
||||
*/
|
||||
void SetValue(const Type& value) override {
|
||||
this->global = std::clamp(value, minimum, maximum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like BasicSetting's assignment overload, except value is clamped to the range of the setting.
|
||||
*
|
||||
* @param value The desired value
|
||||
* @returns A reference to the setting's value
|
||||
*/
|
||||
const Type& operator=(const Type& value) override {
|
||||
this->global = std::clamp(value, minimum, maximum);
|
||||
return this->global;
|
||||
}
|
||||
|
||||
const Type minimum; ///< Minimum allowed value of the setting
|
||||
const Type maximum; ///< Maximum allowed value of the setting
|
||||
};
|
||||
|
||||
/**
|
||||
* The Setting class is a slightly more complex version of the BasicSetting class. This adds a
|
||||
* custom setting to switch to when a guest application specifically requires it. The effect is that
|
||||
@@ -203,7 +141,7 @@ public:
|
||||
* Like the BasicSetting, this requires setting a default value and label to use.
|
||||
*/
|
||||
template <typename Type>
|
||||
class Setting : virtual public BasicSetting<Type> {
|
||||
class Setting final : public BasicSetting<Type> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
@@ -213,7 +151,7 @@ public:
|
||||
*/
|
||||
explicit Setting(const Type& default_val, const std::string& name)
|
||||
: BasicSetting<Type>(default_val, name) {}
|
||||
virtual ~Setting() = default;
|
||||
~Setting() = default;
|
||||
|
||||
/**
|
||||
* Tells this setting to represent either the global or custom setting when other member
|
||||
@@ -242,13 +180,7 @@ public:
|
||||
*
|
||||
* @returns The required value of the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const override {
|
||||
if (use_global) {
|
||||
return this->global;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
[[nodiscard]] virtual const Type& GetValue(bool need_global) const {
|
||||
[[nodiscard]] const Type& GetValue(bool need_global = false) const {
|
||||
if (use_global || need_global) {
|
||||
return this->global;
|
||||
}
|
||||
@@ -260,7 +192,7 @@ public:
|
||||
*
|
||||
* @param value The new value
|
||||
*/
|
||||
void SetValue(const Type& value) override {
|
||||
void SetValue(const Type& value) {
|
||||
Type temp{value};
|
||||
if (use_global) {
|
||||
std::swap(this->global, temp);
|
||||
@@ -276,7 +208,7 @@ public:
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
const Type& operator=(const Type& value) override {
|
||||
const Type& operator=(const Type& value) {
|
||||
Type temp{value};
|
||||
if (use_global) {
|
||||
std::swap(this->global, temp);
|
||||
@@ -291,87 +223,18 @@ public:
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
virtual explicit operator const Type&() const override {
|
||||
explicit operator const Type&() const {
|
||||
if (use_global) {
|
||||
return this->global;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool use_global{true}; ///< The setting's global state
|
||||
Type custom{}; ///< The custom value of the setting
|
||||
};
|
||||
|
||||
/**
|
||||
* RangedSetting is a Setting that implements a maximum and minimum value for its setting. Intended
|
||||
* for use with quantifiable settings.
|
||||
*/
|
||||
template <typename Type>
|
||||
class RangedSetting final : public BasicRangedSetting<Type>, public Setting<Type> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param default_val Intial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit RangedSetting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
: BasicSetting<Type>{default_val, name},
|
||||
BasicRangedSetting<Type>{default_val, min_val, max_val, name}, Setting<Type>{default_val,
|
||||
name} {}
|
||||
virtual ~RangedSetting() = default;
|
||||
|
||||
// The following are needed to avoid a MSVC bug
|
||||
// (source: https://stackoverflow.com/questions/469508)
|
||||
[[nodiscard]] const Type& GetValue() const override {
|
||||
return Setting<Type>::GetValue();
|
||||
}
|
||||
[[nodiscard]] const Type& GetValue(bool need_global) const override {
|
||||
return Setting<Type>::GetValue(need_global);
|
||||
}
|
||||
explicit operator const Type&() const override {
|
||||
if (this->use_global) {
|
||||
return this->global;
|
||||
}
|
||||
return this->custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like BasicSetting's SetValue, except value is clamped to the range of the setting. Sets the
|
||||
* appropriate value depending on the global state.
|
||||
*
|
||||
* @param value The desired value
|
||||
*/
|
||||
void SetValue(const Type& value) override {
|
||||
const Type temp = std::clamp(value, this->minimum, this->maximum);
|
||||
if (this->use_global) {
|
||||
this->global = temp;
|
||||
}
|
||||
this->custom = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like BasicSetting's assignment overload, except value is clamped to the range of the setting.
|
||||
* Uses the appropriate value depending on the global state.
|
||||
*
|
||||
* @param value The desired value
|
||||
* @returns A reference to the setting's value
|
||||
*/
|
||||
const Type& operator=(const Type& value) override {
|
||||
const Type temp = std::clamp(value, this->minimum, this->maximum);
|
||||
if (this->use_global) {
|
||||
this->global = temp;
|
||||
return this->global;
|
||||
}
|
||||
this->custom = temp;
|
||||
return this->custom;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The InputSetting class allows for getting a reference to either the global or custom members.
|
||||
* This is required as we cannot easily modify the values of user-defined types within containers
|
||||
@@ -414,14 +277,14 @@ 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"};
|
||||
RangedSetting<u8> volume{100, 0, 100, "volume"};
|
||||
Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"};
|
||||
Setting<float> volume{1.0f, "volume"};
|
||||
|
||||
// Core
|
||||
Setting<bool> use_multi_core{true, "use_multi_core"};
|
||||
|
||||
// Cpu
|
||||
RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
|
||||
CPUAccuracy::Unsafe, "cpu_accuracy"};
|
||||
Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, "cpu_accuracy"};
|
||||
// TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
|
||||
BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"};
|
||||
BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"};
|
||||
@@ -443,46 +306,39 @@ struct Values {
|
||||
Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"};
|
||||
|
||||
// Renderer
|
||||
RangedSetting<RendererBackend> renderer_backend{
|
||||
RendererBackend::OpenGL, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"};
|
||||
Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"};
|
||||
BasicSetting<bool> renderer_debug{false, "debug"};
|
||||
BasicSetting<bool> renderer_shader_feedback{false, "shader_feedback"};
|
||||
BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"};
|
||||
BasicSetting<bool> disable_shader_loop_safety_checks{false,
|
||||
"disable_shader_loop_safety_checks"};
|
||||
Setting<int> vulkan_device{0, "vulkan_device"};
|
||||
|
||||
Setting<u16> resolution_factor{1, "resolution_factor"};
|
||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||
// Default to exclusive fullscreen on these platforms for now.
|
||||
RangedSetting<FullscreenMode> fullscreen_mode{
|
||||
Setting<int> fullscreen_mode{
|
||||
#ifdef _WIN32
|
||||
FullscreenMode::Borderless,
|
||||
0,
|
||||
#else
|
||||
FullscreenMode::Exclusive,
|
||||
1,
|
||||
#endif
|
||||
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
|
||||
RangedSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"};
|
||||
RangedSetting<int> max_anisotropy{0, 0, 4, "max_anisotropy"};
|
||||
Setting<bool> use_speed_limit{true, "use_speed_limit"};
|
||||
RangedSetting<u16> speed_limit{100, 0, 9999, "speed_limit"};
|
||||
"fullscreen_mode"};
|
||||
Setting<int> aspect_ratio{0, "aspect_ratio"};
|
||||
Setting<int> max_anisotropy{0, "max_anisotropy"};
|
||||
Setting<bool> use_frame_limit{true, "use_frame_limit"};
|
||||
Setting<u16> frame_limit{100, "frame_limit"};
|
||||
Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
|
||||
RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||
Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"};
|
||||
Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||
Setting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||
Setting<bool> use_nvdec_emulation{true, "use_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"};
|
||||
BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"};
|
||||
RangedSetting<ShaderBackend> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
Setting<bool> use_assembly_shaders{false, "use_assembly_shaders"};
|
||||
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"};
|
||||
Setting<u8> bg_blue{0, "bg_blue"};
|
||||
Setting<float> bg_red{0.0f, "bg_red"};
|
||||
Setting<float> bg_green{0.0f, "bg_green"};
|
||||
Setting<float> bg_blue{0.0f, "bg_blue"};
|
||||
|
||||
// System
|
||||
Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
|
||||
@@ -492,33 +348,27 @@ struct Values {
|
||||
std::chrono::seconds custom_rtc_differential;
|
||||
|
||||
BasicSetting<s32> current_user{0, "current_user"};
|
||||
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"};
|
||||
Setting<s32> language_index{1, "language_index"};
|
||||
Setting<s32> region_index{1, "region_index"};
|
||||
Setting<s32> time_zone_index{0, "time_zone_index"};
|
||||
Setting<s32> sound_index{1, "sound_index"};
|
||||
|
||||
// Controls
|
||||
InputSetting<std::array<PlayerInput, 10>> players;
|
||||
|
||||
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{"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<std::string> udp_input_servers{InputCommon::CemuhookUDP::DEFAULT_SRV,
|
||||
"udp_input_servers"};
|
||||
|
||||
BasicSetting<bool> mouse_panning{false, "mouse_panning"};
|
||||
BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
|
||||
BasicSetting<float> mouse_panning_sensitivity{1.0f, "mouse_panning_sensitivity"};
|
||||
BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
|
||||
std::string mouse_device;
|
||||
MouseButtonsRaw mouse_buttons;
|
||||
@@ -567,10 +417,9 @@ struct Values {
|
||||
BasicSetting<std::string> log_filter{"*:Info", "log_filter"};
|
||||
BasicSetting<bool> use_dev_keys{false, "use_dev_keys"};
|
||||
|
||||
// Network
|
||||
// Services
|
||||
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
|
||||
BasicSetting<bool> enable_telemetry{true, "enable_telemetry"};
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/thread.h"
|
||||
#ifdef __APPLE__
|
||||
@@ -23,6 +21,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define cpu_set_t cpuset_t
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <stop_token>
|
||||
@@ -40,7 +39,7 @@ public:
|
||||
const auto lambda = [this, func](std::stop_token stop_token) {
|
||||
Common::SetCurrentThreadName(thread_name.c_str());
|
||||
{
|
||||
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func()};
|
||||
std::conditional_t<with_state, StateType, int> state{func()};
|
||||
while (!stop_token.stop_requested()) {
|
||||
Task task;
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <utility>
|
||||
|
||||
namespace Common {
|
||||
template <typename T, bool with_stop_token = false>
|
||||
template <typename T>
|
||||
class SPSCQueue {
|
||||
public:
|
||||
SPSCQueue() {
|
||||
@@ -46,13 +46,15 @@ public:
|
||||
ElementPtr* new_ptr = new ElementPtr();
|
||||
write_ptr->next.store(new_ptr, std::memory_order_release);
|
||||
write_ptr = new_ptr;
|
||||
++size;
|
||||
|
||||
// cv_mutex must be held or else there will be a missed wakeup if the other thread is in the
|
||||
// line before cv.wait
|
||||
const size_t previous_size{size++};
|
||||
|
||||
// Acquire the mutex and then immediately release it as a fence.
|
||||
// TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported.
|
||||
// See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details.
|
||||
std::lock_guard lock{cv_mutex};
|
||||
if (previous_size == 0) {
|
||||
std::lock_guard lock{cv_mutex};
|
||||
}
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
@@ -84,7 +86,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,19 +97,6 @@ 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);
|
||||
@@ -136,13 +125,13 @@ private:
|
||||
ElementPtr* read_ptr;
|
||||
std::atomic_size_t size{0};
|
||||
std::mutex cv_mutex;
|
||||
std::conditional_t<with_stop_token, std::condition_variable_any, std::condition_variable> cv;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
|
||||
// a simple thread-safe,
|
||||
// single reader, multiple writer queue
|
||||
|
||||
template <typename T, bool with_stop_token = false>
|
||||
template <typename T>
|
||||
class MPSCQueue {
|
||||
public:
|
||||
[[nodiscard]] std::size_t Size() const {
|
||||
@@ -179,17 +168,13 @@ 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, with_stop_token> spsc_queue;
|
||||
SPSCQueue<T> spsc_queue;
|
||||
std::mutex write_lock;
|
||||
};
|
||||
} // namespace Common
|
||||
+1
-55
@@ -6,64 +6,10 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/uuid.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsHexDigit(char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
u8 HexCharToByte(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return static_cast<u8>(c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return static_cast<u8>(c - 'a' + 10);
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return static_cast<u8>(c - 'A' + 10);
|
||||
}
|
||||
ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
|
||||
return u8{0};
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
u128 HexStringToU128(std::string_view hex_string) {
|
||||
const size_t length = hex_string.length();
|
||||
|
||||
// Detect "0x" prefix.
|
||||
const bool has_0x_prefix = length > 2 && hex_string[0] == '0' && hex_string[1] == 'x';
|
||||
const size_t offset = has_0x_prefix ? 2 : 0;
|
||||
|
||||
// Check length.
|
||||
if (length > 32 + offset) {
|
||||
ASSERT_MSG(false, "hex_string has more than 32 hexadecimal characters!");
|
||||
return INVALID_UUID;
|
||||
}
|
||||
|
||||
u64 lo = 0;
|
||||
u64 hi = 0;
|
||||
for (size_t i = 0; i < length - offset; ++i) {
|
||||
const char c = hex_string[length - 1 - i];
|
||||
if (!IsHexDigit(c)) {
|
||||
ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
|
||||
return INVALID_UUID;
|
||||
}
|
||||
if (i < 16) {
|
||||
lo |= u64{HexCharToByte(c)} << (i * 4);
|
||||
}
|
||||
if (i >= 16) {
|
||||
hi |= u64{HexCharToByte(c)} << ((i - 16) * 4);
|
||||
}
|
||||
}
|
||||
return u128{lo, hi};
|
||||
}
|
||||
|
||||
UUID UUID::Generate() {
|
||||
std::random_device device;
|
||||
std::mt19937 gen(device());
|
||||
@@ -72,7 +18,7 @@ UUID UUID::Generate() {
|
||||
}
|
||||
|
||||
std::string UUID::Format() const {
|
||||
return fmt::format("{:016x}{:016x}", uuid[1], uuid[0]);
|
||||
return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]);
|
||||
}
|
||||
|
||||
std::string UUID::FormatSwitch() const {
|
||||
|
||||
+3
-32
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
@@ -13,37 +12,20 @@ namespace Common {
|
||||
|
||||
constexpr u128 INVALID_UUID{{0, 0}};
|
||||
|
||||
/**
|
||||
* Converts a hex string to a 128-bit unsigned integer.
|
||||
*
|
||||
* The hex string can be formatted in lowercase or uppercase, with or without the "0x" prefix.
|
||||
*
|
||||
* This function will assert and return INVALID_UUID under the following conditions:
|
||||
* - If the hex string is more than 32 characters long
|
||||
* - If the hex string contains non-hexadecimal characters
|
||||
*
|
||||
* @param hex_string Hexadecimal string
|
||||
*
|
||||
* @returns A 128-bit unsigned integer if successfully converted, INVALID_UUID otherwise.
|
||||
*/
|
||||
[[nodiscard]] u128 HexStringToU128(std::string_view hex_string);
|
||||
|
||||
struct UUID {
|
||||
// UUIDs which are 0 are considered invalid!
|
||||
u128 uuid;
|
||||
UUID() = default;
|
||||
constexpr explicit UUID(const u128& id) : uuid{id} {}
|
||||
constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {}
|
||||
explicit UUID(std::string_view hex_string) {
|
||||
uuid = HexStringToU128(hex_string);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr explicit operator bool() const {
|
||||
return uuid != INVALID_UUID;
|
||||
return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator==(const UUID& rhs) const {
|
||||
return uuid == rhs.uuid;
|
||||
// TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20
|
||||
return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator!=(const UUID& rhs) const {
|
||||
@@ -69,14 +51,3 @@ struct UUID {
|
||||
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
|
||||
|
||||
} // namespace Common
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<Common::UUID> {
|
||||
size_t operator()(const Common::UUID& uuid) const noexcept {
|
||||
return uuid.uuid[1] ^ uuid.uuid[0];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include <xbyak.h>
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include <xbyak.h>
|
||||
#include "common/x64/xbyak_abi.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
+36
-44
@@ -263,8 +263,6 @@ 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
|
||||
@@ -274,22 +272,22 @@ add_library(core STATIC
|
||||
hle/service/am/applet_ae.h
|
||||
hle/service/am/applet_oe.cpp
|
||||
hle/service/am/applet_oe.h
|
||||
hle/service/am/applets/applet_controller.cpp
|
||||
hle/service/am/applets/applet_controller.h
|
||||
hle/service/am/applets/applet_error.cpp
|
||||
hle/service/am/applets/applet_error.h
|
||||
hle/service/am/applets/applet_general_backend.cpp
|
||||
hle/service/am/applets/applet_general_backend.h
|
||||
hle/service/am/applets/applet_profile_select.cpp
|
||||
hle/service/am/applets/applet_profile_select.h
|
||||
hle/service/am/applets/applet_software_keyboard.cpp
|
||||
hle/service/am/applets/applet_software_keyboard.h
|
||||
hle/service/am/applets/applet_software_keyboard_types.h
|
||||
hle/service/am/applets/applet_web_browser.cpp
|
||||
hle/service/am/applets/applet_web_browser.h
|
||||
hle/service/am/applets/applet_web_browser_types.h
|
||||
hle/service/am/applets/applets.cpp
|
||||
hle/service/am/applets/applets.h
|
||||
hle/service/am/applets/controller.cpp
|
||||
hle/service/am/applets/controller.h
|
||||
hle/service/am/applets/error.cpp
|
||||
hle/service/am/applets/error.h
|
||||
hle/service/am/applets/general_backend.cpp
|
||||
hle/service/am/applets/general_backend.h
|
||||
hle/service/am/applets/profile_select.cpp
|
||||
hle/service/am/applets/profile_select.h
|
||||
hle/service/am/applets/software_keyboard.cpp
|
||||
hle/service/am/applets/software_keyboard.h
|
||||
hle/service/am/applets/software_keyboard_types.h
|
||||
hle/service/am/applets/web_browser.cpp
|
||||
hle/service/am/applets/web_browser.h
|
||||
hle/service/am/applets/web_types.h
|
||||
hle/service/am/idle.cpp
|
||||
hle/service/am/idle.h
|
||||
hle/service/am/omm.cpp
|
||||
@@ -302,10 +300,10 @@ add_library(core STATIC
|
||||
hle/service/aoc/aoc_u.h
|
||||
hle/service/apm/apm.cpp
|
||||
hle/service/apm/apm.h
|
||||
hle/service/apm/apm_controller.cpp
|
||||
hle/service/apm/apm_controller.h
|
||||
hle/service/apm/apm_interface.cpp
|
||||
hle/service/apm/apm_interface.h
|
||||
hle/service/apm/controller.cpp
|
||||
hle/service/apm/controller.h
|
||||
hle/service/apm/interface.cpp
|
||||
hle/service/apm/interface.h
|
||||
hle/service/audio/audctl.cpp
|
||||
hle/service/audio/audctl.h
|
||||
hle/service/audio/auddbg.cpp
|
||||
@@ -337,8 +335,8 @@ add_library(core STATIC
|
||||
hle/service/bcat/backend/backend.h
|
||||
hle/service/bcat/bcat.cpp
|
||||
hle/service/bcat/bcat.h
|
||||
hle/service/bcat/bcat_module.cpp
|
||||
hle/service/bcat/bcat_module.h
|
||||
hle/service/bcat/module.cpp
|
||||
hle/service/bcat/module.h
|
||||
hle/service/bpc/bpc.cpp
|
||||
hle/service/bpc/bpc.h
|
||||
hle/service/btdrv/btdrv.cpp
|
||||
@@ -384,8 +382,8 @@ add_library(core STATIC
|
||||
hle/service/friend/errors.h
|
||||
hle/service/friend/friend.cpp
|
||||
hle/service/friend/friend.h
|
||||
hle/service/friend/friend_interface.cpp
|
||||
hle/service/friend/friend_interface.h
|
||||
hle/service/friend/interface.cpp
|
||||
hle/service/friend/interface.h
|
||||
hle/service/glue/arp.cpp
|
||||
hle/service/glue/arp.h
|
||||
hle/service/glue/bgtc.cpp
|
||||
@@ -395,8 +393,8 @@ add_library(core STATIC
|
||||
hle/service/glue/errors.h
|
||||
hle/service/glue/glue.cpp
|
||||
hle/service/glue/glue.h
|
||||
hle/service/glue/glue_manager.cpp
|
||||
hle/service/glue/glue_manager.h
|
||||
hle/service/glue/manager.cpp
|
||||
hle/service/glue/manager.h
|
||||
hle/service/grc/grc.cpp
|
||||
hle/service/grc/grc.h
|
||||
hle/service/hid/hid.cpp
|
||||
@@ -437,10 +435,10 @@ add_library(core STATIC
|
||||
hle/service/lm/lm.h
|
||||
hle/service/mig/mig.cpp
|
||||
hle/service/mig/mig.h
|
||||
hle/service/mii/manager.cpp
|
||||
hle/service/mii/manager.h
|
||||
hle/service/mii/mii.cpp
|
||||
hle/service/mii/mii.h
|
||||
hle/service/mii/mii_manager.cpp
|
||||
hle/service/mii/mii_manager.h
|
||||
hle/service/mii/raw_data.cpp
|
||||
hle/service/mii/raw_data.h
|
||||
hle/service/mii/types.h
|
||||
@@ -454,8 +452,6 @@ 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
|
||||
@@ -490,11 +486,11 @@ add_library(core STATIC
|
||||
hle/service/nvdrv/devices/nvhost_vic.h
|
||||
hle/service/nvdrv/devices/nvmap.cpp
|
||||
hle/service/nvdrv/devices/nvmap.h
|
||||
hle/service/nvdrv/interface.cpp
|
||||
hle/service/nvdrv/interface.h
|
||||
hle/service/nvdrv/nvdata.h
|
||||
hle/service/nvdrv/nvdrv.cpp
|
||||
hle/service/nvdrv/nvdrv.h
|
||||
hle/service/nvdrv/nvdrv_interface.cpp
|
||||
hle/service/nvdrv/nvdrv_interface.h
|
||||
hle/service/nvdrv/nvmemp.cpp
|
||||
hle/service/nvdrv/nvmemp.h
|
||||
hle/service/nvdrv/syncpoint_manager.cpp
|
||||
@@ -507,10 +503,10 @@ add_library(core STATIC
|
||||
hle/service/olsc/olsc.h
|
||||
hle/service/pcie/pcie.cpp
|
||||
hle/service/pcie/pcie.h
|
||||
hle/service/pctl/module.cpp
|
||||
hle/service/pctl/module.h
|
||||
hle/service/pctl/pctl.cpp
|
||||
hle/service/pctl/pctl.h
|
||||
hle/service/pctl/pctl_module.cpp
|
||||
hle/service/pctl/pctl_module.h
|
||||
hle/service/pcv/pcv.cpp
|
||||
hle/service/pcv/pcv.h
|
||||
hle/service/pm/pm.cpp
|
||||
@@ -521,8 +517,6 @@ add_library(core STATIC
|
||||
hle/service/psc/psc.h
|
||||
hle/service/ptm/psm.cpp
|
||||
hle/service/ptm/psm.h
|
||||
hle/service/kernel_helpers.cpp
|
||||
hle/service/kernel_helpers.h
|
||||
hle/service/service.cpp
|
||||
hle/service/service.h
|
||||
hle/service/set/set.cpp
|
||||
@@ -535,10 +529,10 @@ add_library(core STATIC
|
||||
hle/service/set/set_sys.h
|
||||
hle/service/set/settings.cpp
|
||||
hle/service/set/settings.h
|
||||
hle/service/sm/controller.cpp
|
||||
hle/service/sm/controller.h
|
||||
hle/service/sm/sm.cpp
|
||||
hle/service/sm/sm.h
|
||||
hle/service/sm/sm_controller.cpp
|
||||
hle/service/sm/sm_controller.h
|
||||
hle/service/sockets/bsd.cpp
|
||||
hle/service/sockets/bsd.h
|
||||
hle/service/sockets/ethc.cpp
|
||||
@@ -553,10 +547,10 @@ add_library(core STATIC
|
||||
hle/service/sockets/sockets_translate.h
|
||||
hle/service/spl/csrng.cpp
|
||||
hle/service/spl/csrng.h
|
||||
hle/service/spl/module.cpp
|
||||
hle/service/spl/module.h
|
||||
hle/service/spl/spl.cpp
|
||||
hle/service/spl/spl.h
|
||||
hle/service/spl/spl_module.cpp
|
||||
hle/service/spl/spl_module.h
|
||||
hle/service/spl/spl_results.h
|
||||
hle/service/spl/spl_types.h
|
||||
hle/service/ssl/ssl.cpp
|
||||
@@ -565,6 +559,8 @@ add_library(core STATIC
|
||||
hle/service/time/ephemeral_network_system_clock_context_writer.h
|
||||
hle/service/time/ephemeral_network_system_clock_core.h
|
||||
hle/service/time/errors.h
|
||||
hle/service/time/interface.cpp
|
||||
hle/service/time/interface.h
|
||||
hle/service/time/local_system_clock_context_writer.h
|
||||
hle/service/time/network_system_clock_context_writer.h
|
||||
hle/service/time/standard_local_system_clock_core.h
|
||||
@@ -582,8 +578,6 @@ add_library(core STATIC
|
||||
hle/service/time/tick_based_steady_clock_core.h
|
||||
hle/service/time/time.cpp
|
||||
hle/service/time/time.h
|
||||
hle/service/time/time_interface.cpp
|
||||
hle/service/time/time_interface.h
|
||||
hle/service/time/time_manager.cpp
|
||||
hle/service/time/time_manager.h
|
||||
hle/service/time/time_sharedmemory.cpp
|
||||
@@ -640,8 +634,6 @@ add_library(core STATIC
|
||||
memory.h
|
||||
network/network.cpp
|
||||
network/network.h
|
||||
network/network_interface.cpp
|
||||
network/network_interface.h
|
||||
network/sockets.h
|
||||
perf_stats.cpp
|
||||
perf_stats.h
|
||||
|
||||
+24
-41
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -36,9 +35,9 @@
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/apm/apm_controller.h"
|
||||
#include "core/hle/service/apm/controller.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/glue/manager.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
@@ -83,14 +82,10 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||
}
|
||||
}
|
||||
|
||||
void KProcessDeleter(Kernel::KProcess* process) {
|
||||
process->Destroy();
|
||||
}
|
||||
|
||||
using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
/*static*/ System System::s_instance;
|
||||
|
||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
const std::string& path) {
|
||||
// To account for split 00+01+etc files.
|
||||
@@ -221,9 +216,9 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id, std::size_t program_index) {
|
||||
std::size_t program_index) {
|
||||
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
|
||||
program_id, program_index);
|
||||
program_index);
|
||||
|
||||
if (!app_loader) {
|
||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||
@@ -239,8 +234,8 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||
main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
|
||||
auto main_process = Kernel::KProcess::Create(system.Kernel());
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
|
||||
Kernel::KProcess::ProcessType::Userland)
|
||||
.IsSuccess());
|
||||
main_process->Open();
|
||||
@@ -253,7 +248,7 @@ struct System::Impl {
|
||||
static_cast<u32>(load_result));
|
||||
}
|
||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||
kernel.MakeCurrentProcess(main_process.get());
|
||||
kernel.MakeCurrentProcess(main_process);
|
||||
kernel.InitializeCores();
|
||||
|
||||
// Initialize cheat engine
|
||||
@@ -274,10 +269,11 @@ struct System::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) {
|
||||
u64 title_id{0};
|
||||
if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
|
||||
LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
|
||||
}
|
||||
perf_stats = std::make_unique<PerfStats>(program_id);
|
||||
perf_stats = std::make_unique<PerfStats>(title_id);
|
||||
// Reset counters and set time origin to current frame
|
||||
GetAndResetPerfStats();
|
||||
perf_stats->BeginSystemFrame();
|
||||
@@ -305,7 +301,10 @@ struct System::Impl {
|
||||
is_powered_on = false;
|
||||
exit_lock = false;
|
||||
|
||||
gpu_core.reset();
|
||||
if (gpu_core) {
|
||||
gpu_core->ShutDown();
|
||||
}
|
||||
|
||||
services.reset();
|
||||
service_manager.reset();
|
||||
cheat_engine.reset();
|
||||
@@ -314,12 +313,11 @@ struct System::Impl {
|
||||
time_manager.Shutdown();
|
||||
core_timing.Shutdown();
|
||||
app_loader.reset();
|
||||
gpu_core.reset();
|
||||
perf_stats.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");
|
||||
}
|
||||
@@ -378,7 +376,6 @@ 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{};
|
||||
@@ -415,7 +412,7 @@ struct System::Impl {
|
||||
std::string status_details = "";
|
||||
|
||||
std::unique_ptr<Core::PerfStats> perf_stats;
|
||||
Core::SpeedLimiter speed_limiter;
|
||||
Core::FrameLimiter frame_limiter;
|
||||
|
||||
bool is_multicore{};
|
||||
bool is_async_gpu{};
|
||||
@@ -429,20 +426,6 @@ 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;
|
||||
}
|
||||
@@ -476,8 +459,8 @@ void System::Shutdown() {
|
||||
}
|
||||
|
||||
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id, std::size_t program_index) {
|
||||
return impl->Load(*this, emu_window, filepath, program_id, program_index);
|
||||
std::size_t program_index) {
|
||||
return impl->Load(*this, emu_window, filepath, program_index);
|
||||
}
|
||||
|
||||
bool System::IsPoweredOn() const {
|
||||
@@ -624,12 +607,12 @@ const Core::PerfStats& System::GetPerfStats() const {
|
||||
return *impl->perf_stats;
|
||||
}
|
||||
|
||||
Core::SpeedLimiter& System::SpeedLimiter() {
|
||||
return impl->speed_limiter;
|
||||
Core::FrameLimiter& System::FrameLimiter() {
|
||||
return impl->frame_limiter;
|
||||
}
|
||||
|
||||
const Core::SpeedLimiter& System::SpeedLimiter() const {
|
||||
return impl->speed_limiter;
|
||||
const Core::FrameLimiter& System::FrameLimiter() const {
|
||||
return impl->frame_limiter;
|
||||
}
|
||||
|
||||
Loader::ResultStatus System::GetGameName(std::string& out) const {
|
||||
|
||||
+10
-10
@@ -94,7 +94,7 @@ class ARM_Interface;
|
||||
class CpuManager;
|
||||
class DeviceMemory;
|
||||
class ExclusiveMonitor;
|
||||
class SpeedLimiter;
|
||||
class FrameLimiter;
|
||||
class PerfStats;
|
||||
class Reporter;
|
||||
class TelemetrySession;
|
||||
@@ -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();
|
||||
|
||||
static void InitializeGlobalInstance();
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||
enum class ResultStatus : u32 {
|
||||
@@ -175,7 +175,7 @@ public:
|
||||
* @returns ResultStatus code, indicating if the operation succeeded.
|
||||
*/
|
||||
[[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id = 0, std::size_t program_index = 0);
|
||||
std::size_t program_index = 0);
|
||||
|
||||
/**
|
||||
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
||||
@@ -292,11 +292,11 @@ public:
|
||||
/// Provides a constant reference to the internal PerfStats instance.
|
||||
[[nodiscard]] const Core::PerfStats& GetPerfStats() const;
|
||||
|
||||
/// Provides a reference to the speed limiter;
|
||||
[[nodiscard]] Core::SpeedLimiter& SpeedLimiter();
|
||||
/// Provides a reference to the frame limiter;
|
||||
[[nodiscard]] Core::FrameLimiter& FrameLimiter();
|
||||
|
||||
/// Provides a constant reference to the speed limiter
|
||||
[[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const;
|
||||
/// Provides a constant referent to the frame limiter
|
||||
[[nodiscard]] const Core::FrameLimiter& FrameLimiter() const;
|
||||
|
||||
/// Gets the name of the current game
|
||||
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
|
||||
@@ -396,7 +396,7 @@ private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
inline static std::unique_ptr<System> s_instance{};
|
||||
static System s_instance;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
+15
-10
@@ -21,25 +21,34 @@ namespace Core {
|
||||
CpuManager::CpuManager(System& system_) : system{system_} {}
|
||||
CpuManager::~CpuManager() = default;
|
||||
|
||||
void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
|
||||
std::size_t core) {
|
||||
cpu_manager.RunThread(stop_token, core);
|
||||
void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) {
|
||||
cpu_manager.RunThread(core);
|
||||
}
|
||||
|
||||
void CpuManager::Initialize() {
|
||||
running_mode = true;
|
||||
if (is_multicore) {
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
|
||||
core_data[core].host_thread =
|
||||
std::make_unique<std::thread>(ThreadStart, std::ref(*this), core);
|
||||
}
|
||||
} else {
|
||||
core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0);
|
||||
core_data[0].host_thread = std::make_unique<std::thread>(ThreadStart, std::ref(*this), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::Shutdown() {
|
||||
running_mode = false;
|
||||
Pause(false);
|
||||
if (is_multicore) {
|
||||
for (auto& data : core_data) {
|
||||
data.host_thread->join();
|
||||
data.host_thread.reset();
|
||||
}
|
||||
} else {
|
||||
core_data[0].host_thread->join();
|
||||
core_data[0].host_thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() {
|
||||
@@ -308,7 +317,7 @@ void CpuManager::Pause(bool paused) {
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
|
||||
void CpuManager::RunThread(std::size_t core) {
|
||||
/// Initialization
|
||||
system.RegisterCoreThread(core);
|
||||
std::string name;
|
||||
@@ -352,10 +361,6 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
|
||||
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());
|
||||
|
||||
@@ -78,9 +78,9 @@ private:
|
||||
void SingleCoreRunSuspendThread();
|
||||
void SingleCorePause(bool paused);
|
||||
|
||||
static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
|
||||
static void ThreadStart(CpuManager& cpu_manager, std::size_t core);
|
||||
|
||||
void RunThread(std::stop_token stop_token, std::size_t core);
|
||||
void RunThread(std::size_t core);
|
||||
|
||||
struct CoreData {
|
||||
std::shared_ptr<Common::Fiber> host_context;
|
||||
@@ -89,7 +89,7 @@ private:
|
||||
std::atomic<bool> is_running;
|
||||
std::atomic<bool> is_paused;
|
||||
std::atomic<bool> initialized;
|
||||
std::jthread host_thread;
|
||||
std::unique_ptr<std::thread> host_thread;
|
||||
};
|
||||
|
||||
std::atomic<bool> running_mode{};
|
||||
|
||||
@@ -29,7 +29,7 @@ constexpr std::array partition_names{
|
||||
"logo",
|
||||
};
|
||||
|
||||
XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
||||
XCI::XCI(VirtualFile file_, std::size_t program_index)
|
||||
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
|
||||
partitions(partition_names.size()),
|
||||
partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
|
||||
@@ -63,12 +63,12 @@ XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
|
||||
|
||||
secure_partition = std::make_shared<NSP>(
|
||||
main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]),
|
||||
program_id, program_index);
|
||||
program_index);
|
||||
|
||||
ncas = secure_partition->GetNCAsCollapsed();
|
||||
program =
|
||||
secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program);
|
||||
program_nca_status = secure_partition->GetProgramStatus();
|
||||
program_nca_status = secure_partition->GetProgramStatus(secure_partition->GetProgramTitleID());
|
||||
if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) {
|
||||
program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA;
|
||||
}
|
||||
@@ -174,10 +174,6 @@ u64 XCI::GetProgramTitleID() const {
|
||||
return secure_partition->GetProgramTitleID();
|
||||
}
|
||||
|
||||
std::vector<u64> XCI::GetProgramTitleIDs() const {
|
||||
return secure_partition->GetProgramTitleIDs();
|
||||
}
|
||||
|
||||
u32 XCI::GetSystemUpdateVersion() {
|
||||
const auto update = GetPartition(XCIPartition::Update);
|
||||
if (update == nullptr) {
|
||||
@@ -233,11 +229,9 @@ const std::vector<std::shared_ptr<NCA>>& XCI::GetNCAs() const {
|
||||
}
|
||||
|
||||
std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const {
|
||||
const auto program_id = secure_partition->GetProgramTitleID();
|
||||
const auto iter = std::find_if(
|
||||
ncas.begin(), ncas.end(), [this, type, program_id](const std::shared_ptr<NCA>& nca) {
|
||||
return nca->GetType() == type && nca->GetTitleId() == program_id;
|
||||
});
|
||||
const auto iter =
|
||||
std::find_if(ncas.begin(), ncas.end(),
|
||||
[type](const std::shared_ptr<NCA>& nca) { return nca->GetType() == type; });
|
||||
return iter == ncas.end() ? nullptr : *iter;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo };
|
||||
|
||||
class XCI : public ReadOnlyVfsDirectory {
|
||||
public:
|
||||
explicit XCI(VirtualFile file, u64 program_id = 0, size_t program_index = 0);
|
||||
explicit XCI(VirtualFile file, std::size_t program_index = 0);
|
||||
~XCI() override;
|
||||
|
||||
Loader::ResultStatus GetStatus() const;
|
||||
@@ -104,7 +104,6 @@ public:
|
||||
VirtualFile GetLogoPartitionRaw() const;
|
||||
|
||||
u64 GetProgramTitleID() const;
|
||||
std::vector<u64> GetProgramTitleIDs() const;
|
||||
u32 GetSystemUpdateVersion();
|
||||
u64 GetSystemUpdateTitleID() const;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_)
|
||||
: file(std::move(file_)), expected_program_id(title_id_),
|
||||
program_index(program_index_), status{Loader::ResultStatus::Success},
|
||||
NSP::NSP(VirtualFile file_, std::size_t program_index_)
|
||||
: file(std::move(file_)), program_index(program_index_), status{Loader::ResultStatus::Success},
|
||||
pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||
if (pfs->GetStatus() != Loader::ResultStatus::Success) {
|
||||
status = pfs->GetStatus();
|
||||
@@ -47,59 +46,60 @@ Loader::ResultStatus NSP::GetStatus() const {
|
||||
return status;
|
||||
}
|
||||
|
||||
Loader::ResultStatus NSP::GetProgramStatus() const {
|
||||
Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const {
|
||||
if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) {
|
||||
return Loader::ResultStatus::Success;
|
||||
}
|
||||
|
||||
const auto iter = program_status.find(GetProgramTitleID());
|
||||
const auto iter = program_status.find(title_id);
|
||||
if (iter == program_status.end())
|
||||
return Loader::ResultStatus::ErrorNSPMissingProgramNCA;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
u64 NSP::GetProgramTitleID() const {
|
||||
u64 NSP::GetFirstTitleID() const {
|
||||
if (IsExtractedType()) {
|
||||
return GetExtractedTitleID() + program_index;
|
||||
return GetProgramTitleID();
|
||||
}
|
||||
|
||||
auto program_id = expected_program_id;
|
||||
if (program_id == 0) {
|
||||
if (!program_status.empty()) {
|
||||
program_id = program_status.begin()->first;
|
||||
if (program_status.empty())
|
||||
return 0;
|
||||
return program_status.begin()->first;
|
||||
}
|
||||
|
||||
u64 NSP::GetProgramTitleID() const {
|
||||
if (IsExtractedType()) {
|
||||
if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProgramMetadata meta;
|
||||
if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) {
|
||||
return meta.GetTitleID();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
program_id = program_id + program_index;
|
||||
if (program_status.find(program_id) != program_status.end()) {
|
||||
return program_id;
|
||||
}
|
||||
const auto out = GetFirstTitleID();
|
||||
if ((out & 0x800) == 0)
|
||||
return out;
|
||||
|
||||
const auto ids = GetProgramTitleIDs();
|
||||
const auto ids = GetTitleIDs();
|
||||
const auto iter =
|
||||
std::find_if(ids.begin(), ids.end(), [](u64 tid) { return (tid & 0x800) == 0; });
|
||||
return iter == ids.end() ? 0 : *iter;
|
||||
return iter == ids.end() ? out : *iter;
|
||||
}
|
||||
|
||||
u64 NSP::GetExtractedTitleID() const {
|
||||
if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProgramMetadata meta;
|
||||
if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) {
|
||||
return meta.GetTitleID();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u64> NSP::GetProgramTitleIDs() const {
|
||||
std::vector<u64> NSP::GetTitleIDs() const {
|
||||
if (IsExtractedType()) {
|
||||
return {GetExtractedTitleID()};
|
||||
return {GetProgramTitleID()};
|
||||
}
|
||||
|
||||
std::vector<u64> out{program_ids.cbegin(), program_ids.cend()};
|
||||
std::vector<u64> out;
|
||||
out.reserve(ncas.size());
|
||||
for (const auto& kv : ncas)
|
||||
out.push_back(kv.first);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType
|
||||
if (extracted)
|
||||
LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
|
||||
|
||||
const auto title_id_iter = ncas.find(title_id);
|
||||
const auto title_id_iter = ncas.find(title_id + program_index);
|
||||
if (title_id_iter == ncas.end())
|
||||
return nullptr;
|
||||
|
||||
@@ -160,7 +160,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType
|
||||
VirtualFile NSP::GetNCAFile(u64 title_id, ContentRecordType type, TitleType title_type) const {
|
||||
if (extracted)
|
||||
LOG_WARNING(Service_FS, "called on an NSP that is of type extracted.");
|
||||
const auto nca = GetNCA(title_id, type, title_type);
|
||||
const auto nca = GetNCA(title_id, type);
|
||||
if (nca != nullptr)
|
||||
return nca->GetBaseFile();
|
||||
return nullptr;
|
||||
@@ -286,7 +286,6 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
|
||||
|
||||
if (next_nca->GetType() == NCAContentType::Program) {
|
||||
program_status[next_nca->GetTitleId()] = next_nca->GetStatus();
|
||||
program_ids.insert(next_nca->GetTitleId() & 0xFFFFFFFFFFFFF000);
|
||||
}
|
||||
|
||||
if (next_nca->GetStatus() != Loader::ResultStatus::Success &&
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
@@ -28,15 +27,15 @@ enum class ContentRecordType : u8;
|
||||
|
||||
class NSP : public ReadOnlyVfsDirectory {
|
||||
public:
|
||||
explicit NSP(VirtualFile file_, u64 title_id = 0, std::size_t program_index_ = 0);
|
||||
explicit NSP(VirtualFile file_, std::size_t program_index_ = 0);
|
||||
~NSP() override;
|
||||
|
||||
Loader::ResultStatus GetStatus() const;
|
||||
Loader::ResultStatus GetProgramStatus() const;
|
||||
Loader::ResultStatus GetProgramStatus(u64 title_id) const;
|
||||
// Should only be used when one title id can be assured.
|
||||
u64 GetFirstTitleID() const;
|
||||
u64 GetProgramTitleID() const;
|
||||
u64 GetExtractedTitleID() const;
|
||||
std::vector<u64> GetProgramTitleIDs() const;
|
||||
std::vector<u64> GetTitleIDs() const;
|
||||
|
||||
bool IsExtractedType() const;
|
||||
|
||||
@@ -70,7 +69,6 @@ private:
|
||||
|
||||
VirtualFile file;
|
||||
|
||||
const u64 expected_program_id;
|
||||
const std::size_t program_index;
|
||||
|
||||
bool extracted = false;
|
||||
@@ -80,7 +78,6 @@ private:
|
||||
std::shared_ptr<PartitionFilesystem> pfs;
|
||||
// Map title id -> {map type -> NCA}
|
||||
std::map<u64, std::map<std::pair<TitleType, ContentRecordType>, std::shared_ptr<NCA>>> ncas;
|
||||
std::set<u64> program_ids;
|
||||
std::vector<VirtualFile> ticket_files;
|
||||
|
||||
Core::Crypto::KeyManager& keys;
|
||||
|
||||
@@ -273,10 +273,6 @@ 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,9 +199,6 @@ 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
|
||||
|
||||
@@ -13,13 +13,6 @@
|
||||
#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;
|
||||
@@ -399,28 +392,6 @@ 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,7 +86,6 @@ 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,8 +6,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
class VfsDirectory;
|
||||
@@ -20,11 +18,4 @@ 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
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
|
||||
#include "core/hle/service/am/applets/software_keyboard_types.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/hle/service/am/applets/applet_web_browser_types.h"
|
||||
#include "core/hle/service/am/applets/web_types.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hardware_interrupt_manager.h"
|
||||
#include "core/hle/service/nvdrv/nvdrv_interface.h"
|
||||
#include "core/hle/service/nvdrv/interface.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Core::Hardware {
|
||||
|
||||
+11
-18
@@ -12,9 +12,9 @@ namespace HLE::ApiVersion {
|
||||
|
||||
// Horizon OS version constants.
|
||||
|
||||
constexpr u8 HOS_VERSION_MAJOR = 12;
|
||||
constexpr u8 HOS_VERSION_MINOR = 1;
|
||||
constexpr u8 HOS_VERSION_MICRO = 0;
|
||||
constexpr u8 HOS_VERSION_MAJOR = 11;
|
||||
constexpr u8 HOS_VERSION_MINOR = 0;
|
||||
constexpr u8 HOS_VERSION_MICRO = 1;
|
||||
|
||||
// NintendoSDK version constants.
|
||||
|
||||
@@ -22,26 +22,19 @@ constexpr u8 SDK_REVISION_MAJOR = 1;
|
||||
constexpr u8 SDK_REVISION_MINOR = 0;
|
||||
|
||||
constexpr char PLATFORM_STRING[] = "NX";
|
||||
constexpr char VERSION_HASH[] = "76b10c2dab7d3aa73fc162f8dff1655e6a21caf4";
|
||||
constexpr char DISPLAY_VERSION[] = "12.1.0";
|
||||
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0";
|
||||
constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
|
||||
constexpr char DISPLAY_VERSION[] = "11.0.1";
|
||||
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
|
||||
|
||||
// Atmosphere version constants.
|
||||
|
||||
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 u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
|
||||
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 4;
|
||||
|
||||
constexpr u32 GetTargetFirmware() {
|
||||
return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO);
|
||||
return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
|
||||
u32{HOS_VERSION_MICRO} << 8 | 0U;
|
||||
}
|
||||
|
||||
} // namespace HLE::ApiVersion
|
||||
@@ -58,9 +58,6 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co
|
||||
|
||||
void SessionRequestHandler::ClientConnected(KServerSession* session) {
|
||||
session->ClientConnected(shared_from_this());
|
||||
|
||||
// Ensure our server session is tracked globally.
|
||||
kernel.RegisterServerSession(session);
|
||||
}
|
||||
|
||||
void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
@@ -12,12 +11,4 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
void KAutoObject::RegisterWithKernel() {
|
||||
kernel.RegisterKernelObject(this);
|
||||
}
|
||||
|
||||
void KAutoObject::UnregisterWithKernel() {
|
||||
kernel.UnregisterKernelObject(this);
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -85,12 +85,8 @@ private:
|
||||
KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject);
|
||||
|
||||
public:
|
||||
explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {
|
||||
RegisterWithKernel();
|
||||
}
|
||||
virtual ~KAutoObject() {
|
||||
UnregisterWithKernel();
|
||||
}
|
||||
explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {}
|
||||
virtual ~KAutoObject() = default;
|
||||
|
||||
static KAutoObject* Create(KAutoObject* ptr);
|
||||
|
||||
@@ -170,10 +166,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void RegisterWithKernel();
|
||||
void UnregisterWithKernel();
|
||||
|
||||
protected:
|
||||
KernelCore& kernel;
|
||||
std::string name;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/device_memory.h"
|
||||
@@ -44,8 +43,6 @@ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority
|
||||
ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1));
|
||||
|
||||
KThread* thread = KThread::Create(system.Kernel());
|
||||
SCOPE_EXIT({ thread->Close(); });
|
||||
|
||||
ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority,
|
||||
owner_process.GetIdealCoreId(), &owner_process)
|
||||
.IsSuccess());
|
||||
@@ -165,7 +162,7 @@ void KProcess::DecrementThreadCount() {
|
||||
ASSERT(num_threads > 0);
|
||||
|
||||
if (const auto count = --num_threads; count == 0) {
|
||||
LOG_WARNING(Kernel, "Process termination is not fully implemented.");
|
||||
UNIMPLEMENTED_MSG("Process termination is not implemented!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,9 +406,6 @@ void KProcess::Finalize() {
|
||||
resource_limit->Close();
|
||||
}
|
||||
|
||||
// Finalize the handle table and close any open handles.
|
||||
handle_table.Finalize();
|
||||
|
||||
// Perform inherited finalization.
|
||||
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
|
||||
}
|
||||
|
||||
@@ -28,10 +28,7 @@ namespace Kernel {
|
||||
|
||||
KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
|
||||
|
||||
KServerSession::~KServerSession() {
|
||||
// Ensure that the global list tracking server sessions does not hold on to a reference.
|
||||
kernel.UnregisterServerSession(this);
|
||||
}
|
||||
KServerSession::~KServerSession() {}
|
||||
|
||||
void KServerSession::Initialize(KSession* parent_session_, std::string&& name_,
|
||||
std::shared_ptr<SessionRequestManager> manager_) {
|
||||
|
||||
@@ -61,7 +61,6 @@ struct KernelCore::Impl {
|
||||
void Initialize(KernelCore& kernel) {
|
||||
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
||||
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
||||
global_handle_table->Initialize(KHandleTable::MaxTableSize);
|
||||
|
||||
is_phantom_mode_for_singlecore = false;
|
||||
|
||||
@@ -91,39 +90,9 @@ struct KernelCore::Impl {
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
// Shutdown all processes.
|
||||
if (current_process) {
|
||||
current_process->Finalize();
|
||||
current_process->Close();
|
||||
current_process = nullptr;
|
||||
}
|
||||
process_list.clear();
|
||||
|
||||
// Close all open server ports.
|
||||
std::unordered_set<KServerPort*> server_ports_;
|
||||
{
|
||||
std::lock_guard lk(server_ports_lock);
|
||||
server_ports_ = server_ports;
|
||||
server_ports.clear();
|
||||
}
|
||||
for (auto* server_port : server_ports_) {
|
||||
server_port->Close();
|
||||
}
|
||||
// Close all open server sessions.
|
||||
std::unordered_set<KServerSession*> server_sessions_;
|
||||
{
|
||||
std::lock_guard lk(server_sessions_lock);
|
||||
server_sessions_ = server_sessions;
|
||||
server_sessions.clear();
|
||||
}
|
||||
for (auto* server_session : server_sessions_) {
|
||||
server_session->Close();
|
||||
}
|
||||
|
||||
// Ensure that the object list container is finalized and properly shutdown.
|
||||
object_list_container.Finalize();
|
||||
|
||||
// Ensures all service threads gracefully shutdown.
|
||||
// Ensures all service threads gracefully shutdown
|
||||
service_threads.clear();
|
||||
|
||||
next_object_id = 0;
|
||||
@@ -142,7 +111,11 @@ struct KernelCore::Impl {
|
||||
|
||||
cores.clear();
|
||||
|
||||
global_handle_table->Finalize();
|
||||
if (current_process) {
|
||||
current_process->Close();
|
||||
current_process = nullptr;
|
||||
}
|
||||
|
||||
global_handle_table.reset();
|
||||
|
||||
preemption_event = nullptr;
|
||||
@@ -169,16 +142,6 @@ struct KernelCore::Impl {
|
||||
|
||||
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
|
||||
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
|
||||
|
||||
// Track kernel objects that were not freed on shutdown
|
||||
{
|
||||
std::lock_guard lk(registered_objects_lock);
|
||||
if (registered_objects.size()) {
|
||||
LOG_WARNING(Kernel, "{} kernel objects were dangling on shutdown!",
|
||||
registered_objects.size());
|
||||
registered_objects.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitializePhysicalCores() {
|
||||
@@ -267,23 +230,20 @@ struct KernelCore::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
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::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);
|
||||
/// 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++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) {
|
||||
const thread_local auto host_thread_id{AllocateHostThreadId(core_id)};
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
@@ -670,21 +630,6 @@ struct KernelCore::Impl {
|
||||
user_slab_heap_size);
|
||||
}
|
||||
|
||||
KClientPort* CreateNamedServicePort(std::string name) {
|
||||
auto search = service_interface_factory.find(name);
|
||||
if (search == service_interface_factory.end()) {
|
||||
UNIMPLEMENTED();
|
||||
return {};
|
||||
}
|
||||
|
||||
KClientPort* port = &search->second(system.ServiceManager(), system);
|
||||
{
|
||||
std::lock_guard lk(server_ports_lock);
|
||||
server_ports.insert(&port->GetParent()->GetServerPort());
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
std::atomic<u32> next_object_id{0};
|
||||
std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
|
||||
std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin};
|
||||
@@ -711,12 +656,6 @@ struct KernelCore::Impl {
|
||||
/// the ConnectToPort SVC.
|
||||
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
|
||||
NamedPortTable named_ports;
|
||||
std::unordered_set<KServerPort*> server_ports;
|
||||
std::unordered_set<KServerSession*> server_sessions;
|
||||
std::unordered_set<KAutoObject*> registered_objects;
|
||||
std::mutex server_ports_lock;
|
||||
std::mutex server_sessions_lock;
|
||||
std::mutex registered_objects_lock;
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
|
||||
std::vector<Kernel::PhysicalCore> cores;
|
||||
@@ -905,27 +844,12 @@ void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&
|
||||
}
|
||||
|
||||
KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
|
||||
return impl->CreateNamedServicePort(std::move(name));
|
||||
}
|
||||
|
||||
void KernelCore::RegisterServerSession(KServerSession* server_session) {
|
||||
std::lock_guard lk(impl->server_sessions_lock);
|
||||
impl->server_sessions.insert(server_session);
|
||||
}
|
||||
|
||||
void KernelCore::UnregisterServerSession(KServerSession* server_session) {
|
||||
std::lock_guard lk(impl->server_sessions_lock);
|
||||
impl->server_sessions.erase(server_session);
|
||||
}
|
||||
|
||||
void KernelCore::RegisterKernelObject(KAutoObject* object) {
|
||||
std::lock_guard lk(impl->registered_objects_lock);
|
||||
impl->registered_objects.insert(object);
|
||||
}
|
||||
|
||||
void KernelCore::UnregisterKernelObject(KAutoObject* object) {
|
||||
std::lock_guard lk(impl->registered_objects_lock);
|
||||
impl->registered_objects.erase(object);
|
||||
auto search = impl->service_interface_factory.find(name);
|
||||
if (search == impl->service_interface_factory.end()) {
|
||||
UNIMPLEMENTED();
|
||||
return {};
|
||||
}
|
||||
return &search->second(impl->system.ServiceManager(), impl->system);
|
||||
}
|
||||
|
||||
bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -46,7 +45,6 @@ class KPort;
|
||||
class KProcess;
|
||||
class KResourceLimit;
|
||||
class KScheduler;
|
||||
class KServerSession;
|
||||
class KSession;
|
||||
class KSharedMemory;
|
||||
class KThread;
|
||||
@@ -187,22 +185,6 @@ public:
|
||||
/// Opens a port to a service previously registered with RegisterNamedService.
|
||||
KClientPort* CreateNamedServicePort(std::string name);
|
||||
|
||||
/// Registers a server session with the gobal emulation state, to be freed on shutdown. This is
|
||||
/// necessary because we do not emulate processes for HLE sessions.
|
||||
void RegisterServerSession(KServerSession* server_session);
|
||||
|
||||
/// Unregisters a server session previously registered with RegisterServerSession when it was
|
||||
/// destroyed during the current emulation session.
|
||||
void UnregisterServerSession(KServerSession* server_session);
|
||||
|
||||
/// Registers all kernel objects with the global emulation state, this is purely for tracking
|
||||
/// leaks after emulation has been shutdown.
|
||||
void RegisterKernelObject(KAutoObject* object);
|
||||
|
||||
/// Unregisters a kernel object previously registered with RegisterKernelObject when it was
|
||||
/// destroyed during the current emulation session.
|
||||
void UnregisterKernelObject(KAutoObject* object);
|
||||
|
||||
/// Determines whether or not the given port is a valid named port.
|
||||
bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
|
||||
|
||||
|
||||
@@ -298,7 +298,6 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr po
|
||||
// Create a session.
|
||||
KClientSession* session{};
|
||||
R_TRY(port->CreateSession(std::addressof(session)));
|
||||
port->Close();
|
||||
|
||||
// Register the session in the table, close the extra reference.
|
||||
handle_table.Register(*out, session);
|
||||
@@ -1078,8 +1077,8 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
|
||||
for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
||||
if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) {
|
||||
current = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// If the thread is current, retry until it isn't.
|
||||
@@ -1440,6 +1439,11 @@ static void ExitProcess(Core::System& system) {
|
||||
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
|
||||
ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running,
|
||||
"Process has already exited");
|
||||
|
||||
current_process->PrepareForTermination();
|
||||
|
||||
// Kill the current thread
|
||||
system.Kernel().CurrentScheduler()->GetCurrentThread()->Exit();
|
||||
}
|
||||
|
||||
static void ExitProcess32(Core::System& system) {
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
#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"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/glue/manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
@@ -293,7 +292,7 @@ public:
|
||||
|
||||
protected:
|
||||
void Get(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
ProfileBase profile_base{};
|
||||
ProfileData data{};
|
||||
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
|
||||
@@ -302,7 +301,7 @@ protected:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(profile_base);
|
||||
} else {
|
||||
LOG_ERROR(Service_ACC, "Failed to get profile base and data for user=0x{}",
|
||||
LOG_ERROR(Service_ACC, "Failed to get profile base and data for user={}",
|
||||
user_id.Format());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code
|
||||
@@ -310,14 +309,14 @@ protected:
|
||||
}
|
||||
|
||||
void GetBase(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
ProfileBase profile_base{};
|
||||
if (profile_manager.GetProfileBase(user_id, profile_base)) {
|
||||
IPC::ResponseBuilder rb{ctx, 16};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(profile_base);
|
||||
} else {
|
||||
LOG_ERROR(Service_ACC, "Failed to get profile base for user=0x{}", user_id.Format());
|
||||
LOG_ERROR(Service_ACC, "Failed to get profile base for user={}", user_id.Format());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code
|
||||
}
|
||||
@@ -373,7 +372,7 @@ protected:
|
||||
|
||||
const auto user_data = ctx.ReadBuffer();
|
||||
|
||||
LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid=0x{}",
|
||||
LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}",
|
||||
Common::StringFromFixedZeroTerminatedBuffer(
|
||||
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
|
||||
base.timestamp, base.user_uuid.Format());
|
||||
@@ -406,7 +405,7 @@ protected:
|
||||
const auto user_data = ctx.ReadBuffer();
|
||||
const auto image_data = ctx.ReadBuffer(1);
|
||||
|
||||
LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid=0x{}",
|
||||
LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}",
|
||||
Common::StringFromFixedZeroTerminatedBuffer(
|
||||
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
|
||||
base.timestamp, base.user_uuid.Format());
|
||||
@@ -455,6 +454,22 @@ 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)
|
||||
@@ -489,44 +504,16 @@ 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"},
|
||||
ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
|
||||
user_id{user_id_} {
|
||||
: ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
|
||||
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
|
||||
{2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"},
|
||||
{3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"},
|
||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
{3, nullptr, "LoadIdTokenCache"},
|
||||
{130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"},
|
||||
{150, nullptr, "CreateAuthorizationRequest"},
|
||||
{160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
|
||||
@@ -553,20 +540,6 @@ 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");
|
||||
|
||||
@@ -589,7 +562,6 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
|
||||
Common::UUID user_id{Common::INVALID_UUID};
|
||||
};
|
||||
|
||||
@@ -690,7 +662,7 @@ void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
Common::UUID user_id = rp.PopRaw<Common::UUID>();
|
||||
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
@@ -721,7 +693,7 @@ void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
Common::UUID user_id = rp.PopRaw<Common::UUID>();
|
||||
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@@ -830,7 +802,7 @@ void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
Common::UUID user_id = rp.PopRaw<Common::UUID>();
|
||||
|
||||
LOG_DEBUG(Service_ACC, "called, user_id=0x{}", user_id.Format());
|
||||
LOG_DEBUG(Service_ACC, "called, user_id={}", user_id.Format());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
@@ -872,7 +844,7 @@ void Module::Interface::StoreSaveDataThumbnailApplication(Kernel::HLERequestCont
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto uuid = rp.PopRaw<Common::UUID>();
|
||||
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called, uuid=0x{}", uuid.Format());
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called, uuid={}", uuid.Format());
|
||||
|
||||
// TODO(ogniK): Check if application ID is zero on acc initialize. As we don't have a reliable
|
||||
// way of confirming things like the TID, we're going to assume a non zero value for the time
|
||||
@@ -886,7 +858,7 @@ void Module::Interface::StoreSaveDataThumbnailSystem(Kernel::HLERequestContext&
|
||||
const auto uuid = rp.PopRaw<Common::UUID>();
|
||||
const auto tid = rp.Pop<u64_le>();
|
||||
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called, uuid=0x{}, tid={:016X}", uuid.Format(), tid);
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called, uuid={}, tid={:016X}", uuid.Format(), tid);
|
||||
StoreSaveDataThumbnail(ctx, uuid, tid);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/glue/manager.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::Account {
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// 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/service/acc/async_context.h"
|
||||
|
||||
namespace Service::Account {
|
||||
IAsyncContext::IAsyncContext(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAsyncContext"}, compeletion_event{system_.Kernel()} {
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(compeletion_event));
|
||||
compeletion_event.Initialize("IAsyncContext:CompletionEvent");
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(compeletion_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);
|
||||
compeletion_event.GetWritableEvent().Signal();
|
||||
}
|
||||
|
||||
} // namespace Service::Account
|
||||
@@ -1,37 +0,0 @@
|
||||
// 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/kernel/k_event.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_);
|
||||
|
||||
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();
|
||||
|
||||
std::atomic<bool> is_complete{false};
|
||||
Kernel::KEvent compeletion_event;
|
||||
};
|
||||
|
||||
} // namespace Service::Account
|
||||
@@ -24,16 +24,16 @@
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
||||
#include "core/hle/service/am/applets/applet_software_keyboard.h"
|
||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/am/applets/profile_select.h"
|
||||
#include "core/hle/service/am/applets/software_keyboard.h"
|
||||
#include "core/hle/service/am/applets/web_browser.h"
|
||||
#include "core/hle/service/am/idle.h"
|
||||
#include "core/hle/service/am/omm.h"
|
||||
#include "core/hle/service/am/spsm.h"
|
||||
#include "core/hle/service/am/tcap.h"
|
||||
#include "core/hle/service/apm/apm_controller.h"
|
||||
#include "core/hle/service/apm/apm_interface.h"
|
||||
#include "core/hle/service/apm/controller.h"
|
||||
#include "core/hle/service/apm/interface.h"
|
||||
#include "core/hle/service/bcat/backend/backend.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
@@ -1270,8 +1270,7 @@ 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()},
|
||||
notification_storage_channel_event{system.Kernel()}, health_warning_disappeared_system_event{
|
||||
system.Kernel()} {
|
||||
health_warning_disappeared_system_event{system.Kernel()} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
||||
@@ -1323,7 +1322,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
|
||||
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
|
||||
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
|
||||
{150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
|
||||
{150, nullptr, "GetNotificationStorageChannelEvent"},
|
||||
{151, nullptr, "TryPopFromNotificationStorageChannel"},
|
||||
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
|
||||
{170, nullptr, "SetHdcpAuthenticationActivated"},
|
||||
@@ -1341,14 +1340,11 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
|
||||
Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event));
|
||||
Kernel::KAutoObject::Create(std::addressof(notification_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");
|
||||
notification_storage_channel_event.Initialize(
|
||||
"IApplicationFunctions:NotificationStorageChannelEvent");
|
||||
health_warning_disappeared_system_event.Initialize(
|
||||
"IApplicationFunctions:HealthWarningDisappearedSystemEvent");
|
||||
}
|
||||
@@ -1766,14 +1762,6 @@ 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");
|
||||
|
||||
|
||||
@@ -295,7 +295,6 @@ 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);
|
||||
|
||||
bool launch_popped_application_specific = false;
|
||||
@@ -303,7 +302,6 @@ private:
|
||||
s32 previous_program_index{-1};
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/am/applets/applet_controller.h"
|
||||
#include "core/hle/service/am/applets/applet_error.h"
|
||||
#include "core/hle/service/am/applets/applet_general_backend.h"
|
||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
||||
#include "core/hle/service/am/applets/applet_software_keyboard.h"
|
||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/am/applets/controller.h"
|
||||
#include "core/hle/service/am/applets/error.h"
|
||||
#include "core/hle/service/am/applets/general_backend.h"
|
||||
#include "core/hle/service/am/applets/profile_select.h"
|
||||
#include "core/hle/service/am/applets/software_keyboard.h"
|
||||
#include "core/hle/service/am/applets/web_browser.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
+2
-21
@@ -12,7 +12,7 @@
|
||||
#include "core/frontend/applets/controller.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_controller.h"
|
||||
#include "core/hle/service/am/applets/controller.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
@@ -87,10 +87,6 @@ void Controller::Initialize() {
|
||||
case sizeof(ControllerUpdateFirmwareArg):
|
||||
controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate;
|
||||
break;
|
||||
case sizeof(ControllerKeyRemappingArg):
|
||||
controller_private_arg.mode =
|
||||
ControllerSupportMode::ShowControllerKeyRemappingForSystem;
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}",
|
||||
controller_private_arg.mode, controller_private_arg.arg_size);
|
||||
@@ -103,9 +99,7 @@ void Controller::Initialize() {
|
||||
// This is always 0 (Application) except with ShowControllerFirmwareUpdateForSystem.
|
||||
if (controller_private_arg.caller >= ControllerSupportCaller::MaxControllerSupportCaller) {
|
||||
if (controller_private_arg.flag_1 &&
|
||||
(controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate ||
|
||||
controller_private_arg.mode ==
|
||||
ControllerSupportMode::ShowControllerKeyRemappingForSystem)) {
|
||||
controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate) {
|
||||
controller_private_arg.caller = ControllerSupportCaller::System;
|
||||
} else {
|
||||
controller_private_arg.caller = ControllerSupportCaller::Application;
|
||||
@@ -127,7 +121,6 @@ void Controller::Initialize() {
|
||||
std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size());
|
||||
break;
|
||||
case ControllerAppletVersion::Version7:
|
||||
case ControllerAppletVersion::Version8:
|
||||
ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew));
|
||||
std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size());
|
||||
break;
|
||||
@@ -150,16 +143,6 @@ void Controller::Initialize() {
|
||||
std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size());
|
||||
break;
|
||||
}
|
||||
case ControllerSupportMode::ShowControllerKeyRemappingForSystem: {
|
||||
const auto remapping_arg_storage = broker.PopNormalDataToApplet();
|
||||
ASSERT(remapping_arg_storage != nullptr);
|
||||
|
||||
const auto& remapping_arg = remapping_arg_storage->GetData();
|
||||
ASSERT(remapping_arg.size() == sizeof(ControllerKeyRemappingArg));
|
||||
|
||||
std::memcpy(&controller_key_remapping_arg, remapping_arg.data(), remapping_arg.size());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode);
|
||||
break;
|
||||
@@ -196,7 +179,6 @@ void Controller::Execute() {
|
||||
std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(),
|
||||
controller_user_arg_old.explain_text.end()));
|
||||
case ControllerAppletVersion::Version7:
|
||||
case ControllerAppletVersion::Version8:
|
||||
default:
|
||||
return ConvertToFrontendParameters(
|
||||
controller_private_arg, controller_user_arg_new.header,
|
||||
@@ -228,7 +210,6 @@ void Controller::Execute() {
|
||||
}
|
||||
case ControllerSupportMode::ShowControllerStrapGuide:
|
||||
case ControllerSupportMode::ShowControllerFirmwareUpdate:
|
||||
case ControllerSupportMode::ShowControllerKeyRemappingForSystem:
|
||||
UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented",
|
||||
controller_private_arg.mode);
|
||||
ConfigurationComplete();
|
||||
+2
-13
@@ -25,15 +25,13 @@ enum class ControllerAppletVersion : u32_le {
|
||||
Version3 = 0x3, // 1.0.0 - 2.3.0
|
||||
Version4 = 0x4, // 3.0.0 - 5.1.0
|
||||
Version5 = 0x5, // 6.0.0 - 7.0.1
|
||||
Version7 = 0x7, // 8.0.0 - 10.2.0
|
||||
Version8 = 0x8, // 11.0.0+
|
||||
Version7 = 0x7, // 8.0.0+
|
||||
};
|
||||
|
||||
enum class ControllerSupportMode : u8 {
|
||||
ShowControllerSupport,
|
||||
ShowControllerStrapGuide,
|
||||
ShowControllerFirmwareUpdate,
|
||||
ShowControllerKeyRemappingForSystem,
|
||||
|
||||
MaxControllerSupportMode,
|
||||
};
|
||||
@@ -80,7 +78,7 @@ struct ControllerSupportArgOld {
|
||||
static_assert(sizeof(ControllerSupportArgOld) == 0x21C,
|
||||
"ControllerSupportArgOld has incorrect size.");
|
||||
|
||||
// LibraryAppletVersion 0x7, 0x8
|
||||
// LibraryAppletVersion 0x7
|
||||
struct ControllerSupportArgNew {
|
||||
ControllerSupportArgHeader header{};
|
||||
std::array<IdentificationColor, 8> identification_colors{};
|
||||
@@ -97,14 +95,6 @@ struct ControllerUpdateFirmwareArg {
|
||||
static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4,
|
||||
"ControllerUpdateFirmwareArg has incorrect size.");
|
||||
|
||||
struct ControllerKeyRemappingArg {
|
||||
u64 unknown{};
|
||||
u32 unknown_2{};
|
||||
INSERT_PADDING_WORDS(1);
|
||||
};
|
||||
static_assert(sizeof(ControllerKeyRemappingArg) == 0x10,
|
||||
"ControllerKeyRemappingArg has incorrect size.");
|
||||
|
||||
struct ControllerSupportResultInfo {
|
||||
s8 player_count{};
|
||||
INSERT_PADDING_BYTES(3);
|
||||
@@ -138,7 +128,6 @@ private:
|
||||
ControllerSupportArgOld controller_user_arg_old;
|
||||
ControllerSupportArgNew controller_user_arg_new;
|
||||
ControllerUpdateFirmwareArg controller_update_arg;
|
||||
ControllerKeyRemappingArg controller_key_remapping_arg;
|
||||
bool complete{false};
|
||||
ResultCode status{ResultSuccess};
|
||||
bool is_single_mode{false};
|
||||
+7
-26
@@ -11,35 +11,11 @@
|
||||
#include "core/frontend/applets/error.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_error.h"
|
||||
#include "core/hle/service/am/applets/error.h"
|
||||
#include "core/reporter.h"
|
||||
|
||||
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;
|
||||
@@ -100,7 +76,12 @@ void CopyArgumentData(const std::vector<u8>& data, T& variable) {
|
||||
}
|
||||
|
||||
ResultCode Decode64BitError(u64 error) {
|
||||
return ErrorCode::FromU64(error).ToResultCode();
|
||||
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)};
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
File renamed without changes.
+1
-1
@@ -12,7 +12,7 @@
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_general_backend.h"
|
||||
#include "core/hle/service/am/applets/general_backend.h"
|
||||
#include "core/reporter.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
File renamed without changes.
+1
-1
@@ -9,7 +9,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/applets/profile_select.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
||||
#include "core/hle/service/am/applets/profile_select.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
File renamed without changes.
+3
-5
@@ -6,7 +6,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/applets/software_keyboard.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_software_keyboard.h"
|
||||
#include "core/hle/service/am/applets/software_keyboard.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
@@ -377,8 +377,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
|
||||
|
||||
if (swkbd_config_common.use_utf8) {
|
||||
std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text);
|
||||
// Include the null terminator in the buffer size.
|
||||
const u64 buffer_size = utf8_submitted_text.size() + 1;
|
||||
const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size();
|
||||
|
||||
LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size,
|
||||
utf8_submitted_text);
|
||||
@@ -387,8 +386,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
|
||||
std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(),
|
||||
utf8_submitted_text.size());
|
||||
} else {
|
||||
// Include the null terminator in the buffer size.
|
||||
const u64 buffer_size = (current_text.size() + 1) * sizeof(char16_t);
|
||||
const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t);
|
||||
|
||||
LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size,
|
||||
Common::UTF16ToUTF8(current_text));
|
||||
+1
-1
@@ -7,8 +7,8 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/am/applets/software_keyboard_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
File renamed without changes.
+1
-14
@@ -21,7 +21,7 @@
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
||||
#include "core/hle/service/am/applets/web_browser.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/pl_u.h"
|
||||
|
||||
@@ -58,16 +58,6 @@ std::string GetMainURL(const std::string& url) {
|
||||
return url.substr(0, index);
|
||||
}
|
||||
|
||||
std::string ResolveURL(const std::string& url) {
|
||||
const auto index = url.find_first_of('%');
|
||||
|
||||
if (index == std::string::npos) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return url.substr(0, index) + "lp1" + url.substr(index + 1);
|
||||
}
|
||||
|
||||
WebArgInputTLVMap ReadWebArgs(const std::vector<u8>& web_arg, WebArgHeader& web_arg_header) {
|
||||
std::memcpy(&web_arg_header, web_arg.data(), sizeof(WebArgHeader));
|
||||
|
||||
@@ -417,9 +407,6 @@ void WebBrowser::InitializeShare() {}
|
||||
|
||||
void WebBrowser::InitializeWeb() {
|
||||
external_url = ParseStringValue(GetInputTLVData(WebArgInputTLVType::InitialURL).value());
|
||||
|
||||
// Resolve Nintendo CDN URLs.
|
||||
external_url = ResolveURL(external_url);
|
||||
}
|
||||
|
||||
void WebBrowser::InitializeWifi() {}
|
||||
+1
-1
@@ -11,8 +11,8 @@
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/applets/applet_web_browser_types.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
#include "core/hle/service/am/applets/web_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
File renamed without changes.
@@ -5,7 +5,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/apm/apm.h"
|
||||
#include "core/hle/service/apm/apm_interface.h"
|
||||
#include "core/hle/service/apm/interface.h"
|
||||
|
||||
namespace Service::APM {
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/service/apm/apm_controller.h"
|
||||
#include "core/hle/service/apm/controller.h"
|
||||
|
||||
namespace Service::APM {
|
||||
|
||||
File renamed without changes.
@@ -5,8 +5,8 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/apm/apm.h"
|
||||
#include "core/hle/service/apm/apm_controller.h"
|
||||
#include "core/hle/service/apm/apm_interface.h"
|
||||
#include "core/hle/service/apm/controller.h"
|
||||
#include "core/hle/service/apm/interface.h"
|
||||
|
||||
namespace Service::APM {
|
||||
|
||||
File renamed without changes.
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/bcat/bcat_module.h"
|
||||
#include "core/hle/service/bcat/module.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/service/bcat/backend/backend.h"
|
||||
#include "core/hle/service/bcat/bcat.h"
|
||||
#include "core/hle/service/bcat/bcat_module.h"
|
||||
#include "core/hle/service/bcat/module.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
|
||||
namespace Service::BCAT {
|
||||
File renamed without changes.
@@ -97,24 +97,14 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
|
||||
|
||||
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
|
||||
std::string path(Common::FS::SanitizePath(path_));
|
||||
|
||||
// NOTE: This is inaccurate behavior. CreateDirectory is not recursive.
|
||||
// CreateDirectory should return PathNotFound if the parent directory does not exist.
|
||||
// This is here temporarily in order to have UMM "work" in the meantime.
|
||||
// TODO (Morph): Remove this when a hardware test verifies the correct behavior.
|
||||
const auto components = Common::FS::SplitPathComponents(path);
|
||||
std::string relative_path;
|
||||
for (const auto& component : components) {
|
||||
// Skip empty path components
|
||||
if (component.empty()) {
|
||||
continue;
|
||||
}
|
||||
relative_path = Common::FS::SanitizePath(relative_path + '/' + component);
|
||||
auto new_dir = backing->CreateSubdirectory(relative_path);
|
||||
if (new_dir == nullptr) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||
if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) {
|
||||
dir = backing;
|
||||
}
|
||||
auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path));
|
||||
if (new_dir == nullptr) {
|
||||
// TODO(DarkLordZach): Find a better error code for this
|
||||
return ResultUnknown;
|
||||
}
|
||||
return ResultSuccess;
|
||||
}
|
||||
@@ -261,18 +251,6 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
|
||||
const std::string& path) const {
|
||||
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
|
||||
if (dir == nullptr) {
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
if (GetEntryType(path).Failed()) {
|
||||
return FileSys::ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
return MakeResult(dir->GetFileTimeStamp(Common::FS::GetFilename(path)));
|
||||
}
|
||||
|
||||
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
|
||||
|
||||
FileSystemController::~FileSystemController() = default;
|
||||
|
||||
@@ -240,12 +240,6 @@ public:
|
||||
*/
|
||||
ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
|
||||
|
||||
/**
|
||||
* Get the timestamp of the specified path
|
||||
* @return The timestamp of the specified path or error code
|
||||
*/
|
||||
ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const;
|
||||
|
||||
private:
|
||||
FileSys::VirtualDir backing;
|
||||
};
|
||||
|
||||
Loaded 100 of 699 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user