Compare commits

..

47 Commits

Author SHA1 Message Date
Morph
2f5808b7ff service: am: Make use of Exit to exit the currently running application
This also moves the call to the end to ensure services are properly destructed on exit.
2021-10-01 23:39:55 -04:00
Morph
282bdfd1bf yuzu: main: Register a callback for Exit 2021-10-01 23:39:54 -04:00
Morph
d8467ca6c0 core: Add Exit and ExitCallback
This allows ISelfController::Exit to stop the currently running application. This is typically used by homebrew to exit back to the homebrew menu after calling consoleExit with libnx.
2021-10-01 23:39:54 -04:00
bunnei
3a33519598 Merge pull request #7102 from Morph1984/remove-boxcat
Remove Boxcat BCAT backend
2021-10-01 18:41:41 -07:00
bunnei
36d45b4a7f Merge pull request #7114 from ameerj/msvc-ubuntu-version
ci: Use latest ubuntu image for mainline/patreon step 1
2021-10-01 16:23:15 -07:00
ameerj
6f1c6e6ba9 ci: Use latest ubuntu image for mainline/patreon step 1 2021-10-01 19:20:28 -04:00
bunnei
c3784b2a08 Merge pull request #7075 from v1993/power-of-tea
applets: Use subdirectory of main data directory for QtWebEngine storage
2021-09-30 16:29:28 -07:00
bunnei
8bd5742349 Merge pull request #7061 from ameerj/dma-buffer-misc
buffer_cache, maxwell_dma: Minor refactoring and code fixes
2021-09-30 12:34:28 -07:00
Mai M
b9251155f8 Merge pull request #7104 from Morph1984/style
style: Remove extra space preceding the :: operator
2021-09-29 19:32:39 -04:00
bunnei
91341b421d Merge pull request #7036 from ameerj/ogl-bgr-v2
gl_texture_cache: Unify BGR copy passes using PBOs
2021-09-29 16:10:56 -07:00
bunnei
9ad6c26821 Merge pull request #7106 from astrelsky/invalid_iterator_fix
Fixed invalid iterator usage
2021-09-29 09:35:01 -07:00
Andrew Strelsky
3fc7aceea7 Fixed invalid iterator usage 2021-09-29 06:58:48 -04:00
Morph
e29f3b87f1 style: Remove extra space preceding the :: operator 2021-09-29 01:26:01 -04:00
Morph
839547dc90 CMakeLists: Remove BoxCat build option 2021-09-29 01:24:21 -04:00
Morph
8af9f3216e settings: Remove BCAT settings 2021-09-29 01:24:21 -04:00
Morph
673d37a7c2 configure_network: Remove BCAT 2021-09-29 01:24:21 -04:00
Morph
4acec5283e service: bcat: Remove BoxCat BCAT implementation
The current implementation of BoxCat as it stands is non-functional due to the reliance on a server providing BCAT files.
This implementation will eventually be replaced with one that allows the use of local BCAT files dumped from a Nintendo Switch.
2021-09-29 01:21:35 -04:00
Morph
5f6cd32c9e externals: Remove libzip 2021-09-28 23:18:39 -04:00
Morph
616d0236f5 file_sys: Remove vfs_libzip 2021-09-28 23:18:39 -04:00
Morph
781c1d8df8 Merge pull request #7018 from lat9nq/splat-stubs
audin_u: stub Start, RegisterBufferEvent, AppendAudioInBufferAuto
2021-09-28 22:06:11 -04:00
Ameer J
fba301155b Merge pull request #7042 from v1993/patch-7
Hide XInput bypass on non-Windows OSes
2021-09-28 17:07:12 -04:00
bunnei
24c0dde958 Merge pull request #7076 from ameerj/amd-botw
vk_texture_cache: Disable cube compatibility flag on non-mesa AMD GCN4 and earlier
2021-09-28 10:46:56 -07:00
bunnei
90014ada8f Merge pull request #7096 from german77/update_13.0.0
Update function tables to FW 13.0.0
2021-09-27 11:44:17 -07:00
german77
bc4b4e3f56 service/es: Update to 13.0.0 2021-09-26 20:17:07 -05:00
german77
d780eab357 service/npns: Update to 13.0.0 2021-09-26 20:13:09 -05:00
german77
b0e83f949e service/vi: Update to 13.0.0 2021-09-26 20:12:02 -05:00
german77
321c64a122 service/am: Update to 13.0.0 2021-09-26 20:00:12 -05:00
german77
d103e2daf9 service/audio: Update to 13.0.0 2021-09-26 19:49:09 -05:00
german77
e401c77351 service/hid: Update to 13.0.0 2021-09-26 19:45:47 -05:00
german77
4b5f0af3fd service/btdrv: Update to 13.0.0 2021-09-26 19:32:45 -05:00
german77
f5b41068e6 service/usb: Update to 13.0.0 2021-09-26 19:26:52 -05:00
Morph
5114819b6b Merge pull request #7078 from ameerj/vc-jthread-fixes
video_core: Fix jthread related hangs when stopping emulation
2021-09-26 16:40:13 -04:00
bunnei
4f9d58621c Merge pull request #7085 from Morph1984/bsd-read-stub
service: bsd: Stub Read
2021-09-25 05:12:23 -07:00
Morph
7dd7c54add service: bsd: Stub Read
- Used by Diablo II: Resurrected
2021-09-25 08:04:33 -04:00
bunnei
db9b80399b Merge pull request #7082 from Morph1984/bsd-read
service: bsd: Implement Read
2021-09-24 22:34:32 -07:00
ameerj
ab63a193d7 video_core: Fix jthread related hangs when stopping emulation
jthread on some compilers is more picky when it comes to the order in which objects are destroyed.
2021-09-23 20:34:02 -04:00
ameerj
1e1ecca691 vk_texture_cache: Disable cube compatibility flag on non-mesa AMD GCN4 and earlier
Fixes rainbow textures on BOTW.
2021-09-23 19:40:53 -04:00
v1993
3e07655b1b Use subdirectory of main data directory for QtWebEngine storage
Previously, an unrelated directory was used for this. Keep everything together for consistency.
2021-09-24 00:49:39 +03:00
ameerj
24049591f6 maxwell_dma: Minor refactoring 2021-09-19 20:36:41 -04:00
ameerj
1ea8073783 buffer_cache: Minor fixes
Loop through the tmp_intervals by reference, rather than by copy, and fix gl clear buffer size calculation.
2021-09-19 20:35:07 -04:00
Valeri
738cd1896b If not on Windows, disable raw input
This way, if someone copies their Windows config to other OS, they won't be stuck without web applet for no apparent reason.
2021-09-18 15:10:00 +03:00
Valeri
b54bf126f7 Hide XInput bypass on non-Windows OSes
Follow-up to #6950. This option is a no-op on other OSes and only serves to spread confusion there.
2021-09-18 14:41:51 +03:00
ameerj
22162f906b host_shaders: Remove opengl_copy_bgra.comp 2021-09-16 19:49:13 -04:00
ameerj
ab808fe7cf gl_texture_cache: Migrate BGRCopyPass from util_shaders
The BGR copies no longer use shaders.
2021-09-16 19:49:12 -04:00
ameerj
7f737b022a util_shaders: Unify BGRA copy passes 2021-09-15 21:10:52 -04:00
lat9nq
7bc07195c5 audin_u: Return a buffer event in RegisterBufferEvent
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
2021-09-15 16:38:12 -04:00
lat9nq
17b0955f9a audin_u: stub Start, RegisterBufferEvent, AppendAudioInBufferAuto
This also moves IAudioIn's definition to the header.

Required for Splatoon 2 LAN play.
2021-09-15 15:52:09 -04:00
68 changed files with 304 additions and 1840 deletions

View File

@@ -1,6 +1,9 @@
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: merge
displayName: 'merge'

View File

@@ -1,6 +1,9 @@
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: merge
displayName: 'merge'

3
.gitmodules vendored
View File

@@ -28,9 +28,6 @@
[submodule "mbedtls"]
path = externals/mbedtls
url = https://github.com/yuzu-emu/mbedtls
[submodule "libzip"]
path = externals/libzip/libzip
url = https://github.com/nih-at/libzip.git
[submodule "xbyak"]
path = externals/xbyak
url = https://github.com/herumi/xbyak.git

View File

@@ -29,16 +29,10 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
option(YUZU_ENABLE_BOXCAT "Enable the Boxcat service, a yuzu high-level implementation of BCAT" ON)
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
if (NOT ENABLE_WEB_SERVICE)
set(YUZU_ENABLE_BOXCAT OFF)
endif()
# Default to a Release build
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
@@ -422,11 +416,6 @@ if (CONAN_REQUIRED_LIBS)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
set(CONAN_LIB_OPTIONS
libzip:with_openssl=False
libzip:enable_windows_crypto=False
)
conan_check(VERSION 1.24.0 REQUIRED)
# Manually add iconv to fix a dep conflict between qt and sdl2

View File

@@ -93,13 +93,6 @@ endif()
# Sirit
add_subdirectory(sirit)
# libzip
find_package(libzip 1.5)
if (NOT libzip_FOUND)
message(STATUS "libzip 1.5 or newer not found, falling back to externals")
add_subdirectory(libzip EXCLUDE_FROM_ALL)
endif()
if (ENABLE_WEB_SERVICE)
find_package(OpenSSL 1.1)
if (OPENSSL_FOUND)

View File

@@ -1,72 +0,0 @@
find_package(PkgConfig QUIET)
pkg_check_modules(PC_libzip QUIET libzip)
find_path(libzip_INCLUDE_DIR
NAMES zip.h
PATHS ${PC_libzip_INCLUDE_DIRS}
"$ENV{LIB_DIR}/include"
"$ENV{INCLUDE}"
/usr/local/include
/usr/include
)
find_path(libzip_INCLUDE_DIR_ZIPCONF
NAMES zipconf.h
HINTS ${PC_libzip_INCLUDE_DIRS}
"$ENV{LIB_DIR}/include"
"$ENV{LIB_DIR}/lib/libzip/include"
"$ENV{LIB}/lib/libzip/include"
/usr/local/lib/libzip/include
/usr/lib/libzip/include
/usr/local/include
/usr/include
"$ENV{INCLUDE}"
)
find_library(libzip_LIBRARY
NAMES zip
PATHS ${PC_libzip_LIBRARY_DIRS}
"$ENV{LIB_DIR}/lib" "$ENV{LIB}" /usr/local/lib /usr/lib
)
if (libzip_INCLUDE_DIR_ZIPCONF)
FILE(READ "${libzip_INCLUDE_DIR_ZIPCONF}/zipconf.h" _libzip_VERSION_CONTENTS)
if (_libzip_VERSION_CONTENTS)
STRING(REGEX REPLACE ".*#define LIBZIP_VERSION \"([0-9.]+)\".*" "\\1" libzip_VERSION "${_libzip_VERSION_CONTENTS}")
endif()
unset(_libzip_VERSION_CONTENTS)
endif()
set(libzip_VERSION ${libzip_VERSION} CACHE STRING "Version number of libzip")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(libzip
FOUND_VAR libzip_FOUND
REQUIRED_VARS
libzip_LIBRARY
libzip_INCLUDE_DIR
libzip_INCLUDE_DIR_ZIPCONF
libzip_VERSION
VERSION_VAR libzip_VERSION
)
if(libzip_FOUND)
set(libzip_LIBRARIES ${libzip_LIBRARY})
set(libzip_INCLUDE_DIRS ${libzip_INCLUDE_DIR})
set(libzip_DEFINITIONS ${PC_libzip_CFLAGS_OTHER})
endif()
if(libzip_FOUND AND NOT TARGET libzip::libzip)
add_library(libzip::libzip UNKNOWN IMPORTED)
set_target_properties(libzip::libzip PROPERTIES
IMPORTED_LOCATION "${libzip_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${PC_libzip_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${libzip_INCLUDE_DIR}"
)
endif()
mark_as_advanced(
libzip_INCLUDE_DIR
libzip_INCLUDE_DIR_ZIPCONF
libzip_LIBRARY
libzip_VERSION
)

View File

@@ -1,564 +0,0 @@
# TODO:
# create usable libtool .la file
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libzip")
PROJECT(libzip C)
OPTION(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" ON)
OPTION(ENABLE_GNUTLS "Enable use of GnuTLS" ON)
OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
OPTION(ENABLE_WINDOWS_CRYPTO "Enable use of Windows cryptography libraries" ON)
OPTION(ENABLE_BZIP2 "Enable use of BZip2" OFF)
OPTION(ENABLE_LZMA "Enable use of LZMA" OFF)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckTypeSize)
INCLUDE(CheckCSourceRuns)
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckStructHasMember)
INCLUDE(TestBigEndian)
INCLUDE(GNUInstallDirs)
IF(ENABLE_COMMONCRYPTO)
CHECK_INCLUDE_FILES(CommonCrypto/CommonCrypto.h COMMONCRYPTO_FOUND)
ELSE()
SET(COMMONCRYPTO_FOUND FALSE)
ENDIF()
IF(ENABLE_GNUTLS)
INCLUDE(FindNettle)
INCLUDE(FindGnuTLS)
ELSE()
SET(GNUTLS_FOUND FALSE)
ENDIF()
IF(ENABLE_MBEDTLS)
FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/aes.h)
FIND_LIBRARY(MBEDTLS_LIBRARIES NAMES mbedcrypto)
ELSE()
SET(MBEDTLS_LIBRARIES FALSE)
ENDIF()
IF(ENABLE_OPENSSL)
INCLUDE(FindOpenSSL)
ELSE()
SET(OPENSSL_FOUND FALSE)
ENDIF()
IF(WIN32)
IF(ENABLE_WINDOWS_CRYPTO)
SET(WINDOWS_CRYPTO_FOUND TRUE)
ENDIF()
ELSE()
SET(WINDOWS_CRYPTO_FOUND FALSE)
ENDIF()
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
OPTION(SHARED_LIB_VERSIONNING "Add SO version in .so build" ON)
SET(PACKAGE "libzip")
SET(PACKAGE_NAME ${PACKAGE})
SET(PACKAGE_VERSION_MAJOR "1")
SET(PACKAGE_VERSION_MINOR "5")
SET(PACKAGE_VERSION_MICRO "2a")
#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_MICRO}")
SET(PACKAGE_VERSION ${VERSION})
SET(LIBZIP_VERSION ${PACKAGE_VERSION})
SET(LIBZIP_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR})
SET(LIBZIP_VERSION_MINOR ${PACKAGE_VERSION_MINOR})
SET(LIBZIP_VERSION_MICRO ${PACKAGE_VERSION_MICRO})
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
SET(ARCHIVE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
IF(NOT TARGET dist)
ADD_CUSTOM_TARGET(dist
COMMAND git config tar.tar.xz.command "xz -c"
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.gz HEAD
COMMAND git archive --prefix=${ARCHIVE_NAME}/ -o ${ARCHIVE_NAME}.tar.xz HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
ADD_CUSTOM_TARGET(distcheck
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest 2>/dev/null || true
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND cmake -E tar xf ${ARCHIVE_NAME}.tar.gz
COMMAND chmod -R u-w ${ARCHIVE_NAME}
COMMAND mkdir ${ARCHIVE_NAME}-build
COMMAND mkdir ${ARCHIVE_NAME}-dest
COMMAND cd ${ARCHIVE_NAME}-build && cmake -DCMAKE_INSTALL_PREFIX=../${ARCHIVE_NAME}-dest ../${ARCHIVE_NAME}
COMMAND cd ${ARCHIVE_NAME}-build && make -j4
COMMAND cd ${ARCHIVE_NAME}-build && make test
COMMAND cd ${ARCHIVE_NAME}-build && make install
# COMMAND cd ${ARCHIVE_NAME}-build && make uninstall
# COMMAND if [ `find ${ARCHIVE_NAME}-dest ! -type d | wc -l` -ne 0 ]; then echo leftover files in ${ARCHIVE_NAME}-dest; false; fi
COMMAND cd ${ARCHIVE_NAME}-build && make clean
COMMAND chmod -R u+w ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND rm -rf ${ARCHIVE_NAME} ${ARCHIVE_NAME}-build ${ARCHIVE_NAME}-dest
COMMAND echo "${ARCHIVE_NAME}.tar.gz is ready for distribution."
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
ADD_DEPENDENCIES(distcheck dist)
ENDIF(NOT TARGET dist)
IF(BUILD_SHARED_LIBS)
SET(HAVE_SHARED TRUE)
ELSE()
SET(ZIP_STATIC TRUE)
ENDIF()
# Checks
CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD)
CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE)
CHECK_FUNCTION_EXISTS(_dup HAVE__DUP)
CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN)
CHECK_FUNCTION_EXISTS(_fileno HAVE__FILENO)
CHECK_FUNCTION_EXISTS(_open HAVE__OPEN)
CHECK_FUNCTION_EXISTS(_setmode HAVE__SETMODE)
CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
CHECK_FUNCTION_EXISTS(_strdup HAVE__STRDUP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64)
CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64)
CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK)
CHECK_FUNCTION_EXISTS(arc4random HAVE_ARC4RANDOM)
CHECK_FUNCTION_EXISTS(clonefile HAVE_CLONEFILE)
CHECK_FUNCTION_EXISTS(explicit_bzero HAVE_EXPLICIT_BZERO)
CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET)
CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO)
CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
CHECK_FUNCTION_EXISTS(ftello HAVE_FTELLO)
CHECK_FUNCTION_EXISTS(getprogname HAVE_GETPROGNAME)
CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS(open HAVE_OPEN)
CHECK_FUNCTION_EXISTS(setmode HAVE_SETMODE)
CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP)
CHECK_FUNCTION_EXISTS(stricmp HAVE_STRICMP)
CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL)
CHECK_FUNCTION_EXISTS(strtoull HAVE_STRTOULL)
CHECK_INCLUDE_FILES("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H)
CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H_LIBZIP)
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H_LIBZIP)
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H_LIBZIP)
# TODO: fix test
# this test does not find __progname even when it exists
#CHECK_SYMBOL_EXISTS(__progname stdlib.h HAVE___PROGNAME)
CHECK_TYPE_SIZE(__int8 __INT8_LIBZIP)
CHECK_TYPE_SIZE(int8_t INT8_T_LIBZIP)
CHECK_TYPE_SIZE(uint8_t UINT8_T_LIBZIP)
CHECK_TYPE_SIZE(__int16 __INT16_LIBZIP)
CHECK_TYPE_SIZE(int16_t INT16_T_LIBZIP)
CHECK_TYPE_SIZE(uint16_t UINT16_T_LIBZIP)
CHECK_TYPE_SIZE(__int32 __INT32_LIBZIP)
CHECK_TYPE_SIZE(int32_t INT32_T_LIBZIP)
CHECK_TYPE_SIZE(uint32_t UINT32_T_LIBZIP)
CHECK_TYPE_SIZE(__int64 __INT64_LIBZIP)
CHECK_TYPE_SIZE(int64_t INT64_T_LIBZIP)
CHECK_TYPE_SIZE(uint64_t UINT64_T_LIBZIP)
CHECK_TYPE_SIZE("short" SHORT_LIBZIP)
CHECK_TYPE_SIZE("int" INT_LIBZIP)
CHECK_TYPE_SIZE("long" LONG_LIBZIP)
CHECK_TYPE_SIZE("long long" LONG_LONG_LIBZIP)
CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T)
CHECK_TYPE_SIZE("size_t" SIZE_T_LIBZIP)
CHECK_TYPE_SIZE("ssize_t" SSIZE_T_LIBZIP)
CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
#include <linux/fs.h>
int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE)
CHECK_C_SOURCE_COMPILES("
int foo(char * _Nullable bar);
int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
#FIND_PACKAGE(ZLIB 1.1.2 REQUIRED)
INCLUDE_DIRECTORIES(../zlib/zlib)
SET(CMAKE_REQUIRED_INCLUDES ../zlib/zlib)
IF(ENABLE_BZIP2)
FIND_PACKAGE(BZip2)
IF(BZIP2_FOUND)
SET (HAVE_LIBBZ2 1)
INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${BZIP2_LIBRARIES})
ELSE()
MESSAGE(WARNING "-- bzip2 library not found; bzip2 support disabled")
ENDIF(BZIP2_FOUND)
ENDIF(ENABLE_BZIP2)
IF(ENABLE_LZMA)
FIND_PACKAGE(LibLZMA)
IF(LIBLZMA_FOUND)
SET (HAVE_LIBLZMA 1)
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${LIBLZMA_LIBRARY})
ELSE()
MESSAGE(WARNING "-- lzma library not found; lzma support disabled")
ENDIF(LIBLZMA_FOUND)
ENDIF(ENABLE_LZMA)
IF (COMMONCRYPTO_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_COMMONCRYPTO 1)
ELSEIF (WINDOWS_CRYPTO_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_WINDOWS_CRYPTO 1)
ELSEIF (GNUTLS_FOUND AND NETTLE_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_GNUTLS 1)
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR} ${NETTLE_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${GNUTLS_LIBRARY} ${NETTLE_LIBRARY})
ELSEIF (OPENSSL_FOUND)
SET (HAVE_CRYPTO 1)
SET (HAVE_OPENSSL 1)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${OPENSSL_LIBRARIES})
ELSEIF (MBEDTLS_LIBRARIES)
SET (HAVE_CRYPTO 1)
SET (HAVE_MBEDTLS 1)
INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} ${MBEDTLS_LIBRARIES})
ENDIF()
IF (NOT HAVE_CRYPTO)
MESSAGE(WARNING "-- neither Common Crypto, GnuTLS, mbed TLS, OpenSSL, nor Windows Cryptography found; AES support disabled")
ENDIF()
IF(MSVC)
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS")
ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE")
ENDIF(MSVC)
if(WIN32)
if(HAVE_WINDOWS_CRYPTO)
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} bcrypt)
endif()
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
ADD_DEFINITIONS(-DMS_UWP)
else(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
SET (OPTIONAL_LIBRARY ${OPTIONAL_LIBRARY} advapi32)
endif(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
endif(WIN32)
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
# rpath handling: use rpath in installed binaries
IF(NOT CMAKE_SYSTEM_NAME MATCHES Linux)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
ENDIF()
# fixed size integral types
IF(HAVE_INTTYPES_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>")
ELSEIF(HAVE_STDINT_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#include <stdint.h>")
ELSEIF(HAVE_SYS_TYPES_H_LIBZIP)
SET(LIBZIP_TYPES_INCLUDE "#include <sys/types.h>")
ENDIF()
IF(HAVE_INT8_T_LIBZIP)
SET(ZIP_INT8_T int8_t)
ELSEIF(HAVE___INT8_LIBZIP)
SET(ZIP_INT8_T __int8)
ELSE()
SET(ZIP_INT8_T "signed char")
ENDIF()
IF(HAVE_UINT8_T_LIBZIP)
SET(ZIP_UINT8_T uint8_t)
ELSEIF(HAVE___INT8_LIBZIP)
SET(ZIP_UINT8_T "unsigned __int8")
ELSE()
SET(ZIP_UINT8_T "unsigned char")
ENDIF()
IF(HAVE_INT16_T_LIBZIP)
SET(ZIP_INT16_T int16_t)
ELSEIF(HAVE___INT16_LIBZIP)
SET(INT16_T_LIBZIP __int16)
ELSEIF(SHORT_LIBZIP EQUAL 2)
SET(INT16_T_LIBZIP short)
ENDIF()
IF(HAVE_UINT16_T_LIBZIP)
SET(ZIP_UINT16_T uint16_t)
ELSEIF(HAVE___INT16_LIBZIP)
SET(UINT16_T_LIBZIP "unsigned __int16")
ELSEIF(SHORT_LIBZIP EQUAL 2)
SET(UINT16_T_LIBZIP "unsigned short")
ENDIF()
IF(HAVE_INT32_T_LIBZIP)
SET(ZIP_INT32_T int32_t)
ELSEIF(HAVE___INT32_LIBZIP)
SET(ZIP_INT32_T __int32)
ELSEIF(INT_LIBZIP EQUAL 4)
SET(ZIP_INT32_T int)
ELSEIF(LONG_LIBZIP EQUAL 4)
SET(ZIP_INT32_T long)
ENDIF()
IF(HAVE_UINT32_T_LIBZIP)
SET(ZIP_UINT32_T uint32_t)
ELSEIF(HAVE___INT32_LIBZIP)
SET(ZIP_UINT32_T "unsigned __int32")
ELSEIF(INT_LIBZIP EQUAL 4)
SET(ZIP_UINT32_T "unsigned int")
ELSEIF(LONG_LIBZIP EQUAL 4)
SET(ZIP_UINT32_T "unsigned long")
ENDIF()
IF(HAVE_INT64_T_LIBZIP)
SET(ZIP_INT64_T int64_t)
ELSEIF(HAVE___INT64_LIBZIP)
SET(ZIP_INT64_T __int64)
ELSEIF(LONG_LIBZIP EQUAL 8)
SET(ZIP_INT64_T long)
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
SET(ZIP_INT64_T "long long")
ENDIF()
IF(HAVE_UINT64_T_LIBZIP)
SET(ZIP_UINT64_T uint64_t)
ELSEIF(HAVE___INT64_LIBZIP)
SET(ZIP_UINT64_T "unsigned __int64")
ELSEIF(LONG_LIBZIP EQUAL 8)
SET(ZIP_UINT64_T "unsigned long")
ELSEIF(LONG_LONG_LIBZIP EQUAL 8)
SET(ZIP_UINT64_T "unsigned long long")
ENDIF()
IF(HAVE_NULLABLE)
SET(ZIP_NULLABLE_DEFINES)
ELSE()
SET(ZIP_NULLABLE_DEFINES "#define _Nullable
#define _Nonnull")
ENDIF()
# write out config file
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/config.h)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libzip/cmake-zipconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h)
# installation
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip/zipconf.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
INSTALL(FILES libzip/lib/zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
SET(CMAKE_C_VISIBILITY_PRESET hidden)
ADD_LIBRARY(zip
libzip/lib/zip_add.c
libzip/lib/zip_add_dir.c
libzip/lib/zip_add_entry.c
libzip/lib/zip_algorithm_deflate.c
libzip/lib/zip_buffer.c
libzip/lib/zip_close.c
libzip/lib/zip_delete.c
libzip/lib/zip_dir_add.c
libzip/lib/zip_dirent.c
libzip/lib/zip_discard.c
libzip/lib/zip_entry.c
libzip/lib/zip_err_str.c
libzip/lib/zip_error.c
libzip/lib/zip_error_clear.c
libzip/lib/zip_error_get.c
libzip/lib/zip_error_get_sys_type.c
libzip/lib/zip_error_strerror.c
libzip/lib/zip_error_to_str.c
libzip/lib/zip_extra_field.c
libzip/lib/zip_extra_field_api.c
libzip/lib/zip_fclose.c
libzip/lib/zip_fdopen.c
libzip/lib/zip_file_add.c
libzip/lib/zip_file_error_clear.c
libzip/lib/zip_file_error_get.c
libzip/lib/zip_file_get_comment.c
libzip/lib/zip_file_get_external_attributes.c
libzip/lib/zip_file_get_offset.c
libzip/lib/zip_file_rename.c
libzip/lib/zip_file_replace.c
libzip/lib/zip_file_set_comment.c
libzip/lib/zip_file_set_encryption.c
libzip/lib/zip_file_set_external_attributes.c
libzip/lib/zip_file_set_mtime.c
libzip/lib/zip_file_strerror.c
libzip/lib/zip_filerange_crc.c
libzip/lib/zip_fopen.c
libzip/lib/zip_fopen_encrypted.c
libzip/lib/zip_fopen_index.c
libzip/lib/zip_fopen_index_encrypted.c
libzip/lib/zip_fread.c
libzip/lib/zip_fseek.c
libzip/lib/zip_ftell.c
libzip/lib/zip_get_archive_comment.c
libzip/lib/zip_get_archive_flag.c
libzip/lib/zip_get_encryption_implementation.c
libzip/lib/zip_get_file_comment.c
libzip/lib/zip_get_name.c
libzip/lib/zip_get_num_entries.c
libzip/lib/zip_get_num_files.c
libzip/lib/zip_hash.c
libzip/lib/zip_io_util.c
libzip/lib/zip_libzip_version.c
libzip/lib/zip_memdup.c
libzip/lib/zip_name_locate.c
libzip/lib/zip_new.c
libzip/lib/zip_open.c
libzip/lib/zip_progress.c
libzip/lib/zip_rename.c
libzip/lib/zip_replace.c
libzip/lib/zip_set_archive_comment.c
libzip/lib/zip_set_archive_flag.c
libzip/lib/zip_set_default_password.c
libzip/lib/zip_set_file_comment.c
libzip/lib/zip_set_file_compression.c
libzip/lib/zip_set_name.c
libzip/lib/zip_source_accept_empty.c
libzip/lib/zip_source_begin_write.c
libzip/lib/zip_source_begin_write_cloning.c
libzip/lib/zip_source_buffer.c
libzip/lib/zip_source_call.c
libzip/lib/zip_source_close.c
libzip/lib/zip_source_commit_write.c
libzip/lib/zip_source_compress.c
libzip/lib/zip_source_crc.c
libzip/lib/zip_source_error.c
libzip/lib/zip_source_filep.c
libzip/lib/zip_source_free.c
libzip/lib/zip_source_function.c
libzip/lib/zip_source_get_compression_flags.c
libzip/lib/zip_source_is_deleted.c
libzip/lib/zip_source_layered.c
libzip/lib/zip_source_open.c
libzip/lib/zip_source_pkware.c
libzip/lib/zip_source_read.c
libzip/lib/zip_source_remove.c
libzip/lib/zip_source_rollback_write.c
libzip/lib/zip_source_seek.c
libzip/lib/zip_source_seek_write.c
libzip/lib/zip_source_stat.c
libzip/lib/zip_source_supports.c
libzip/lib/zip_source_tell.c
libzip/lib/zip_source_tell_write.c
libzip/lib/zip_source_window.c
libzip/lib/zip_source_write.c
libzip/lib/zip_source_zip.c
libzip/lib/zip_source_zip_new.c
libzip/lib/zip_stat.c
libzip/lib/zip_stat_index.c
libzip/lib/zip_stat_init.c
libzip/lib/zip_strerror.c
libzip/lib/zip_string.c
libzip/lib/zip_unchange.c
libzip/lib/zip_unchange_all.c
libzip/lib/zip_unchange_archive.c
libzip/lib/zip_unchange_data.c
libzip/lib/zip_utf-8.c
)
IF(WIN32)
target_sources(zip PRIVATE
libzip/lib/zip_source_win32handle.c
libzip/lib/zip_source_win32utf8.c
libzip/lib/zip_source_win32w.c
)
IF(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
ELSE()
target_sources(zip PRIVATE libzip/lib/zip_source_win32a.c)
ENDIF()
ELSE()
target_sources(zip PRIVATE
libzip/lib/zip_mkstempm.c
libzip/lib/zip_source_file.c
libzip/lib/zip_random_unix.c
)
ENDIF()
IF(HAVE_LIBBZ2)
target_sources(zip PRIVATE libzip/lib/zip_algorithm_bzip2.c)
ENDIF()
IF(HAVE_LIBLZMA)
target_sources(zip PRIVATE libzip/lib/zip_algorithm_xz.c)
ENDIF()
IF(HAVE_COMMONCRYPTO)
target_sources(zip PRIVATE libzip/lib/zip_crypto_commoncrypto.c)
ELSEIF(HAVE_WINDOWS_CRYPTO)
target_sources(zip PRIVATE libzip/lib/zip_crypto_win.c)
ELSEIF(HAVE_GNUTLS)
target_sources(zip PRIVATE libzip/lib/zip_crypto_gnutls.c)
ELSEIF(HAVE_OPENSSL)
target_sources(zip PRIVATE libzip/lib/zip_crypto_openssl.c)
ELSEIF(HAVE_MBEDTLS)
target_sources(zip PRIVATE libzip/lib/zip_crypto_mbedtls.c)
ENDIF()
IF(HAVE_CRYPTO)
target_sources(zip PRIVATE
libzip/lib/zip_winzip_aes.c
libzip/lib/zip_source_winzip_aes_decode.c
libzip/lib/zip_source_winzip_aes_encode.c
)
ENDIF()
target_include_directories(zip
PUBLIC
libzip/lib
${CMAKE_CURRENT_BINARY_DIR}/libzip
)
# pkgconfig file
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(exec_prefix \${prefix})
SET(bindir \${exec_prefix}/${CMAKE_INSTALL_BINDIR})
SET(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
SET(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
IF(CMAKE_SYSTEM_NAME MATCHES BSD)
SET(PKG_CONFIG_RPATH "-Wl,-R\${libdir}")
ENDIF(CMAKE_SYSTEM_NAME MATCHES BSD)
get_target_property(LIBS_PRIVATE zip LINK_LIBRARIES)
foreach(LIB ${LIBS_PRIVATE})
if(LIB MATCHES "^/")
get_filename_component(LIB ${LIB} NAME_WE)
string(REGEX REPLACE "^lib" "" LIB ${LIB})
endif()
set(LIBS "${LIBS} -l${LIB}")
endforeach()
CONFIGURE_FILE(libzip/libzip.pc.in libzip/libzip.pc @ONLY)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzip.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
ADD_CUSTOM_TARGET(update_zip_err_str
COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip_err_str.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/zip.h ${CMAKE_CURRENT_SOURCE_DIR}/libzip/lib/make_zip_err_str.sh
)
IF(SHARED_LIB_VERSIONNING)
SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 5.0 SOVERSION 5)
ENDIF()
TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARIES} ${OPTIONAL_LIBRARY})
INSTALL(TARGETS zip
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

Submodule externals/libzip/libzip deleted from 89bd6d63bd

View File

@@ -314,8 +314,8 @@ private:
}
void UntrackPlaceholder(boost::icl::separate_interval_set<size_t>::iterator it) {
placeholders.erase(it);
placeholder_host_pointers.erase(it->lower());
placeholders.erase(it);
}
/// Return true when a given memory region is a "nieche" and the placeholders don't have to be

View File

@@ -69,8 +69,6 @@ void LogSettings() {
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
log_setting("Debugging_ProgramArgs", values.program_args.GetValue());
log_setting("Services_BCATBackend", values.bcat_backend.GetValue());
log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local.GetValue());
log_setting("Input_EnableMotion", values.motion_enabled.GetValue());
log_setting("Input_EnableVibration", values.vibration_enabled.GetValue());
log_setting("Input_EnableRawInput", values.enable_raw_input.GetValue());

View File

@@ -568,8 +568,6 @@ struct Values {
BasicSetting<bool> use_dev_keys{false, "use_dev_keys"};
// Network
BasicSetting<std::string> bcat_backend{"none", "bcat_backend"};
BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"};
BasicSetting<std::string> network_interface{std::string(), "network_interface"};
// WebService

View File

@@ -106,8 +106,6 @@ add_library(core STATIC
file_sys/vfs_concat.h
file_sys/vfs_layered.cpp
file_sys/vfs_layered.h
file_sys/vfs_libzip.cpp
file_sys/vfs_libzip.h
file_sys/vfs_offset.cpp
file_sys/vfs_offset.h
file_sys/vfs_real.cpp
@@ -653,13 +651,6 @@ add_library(core STATIC
tools/freezer.h
)
if (YUZU_ENABLE_BOXCAT)
target_sources(core PRIVATE
hle/service/bcat/backend/boxcat.cpp
hle/service/bcat/backend/boxcat.h
)
endif()
if (MSVC)
target_compile_options(core PRIVATE
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
@@ -690,12 +681,7 @@ endif()
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus zip)
if (YUZU_ENABLE_BOXCAT)
target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT)
target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json)
endif()
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)

View File

@@ -305,7 +305,6 @@ struct System::Impl {
is_powered_on = false;
exit_lock = false;
gpu_core.reset();
services.reset();
service_manager.reset();
cheat_engine.reset();
@@ -315,6 +314,7 @@ struct System::Impl {
core_timing.Shutdown();
app_loader.reset();
perf_stats.reset();
gpu_core.reset();
kernel.Shutdown();
memory.Reset();
applet_manager.ClearAll();
@@ -421,6 +421,7 @@ struct System::Impl {
bool is_async_gpu{};
ExecuteProgramCallback execute_program_callback;
ExitCallback exit_callback;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
@@ -798,6 +799,18 @@ void System::ExecuteProgram(std::size_t program_index) {
}
}
void System::RegisterExitCallback(ExitCallback&& callback) {
impl->exit_callback = std::move(callback);
}
void System::Exit() {
if (impl->exit_callback) {
impl->exit_callback();
} else {
LOG_CRITICAL(Core, "exit_callback must be initialized by the frontend");
}
}
void System::ApplySettings() {
if (IsPoweredOn()) {
Renderer().RefreshBaseSettings();

View File

@@ -387,6 +387,18 @@ public:
*/
void ExecuteProgram(std::size_t program_index);
/// Type used for the frontend to designate a callback for System to exit the application.
using ExitCallback = std::function<void()>;
/**
* Registers a callback from the frontend for System to exit the application.
* @param callback Callback from the frontend to exit the application.
*/
void RegisterExitCallback(ExitCallback&& callback);
/// Instructs the frontend to exit the application.
void Exit();
/// Applies any changes to settings to this core instance.
void ApplySettings();

View File

@@ -77,7 +77,7 @@ void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address
aci_header.title_id = title_id;
aci_file_access.permissions = filesystem_permissions;
npdm_header.system_resource_size = system_resource_size;
aci_kernel_capabilities = std ::move(capabilities);
aci_kernel_capabilities = std::move(capabilities);
}
bool ProgramMetadata::Is64BitProgram() const {

View File

@@ -1,88 +0,0 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <string>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#endif
#include <zip.h>
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "common/fs/path_util.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_libzip.h"
#include "core/file_sys/vfs_vector.h"
namespace FileSys {
VirtualDir ExtractZIP(VirtualFile file) {
zip_error_t error{};
const auto data = file->ReadAllBytes();
std::unique_ptr<zip_source_t, decltype(&zip_source_close)> src{
zip_source_buffer_create(data.data(), data.size(), 0, &error), zip_source_close};
if (src == nullptr)
return nullptr;
std::unique_ptr<zip_t, decltype(&zip_close)> zip{zip_open_from_source(src.get(), 0, &error),
zip_close};
if (zip == nullptr)
return nullptr;
std::shared_ptr<VectorVfsDirectory> out = std::make_shared<VectorVfsDirectory>();
const auto num_entries = static_cast<std::size_t>(zip_get_num_entries(zip.get(), 0));
zip_stat_t stat{};
zip_stat_init(&stat);
for (std::size_t i = 0; i < num_entries; ++i) {
const auto stat_res = zip_stat_index(zip.get(), i, 0, &stat);
if (stat_res == -1)
return nullptr;
const std::string name(stat.name);
if (name.empty())
continue;
if (name.back() != '/') {
std::unique_ptr<zip_file_t, decltype(&zip_fclose)> file2{
zip_fopen_index(zip.get(), i, 0), zip_fclose};
std::vector<u8> buf(stat.size);
if (zip_fread(file2.get(), buf.data(), buf.size()) != s64(buf.size()))
return nullptr;
const auto parts = Common::FS::SplitPathComponents(stat.name);
const auto new_file = std::make_shared<VectorVfsFile>(buf, parts.back());
std::shared_ptr<VectorVfsDirectory> dtrv = out;
for (std::size_t j = 0; j < parts.size() - 1; ++j) {
if (dtrv == nullptr)
return nullptr;
const auto subdir = dtrv->GetSubdirectory(parts[j]);
if (subdir == nullptr) {
const auto temp = std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parts[j]);
dtrv->AddDirectory(temp);
dtrv = temp;
} else {
dtrv = std::dynamic_pointer_cast<VectorVfsDirectory>(subdir);
}
}
if (dtrv == nullptr)
return nullptr;
dtrv->AddFile(new_file);
}
}
return out;
}
} // namespace FileSys

View File

@@ -1,13 +0,0 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/file_sys/vfs_types.h"
namespace FileSys {
VirtualDir ExtractZIP(VirtualFile zip);
} // namespace FileSys

View File

@@ -7,7 +7,7 @@
namespace Kernel {
KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
KHandleTable ::~KHandleTable() = default;
KHandleTable::~KHandleTable() = default;
ResultCode KHandleTable::Finalize() {
// Get the table and clear our record of it.

View File

@@ -275,12 +275,14 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
{19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
{21, nullptr, "GetScreenShotProgramId"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
@@ -302,6 +304,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
{100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
{110, nullptr, "SetApplicationAlbumUserData"},
{120, nullptr, "SaveCurrentScreenshot"},
{130, nullptr, "SetRecordVolumeMuted"},
{1000, nullptr, "GetDebugStorageChannel"},
};
// clang-format on
@@ -329,10 +332,10 @@ ISelfController::~ISelfController() = default;
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
system.Shutdown();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
system.Exit();
}
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
@@ -683,6 +686,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{91, nullptr, "GetCurrentPerformanceConfiguration"},
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
{110, nullptr, "OpenMyGpuErrorHandler"},
{120, nullptr, "GetAppletLaunchedHistory"},
{200, nullptr, "GetOperationModeSystemInfo"},
{300, nullptr, "GetSettingsPlatformRegion"},
{400, nullptr, "ActivateMigrationService"},

View File

@@ -41,6 +41,14 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, nullptr, "Unknown30"},
{31, nullptr, "Unknown31"},
{32, nullptr, "Unknown32"},
{33, nullptr, "Unknown33"},
{34, nullptr, "Unknown34"},
{10000, nullptr, "Unknown10000"},
{10001, nullptr, "Unknown10001"},
{10002, nullptr, "Unknown10002"},
};
// clang-format on

View File

@@ -3,38 +3,65 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/audio/audin_u.h"
namespace Service::Audio {
class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
explicit IAudioIn(Core::System& system_) : ServiceFramework{system_, "IAudioIn"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetAudioInState"},
{1, nullptr, "Start"},
{2, nullptr, "Stop"},
{3, nullptr, "AppendAudioInBuffer"},
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedAudioInBuffer"},
{6, nullptr, "ContainsAudioInBuffer"},
{7, nullptr, "AppendUacInBuffer"},
{8, nullptr, "AppendAudioInBufferAuto"},
{9, nullptr, "GetReleasedAudioInBuffersAuto"},
{10, nullptr, "AppendUacInBufferAuto"},
{11, nullptr, "GetAudioInBufferCount"},
{12, nullptr, "SetDeviceGain"},
{13, nullptr, "GetDeviceGain"},
{14, nullptr, "FlushAudioInBuffers"},
};
// clang-format on
IAudioIn::IAudioIn(Core::System& system_)
: ServiceFramework{system_, "IAudioIn"}, buffer_event{system_.Kernel()} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetAudioInState"},
{1, &IAudioIn::Start, "Start"},
{2, nullptr, "Stop"},
{3, nullptr, "AppendAudioInBuffer"},
{4, &IAudioIn::RegisterBufferEvent, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedAudioInBuffer"},
{6, nullptr, "ContainsAudioInBuffer"},
{7, nullptr, "AppendUacInBuffer"},
{8, &IAudioIn::AppendAudioInBufferAuto, "AppendAudioInBufferAuto"},
{9, nullptr, "GetReleasedAudioInBuffersAuto"},
{10, nullptr, "AppendUacInBufferAuto"},
{11, nullptr, "GetAudioInBufferCount"},
{12, nullptr, "SetDeviceGain"},
{13, nullptr, "GetDeviceGain"},
{14, nullptr, "FlushAudioInBuffers"},
};
// clang-format on
RegisterHandlers(functions);
}
};
RegisterHandlers(functions);
Kernel::KAutoObject::Create(std::addressof(buffer_event));
buffer_event.Initialize("IAudioIn:BufferEvent");
}
IAudioIn::~IAudioIn() = default;
void IAudioIn::Start(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IAudioIn::RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(buffer_event.GetReadableEvent());
}
void IAudioIn::AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
AudInU::AudInU(Core::System& system_) : ServiceFramework{system_, "audin:u"} {
// clang-format off

View File

@@ -4,6 +4,7 @@
#pragma once
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -16,6 +17,19 @@ class HLERequestContext;
namespace Service::Audio {
class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
explicit IAudioIn(Core::System& system_);
~IAudioIn() override;
private:
void Start(Kernel::HLERequestContext& ctx);
void RegisterBufferEvent(Kernel::HLERequestContext& ctx);
void AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx);
Kernel::KEvent buffer_event;
};
class AudInU final : public ServiceFramework<AudInU> {
public:
explicit AudInU(Core::System& system_);

View File

@@ -187,7 +187,8 @@ public:
{10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
{11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
{12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
{13, nullptr, "GetAudioSystemMasterVolumeSetting"},
{13, nullptr, "GetActiveAudioOutputDeviceName"},
{14, nullptr, "ListAudioOutputDeviceName"},
};
RegisterHandlers(functions);
}

View File

@@ -1,548 +0,0 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <fmt/ostream.h>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#endif
#include <httplib.h>
#include <mbedtls/sha256.h>
#include <nlohmann/json.hpp>
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_libzip.h"
#include "core/file_sys/vfs_vector.h"
#include "core/frontend/applets/error.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/bcat/backend/boxcat.h"
namespace Service::BCAT {
namespace {
// Prevents conflicts with windows macro called CreateFile
FileSys::VirtualFile VfsCreateFileWrap(FileSys::VirtualDir dir, std::string_view name) {
return dir->CreateFile(name);
}
// Prevents conflicts with windows macro called DeleteFile
bool VfsDeleteFileWrap(FileSys::VirtualDir dir, std::string_view name) {
return dir->DeleteFile(name);
}
constexpr ResultCode ERROR_GENERAL_BCAT_FAILURE{ErrorModule::BCAT, 1};
constexpr char BOXCAT_HOSTNAME[] = "api.yuzu-emu.org";
// Formatted using fmt with arg[0] = hex title id
constexpr char BOXCAT_PATHNAME_DATA[] = "/game-assets/{:016X}/boxcat";
constexpr char BOXCAT_PATHNAME_LAUNCHPARAM[] = "/game-assets/{:016X}/launchparam";
constexpr char BOXCAT_PATHNAME_EVENTS[] = "/game-assets/boxcat/events";
constexpr char BOXCAT_API_VERSION[] = "1";
constexpr char BOXCAT_CLIENT_TYPE[] = "yuzu";
// HTTP status codes for Boxcat
enum class ResponseStatus {
Ok = 200, ///< Operation completed successfully.
BadClientVersion = 301, ///< The Boxcat-Client-Version doesn't match the server.
NoUpdate = 304, ///< The digest provided would match the new data, no need to update.
NoMatchTitleId = 404, ///< The title ID provided doesn't have a boxcat implementation.
NoMatchBuildId = 406, ///< The build ID provided is blacklisted (potentially because of format
///< issues or whatnot) and has no data.
};
enum class DownloadResult {
Success = 0,
NoResponse,
GeneralWebError,
NoMatchTitleId,
NoMatchBuildId,
InvalidContentType,
GeneralFSError,
BadClientVersion,
};
constexpr std::array<const char*, 8> DOWNLOAD_RESULT_LOG_MESSAGES{
"Success",
"There was no response from the server.",
"There was a general web error code returned from the server.",
"The title ID of the current game doesn't have a boxcat implementation. If you believe an "
"implementation should be added, contact yuzu support.",
"The build ID of the current version of the game is marked as incompatible with the current "
"BCAT distribution. Try upgrading or downgrading your game version or contacting yuzu support.",
"The content type of the web response was invalid.",
"There was a general filesystem error while saving the zip file.",
"The server is either too new or too old to serve the request. Try using the latest version of "
"an official release of yuzu.",
};
std::ostream& operator<<(std::ostream& os, DownloadResult result) {
return os << DOWNLOAD_RESULT_LOG_MESSAGES.at(static_cast<std::size_t>(result));
}
constexpr u32 PORT = 443;
constexpr u32 TIMEOUT_SECONDS = 30;
[[maybe_unused]] constexpr u64 VFS_COPY_BLOCK_SIZE = 1ULL << 24; // 4MB
std::filesystem::path GetBINFilePath(u64 title_id) {
return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
fmt::format("{:016X}/launchparam.bin", title_id);
}
std::filesystem::path GetZIPFilePath(u64 title_id) {
return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
fmt::format("{:016X}/data.zip", title_id);
}
// If the error is something the user should know about (build ID mismatch, bad client version),
// display an error.
void HandleDownloadDisplayResult(const AM::Applets::AppletManager& applet_manager,
DownloadResult res) {
if (res == DownloadResult::Success || res == DownloadResult::NoResponse ||
res == DownloadResult::GeneralWebError || res == DownloadResult::GeneralFSError ||
res == DownloadResult::NoMatchTitleId || res == DownloadResult::InvalidContentType) {
return;
}
const auto& frontend{applet_manager.GetAppletFrontendSet()};
frontend.error->ShowCustomErrorText(
ResultUnknown, "There was an error while attempting to use Boxcat.",
DOWNLOAD_RESULT_LOG_MESSAGES[static_cast<std::size_t>(res)], [] {});
}
bool VfsRawCopyProgress(FileSys::VirtualFile src, FileSys::VirtualFile dest,
std::string_view dir_name, ProgressServiceBackend& progress,
std::size_t block_size = 0x1000) {
if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
return false;
if (!dest->Resize(src->GetSize()))
return false;
progress.StartDownloadingFile(dir_name, src->GetName(), src->GetSize());
std::vector<u8> temp(std::min(block_size, src->GetSize()));
for (std::size_t i = 0; i < src->GetSize(); i += block_size) {
const auto read = std::min(block_size, src->GetSize() - i);
if (src->Read(temp.data(), read, i) != read) {
return false;
}
if (dest->Write(temp.data(), read, i) != read) {
return false;
}
progress.UpdateFileProgress(i);
}
progress.FinishDownloadingFile();
return true;
}
bool VfsRawCopyDProgressSingle(FileSys::VirtualDir src, FileSys::VirtualDir dest,
ProgressServiceBackend& progress, std::size_t block_size = 0x1000) {
if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
return false;
for (const auto& file : src->GetFiles()) {
const auto out_file = VfsCreateFileWrap(dest, file->GetName());
if (!VfsRawCopyProgress(file, out_file, src->GetName(), progress, block_size)) {
return false;
}
}
progress.CommitDirectory(src->GetName());
return true;
}
bool VfsRawCopyDProgress(FileSys::VirtualDir src, FileSys::VirtualDir dest,
ProgressServiceBackend& progress, std::size_t block_size = 0x1000) {
if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
return false;
for (const auto& dir : src->GetSubdirectories()) {
const auto out = dest->CreateSubdirectory(dir->GetName());
if (!VfsRawCopyDProgressSingle(dir, out, progress, block_size)) {
return false;
}
}
return true;
}
} // Anonymous namespace
class Boxcat::Client {
public:
Client(std::filesystem::path path_, u64 title_id_, u64 build_id_)
: path(std::move(path_)), title_id(title_id_), build_id(build_id_) {}
DownloadResult DownloadDataZip() {
return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS,
"application/zip");
}
DownloadResult DownloadLaunchParam() {
return DownloadInternal(fmt::format(BOXCAT_PATHNAME_LAUNCHPARAM, title_id),
TIMEOUT_SECONDS / 3, "application/octet-stream");
}
private:
DownloadResult DownloadInternal(const std::string& resolved_path, u32 timeout_seconds,
const std::string& content_type_name) {
if (client == nullptr) {
client = std::make_unique<httplib::SSLClient>(BOXCAT_HOSTNAME, PORT);
client->set_connection_timeout(timeout_seconds);
client->set_read_timeout(timeout_seconds);
client->set_write_timeout(timeout_seconds);
}
httplib::Headers headers{
{std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
{std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)},
{std::string("Game-Build-Id"), fmt::format("{:016X}", build_id)},
};
if (Common::FS::Exists(path)) {
Common::FS::IOFile file{path, Common::FS::FileAccessMode::Read,
Common::FS::FileType::BinaryFile};
if (file.IsOpen()) {
std::vector<u8> bytes(file.GetSize());
void(file.Read(bytes));
const auto digest = DigestFile(bytes);
headers.insert({std::string("If-None-Match"), Common::HexToString(digest, false)});
}
}
const auto response = client->Get(resolved_path.c_str(), headers);
if (response == nullptr)
return DownloadResult::NoResponse;
if (response->status == static_cast<int>(ResponseStatus::NoUpdate))
return DownloadResult::Success;
if (response->status == static_cast<int>(ResponseStatus::BadClientVersion))
return DownloadResult::BadClientVersion;
if (response->status == static_cast<int>(ResponseStatus::NoMatchTitleId))
return DownloadResult::NoMatchTitleId;
if (response->status == static_cast<int>(ResponseStatus::NoMatchBuildId))
return DownloadResult::NoMatchBuildId;
if (response->status != static_cast<int>(ResponseStatus::Ok))
return DownloadResult::GeneralWebError;
const auto content_type = response->headers.find("content-type");
if (content_type == response->headers.end() ||
content_type->second.find(content_type_name) == std::string::npos) {
return DownloadResult::InvalidContentType;
}
if (!Common::FS::CreateDirs(path)) {
return DownloadResult::GeneralFSError;
}
Common::FS::IOFile file{path, Common::FS::FileAccessMode::Append,
Common::FS::FileType::BinaryFile};
if (!file.IsOpen()) {
return DownloadResult::GeneralFSError;
}
if (!file.SetSize(response->body.size())) {
return DownloadResult::GeneralFSError;
}
if (file.Write(response->body) != response->body.size()) {
return DownloadResult::GeneralFSError;
}
return DownloadResult::Success;
}
using Digest = std::array<u8, 0x20>;
static Digest DigestFile(std::vector<u8> bytes) {
Digest out{};
mbedtls_sha256_ret(bytes.data(), bytes.size(), out.data(), 0);
return out;
}
std::unique_ptr<httplib::SSLClient> client;
std::filesystem::path path;
u64 title_id;
u64 build_id;
};
Boxcat::Boxcat(AM::Applets::AppletManager& applet_manager_, DirectoryGetter getter)
: Backend(std::move(getter)), applet_manager{applet_manager_} {}
Boxcat::~Boxcat() = default;
void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGetter dir_getter,
TitleIDVersion title, ProgressServiceBackend& progress,
std::optional<std::string> dir_name = {}) {
progress.SetNeedHLELock(true);
if (Settings::values.bcat_boxcat_local) {
LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download.");
const auto dir = dir_getter(title.title_id);
if (dir)
progress.SetTotalSize(dir->GetSize());
progress.FinishDownload(ResultSuccess);
return;
}
const auto zip_path = GetZIPFilePath(title.title_id);
Boxcat::Client client{zip_path, title.title_id, title.build_id};
progress.StartConnecting();
const auto res = client.DownloadDataZip();
if (res != DownloadResult::Success) {
LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
Common::FS::RemoveFile(zip_path);
}
HandleDownloadDisplayResult(applet_manager, res);
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
progress.StartProcessingDataList();
Common::FS::IOFile zip{zip_path, Common::FS::FileAccessMode::Read,
Common::FS::FileType::BinaryFile};
const auto size = zip.GetSize();
std::vector<u8> bytes(size);
if (!zip.IsOpen() || size == 0 || zip.Read(bytes) != bytes.size()) {
LOG_ERROR(Service_BCAT, "Boxcat failed to read ZIP file at path '{}'!",
Common::FS::PathToUTF8String(zip_path));
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
const auto extracted = FileSys::ExtractZIP(std::make_shared<FileSys::VectorVfsFile>(bytes));
if (extracted == nullptr) {
LOG_ERROR(Service_BCAT, "Boxcat failed to extract ZIP file!");
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
if (dir_name == std::nullopt) {
progress.SetTotalSize(extracted->GetSize());
const auto target_dir = dir_getter(title.title_id);
if (target_dir == nullptr || !VfsRawCopyDProgress(extracted, target_dir, progress)) {
LOG_ERROR(Service_BCAT, "Boxcat failed to copy extracted ZIP to target directory!");
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
} else {
const auto target_dir = dir_getter(title.title_id);
if (target_dir == nullptr) {
LOG_ERROR(Service_BCAT, "Boxcat failed to get directory for title ID!");
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
const auto target_sub = target_dir->GetSubdirectory(*dir_name);
const auto source_sub = extracted->GetSubdirectory(*dir_name);
progress.SetTotalSize(source_sub->GetSize());
std::vector<std::string> filenames;
{
const auto files = target_sub->GetFiles();
std::transform(files.begin(), files.end(), std::back_inserter(filenames),
[](const auto& vfile) { return vfile->GetName(); });
}
for (const auto& filename : filenames) {
VfsDeleteFileWrap(target_sub, filename);
}
if (target_sub == nullptr || source_sub == nullptr ||
!VfsRawCopyDProgressSingle(source_sub, target_sub, progress)) {
LOG_ERROR(Service_BCAT, "Boxcat failed to copy extracted ZIP to target directory!");
progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
return;
}
}
progress.FinishDownload(ResultSuccess);
}
bool Boxcat::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) {
is_syncing.exchange(true);
std::thread([this, title, &progress] {
SynchronizeInternal(applet_manager, dir_getter, title, progress);
}).detach();
return true;
}
bool Boxcat::SynchronizeDirectory(TitleIDVersion title, std::string name,
ProgressServiceBackend& progress) {
is_syncing.exchange(true);
std::thread([this, title, name, &progress] {
SynchronizeInternal(applet_manager, dir_getter, title, progress, name);
}).detach();
return true;
}
bool Boxcat::Clear(u64 title_id) {
if (Settings::values.bcat_boxcat_local) {
LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping clear.");
return true;
}
const auto dir = dir_getter(title_id);
std::vector<std::string> dirnames;
for (const auto& subdir : dir->GetSubdirectories())
dirnames.push_back(subdir->GetName());
for (const auto& subdir : dirnames) {
if (!dir->DeleteSubdirectoryRecursive(subdir))
return false;
}
return true;
}
void Boxcat::SetPassphrase(u64 title_id, const Passphrase& passphrase) {
LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id,
Common::HexToString(passphrase));
}
std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) {
const auto bin_file_path = GetBINFilePath(title.title_id);
if (Settings::values.bcat_boxcat_local) {
LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download.");
} else {
Client launch_client{bin_file_path, title.title_id, title.build_id};
const auto res = launch_client.DownloadLaunchParam();
if (res != DownloadResult::Success) {
LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
Common::FS::RemoveFile(bin_file_path);
}
HandleDownloadDisplayResult(applet_manager, res);
return std::nullopt;
}
}
Common::FS::IOFile bin{bin_file_path, Common::FS::FileAccessMode::Read,
Common::FS::FileType::BinaryFile};
const auto size = bin.GetSize();
std::vector<u8> bytes(size);
if (!bin.IsOpen() || size == 0 || bin.Read(bytes) != bytes.size()) {
LOG_ERROR(Service_BCAT, "Boxcat failed to read launch parameter binary at path '{}'!",
Common::FS::PathToUTF8String(bin_file_path));
return std::nullopt;
}
return bytes;
}
Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
std::map<std::string, EventStatus>& games) {
httplib::SSLClient client{BOXCAT_HOSTNAME, static_cast<int>(PORT)};
client.set_connection_timeout(static_cast<int>(TIMEOUT_SECONDS));
client.set_read_timeout(static_cast<int>(TIMEOUT_SECONDS));
client.set_write_timeout(static_cast<int>(TIMEOUT_SECONDS));
httplib::Headers headers{
{std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
{std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)},
};
if (!client.is_valid()) {
LOG_ERROR(Service_BCAT, "Client is invalid, going offline!");
return StatusResult::Offline;
}
if (!client.is_socket_open()) {
LOG_ERROR(Service_BCAT, "Failed to open socket, going offline!");
return StatusResult::Offline;
}
const auto response = client.Get(BOXCAT_PATHNAME_EVENTS, headers);
if (response == nullptr)
return StatusResult::Offline;
if (response->status == static_cast<int>(ResponseStatus::BadClientVersion))
return StatusResult::BadClientVersion;
try {
nlohmann::json json = nlohmann::json::parse(response->body);
if (!json["online"].get<bool>())
return StatusResult::Offline;
if (json["global"].is_null())
global = std::nullopt;
else
global = json["global"].get<std::string>();
if (json["games"].is_array()) {
for (const auto& object : json["games"]) {
if (object.is_object() && object.find("name") != object.end()) {
EventStatus detail{};
if (object["header"].is_string()) {
detail.header = object["header"].get<std::string>();
} else {
detail.header = std::nullopt;
}
if (object["footer"].is_string()) {
detail.footer = object["footer"].get<std::string>();
} else {
detail.footer = std::nullopt;
}
if (object["events"].is_array()) {
for (const auto& event : object["events"]) {
if (!event.is_string())
continue;
detail.events.push_back(event.get<std::string>());
}
}
games.insert_or_assign(object["name"], std::move(detail));
}
}
}
return StatusResult::Success;
} catch (const nlohmann::json::parse_error& error) {
LOG_ERROR(Service_BCAT, "{}", error.what());
return StatusResult::ParseError;
}
}
} // namespace Service::BCAT

View File

@@ -1,64 +0,0 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <atomic>
#include <map>
#include <optional>
#include "core/hle/service/bcat/backend/backend.h"
namespace Service::AM::Applets {
class AppletManager;
}
namespace Service::BCAT {
struct EventStatus {
std::optional<std::string> header;
std::optional<std::string> footer;
std::vector<std::string> events;
};
/// Boxcat is yuzu's custom backend implementation of Nintendo's BCAT service. It is free to use and
/// doesn't require a switch or nintendo account. The content is controlled by the yuzu team.
class Boxcat final : public Backend {
friend void SynchronizeInternal(AM::Applets::AppletManager& applet_manager,
DirectoryGetter dir_getter, TitleIDVersion title,
ProgressServiceBackend& progress,
std::optional<std::string> dir_name);
public:
explicit Boxcat(AM::Applets::AppletManager& applet_manager_, DirectoryGetter getter);
~Boxcat() override;
bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override;
bool SynchronizeDirectory(TitleIDVersion title, std::string name,
ProgressServiceBackend& progress) override;
bool Clear(u64 title_id) override;
void SetPassphrase(u64 title_id, const Passphrase& passphrase) override;
std::optional<std::vector<u8>> GetLaunchParameter(TitleIDVersion title) override;
enum class StatusResult {
Success,
Offline,
ParseError,
BadClientVersion,
};
static StatusResult GetStatus(std::optional<std::string>& global,
std::map<std::string, EventStatus>& games);
private:
std::atomic_bool is_syncing{false};
class Client;
std::unique_ptr<Client> client;
AM::Applets::AppletManager& applet_manager;
};
} // namespace Service::BCAT

View File

@@ -4,7 +4,6 @@
#include <cctype>
#include <mbedtls/md5.h>
#include "backend/boxcat.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/settings.h"
@@ -578,12 +577,6 @@ void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId(
std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System& system,
DirectoryGetter getter) {
#ifdef YUZU_ENABLE_BOXCAT
if (Settings::values.bcat_backend.GetValue() == "boxcat") {
return std::make_unique<Boxcat>(system.GetAppletManager(), std::move(getter));
}
#endif
return std::make_unique<NullBackend>(std::move(getter));
}

View File

@@ -175,6 +175,10 @@ public:
{143, nullptr, "GetAudioControlInputState"},
{144, nullptr, "AcquireAudioConnectionStateChangedEvent"},
{145, nullptr, "GetConnectedAudioDevice"},
{146, nullptr, "CloseAudioControlInput"},
{147, nullptr, "RegisterAudioControlNotification"},
{148, nullptr, "SendAudioControlPassthroughCommand"},
{149, nullptr, "SendAudioControlSetAbsoluteVolumeCommand"},
{256, nullptr, "IsManufacturingMode"},
{257, nullptr, "EmulateBluetoothCrash"},
{258, nullptr, "GetBleChannelMap"},

View File

@@ -15,6 +15,7 @@ CAPS_SS::CAPS_SS(Core::System& system_) : ServiceFramework{system_, "caps:ss"} {
{204, nullptr, "SaveEditedScreenShotEx0"},
{206, nullptr, "Unknown206"},
{208, nullptr, "SaveScreenShotOfMovieEx1"},
{1000, nullptr, "Unknown1000"},
};
// clang-format on

View File

@@ -55,6 +55,8 @@ public:
{36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"},
{37, nullptr, "OwnTicket2"},
{38, nullptr, "OwnTicket3"},
{39, nullptr, "DeleteAllInactivePersonalizedTicket"},
{40, nullptr, "DeletePrepurchaseRecordByNintendoAccountId"},
{501, nullptr, "Unknown501"},
{502, nullptr, "Unknown502"},
{503, nullptr, "GetTitleKey"},
@@ -88,11 +90,15 @@ public:
{1503, nullptr, "Unknown1503"},
{1504, nullptr, "Unknown1504"},
{1505, nullptr, "Unknown1505"},
{1506, nullptr, "Unknown1506"},
{2000, nullptr, "Unknown2000"},
{2001, nullptr, "Unknown2001"},
{2002, nullptr, "Unknown2002"},
{2003, nullptr, "Unknown2003"},
{2100, nullptr, "Unknown2100"},
{2501, nullptr, "Unknown2501"},
{2502, nullptr, "Unknown2502"},
{2601, nullptr, "Unknown2601"},
{3001, nullptr, "Unknown3001"},
{3002, nullptr, "Unknown3002"},
};

View File

@@ -507,6 +507,7 @@ private:
LarkNesRight = 18,
Lucia = 19,
Verification = 20,
Lagon = 21,
};
struct NPadEntry {

View File

@@ -106,7 +106,7 @@ void IAppletResource::DeactivateController(HidController controller) {
controllers[static_cast<size_t>(controller)]->DeactivateController();
}
IAppletResource ::~IAppletResource() {
IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
}
@@ -239,6 +239,12 @@ Hid::Hid(Core::System& system_)
{81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
{82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
{84, nullptr, "EnableSixAxisSensorUnalteredPassthrough"},
{85, nullptr, "IsSixAxisSensorUnalteredPassthroughEnabled"},
{86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
{87, nullptr, "LoadSixAxisSensorCalibrationParameter"},
{88, nullptr, "GetSixAxisSensorIcInformation"},
{89, nullptr, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
{91, &Hid::ActivateGesture, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
@@ -1656,6 +1662,9 @@ public:
{12, nullptr, "UnsetTouchScreenAutoPilotState"},
{13, nullptr, "GetTouchScreenConfiguration"},
{14, nullptr, "ProcessTouchScreenAutoTune"},
{15, nullptr, "ForceStopTouchScreenManagement"},
{16, nullptr, "ForceRestartTouchScreenManagement"},
{17, nullptr, "IsTouchScreenManaged"},
{20, nullptr, "DeactivateMouse"},
{21, nullptr, "SetMouseAutoPilotState"},
{22, nullptr, "UnsetMouseAutoPilotState"},

View File

@@ -31,6 +31,7 @@ public:
{24, nullptr, "DestroyTokenWithApplicationId"},
{25, nullptr, "QueryIsTokenValid"},
{26, nullptr, "ListenToMyApplicationId"},
{27, nullptr, "DestroyTokenAll"},
{31, nullptr, "UploadTokenToBaaS"},
{32, nullptr, "DestroyTokenForBaaS"},
{33, nullptr, "CreateTokenForBaaS"},

View File

@@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices {
nvdisp_disp0::nvdisp_disp0(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_)
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)} {}
nvdisp_disp0 ::~nvdisp_disp0() = default;
nvdisp_disp0::~nvdisp_disp0() = default;
NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
std::vector<u8>& output) {

View File

@@ -419,13 +419,12 @@ void BSD::Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
LOG_DEBUG(Service, "called. fd={} len={}", fd, ctx.GetWriteBufferSize());
LOG_WARNING(Service, "(STUBBED) called. fd={} len={}", fd, ctx.GetWriteBufferSize());
ExecuteWork(ctx, RecvWork{
.fd = fd,
.flags = 0,
.message = std::vector<u8>(ctx.GetWriteBufferSize()),
});
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u32>(0); // ret
rb.Push<u32>(0); // bsd errno
}
void BSD::Close(Kernel::HLERequestContext& ctx) {

View File

@@ -13,7 +13,7 @@ SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_)
context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
}
SystemClockCore ::~SystemClockCore() = default;
SystemClockCore::~SystemClockCore() = default;
ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
posix_time = 0;

View File

@@ -10,8 +10,8 @@
namespace Service::Time {
ITimeZoneService ::ITimeZoneService(Core::System& system_,
TimeZone::TimeZoneContentManager& time_zone_manager_)
ITimeZoneService::ITimeZoneService(Core::System& system_,
TimeZone::TimeZoneContentManager& time_zone_manager_)
: ServiceFramework{system_, "ITimeZoneService"}, time_zone_content_manager{time_zone_manager_} {
static const FunctionInfo functions[] = {
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},

View File

@@ -97,7 +97,7 @@ public:
{3, nullptr, "GetAlternateInterface"},
{4, nullptr, "GetCurrentFrame"},
{5, nullptr, "CtrlXferAsync"},
{6, nullptr, "Unknown6"},
{6, nullptr, "GetCtrlXferCompletionEvent"},
{7, nullptr, "GetCtrlXferReport"},
{8, nullptr, "ResetDevice"},
{9, nullptr, "OpenUsbEp"},
@@ -183,8 +183,8 @@ public:
{4, nullptr, "GetHostPdcFirmwareRevision"},
{5, nullptr, "GetHostPdcManufactureId"},
{6, nullptr, "GetHostPdcDeviceId"},
{7, nullptr, "AwakeCradle"},
{8, nullptr, "SleepCradle"},
{7, nullptr, "EnableCradleRecovery"},
{8, nullptr, "DisableCradleRecovery"},
};
// clang-format on

View File

@@ -831,6 +831,7 @@ public:
{6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
{6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
{6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
{6013, nullptr, "SetLayerOpacity"},
{7000, nullptr, "SetContentVisibility"},
{8000, nullptr, "SetConductorLayer"},
{8001, nullptr, "SetTimestampTracking"},

View File

@@ -58,8 +58,8 @@ void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding,
const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
const auto cbuf_cast{fmt::format("{}({}[{}]{{}})", cast, cbuf, index)};
const auto extraction{num_bits == 32 ? cbuf_cast
: fmt ::format("bitfieldExtract({},int({}),{})", cbuf_cast,
bit_offset, num_bits)};
: fmt::format("bitfieldExtract({},int({}),{})", cbuf_cast,
bit_offset, num_bits)};
if (!component_indexing_bug) {
const auto result{fmt::format(fmt::runtime(extraction), swizzle)};
ctx.Add("{}={};", ret, result);

View File

@@ -570,13 +570,12 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
ForEachWrittenRange(*cpu_src_address, amount, mirror);
// This subtraction in this order is important for overlapping copies.
common_ranges.subtract(subtract_interval);
bool atleast_1_download = tmp_intervals.size() != 0;
for (const IntervalType add_interval : tmp_intervals) {
const bool has_new_downloads = tmp_intervals.size() != 0;
for (const IntervalType& add_interval : tmp_intervals) {
common_ranges.add(add_interval);
}
runtime.CopyBuffer(dest_buffer, src_buffer, copies);
if (atleast_1_download) {
if (has_new_downloads) {
dest_buffer.MarkRegionAsGpuModified(*cpu_dest_address, amount);
}
std::vector<u8> tmp_buffer(amount);

View File

@@ -82,41 +82,41 @@ void MaxwellDMA::Launch() {
}
void MaxwellDMA::CopyPitchToPitch() {
// When `multi_line_enable` bit is disabled the copy is performed as if we were copying a 1D
// buffer of length `line_length_in`.
// Otherwise we copy a 2D image of dimensions (line_length_in, line_count).
auto& accelerate = rasterizer->AccessAccelerateDMA();
if (!regs.launch_dma.multi_line_enable) {
const bool is_buffer_clear = regs.launch_dma.remap_enable != 0 &&
regs.remap_const.dst_x == RemapConst::Swizzle::CONST_A;
// TODO: allow multisized components.
if (is_buffer_clear) {
ASSERT(regs.remap_const.component_size_minus_one == 3);
accelerate.BufferClear(regs.offset_out, regs.line_length_in, regs.remap_consta_value);
std::vector<u32> tmp_buffer(regs.line_length_in, regs.remap_consta_value);
memory_manager.WriteBlockUnsafe(regs.offset_out,
reinterpret_cast<u8*>(tmp_buffer.data()),
regs.line_length_in * sizeof(u32));
return;
}
UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0);
if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) {
std::vector<u8> tmp_buffer(regs.line_length_in);
memory_manager.ReadBlockUnsafe(regs.offset_in, tmp_buffer.data(), regs.line_length_in);
memory_manager.WriteBlock(regs.offset_out, tmp_buffer.data(), regs.line_length_in);
// When `multi_line_enable` bit is enabled we copy a 2D image of dimensions
// (line_length_in, line_count).
// Otherwise the copy is performed as if we were copying a 1D buffer of length line_length_in.
const bool remap_enabled = regs.launch_dma.remap_enable != 0;
if (regs.launch_dma.multi_line_enable) {
UNIMPLEMENTED_IF(remap_enabled);
// Perform a line-by-line copy.
// We're going to take a subrect of size (line_length_in, line_count) from the source
// rectangle. There is no need to manually flush/invalidate the regions because CopyBlock
// does that for us.
for (u32 line = 0; line < regs.line_count; ++line) {
const GPUVAddr source_line = regs.offset_in + static_cast<size_t>(line) * regs.pitch_in;
const GPUVAddr dest_line = regs.offset_out + static_cast<size_t>(line) * regs.pitch_out;
memory_manager.CopyBlock(dest_line, source_line, regs.line_length_in);
}
return;
}
UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0);
// Perform a line-by-line copy.
// We're going to take a subrect of size (line_length_in, line_count) from the source rectangle.
// There is no need to manually flush/invalidate the regions because CopyBlock does that for us.
for (u32 line = 0; line < regs.line_count; ++line) {
const GPUVAddr source_line = regs.offset_in + static_cast<size_t>(line) * regs.pitch_in;
const GPUVAddr dest_line = regs.offset_out + static_cast<size_t>(line) * regs.pitch_out;
memory_manager.CopyBlock(dest_line, source_line, regs.line_length_in);
// TODO: allow multisized components.
auto& accelerate = rasterizer->AccessAccelerateDMA();
const bool is_const_a_dst = regs.remap_const.dst_x == RemapConst::Swizzle::CONST_A;
const bool is_buffer_clear = remap_enabled && is_const_a_dst;
if (is_buffer_clear) {
ASSERT(regs.remap_const.component_size_minus_one == 3);
accelerate.BufferClear(regs.offset_out, regs.line_length_in, regs.remap_consta_value);
std::vector<u32> tmp_buffer(regs.line_length_in, regs.remap_consta_value);
memory_manager.WriteBlockUnsafe(regs.offset_out, reinterpret_cast<u8*>(tmp_buffer.data()),
regs.line_length_in * sizeof(u32));
return;
}
UNIMPLEMENTED_IF(remap_enabled);
if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) {
std::vector<u8> tmp_buffer(regs.line_length_in);
memory_manager.ReadBlockUnsafe(regs.offset_in, tmp_buffer.data(), regs.line_length_in);
memory_manager.WriteBlock(regs.offset_out, tmp_buffer.data(), regs.line_length_in);
}
}

View File

@@ -175,7 +175,7 @@ public:
static_assert(sizeof(LaunchDMA) == 4);
struct RemapConst {
enum Swizzle : u32 {
enum class Swizzle : u32 {
SRC_X = 0,
SRC_Y = 1,
SRC_Z = 2,

View File

@@ -6,7 +6,6 @@ set(SHADER_FILES
convert_float_to_depth.frag
full_screen_triangle.vert
opengl_copy_bc4.comp
opengl_copy_bgra.comp
opengl_present.frag
opengl_present.vert
pitch_unswizzle.comp

View File

@@ -1,15 +0,0 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 430 core
layout (local_size_x = 4, local_size_y = 4) in;
layout(binding = 0, rgba8) readonly uniform image2DArray bgr_input;
layout(binding = 1, rgba8) writeonly uniform image2DArray bgr_output;
void main() {
vec4 color = imageLoad(bgr_input, ivec3(gl_GlobalInvocationID));
imageStore(bgr_output, ivec3(gl_GlobalInvocationID), color.bgra);
}

View File

@@ -147,8 +147,7 @@ void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
void BufferCacheRuntime::ClearBuffer(Buffer& dest_buffer, u32 offset, size_t size, u32 value) {
glClearNamedBufferSubData(dest_buffer.Handle(), GL_R32UI, static_cast<GLintptr>(offset),
static_cast<GLsizeiptr>(size / sizeof(u32)), GL_RED, GL_UNSIGNED_INT,
&value);
static_cast<GLsizeiptr>(size), GL_RED, GL_UNSIGNED_INT, &value);
}
void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) {

View File

@@ -461,7 +461,7 @@ bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) {
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
return false;
}
if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
if (IsPixelFormatBGR(dst.info.format) != IsPixelFormatBGR(src.info.format)) {
return false;
}
return true;
@@ -473,7 +473,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src,
ASSERT(src.info.type == ImageType::e3D);
util_shaders.CopyBC4(dst, src, copies);
} else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
util_shaders.CopyBGR(dst, src, copies);
bgr_copy_pass.CopyBGR(dst, src, copies);
} else {
UNREACHABLE();
}
@@ -1112,4 +1112,37 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
framebuffer.handle = handle;
}
void BGRCopyPass::CopyBGR(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies) {
static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0};
const u32 requested_pbo_size =
std::max(src_image.unswizzled_size_bytes, dst_image.unswizzled_size_bytes);
if (bgr_pbo_size < requested_pbo_size) {
bgr_pbo.Create();
bgr_pbo_size = requested_pbo_size;
glNamedBufferData(bgr_pbo.handle, bgr_pbo_size, nullptr, GL_STREAM_COPY);
}
for (const ImageCopy& copy : copies) {
ASSERT(copy.src_offset == zero_offset);
ASSERT(copy.dst_offset == zero_offset);
// Copy from source to PBO
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width);
glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr_pbo.handle);
glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
copy.src_subresource.num_layers, src_image.GlFormat(),
src_image.GlType(), static_cast<GLsizei>(bgr_pbo_size), nullptr);
// Copy from PBO to destination in desired GL format
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr_pbo.handle);
glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
copy.dst_subresource.num_layers, dst_image.GlFormat(),
dst_image.GlType(), nullptr);
}
}
} // namespace OpenGL

View File

@@ -47,6 +47,19 @@ struct FormatProperties {
bool is_compressed;
};
class BGRCopyPass {
public:
BGRCopyPass() = default;
~BGRCopyPass() = default;
void CopyBGR(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies);
private:
OGLBuffer bgr_pbo;
size_t bgr_pbo_size{};
};
class TextureCacheRuntime {
friend Framebuffer;
friend Image;
@@ -118,6 +131,7 @@ private:
const Device& device;
StateTracker& state_tracker;
UtilShaders util_shaders;
BGRCopyPass bgr_copy_pass;
std::array<std::unordered_map<GLenum, FormatProperties>, 3> format_properties;
bool has_broken_texture_view_formats = false;
@@ -162,6 +176,14 @@ public:
return texture.handle;
}
GLuint GlFormat() const noexcept {
return gl_format;
}
GLuint GlType() const noexcept {
return gl_type;
}
private:
void CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);

View File

@@ -52,7 +52,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB
{GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UFLOAT
{GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SFLOAT
{GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4_UNORM
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
{GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, // B8G8R8A8_UNORM
{GL_RGBA32F, GL_RGBA, GL_FLOAT}, // R32G32B32A32_FLOAT
{GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, // R32G32B32A32_SINT
{GL_RG32F, GL_RG, GL_FLOAT}, // R32G32_FLOAT
@@ -81,7 +81,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB
{GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8_UNORM
{GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5_UNORM
{GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4_UNORM
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, // B8G8R8A8_SRGB
{GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, // B8G8R8A8_SRGB
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // BC1_RGBA_SRGB
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // BC2_SRGB
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // BC3_SRGB

View File

@@ -14,7 +14,6 @@
#include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h"
#include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h"
#include "video_core/host_shaders/opengl_copy_bc4_comp.h"
#include "video_core/host_shaders/opengl_copy_bgra_comp.h"
#include "video_core/host_shaders/pitch_unswizzle_comp.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
@@ -44,11 +43,6 @@ namespace {
OGLProgram MakeProgram(std::string_view source) {
return CreateProgram(source, GL_COMPUTE_SHADER);
}
size_t NumPixelsInCopy(const VideoCommon::ImageCopy& copy) {
return static_cast<size_t>(copy.extent.width * copy.extent.height *
copy.src_subresource.num_layers);
}
} // Anonymous namespace
UtilShaders::UtilShaders(ProgramManager& program_manager_)
@@ -56,7 +50,6 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)),
block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)),
pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)),
copy_bgra_program(MakeProgram(OPENGL_COPY_BGRA_COMP)),
copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) {
const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
swizzle_table_buffer.Create();
@@ -255,43 +248,6 @@ void UtilShaders::CopyBC4(Image& dst_image, Image& src_image, std::span<const Im
program_manager.RestoreGuestCompute();
}
void UtilShaders::CopyBGR(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies) {
static constexpr GLuint BINDING_INPUT_IMAGE = 0;
static constexpr GLuint BINDING_OUTPUT_IMAGE = 1;
static constexpr VideoCommon::Offset3D zero_offset{0, 0, 0};
const u32 bytes_per_block = BytesPerBlock(dst_image.info.format);
switch (bytes_per_block) {
case 2:
// BGR565 copy
for (const ImageCopy& copy : copies) {
ASSERT(copy.src_offset == zero_offset);
ASSERT(copy.dst_offset == zero_offset);
bgr_copy_pass.Execute(dst_image, src_image, copy);
}
break;
case 4: {
// BGRA8 copy
program_manager.BindComputeProgram(copy_bgra_program.handle);
constexpr GLenum FORMAT = GL_RGBA8;
for (const ImageCopy& copy : copies) {
ASSERT(copy.src_offset == zero_offset);
ASSERT(copy.dst_offset == zero_offset);
glBindImageTexture(BINDING_INPUT_IMAGE, src_image.StorageHandle(),
copy.src_subresource.base_level, GL_FALSE, 0, GL_READ_ONLY, FORMAT);
glBindImageTexture(BINDING_OUTPUT_IMAGE, dst_image.StorageHandle(),
copy.dst_subresource.base_level, GL_FALSE, 0, GL_WRITE_ONLY, FORMAT);
glDispatchCompute(copy.extent.width, copy.extent.height, copy.extent.depth);
}
program_manager.RestoreGuestCompute();
break;
}
default:
UNREACHABLE();
break;
}
}
GLenum StoreFormat(u32 bytes_per_block) {
switch (bytes_per_block) {
case 1:
@@ -309,36 +265,4 @@ GLenum StoreFormat(u32 bytes_per_block) {
return GL_R8UI;
}
void Bgr565CopyPass::Execute(const Image& dst_image, const Image& src_image,
const ImageCopy& copy) {
if (CopyBufferCreationNeeded(copy)) {
CreateNewCopyBuffer(copy, GL_TEXTURE_2D_ARRAY, GL_RGB565);
}
// Copy from source to PBO
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, copy.extent.width);
glBindBuffer(GL_PIXEL_PACK_BUFFER, bgr16_pbo.handle);
glGetTextureSubImage(src_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
copy.src_subresource.num_layers, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
static_cast<GLsizei>(bgr16_pbo_size), nullptr);
// Copy from PBO to destination in reverse order
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, copy.extent.width);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bgr16_pbo.handle);
glTextureSubImage3D(dst_image.Handle(), 0, 0, 0, 0, copy.extent.width, copy.extent.height,
copy.dst_subresource.num_layers, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV,
nullptr);
}
bool Bgr565CopyPass::CopyBufferCreationNeeded(const ImageCopy& copy) {
return bgr16_pbo_size < NumPixelsInCopy(copy) * sizeof(u16);
}
void Bgr565CopyPass::CreateNewCopyBuffer(const ImageCopy& copy, GLenum target, GLuint format) {
bgr16_pbo.Create();
bgr16_pbo_size = NumPixelsInCopy(copy) * sizeof(u16);
glNamedBufferData(bgr16_pbo.handle, bgr16_pbo_size, nullptr, GL_STREAM_COPY);
}
} // namespace OpenGL

View File

@@ -19,22 +19,6 @@ class ProgramManager;
struct ImageBufferMap;
class Bgr565CopyPass {
public:
Bgr565CopyPass() = default;
~Bgr565CopyPass() = default;
void Execute(const Image& dst_image, const Image& src_image,
const VideoCommon::ImageCopy& copy);
private:
[[nodiscard]] bool CopyBufferCreationNeeded(const VideoCommon::ImageCopy& copy);
void CreateNewCopyBuffer(const VideoCommon::ImageCopy& copy, GLenum target, GLuint format);
OGLBuffer bgr16_pbo;
size_t bgr16_pbo_size{};
};
class UtilShaders {
public:
explicit UtilShaders(ProgramManager& program_manager);
@@ -55,9 +39,6 @@ public:
void CopyBC4(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies);
void CopyBGR(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies);
private:
ProgramManager& program_manager;
@@ -67,10 +48,7 @@ private:
OGLProgram block_linear_unswizzle_2d_program;
OGLProgram block_linear_unswizzle_3d_program;
OGLProgram pitch_unswizzle_program;
OGLProgram copy_bgra_program;
OGLProgram copy_bc4_program;
Bgr565CopyPass bgr_copy_pass;
};
GLenum StoreFormat(u32 bytes_per_block);

View File

@@ -212,7 +212,6 @@ private:
vk::CommandBuffer current_cmdbuf;
std::unique_ptr<CommandChunk> chunk;
std::jthread worker_thread;
State state;
@@ -226,6 +225,7 @@ private:
std::mutex work_mutex;
std::condition_variable_any work_cv;
std::condition_variable wait_cv;
std::jthread worker_thread;
};
} // namespace Vulkan

View File

@@ -127,7 +127,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format);
VkImageCreateFlags flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
if (info.type == ImageType::e2D && info.resources.layers >= 6 &&
info.size.width == info.size.height) {
info.size.width == info.size.height && !device.HasBrokenCubeImageCompability()) {
flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
if (info.type == ImageType::e3D) {

View File

@@ -588,22 +588,27 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
ext_extended_dynamic_state = false;
}
}
sets_per_pool = 64;
if (driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE) {
const bool is_amd =
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
if (is_amd) {
// AMD drivers need a higher amount of Sets per Pool in certain circunstances like in XC2.
sets_per_pool = 96;
}
const bool is_amd = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
driver_id == VK_DRIVER_ID_MESA_RADV ||
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
if (ext_sampler_filter_minmax && is_amd) {
// Disable ext_sampler_filter_minmax on AMD GCN4 and lower as it is broken.
// Disable VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT on AMD GCN4 and lower as it is broken.
if (!is_float16_supported) {
LOG_WARNING(
Render_Vulkan,
"Blacklisting AMD GCN4 and lower for VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME");
"AMD GCN4 and earlier do not properly support VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT");
has_broken_cube_compatibility = true;
}
}
const bool is_amd_or_radv = is_amd || driver_id == VK_DRIVER_ID_MESA_RADV;
if (ext_sampler_filter_minmax && is_amd_or_radv) {
// Disable ext_sampler_filter_minmax on AMD GCN4 and lower as it is broken.
if (!is_float16_supported) {
LOG_WARNING(Render_Vulkan,
"Blacklisting AMD GCN4 and earlier for VK_EXT_sampler_filter_minmax");
ext_sampler_filter_minmax = false;
}
}

View File

@@ -309,6 +309,11 @@ public:
return has_renderdoc || has_nsight_graphics;
}
/// Returns true when the device does not properly support cube compatibility.
bool HasBrokenCubeImageCompability() const {
return has_broken_cube_compatibility;
}
/// Returns the vendor name reported from Vulkan.
std::string_view GetVendorName() const {
return vendor_name;
@@ -417,6 +422,7 @@ private:
bool ext_conservative_rasterization{}; ///< Support for VK_EXT_conservative_rasterization.
bool ext_provoking_vertex{}; ///< Support for VK_EXT_provoking_vertex.
bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
bool has_broken_cube_compatibility{}; ///< Has broken cube compatiblity bit
bool has_renderdoc{}; ///< Has RenderDoc attached
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached

View File

@@ -290,10 +290,6 @@ if (YUZU_USE_QT_WEB_ENGINE)
target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE)
endif ()
if (YUZU_ENABLE_BOXCAT)
target_compile_definitions(yuzu PRIVATE -DYUZU_ENABLE_BOXCAT)
endif ()
if(UNIX AND NOT APPLE)
install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endif()

View File

@@ -54,6 +54,9 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
input_interpreter(std::make_unique<InputInterpreter>(system)),
default_profile{QWebEngineProfile::defaultProfile()},
global_settings{QWebEngineSettings::globalSettings()} {
default_profile->setPersistentStoragePath(QString::fromStdString(Common::FS::PathToUTF8String(
Common::FS::GetYuzuPath(Common::FS::YuzuPath::YuzuDir) / "qtwebengine")));
QWebEngineScript gamepad;
QWebEngineScript window_nx;

View File

@@ -302,12 +302,17 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
Qt::QueuedConnection);
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
}
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
emit ExecuteProgramSignal(program_index);
}
void GRenderWindow::Exit() {
emit ExitSignal();
}
GRenderWindow::~GRenderWindow() {
input_subsystem->Shutdown();
}

View File

@@ -181,6 +181,9 @@ public:
*/
void ExecuteProgram(std::size_t program_index);
/// Instructs the window to exit the application.
void Exit();
public slots:
void OnEmulationStarting(EmuThread* emu_thread);
void OnEmulationStopping();
@@ -191,6 +194,7 @@ signals:
void Closed();
void FirstFrameDisplayed();
void ExecuteProgramSignal(std::size_t program_index);
void ExitSignal();
void MouseActivity();
private:

View File

@@ -562,7 +562,11 @@ void Config::ReadControlValues() {
ReadTouchscreenValues();
ReadMotionTouchValues();
#ifdef _WIN32
ReadBasicSetting(Settings::values.enable_raw_input);
#else
Settings::values.enable_raw_input = false;
#endif
ReadBasicSetting(Settings::values.emulate_analog_keyboard);
Settings::values.mouse_panning = false;
ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
@@ -705,8 +709,6 @@ void Config::ReadDebuggingValues() {
void Config::ReadServiceValues() {
qt_config->beginGroup(QStringLiteral("Services"));
ReadBasicSetting(Settings::values.bcat_backend);
ReadBasicSetting(Settings::values.bcat_boxcat_local);
ReadBasicSetting(Settings::values.network_interface);
qt_config->endGroup();
}
@@ -1265,8 +1267,6 @@ void Config::SaveDebuggingValues() {
void Config::SaveNetworkValues() {
qt_config->beginGroup(QStringLiteral("Services"));
WriteBasicSetting(Settings::values.bcat_backend);
WriteBasicSetting(Settings::values.bcat_boxcat_local);
WriteBasicSetting(Settings::values.network_interface);
qt_config->endGroup();

View File

@@ -88,6 +88,10 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
connect(ui->buttonMotionTouch, &QPushButton::clicked, this,
&ConfigureInputAdvanced::CallMotionTouchConfigDialog);
#ifndef _WIN32
ui->enable_raw_input->setVisible(false);
#endif
LoadConfiguration();
}

View File

@@ -6,64 +6,25 @@
#include <QtConcurrent/QtConcurrent>
#include "common/settings.h"
#include "core/core.h"
#include "core/hle/service/bcat/backend/boxcat.h"
#include "core/network/network_interface.h"
#include "ui_configure_network.h"
#include "yuzu/configuration/configure_network.h"
#ifdef YUZU_ENABLE_BOXCAT
namespace {
QString FormatEventStatusString(const Service::BCAT::EventStatus& status) {
QString out;
if (status.header.has_value()) {
out += QStringLiteral("<i>%1</i><br>").arg(QString::fromStdString(*status.header));
}
if (status.events.size() == 1) {
out += QStringLiteral("%1<br>").arg(QString::fromStdString(status.events.front()));
} else {
for (const auto& event : status.events) {
out += QStringLiteral("- %1<br>").arg(QString::fromStdString(event));
}
}
if (status.footer.has_value()) {
out += QStringLiteral("<i>%1</i><br>").arg(QString::fromStdString(*status.footer));
}
return out;
}
} // Anonymous namespace
#endif
ConfigureNetwork::ConfigureNetwork(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()) {
ui->setupUi(this);
ui->bcat_source->addItem(QStringLiteral("None"));
ui->bcat_empty_label->setHidden(true);
ui->bcat_empty_header->setHidden(true);
#ifdef YUZU_ENABLE_BOXCAT
ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat"));
#endif
ui->network_interface->addItem(tr("None"));
for (const auto& iface : Network::GetAvailableNetworkInterfaces()) {
ui->network_interface->addItem(QString::fromStdString(iface.name));
}
connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureNetwork::OnBCATImplChanged);
this->SetConfiguration();
}
ConfigureNetwork::~ConfigureNetwork() = default;
void ConfigureNetwork::ApplyConfiguration() {
Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString();
Settings::values.network_interface = ui->network_interface->currentText().toStdString();
}
@@ -74,86 +35,8 @@ void ConfigureNetwork::RetranslateUi() {
void ConfigureNetwork::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
const int index =
ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue()));
ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index);
const std::string& network_interface = Settings::values.network_interface.GetValue();
ui->network_interface->setCurrentText(QString::fromStdString(network_interface));
ui->network_interface->setEnabled(runtime_lock);
}
std::pair<QString, QString> ConfigureNetwork::BCATDownloadEvents() {
#ifdef YUZU_ENABLE_BOXCAT
std::optional<std::string> global;
std::map<std::string, Service::BCAT::EventStatus> map;
const auto res = Service::BCAT::Boxcat::GetStatus(global, map);
switch (res) {
case Service::BCAT::Boxcat::StatusResult::Success:
break;
case Service::BCAT::Boxcat::StatusResult::Offline:
return {QString{},
tr("The boxcat service is offline or you are not connected to the internet.")};
case Service::BCAT::Boxcat::StatusResult::ParseError:
return {QString{},
tr("There was an error while processing the boxcat event data. Contact the yuzu "
"developers.")};
case Service::BCAT::Boxcat::StatusResult::BadClientVersion:
return {QString{},
tr("The version of yuzu you are using is either too new or too old for the server. "
"Try updating to the latest official release of yuzu.")};
}
if (map.empty()) {
return {QStringLiteral("Current Boxcat Events"),
tr("There are currently no events on boxcat.")};
}
QString out;
if (global.has_value()) {
out += QStringLiteral("%1<br>").arg(QString::fromStdString(*global));
}
for (const auto& [key, value] : map) {
out += QStringLiteral("%1<b>%2</b><br>%3")
.arg(out.isEmpty() ? QString{} : QStringLiteral("<br>"))
.arg(QString::fromStdString(key))
.arg(FormatEventStatusString(value));
}
return {tr("Current Boxcat Events"), std::move(out)};
#else
return {tr("Current Boxcat Events"), tr("There are currently no events on boxcat.")};
#endif
}
void ConfigureNetwork::OnBCATImplChanged() {
#ifdef YUZU_ENABLE_BOXCAT
const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat");
ui->bcat_empty_header->setHidden(!boxcat);
ui->bcat_empty_label->setHidden(!boxcat);
ui->bcat_empty_header->setText(QString{});
ui->bcat_empty_label->setText(tr("Yuzu is retrieving the latest boxcat status..."));
if (!boxcat)
return;
const auto future = QtConcurrent::run([this] { return BCATDownloadEvents(); });
watcher.setFuture(future);
connect(&watcher, &QFutureWatcher<std::pair<QString, QString>>::finished, this,
[this] { OnUpdateBCATEmptyLabel(watcher.result()); });
#endif
}
void ConfigureNetwork::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) {
#ifdef YUZU_ENABLE_BOXCAT
const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat");
if (boxcat) {
ui->bcat_empty_header->setText(string.first);
ui->bcat_empty_label->setText(string.second);
}
#endif
}

View File

@@ -25,10 +25,5 @@ public:
private:
void SetConfiguration();
std::pair<QString, QString> BCATDownloadEvents();
void OnBCATImplChanged();
void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string);
std::unique_ptr<Ui::ConfigureNetwork> ui;
QFutureWatcher<std::pair<QString, QString>> watcher{this};
};

View File

@@ -35,92 +35,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>BCAT</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="bcat_empty_header">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>BCAT Backend</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLabel" name="label_2">
<property name="maximumSize">
<size>
<width>260</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://yuzu-emu.org/help/feature/boxcat&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Learn more about BCAT, Boxcat, and Current Events&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="bcat_source"/>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLabel" name="bcat_empty_label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>260</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>

View File

@@ -76,7 +76,7 @@ QString GetProfileUsernameFromUser(QWidget* parent, const QString& description_t
}
} // Anonymous namespace
ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
ConfigureProfileManager::ConfigureProfileManager(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureProfileManager),
profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
ui->setupUi(this);

View File

@@ -1384,6 +1384,9 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
system.RegisterExecuteProgramCallback(
[this](std::size_t program_index) { render_window->ExecuteProgram(program_index); });
// Register an Exit callback such that Core can exit the currently running application.
system.RegisterExitCallback([this]() { render_window->Exit(); });
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity);
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
@@ -2469,6 +2472,10 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
BootGame(last_filename_booted, 0, program_index);
}
void GMainWindow::OnExit() {
OnStopGame();
}
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);

View File

@@ -153,6 +153,7 @@ signals:
public slots:
void OnLoadComplete();
void OnExecuteProgram(std::size_t program_index);
void OnExit();
void ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters);
void SoftwareKeyboardInitialize(

View File

@@ -518,10 +518,6 @@ void Config::ReadValues() {
ReadSetting("WebService", Settings::values.web_api_url);
ReadSetting("WebService", Settings::values.yuzu_username);
ReadSetting("WebService", Settings::values.yuzu_token);
// Services
ReadSetting("Services", Settings::values.bcat_backend);
ReadSetting("Services", Settings::values.bcat_boxcat_local);
}
void Config::Reload() {

View File

@@ -428,11 +428,6 @@ web_api_url = https://api.yuzu-emu.org
yuzu_username =
yuzu_token =
[Services]
# The name of the backend to use for BCAT
# If this is set to 'boxcat' boxcat will be used, otherwise a null implementation will be used
bcat_backend =
[AddOns]
# Used to disable add-ons
# List of title IDs of games that will have add-ons disabled (separated by '|'):