summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.ci/scripts/common/post-upload.sh8
-rw-r--r--.ci/scripts/linux/docker.sh3
-rw-r--r--.ci/scripts/linux/upload.sh12
-rw-r--r--.ci/scripts/windows/upload.ps19
-rw-r--r--.ci/scripts/windows/upload.sh10
-rw-r--r--.ci/templates/build-msvc.yml1
-rw-r--r--.gitmodules8
-rw-r--r--externals/CMakeLists.txt1
m---------externals/libzip0
-rw-r--r--externals/libzip/CMakeLists.txt564
m---------externals/libzip/libzip0
-rw-r--r--externals/zlib/CMakeLists.txt81
m---------externals/zlib/zlib (renamed from externals/zlib)0
-rw-r--r--src/common/bit_field.h11
-rw-r--r--src/common/common_funcs.h22
-rw-r--r--src/core/file_sys/content_archive.cpp39
-rw-r--r--src/core/file_sys/romfs.h19
-rw-r--r--src/core/file_sys/savedata_factory.cpp12
-rw-r--r--src/core/hle/ipc.h6
-rw-r--r--src/core/hle/kernel/scheduler.cpp55
-rw-r--r--src/core/hle/kernel/scheduler.h109
-rw-r--r--src/core/hle/service/am/am.cpp31
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/error.cpp11
-rw-r--r--src/core/hle/service/hid/hid.cpp204
-rw-r--r--src/core/hle/service/hid/hid.h14
-rw-r--r--src/core/hle/service/vi/vi.cpp2
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/engines/fermi_2d.cpp30
-rw-r--r--src/video_core/engines/fermi_2d.h12
-rw-r--r--src/video_core/engines/kepler_compute.h18
-rw-r--r--src/video_core/engines/kepler_memory.h4
-rw-r--r--src/video_core/engines/maxwell_3d.h116
-rw-r--r--src/video_core/engines/maxwell_dma.h10
-rw-r--r--src/video_core/engines/shader_bytecode.h30
-rw-r--r--src/video_core/engines/shader_header.h50
-rw-r--r--src/video_core/gpu.h8
-rw-r--r--src/video_core/rasterizer_accelerated.cpp63
-rw-r--r--src/video_core/rasterizer_accelerated.h31
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp38
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h11
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp223
-rw-r--r--src/video_core/renderer_opengl/gl_state.h222
-rw-r--r--src/video_core/shader/decode/texture.cpp27
-rw-r--r--src/video_core/shader/shader_ir.h2
-rw-r--r--src/yuzu/main.cpp21
-rw-r--r--src/yuzu/main.h1
47 files changed, 1441 insertions, 713 deletions
diff --git a/.ci/scripts/common/post-upload.sh b/.ci/scripts/common/post-upload.sh
index bb4e9d328..b80868635 100644
--- a/.ci/scripts/common/post-upload.sh
+++ b/.ci/scripts/common/post-upload.sh
@@ -1,12 +1,12 @@
#!/bin/bash -ex
# Copy documentation
-cp license.txt "$REV_NAME"
-cp README.md "$REV_NAME"
+cp license.txt "$DIR_NAME"
+cp README.md "$DIR_NAME"
-tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME"
+tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME"
-mv "$REV_NAME" $RELEASE_NAME
+mv "$DIR_NAME" $RELEASE_NAME
7z a "$REV_NAME.7z" $RELEASE_NAME
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh
index 090ca75f1..5559a527c 100644
--- a/.ci/scripts/linux/docker.sh
+++ b/.ci/scripts/linux/docker.sh
@@ -11,5 +11,4 @@ ninja
ccache -s
-# Ignore zlib's tests, since they aren't gated behind a CMake option.
-ctest -VV -E "(example|example64)" -C Release
+ctest -VV -C Release
diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh
index 0d131d1dd..ecd77e267 100644
--- a/.ci/scripts/linux/upload.sh
+++ b/.ci/scripts/linux/upload.sh
@@ -6,9 +6,15 @@ REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
-mkdir "$REV_NAME"
+if [ "${RELEASE_NAME}" = "mainline" ]; then
+ DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
+else
+ DIR_NAME="${REV_NAME}"
+fi
-cp build/bin/yuzu-cmd "$REV_NAME"
-cp build/bin/yuzu "$REV_NAME"
+mkdir "$DIR_NAME"
+
+cp build/bin/yuzu-cmd "$DIR_NAME"
+cp build/bin/yuzu "$DIR_NAME"
. .ci/scripts/common/post-upload.sh
diff --git a/.ci/scripts/windows/upload.ps1 b/.ci/scripts/windows/upload.ps1
index 3cb709924..9fb99eaa3 100644
--- a/.ci/scripts/windows/upload.ps1
+++ b/.ci/scripts/windows/upload.ps1
@@ -1,6 +1,13 @@
+param($BUILD_NAME)
+
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
$GITREV = $(git show -s --format='%h')
-$RELEASE_DIST = "yuzu-windows-msvc"
+
+if ("$BUILD_NAME" -eq "mainline") {
+ $RELEASE_DIST = "yuzu-windows-msvc-$BUILD_NAME"
+} else {
+ $RELEASE_DIST = "yuzu-windows-msvc"
+}
$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
$MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", ""
diff --git a/.ci/scripts/windows/upload.sh b/.ci/scripts/windows/upload.sh
index de73d3541..41d87159f 100644
--- a/.ci/scripts/windows/upload.sh
+++ b/.ci/scripts/windows/upload.sh
@@ -6,8 +6,14 @@ REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
-mkdir "$REV_NAME"
+if [ "${RELEASE_NAME}" = "mainline" ]; then
+ DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
+else
+ DIR_NAME="${REV_NAME}"
+fi
+
+mkdir "$DIR_NAME"
# get around the permission issues
-cp -r package/* "$REV_NAME"
+cp -r package/* "$DIR_NAME"
. .ci/scripts/common/post-upload.sh
diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml
index b44a08247..52cebaee0 100644
--- a/.ci/templates/build-msvc.yml
+++ b/.ci/templates/build-msvc.yml
@@ -17,6 +17,7 @@ steps:
inputs:
targetType: 'filePath'
filePath: './.ci/scripts/windows/upload.ps1'
+ arguments: '$(BuildName)'
- publish: artifacts
artifact: 'yuzu-$(BuildName)-windows-msvc'
displayName: 'Upload Artifacts'
diff --git a/.gitmodules b/.gitmodules
index ee0dc6c19..63bf2cda0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -47,8 +47,8 @@
path = externals/sirit
url = https://github.com/ReinUsesLisp/sirit
[submodule "libzip"]
- path = externals/libzip
- url = https://github.com/DarkLordZach/libzip
+ path = externals/libzip/libzip
+ url = https://github.com/nih-at/libzip.git
[submodule "zlib"]
- path = externals/zlib
- url = https://github.com/madler/zlib
+ path = externals/zlib/zlib
+ url = https://github.com/madler/zlib.git
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index ac7529edd..61ad3487a 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -76,6 +76,7 @@ endif()
# zlib
add_subdirectory(zlib EXCLUDE_FROM_ALL)
+set(ZLIB_LIBRARIES z)
# libzip
add_subdirectory(libzip EXCLUDE_FROM_ALL)
diff --git a/externals/libzip b/externals/libzip
deleted file mode 160000
-Subproject bd7a8103e96bc6d50164447f6b7b57bb786d8e2
diff --git a/externals/libzip/CMakeLists.txt b/externals/libzip/CMakeLists.txt
new file mode 100644
index 000000000..ea5329fa0
--- /dev/null
+++ b/externals/libzip/CMakeLists.txt
@@ -0,0 +1,564 @@
+# 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}
+)
+
diff --git a/externals/libzip/libzip b/externals/libzip/libzip
new file mode 160000
+Subproject 89bd6d63bdea9da7627695f6c82e54f16d368b5
diff --git a/externals/zlib/CMakeLists.txt b/externals/zlib/CMakeLists.txt
new file mode 100644
index 000000000..0ca32aae4
--- /dev/null
+++ b/externals/zlib/CMakeLists.txt
@@ -0,0 +1,81 @@
+project(zlib C)
+
+include(CheckTypeSize)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stddef.h HAVE_STDDEF_H)
+
+# Check to see if we have large file support
+set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
+# We add these other definitions here because CheckTypeSize.cmake
+# in CMake 2.4.x does not automatically do so and we want
+# compatibility with CMake 2.4.x.
+if(HAVE_SYS_TYPES_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
+endif()
+if(HAVE_STDINT_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
+endif()
+if(HAVE_STDDEF_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
+endif()
+check_type_size(off64_t OFF64_T)
+if(HAVE_OFF64_T)
+ add_definitions(-D_LARGEFILE64_SOURCE=1)
+endif()
+set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
+
+# Check for fseeko
+check_function_exists(fseeko HAVE_FSEEKO)
+if(NOT HAVE_FSEEKO)
+ add_definitions(-DNO_FSEEKO)
+endif()
+
+# Check for unistd.h
+check_include_file(unistd.h HAVE_UNISTD_H)
+if(HAVE_UNISTD_H)
+ add_definitions(-DHAVE_UNISTD_H)
+endif()
+
+if(MSVC)
+ add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
+ add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+endif()
+
+add_library(z STATIC
+ zlib/adler32.c
+ zlib/compress.c
+ zlib/crc32.c
+ zlib/crc32.h
+ zlib/deflate.c
+ zlib/deflate.h
+ zlib/gzclose.c
+ zlib/gzguts.h
+ zlib/gzlib.c
+ zlib/gzread.c
+ zlib/gzwrite.c
+ zlib/inffast.h
+ zlib/inffixed.h
+ zlib/inflate.c
+ zlib/inflate.h
+ zlib/infback.c
+ zlib/inftrees.c
+ zlib/inftrees.h
+ zlib/inffast.c
+ zlib/trees.c
+ zlib/trees.h
+ zlib/uncompr.c
+ zlib/zconf.h
+ zlib/zlib.h
+ zlib/zutil.c
+ zlib/zutil.h
+)
+add_library(ZLIB::ZLIB ALIAS z)
+
+target_include_directories(z
+PUBLIC
+ zlib/
+)
diff --git a/externals/zlib b/externals/zlib/zlib
-Subproject cacf7f1d4e3d44d871b605da3b647f07d718623
+Subproject cacf7f1d4e3d44d871b605da3b647f07d718623
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 902e668e3..fd2bbbd99 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -36,6 +36,13 @@
#include "common/common_funcs.h"
#include "common/swap.h"
+// Inlining
+#ifdef _WIN32
+#define FORCE_INLINE __forceinline
+#else
+#define FORCE_INLINE inline __attribute__((always_inline))
+#endif
+
/*
* Abstract bitfield class
*
@@ -168,11 +175,11 @@ public:
constexpr BitField(BitField&&) noexcept = default;
constexpr BitField& operator=(BitField&&) noexcept = default;
- constexpr FORCE_INLINE operator T() const {
+ constexpr operator T() const {
return Value();
}
- constexpr FORCE_INLINE void Assign(const T& value) {
+ constexpr void Assign(const T& value) {
storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value);
}
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 04ecac959..c029dc7b3 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -1,10 +1,11 @@
-// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <algorithm>
+#include <array>
#include <string>
#if !defined(ARCHITECTURE_x86_64)
@@ -16,18 +17,15 @@
#define CONCAT2(x, y) DO_CONCAT2(x, y)
#define DO_CONCAT2(x, y) x##y
-// helper macro to properly align structure members.
-// Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121",
-// depending on the current source line to make sure variable names are unique.
-#define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)]
-#define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)]
+/// Helper macros to insert unused bytes or words to properly align structs. These values will be
+/// zero-initialized.
+#define INSERT_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__){};
+#define INSERT_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__){};
-// Inlining
-#ifdef _WIN32
-#define FORCE_INLINE __forceinline
-#else
-#define FORCE_INLINE inline __attribute__((always_inline))
-#endif
+/// These are similar to the INSERT_PADDING_* macros, but are needed for padding unions. This is
+/// because unions can only be initialized by one member.
+#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__);
+#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__);
#ifndef _MSC_VER
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index ea5c92f61..b8bbdd1ef 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -32,11 +32,28 @@ enum class NCASectionFilesystemType : u8 {
ROMFS = 0x3,
};
+struct IVFCLevel {
+ u64_le offset;
+ u64_le size;
+ u32_le block_size;
+ u32_le reserved;
+};
+static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
+
+struct IVFCHeader {
+ u32_le magic;
+ u32_le magic_number;
+ INSERT_UNION_PADDING_BYTES(8);
+ std::array<IVFCLevel, 6> levels;
+ INSERT_UNION_PADDING_BYTES(64);
+};
+static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
+
struct NCASectionHeaderBlock {
- INSERT_PADDING_BYTES(3);
+ INSERT_UNION_PADDING_BYTES(3);
NCASectionFilesystemType filesystem_type;
NCASectionCryptoType crypto_type;
- INSERT_PADDING_BYTES(3);
+ INSERT_UNION_PADDING_BYTES(3);
};
static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size.");
@@ -44,7 +61,7 @@ struct NCASectionRaw {
NCASectionHeaderBlock header;
std::array<u8, 0x138> block_data;
std::array<u8, 0x8> section_ctr;
- INSERT_PADDING_BYTES(0xB8);
+ INSERT_UNION_PADDING_BYTES(0xB8);
};
static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size.");
@@ -52,19 +69,19 @@ struct PFS0Superblock {
NCASectionHeaderBlock header_block;
std::array<u8, 0x20> hash;
u32_le size;
- INSERT_PADDING_BYTES(4);
+ INSERT_UNION_PADDING_BYTES(4);
u64_le hash_table_offset;
u64_le hash_table_size;
u64_le pfs0_header_offset;
u64_le pfs0_size;
- INSERT_PADDING_BYTES(0x1B0);
+ INSERT_UNION_PADDING_BYTES(0x1B0);
};
static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
struct RomFSSuperblock {
NCASectionHeaderBlock header_block;
IVFCHeader ivfc;
- INSERT_PADDING_BYTES(0x118);
+ INSERT_UNION_PADDING_BYTES(0x118);
};
static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size.");
@@ -72,24 +89,24 @@ struct BKTRHeader {
u64_le offset;
u64_le size;
u32_le magic;
- INSERT_PADDING_BYTES(0x4);
+ INSERT_UNION_PADDING_BYTES(0x4);
u32_le number_entries;
- INSERT_PADDING_BYTES(0x4);
+ INSERT_UNION_PADDING_BYTES(0x4);
};
static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size.");
struct BKTRSuperblock {
NCASectionHeaderBlock header_block;
IVFCHeader ivfc;
- INSERT_PADDING_BYTES(0x18);
+ INSERT_UNION_PADDING_BYTES(0x18);
BKTRHeader relocation;
BKTRHeader subsection;
- INSERT_PADDING_BYTES(0xC0);
+ INSERT_UNION_PADDING_BYTES(0xC0);
};
static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size.");
union NCASectionHeader {
- NCASectionRaw raw;
+ NCASectionRaw raw{};
PFS0Superblock pfs0;
RomFSSuperblock romfs;
BKTRSuperblock bktr;
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h
index 0f35639bc..1c89be8a4 100644
--- a/src/core/file_sys/romfs.h
+++ b/src/core/file_sys/romfs.h
@@ -13,25 +13,6 @@
namespace FileSys {
-struct RomFSHeader;
-
-struct IVFCLevel {
- u64_le offset;
- u64_le size;
- u32_le block_size;
- u32_le reserved;
-};
-static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
-
-struct IVFCHeader {
- u32_le magic;
- u32_le magic_number;
- INSERT_PADDING_BYTES(8);
- std::array<IVFCLevel, 6> levels;
- INSERT_PADDING_BYTES(64);
-};
-static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
-
enum class RomFSExtractionType {
Full, // Includes data directory
Truncated, // Traverses into data directory
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index fc8755c78..e2a7eaf7b 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -16,6 +16,7 @@ namespace FileSys {
constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
namespace {
+
void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
if (meta.zero_1 != 0) {
@@ -52,6 +53,13 @@ void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
meta.user_id[1], meta.user_id[0]);
}
}
+
+bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataDescriptor& desc) {
+ return desc.type == SaveDataType::CacheStorage || desc.type == SaveDataType::TemporaryStorage ||
+ (space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
+ desc.type == SaveDataType::SaveData && desc.title_id == 0 && desc.save_id == 0);
+}
+
} // Anonymous namespace
std::string SaveDataDescriptor::DebugInfo() const {
@@ -96,6 +104,10 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
auto out = dir->GetDirectoryRelative(save_directory);
+ if (out == nullptr && ShouldSaveDataBeAutomaticallyCreated(space, meta)) {
+ return Create(space, meta);
+ }
+
// Return an error if the save data doesn't actually exist.
if (out == nullptr) {
// TODO(Subv): Find out correct error code.
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index fae54bcc7..7ce313190 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -160,7 +160,7 @@ struct DomainMessageHeader {
// Used when responding to an IPC request, Server -> Client.
struct {
u32_le num_objects;
- INSERT_PADDING_WORDS(3);
+ INSERT_UNION_PADDING_WORDS(3);
};
// Used when performing an IPC request, Client -> Server.
@@ -171,8 +171,10 @@ struct DomainMessageHeader {
BitField<16, 16, u32> size;
};
u32_le object_id;
- INSERT_PADDING_WORDS(2);
+ INSERT_UNION_PADDING_WORDS(2);
};
+
+ std::array<u32, 4> raw{};
};
};
static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect");
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index e6dcb9639..0e2dbf13e 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -22,9 +22,9 @@
namespace Kernel {
-GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {
- is_reselection_pending = false;
-}
+GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {}
+
+GlobalScheduler::~GlobalScheduler() = default;
void GlobalScheduler::AddThread(SharedPtr<Thread> thread) {
thread_list.push_back(std::move(thread));
@@ -35,24 +35,11 @@ void GlobalScheduler::RemoveThread(const Thread* thread) {
thread_list.end());
}
-/*
- * UnloadThread selects a core and forces it to unload its current thread's context
- */
void GlobalScheduler::UnloadThread(s32 core) {
Scheduler& sched = system.Scheduler(core);
sched.UnloadThread();
}
-/*
- * SelectThread takes care of selecting the new scheduled thread.
- * It does it in 3 steps:
- * - First a thread is selected from the top of the priority queue. If no thread
- * is obtained then we move to step two, else we are done.
- * - Second we try to get a suggested thread that's not assigned to any core or
- * that is not the top thread in that core.
- * - Third is no suggested thread is found, we do a second pass and pick a running
- * thread in another core and swap it with its current thread.
- */
void GlobalScheduler::SelectThread(u32 core) {
const auto update_thread = [](Thread* thread, Scheduler& sched) {
if (thread != sched.selected_thread) {
@@ -114,30 +101,19 @@ void GlobalScheduler::SelectThread(u32 core) {
update_thread(current_thread, sched);
}
-/*
- * YieldThread takes a thread and moves it to the back of the it's priority list
- * This operation can be redundant and no scheduling is changed if marked as so.
- */
bool GlobalScheduler::YieldThread(Thread* yielding_thread) {
// Note: caller should use critical section, etc.
const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID());
const u32 priority = yielding_thread->GetPriority();
// Yield the thread
- ASSERT_MSG(yielding_thread == scheduled_queue[core_id].front(priority),
- "Thread yielding without being in front");
+ const Thread* const winner = scheduled_queue[core_id].front(priority);
+ ASSERT_MSG(yielding_thread == winner, "Thread yielding without being in front");
scheduled_queue[core_id].yield(priority);
- Thread* winner = scheduled_queue[core_id].front(priority);
return AskForReselectionOrMarkRedundant(yielding_thread, winner);
}
-/*
- * YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list.
- * Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
- * a better priority than the next thread in the core.
- * This operation can be redundant and no scheduling is changed if marked as so.
- */
bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
// Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
// etc.
@@ -189,12 +165,6 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) {
return AskForReselectionOrMarkRedundant(yielding_thread, winner);
}
-/*
- * YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue
- * and into the suggested queue. If no thread can be squeduled afterwards in that core,
- * a suggested thread is obtained instead.
- * This operation can be redundant and no scheduling is changed if marked as so.
- */
bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread) {
// Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section,
// etc.
@@ -280,7 +250,7 @@ void GlobalScheduler::PreemptThreads() {
if (winner->IsRunning()) {
UnloadThread(winner->GetProcessorID());
}
- TransferToCore(winner->GetPriority(), core_id, winner);
+ TransferToCore(winner->GetPriority(), s32(core_id), winner);
current_thread =
winner->GetPriority() <= current_thread->GetPriority() ? winner : current_thread;
}
@@ -313,7 +283,7 @@ void GlobalScheduler::PreemptThreads() {
if (winner->IsRunning()) {
UnloadThread(winner->GetProcessorID());
}
- TransferToCore(winner->GetPriority(), core_id, winner);
+ TransferToCore(winner->GetPriority(), s32(core_id), winner);
current_thread = winner;
}
}
@@ -331,12 +301,12 @@ void GlobalScheduler::Unsuggest(u32 priority, u32 core, Thread* thread) {
}
void GlobalScheduler::Schedule(u32 priority, u32 core, Thread* thread) {
- ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core.");
+ ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
scheduled_queue[core].add(thread, priority);
}
void GlobalScheduler::SchedulePrepend(u32 priority, u32 core, Thread* thread) {
- ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core.");
+ ASSERT_MSG(thread->GetProcessorID() == s32(core), "Thread must be assigned to this core.");
scheduled_queue[core].add(thread, priority, false);
}
@@ -368,7 +338,8 @@ void GlobalScheduler::TransferToCore(u32 priority, s32 destination_core, Thread*
}
}
-bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner) {
+bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread,
+ const Thread* winner) {
if (current_thread == winner) {
current_thread->IncrementYieldCount();
return true;
@@ -386,8 +357,6 @@ void GlobalScheduler::Shutdown() {
thread_list.clear();
}
-GlobalScheduler::~GlobalScheduler() = default;
-
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id)
: system(system), cpu_core(cpu_core), core_id(core_id) {}
@@ -470,7 +439,7 @@ void Scheduler::SwitchContext() {
// Load context of new thread
if (new_thread) {
- ASSERT_MSG(new_thread->GetProcessorID() == this->core_id,
+ ASSERT_MSG(new_thread->GetProcessorID() == s32(this->core_id),
"Thread must be assigned to this core.");
ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready,
"Thread must be ready to become running.");
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index fcae28e0a..f2d6311b8 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -26,6 +26,7 @@ public:
explicit GlobalScheduler(Core::System& system);
~GlobalScheduler();
+
/// Adds a new thread to the scheduler
void AddThread(SharedPtr<Thread> thread);
@@ -37,47 +38,57 @@ public:
return thread_list;
}
- // Add a thread to the suggested queue of a cpu core. Suggested threads may be
- // picked if no thread is scheduled to run on the core.
+ /**
+ * Add a thread to the suggested queue of a cpu core. Suggested threads may be
+ * picked if no thread is scheduled to run on the core.
+ */
void Suggest(u32 priority, u32 core, Thread* thread);
- // Remove a thread to the suggested queue of a cpu core. Suggested threads may be
- // picked if no thread is scheduled to run on the core.
+ /**
+ * Remove a thread to the suggested queue of a cpu core. Suggested threads may be
+ * picked if no thread is scheduled to run on the core.
+ */
void Unsuggest(u32 priority, u32 core, Thread* thread);
- // Add a thread to the scheduling queue of a cpu core. The thread is added at the
- // back the queue in its priority level
+ /**
+ * Add a thread to the scheduling queue of a cpu core. The thread is added at the
+ * back the queue in its priority level.
+ */
void Schedule(u32 priority, u32 core, Thread* thread);
- // Add a thread to the scheduling queue of a cpu core. The thread is added at the
- // front the queue in its priority level
+ /**
+ * Add a thread to the scheduling queue of a cpu core. The thread is added at the
+ * front the queue in its priority level.
+ */
void SchedulePrepend(u32 priority, u32 core, Thread* thread);
- // Reschedule an already scheduled thread based on a new priority
+ /// Reschedule an already scheduled thread based on a new priority
void Reschedule(u32 priority, u32 core, Thread* thread);
- // Unschedule a thread.
+ /// Unschedules a thread.
void Unschedule(u32 priority, u32 core, Thread* thread);
- // Transfers a thread into an specific core. If the destination_core is -1
- // it will be unscheduled from its source code and added into its suggested
- // queue.
+ /**
+ * Transfers a thread into an specific core. If the destination_core is -1
+ * it will be unscheduled from its source code and added into its suggested
+ * queue.
+ */
void TransferToCore(u32 priority, s32 destination_core, Thread* thread);
- /*
- * UnloadThread selects a core and forces it to unload its current thread's context
- */
+ /// Selects a core and forces it to unload its current thread's context
void UnloadThread(s32 core);
- /*
- * SelectThread takes care of selecting the new scheduled thread.
- * It does it in 3 steps:
- * - First a thread is selected from the top of the priority queue. If no thread
- * is obtained then we move to step two, else we are done.
- * - Second we try to get a suggested thread that's not assigned to any core or
- * that is not the top thread in that core.
- * - Third is no suggested thread is found, we do a second pass and pick a running
- * thread in another core and swap it with its current thread.
+ /**
+ * Takes care of selecting the new scheduled thread in three steps:
+ *
+ * 1. First a thread is selected from the top of the priority queue. If no thread
+ * is obtained then we move to step two, else we are done.
+ *
+ * 2. Second we try to get a suggested thread that's not assigned to any core or
+ * that is not the top thread in that core.
+ *
+ * 3. Third is no suggested thread is found, we do a second pass and pick a running
+ * thread in another core and swap it with its current thread.
*/
void SelectThread(u32 core);
@@ -85,33 +96,37 @@ public:
return !scheduled_queue[core_id].empty();
}
- /*
- * YieldThread takes a thread and moves it to the back of the it's priority list
- * This operation can be redundant and no scheduling is changed if marked as so.
+ /**
+ * Takes a thread and moves it to the back of the it's priority list.
+ *
+ * @note This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThread(Thread* thread);
- /*
- * YieldThreadAndBalanceLoad takes a thread and moves it to the back of the it's priority list.
+ /**
+ * Takes a thread and moves it to the back of the it's priority list.
* Afterwards, tries to pick a suggested thread from the suggested queue that has worse time or
* a better priority than the next thread in the core.
- * This operation can be redundant and no scheduling is changed if marked as so.
+ *
+ * @note This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThreadAndBalanceLoad(Thread* thread);
- /*
- * YieldThreadAndWaitForLoadBalancing takes a thread and moves it out of the scheduling queue
- * and into the suggested queue. If no thread can be squeduled afterwards in that core,
+ /**
+ * Takes a thread and moves it out of the scheduling queue.
+ * and into the suggested queue. If no thread can be scheduled afterwards in that core,
* a suggested thread is obtained instead.
- * This operation can be redundant and no scheduling is changed if marked as so.
+ *
+ * @note This operation can be redundant and no scheduling is changed if marked as so.
*/
bool YieldThreadAndWaitForLoadBalancing(Thread* thread);
- /*
- * PreemptThreads this operation rotates the scheduling queues of threads at
- * a preemption priority and then does some core rebalancing. Preemption priorities
- * can be found in the array 'preemption_priorities'. This operation happens
- * every 10ms.
+ /**
+ * Rotates the scheduling queues of threads at a preemption priority and then does
+ * some core rebalancing. Preemption priorities can be found in the array
+ * 'preemption_priorities'.
+ *
+ * @note This operation happens every 10ms.
*/
void PreemptThreads();
@@ -130,15 +145,15 @@ public:
void Shutdown();
private:
- bool AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner);
+ bool AskForReselectionOrMarkRedundant(Thread* current_thread, const Thread* winner);
static constexpr u32 min_regular_priority = 2;
std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> scheduled_queue;
std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> suggested_queue;
- std::atomic<bool> is_reselection_pending;
+ std::atomic<bool> is_reselection_pending{false};
- // `preemption_priorities` are the priority levels at which the global scheduler
- // preempts threads every 10 ms. They are ordered from Core 0 to Core 3
+ // The priority levels at which the global scheduler preempts threads every 10 ms. They are
+ // ordered from Core 0 to Core 3.
std::array<u32, NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
/// Lists all thread ids that aren't deleted/etc.
@@ -181,10 +196,8 @@ public:
private:
friend class GlobalScheduler;
- /**
- * Switches the CPU's active thread context to that of the specified thread
- * @param new_thread The thread to switch to
- */
+
+ /// Switches the CPU's active thread context to that of the specified thread
void SwitchContext();
/**
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3a32d5b41..3d8a91d22 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1073,9 +1073,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{71, nullptr, "RequestToReboot"},
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
{90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
- {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"},
- {101, nullptr, "SetApplicationCopyrightImage"},
- {102, nullptr, "SetApplicationCopyrightVisibility"},
+ {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
+ {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
+ {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
{110, nullptr, "QueryApplicationPlayStatistics"},
{120, nullptr, "ExecuteProgram"},
{121, nullptr, "ClearUserChannel"},
@@ -1103,6 +1103,31 @@ void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestConte
rb.Push(RESULT_SUCCESS);
}
+void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
+ Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto is_visible = rp.Pop<bool>();
+
+ LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index ccd053c13..2ae9402a8 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -252,6 +252,9 @@ private:
void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
void EndBlockingHomeButton(Kernel::HLERequestContext& ctx);
void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
+ void InitializeApplicationCopyrightFrameBuffer(Kernel::HLERequestContext& ctx);
+ void SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx);
+ void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index a7db26725..eab0d42c9 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -20,9 +20,9 @@ namespace Service::AM::Applets {
struct ShowError {
u8 mode;
bool jump;
- INSERT_PADDING_BYTES(4);
+ INSERT_UNION_PADDING_BYTES(4);
bool use_64bit_error_code;
- INSERT_PADDING_BYTES(1);
+ INSERT_UNION_PADDING_BYTES(1);
u64 error_code_64;
u32 error_code_32;
};
@@ -32,7 +32,7 @@ static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
struct ShowErrorRecord {
u8 mode;
bool jump;
- INSERT_PADDING_BYTES(6);
+ INSERT_UNION_PADDING_BYTES(6);
u64 error_code_64;
u64 posix_time;
};
@@ -41,7 +41,7 @@ static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect si
struct SystemErrorArg {
u8 mode;
bool jump;
- INSERT_PADDING_BYTES(6);
+ INSERT_UNION_PADDING_BYTES(6);
u64 error_code_64;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
@@ -52,7 +52,7 @@ static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect si
struct ApplicationErrorArg {
u8 mode;
bool jump;
- INSERT_PADDING_BYTES(6);
+ INSERT_UNION_PADDING_BYTES(6);
u32 error_code;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
@@ -65,6 +65,7 @@ union Error::ErrorArguments {
ShowErrorRecord error_record;
SystemErrorArg system_error;
ApplicationErrorArg application_error;
+ std::array<u8, 0x1018> raw{};
};
namespace {
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ba1da4181..ecc130f6c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -203,13 +203,13 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
{122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
- {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
+ {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
{125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
{126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
{127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
- {129, nullptr, "GetNpadHandheldActivationMode"},
+ {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
{130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
@@ -557,10 +557,126 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
applet_resource_user_id);
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
+ // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
+ IPC::RequestParser rp{ctx};
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto npad_joy_device_type{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
+ npad_id, applet_resource_user_id, npad_joy_device_type);
+
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_id{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
+ applet_resource_user_id);
+
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto unknown_1{rp.Pop<u32>()};
+ const auto unknown_2{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+ unknown_1, unknown_2, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.StartLRAssignmentMode();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.StopLRAssignmentMode();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto mode{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
+ applet_resource_user_id, mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
+void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_1{rp.Pop<u32>()};
+ const auto npad_2{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
+ applet_resource_user_id, npad_1, npad_2);
+
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ IPC::ResponseBuilder rb{ctx, 2};
+ if (controller.SwapNpadAssignment(npad_1, npad_2)) {
+ rb.Push(RESULT_SUCCESS);
+ } else {
+ LOG_ERROR(Service_HID, "Npads are not connected!");
+ rb.Push(ERR_NPAD_NOT_CONNECTED);
+ }
+}
+
void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
@@ -635,47 +751,6 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration());
}
-void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_id{rp.Pop<u32>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
- applet_resource_user_id);
-
- auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
-
-void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto unknown_1{rp.Pop<u32>()};
- const auto unknown_2{rp.Pop<u32>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
- unknown_1, unknown_2, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
-
-void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto mode{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
- applet_resource_user_id, mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
-
void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
@@ -769,49 +844,6 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
-void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
- auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
- controller.StartLRAssignmentMode();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
-
-void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
- auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
- controller.StopLRAssignmentMode();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
-
-void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_1{rp.Pop<u32>()};
- const auto npad_2{rp.Pop<u32>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
- applet_resource_user_id, npad_1, npad_2);
-
- auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
- IPC::ResponseBuilder rb{ctx, 2};
- if (controller.SwapNpadAssignment(npad_1, npad_2)) {
- rb.Push(RESULT_SUCCESS);
- } else {
- LOG_ERROR(Service_HID, "Npads are not connected!");
- rb.Push(ERR_NPAD_NOT_CONNECTED);
- }
-}
-
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 01852e019..f08e036a3 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -106,14 +106,19 @@ private:
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
+ void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
+ void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
+ void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
+ void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
+ void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
+ void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
void SendVibrationValue(Kernel::HLERequestContext& ctx);
void SendVibrationValues(Kernel::HLERequestContext& ctx);
void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
- void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
- void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
- void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx);
void PermitVibration(Kernel::HLERequestContext& ctx);
@@ -123,9 +128,6 @@ private:
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
- void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
- void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
- void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
std::shared_ptr<IAppletResource> applet_resource;
Core::System& system;
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 199b30635..611cecc20 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -45,7 +45,7 @@ struct DisplayInfo {
/// Whether or not the display has a limited number of layers.
u8 has_limited_layers{1};
- INSERT_PADDING_BYTES(7){};
+ INSERT_PADDING_BYTES(7);
/// Indicates the total amount of layers supported by the display.
/// @note This is only valid if has_limited_layers is set.
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index cb6eda1b8..c911c6ec4 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -36,6 +36,8 @@ add_library(video_core STATIC
memory_manager.h
morton.cpp
morton.h
+ rasterizer_accelerated.cpp
+ rasterizer_accelerated.h
rasterizer_cache.cpp
rasterizer_cache.h
rasterizer_interface.h
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 7ff44f06d..85d308e26 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -28,6 +28,13 @@ void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
}
}
+std::pair<u32, u32> DelimitLine(u32 src_1, u32 src_2, u32 dst_1, u32 dst_2, u32 src_line) {
+ const u32 line_a = src_2 - src_1;
+ const u32 line_b = dst_2 - dst_1;
+ const u32 excess = std::max<s32>(0, line_a - src_line + src_1);
+ return {line_b - (excess * line_b) / line_a, excess};
+}
+
void Fermi2D::HandleSurfaceCopy() {
LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}",
static_cast<u32>(regs.operation));
@@ -47,10 +54,27 @@ void Fermi2D::HandleSurfaceCopy() {
src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width);
src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height);
}
+ u32 dst_blit_x2 = regs.blit_dst_x + regs.blit_dst_width;
+ u32 dst_blit_y2 = regs.blit_dst_y + regs.blit_dst_height;
+ const auto [new_dst_w, src_excess_x] =
+ DelimitLine(src_blit_x1, src_blit_x2, regs.blit_dst_x, dst_blit_x2, regs.src.width);
+ const auto [new_dst_h, src_excess_y] =
+ DelimitLine(src_blit_y1, src_blit_y2, regs.blit_dst_y, dst_blit_y2, regs.src.height);
+ dst_blit_x2 = new_dst_w + regs.blit_dst_x;
+ src_blit_x2 = src_blit_x2 - src_excess_x;
+ dst_blit_y2 = new_dst_h + regs.blit_dst_y;
+ src_blit_y2 = src_blit_y2 - src_excess_y;
+ const auto [new_src_w, dst_excess_x] =
+ DelimitLine(regs.blit_dst_x, dst_blit_x2, src_blit_x1, src_blit_x2, regs.dst.width);
+ const auto [new_src_h, dst_excess_y] =
+ DelimitLine(regs.blit_dst_y, dst_blit_y2, src_blit_y1, src_blit_y2, regs.dst.height);
+ src_blit_x2 = new_src_w + src_blit_x1;
+ dst_blit_x2 = dst_blit_x2 - dst_excess_x;
+ src_blit_y2 = new_src_h + src_blit_y1;
+ dst_blit_y2 = dst_blit_y2 - dst_excess_y;
const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
- const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y,
- regs.blit_dst_x + regs.blit_dst_width,
- regs.blit_dst_y + regs.blit_dst_height};
+ const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2,
+ dst_blit_y2};
Config copy_config;
copy_config.operation = regs.operation;
copy_config.filter = regs.blit_control.filter;
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 0901cf2fa..dba342c70 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -99,19 +99,19 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0x80);
+ INSERT_UNION_PADDING_WORDS(0x80);
Surface dst;
- INSERT_PADDING_WORDS(2);
+ INSERT_UNION_PADDING_WORDS(2);
Surface src;
- INSERT_PADDING_WORDS(0x15);
+ INSERT_UNION_PADDING_WORDS(0x15);
Operation operation;
- INSERT_PADDING_WORDS(0x177);
+ INSERT_UNION_PADDING_WORDS(0x177);
union {
u32 raw;
@@ -119,7 +119,7 @@ public:
BitField<4, 1, Filter> filter;
} blit_control;
- INSERT_PADDING_WORDS(0x8);
+ INSERT_UNION_PADDING_WORDS(0x8);
u32 blit_dst_x;
u32 blit_dst_y;
@@ -130,7 +130,7 @@ public:
u64 blit_src_x;
u64 blit_src_y;
- INSERT_PADDING_WORDS(0x21);
+ INSERT_UNION_PADDING_WORDS(0x21);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index b185c98c7..5259d92bd 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -51,7 +51,7 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0x60);
+ INSERT_UNION_PADDING_WORDS(0x60);
Upload::Registers upload;
@@ -63,7 +63,7 @@ public:
u32 data_upload;
- INSERT_PADDING_WORDS(0x3F);
+ INSERT_UNION_PADDING_WORDS(0x3F);
struct {
u32 address;
@@ -72,11 +72,11 @@ public:
}
} launch_desc_loc;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
u32 launch;
- INSERT_PADDING_WORDS(0x4A7);
+ INSERT_UNION_PADDING_WORDS(0x4A7);
struct {
u32 address_high;
@@ -88,7 +88,7 @@ public:
}
} tsc;
- INSERT_PADDING_WORDS(0x3);
+ INSERT_UNION_PADDING_WORDS(0x3);
struct {
u32 address_high;
@@ -100,7 +100,7 @@ public:
}
} tic;
- INSERT_PADDING_WORDS(0x22);
+ INSERT_UNION_PADDING_WORDS(0x22);
struct {
u32 address_high;
@@ -111,11 +111,11 @@ public:
}
} code_loc;
- INSERT_PADDING_WORDS(0x3FE);
+ INSERT_UNION_PADDING_WORDS(0x3FE);
u32 tex_cb_index;
- INSERT_PADDING_WORDS(0x374);
+ INSERT_UNION_PADDING_WORDS(0x374);
};
std::array<u32, NUM_REGS> reg_array;
};
@@ -179,7 +179,7 @@ public:
};
INSERT_PADDING_WORDS(0x11);
- } launch_description;
+ } launch_description{};
struct {
u32 write_offset = 0;
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index e0e25c321..396fb6e86 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -45,7 +45,7 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0x60);
+ INSERT_UNION_PADDING_WORDS(0x60);
Upload::Registers upload;
@@ -57,7 +57,7 @@ public:
u32 data;
- INSERT_PADDING_WORDS(0x11);
+ INSERT_UNION_PADDING_WORDS(0x11);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 8cc842684..1aa7c274f 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -496,7 +496,7 @@ public:
Equation equation_a;
Factor factor_source_a;
Factor factor_dest_a;
- INSERT_PADDING_WORDS(1);
+ INSERT_UNION_PADDING_WORDS(1);
};
struct RenderTargetConfig {
@@ -517,7 +517,7 @@ public:
};
u32 layer_stride;
u32 base_layer;
- INSERT_PADDING_WORDS(7);
+ INSERT_UNION_PADDING_WORDS(7);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -542,7 +542,7 @@ public:
f32 translate_x;
f32 translate_y;
f32 translate_z;
- INSERT_PADDING_WORDS(2);
+ INSERT_UNION_PADDING_WORDS(2);
Common::Rectangle<s32> GetRect() const {
return {
@@ -606,7 +606,7 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0x45);
+ INSERT_UNION_PADDING_WORDS(0x45);
struct {
u32 upload_address;
@@ -615,7 +615,7 @@ public:
u32 bind;
} macros;
- INSERT_PADDING_WORDS(0x17);
+ INSERT_UNION_PADDING_WORDS(0x17);
Upload::Registers upload;
struct {
@@ -626,7 +626,7 @@ public:
u32 data_upload;
- INSERT_PADDING_WORDS(0x44);
+ INSERT_UNION_PADDING_WORDS(0x44);
struct {
union {
@@ -636,11 +636,11 @@ public:
};
} sync_info;
- INSERT_PADDING_WORDS(0x11E);
+ INSERT_UNION_PADDING_WORDS(0x11E);
u32 tfb_enabled;
- INSERT_PADDING_WORDS(0x2E);
+ INSERT_UNION_PADDING_WORDS(0x2E);
std::array<RenderTargetConfig, NumRenderTargets> rt;
@@ -648,49 +648,49 @@ public:
std::array<ViewPort, NumViewports> viewports;
- INSERT_PADDING_WORDS(0x1D);
+ INSERT_UNION_PADDING_WORDS(0x1D);
struct {
u32 first;
u32 count;
} vertex_buffer;
- INSERT_PADDING_WORDS(1);
+ INSERT_UNION_PADDING_WORDS(1);
float clear_color[4];
float clear_depth;
- INSERT_PADDING_WORDS(0x3);
+ INSERT_UNION_PADDING_WORDS(0x3);
s32 clear_stencil;
- INSERT_PADDING_WORDS(0x7);
+ INSERT_UNION_PADDING_WORDS(0x7);
u32 polygon_offset_point_enable;
u32 polygon_offset_line_enable;
u32 polygon_offset_fill_enable;
- INSERT_PADDING_WORDS(0xD);
+ INSERT_UNION_PADDING_WORDS(0xD);
std::array<ScissorTest, NumViewports> scissor_test;
- INSERT_PADDING_WORDS(0x15);
+ INSERT_UNION_PADDING_WORDS(0x15);
s32 stencil_back_func_ref;
u32 stencil_back_mask;
u32 stencil_back_func_mask;
- INSERT_PADDING_WORDS(0xC);
+ INSERT_UNION_PADDING_WORDS(0xC);
u32 color_mask_common;
- INSERT_PADDING_WORDS(0x6);
+ INSERT_UNION_PADDING_WORDS(0x6);
u32 rt_separate_frag_data;
f32 depth_bounds[2];
- INSERT_PADDING_WORDS(0xA);
+ INSERT_UNION_PADDING_WORDS(0xA);
struct {
u32 address_high;
@@ -710,7 +710,7 @@ public:
}
} zeta;
- INSERT_PADDING_WORDS(0x41);
+ INSERT_UNION_PADDING_WORDS(0x41);
union {
BitField<0, 4, u32> stencil;
@@ -719,11 +719,11 @@ public:
BitField<12, 4, u32> viewport;
} clear_flags;
- INSERT_PADDING_WORDS(0x19);
+ INSERT_UNION_PADDING_WORDS(0x19);
std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
- INSERT_PADDING_WORDS(0xF);
+ INSERT_UNION_PADDING_WORDS(0xF);
struct {
union {
@@ -746,16 +746,16 @@ public:
}
} rt_control;
- INSERT_PADDING_WORDS(0x2);
+ INSERT_UNION_PADDING_WORDS(0x2);
u32 zeta_width;
u32 zeta_height;
- INSERT_PADDING_WORDS(0x27);
+ INSERT_UNION_PADDING_WORDS(0x27);
u32 depth_test_enable;
- INSERT_PADDING_WORDS(0x5);
+ INSERT_UNION_PADDING_WORDS(0x5);
u32 independent_blend_enable;
@@ -763,7 +763,7 @@ public:
u32 alpha_test_enabled;
- INSERT_PADDING_WORDS(0x6);
+ INSERT_UNION_PADDING_WORDS(0x6);
u32 d3d_cull_mode;
@@ -777,7 +777,7 @@ public:
float b;
float a;
} blend_color;
- INSERT_PADDING_WORDS(0x4);
+ INSERT_UNION_PADDING_WORDS(0x4);
struct {
u32 separate_alpha;
@@ -786,7 +786,7 @@ public:
Blend::Factor factor_dest_rgb;
Blend::Equation equation_a;
Blend::Factor factor_source_a;
- INSERT_PADDING_WORDS(1);
+ INSERT_UNION_PADDING_WORDS(1);
Blend::Factor factor_dest_a;
u32 enable_common;
@@ -802,7 +802,7 @@ public:
u32 stencil_front_func_mask;
u32 stencil_front_mask;
- INSERT_PADDING_WORDS(0x2);
+ INSERT_UNION_PADDING_WORDS(0x2);
u32 frag_color_clamp;
@@ -811,12 +811,12 @@ public:
BitField<4, 1, u32> triangle_rast_flip;
} screen_y_control;
- INSERT_PADDING_WORDS(0x21);
+ INSERT_UNION_PADDING_WORDS(0x21);
u32 vb_element_base;
u32 vb_base_instance;
- INSERT_PADDING_WORDS(0x35);
+ INSERT_UNION_PADDING_WORDS(0x35);
union {
BitField<0, 1, u32> c0;
@@ -829,11 +829,11 @@ public:
BitField<7, 1, u32> c7;
} clip_distance_enabled;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
float point_size;
- INSERT_PADDING_WORDS(0x7);
+ INSERT_UNION_PADDING_WORDS(0x7);
u32 zeta_enable;
@@ -842,7 +842,7 @@ public:
BitField<4, 1, u32> alpha_to_one;
} multisample_control;
- INSERT_PADDING_WORDS(0x4);
+ INSERT_UNION_PADDING_WORDS(0x4);
struct {
u32 address_high;
@@ -866,11 +866,11 @@ public:
}
} tsc;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
float polygon_offset_factor;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
struct {
u32 tic_address_high;
@@ -883,7 +883,7 @@ public:
}
} tic;
- INSERT_PADDING_WORDS(0x5);
+ INSERT_UNION_PADDING_WORDS(0x5);
u32 stencil_two_side_enable;
StencilOp stencil_back_op_fail;
@@ -891,13 +891,13 @@ public:
StencilOp stencil_back_op_zpass;
ComparisonOp stencil_back_func_func;
- INSERT_PADDING_WORDS(0x4);
+ INSERT_UNION_PADDING_WORDS(0x4);
u32 framebuffer_srgb;
float polygon_offset_units;
- INSERT_PADDING_WORDS(0x11);
+ INSERT_UNION_PADDING_WORDS(0x11);
union {
BitField<2, 1, u32> coord_origin;
@@ -913,7 +913,7 @@ public:
(static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
}
} code_address;
- INSERT_PADDING_WORDS(1);
+ INSERT_UNION_PADDING_WORDS(1);
struct {
u32 vertex_end_gl;
@@ -925,14 +925,14 @@ public:
};
} draw;
- INSERT_PADDING_WORDS(0xA);
+ INSERT_UNION_PADDING_WORDS(0xA);
struct {
u32 enabled;
u32 index;
} primitive_restart;
- INSERT_PADDING_WORDS(0x5F);
+ INSERT_UNION_PADDING_WORDS(0x5F);
struct {
u32 start_addr_high;
@@ -973,9 +973,9 @@ public:
}
} index_array;
- INSERT_PADDING_WORDS(0x7);
+ INSERT_UNION_PADDING_WORDS(0x7);
- INSERT_PADDING_WORDS(0x1F);
+ INSERT_UNION_PADDING_WORDS(0x1F);
float polygon_offset_clamp;
@@ -989,17 +989,17 @@ public:
}
} instanced_arrays;
- INSERT_PADDING_WORDS(0x6);
+ INSERT_UNION_PADDING_WORDS(0x6);
Cull cull;
u32 pixel_center_integer;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
u32 viewport_transform_enabled;
- INSERT_PADDING_WORDS(0x3);
+ INSERT_UNION_PADDING_WORDS(0x3);
union {
BitField<0, 1, u32> depth_range_0_1;
@@ -1007,13 +1007,13 @@ public:
BitField<4, 1, u32> depth_clamp_far;
} view_volume_clip_control;
- INSERT_PADDING_WORDS(0x21);
+ INSERT_UNION_PADDING_WORDS(0x21);
struct {
u32 enable;
LogicOperation operation;
} logic_op;
- INSERT_PADDING_WORDS(0x1);
+ INSERT_UNION_PADDING_WORDS(0x1);
union {
u32 raw;
@@ -1026,9 +1026,9 @@ public:
BitField<6, 4, u32> RT;
BitField<10, 11, u32> layer;
} clear_buffers;
- INSERT_PADDING_WORDS(0xB);
+ INSERT_UNION_PADDING_WORDS(0xB);
std::array<ColorMask, NumRenderTargets> color_mask;
- INSERT_PADDING_WORDS(0x38);
+ INSERT_UNION_PADDING_WORDS(0x38);
struct {
u32 query_address_high;
@@ -1050,7 +1050,7 @@ public:
}
} query;
- INSERT_PADDING_WORDS(0x3C);
+ INSERT_UNION_PADDING_WORDS(0x3C);
struct {
union {
@@ -1090,10 +1090,10 @@ public:
BitField<4, 4, ShaderProgram> program;
};
u32 offset;
- INSERT_PADDING_WORDS(14);
+ INSERT_UNION_PADDING_WORDS(14);
} shader_config[MaxShaderProgram];
- INSERT_PADDING_WORDS(0x60);
+ INSERT_UNION_PADDING_WORDS(0x60);
u32 firmware[0x20];
@@ -1110,7 +1110,7 @@ public:
}
} const_buffer;
- INSERT_PADDING_WORDS(0x10);
+ INSERT_UNION_PADDING_WORDS(0x10);
struct {
union {
@@ -1118,14 +1118,14 @@ public:
BitField<0, 1, u32> valid;
BitField<4, 5, u32> index;
};
- INSERT_PADDING_WORDS(7);
+ INSERT_UNION_PADDING_WORDS(7);
} cb_bind[MaxShaderStage];
- INSERT_PADDING_WORDS(0x56);
+ INSERT_UNION_PADDING_WORDS(0x56);
u32 tex_cb_index;
- INSERT_PADDING_WORDS(0x395);
+ INSERT_UNION_PADDING_WORDS(0x395);
struct {
/// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1137,14 +1137,14 @@ public:
}
} ssbo_info;
- INSERT_PADDING_WORDS(0x11);
+ INSERT_UNION_PADDING_WORDS(0x11);
struct {
u32 address[MaxShaderStage];
u32 size[MaxShaderStage];
} tex_info_buffers;
- INSERT_PADDING_WORDS(0xCC);
+ INSERT_UNION_PADDING_WORDS(0xCC);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 93808a9bb..4f40d1d1f 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -94,7 +94,7 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0xC0);
+ INSERT_UNION_PADDING_WORDS(0xC0);
struct {
union {
@@ -112,7 +112,7 @@ public:
};
} exec;
- INSERT_PADDING_WORDS(0x3F);
+ INSERT_UNION_PADDING_WORDS(0x3F);
struct {
u32 address_high;
@@ -139,7 +139,7 @@ public:
u32 x_count;
u32 y_count;
- INSERT_PADDING_WORDS(0xB8);
+ INSERT_UNION_PADDING_WORDS(0xB8);
u32 const0;
u32 const1;
@@ -162,11 +162,11 @@ public:
Parameters dst_params;
- INSERT_PADDING_WORDS(1);
+ INSERT_UNION_PADDING_WORDS(1);
Parameters src_params;
- INSERT_PADDING_WORDS(0x13);
+ INSERT_UNION_PADDING_WORDS(0x13);
};
std::array<u32, NUM_REGS> reg_array;
};
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d3d05a866..8f6bc76eb 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1238,6 +1238,32 @@ union Instruction {
} tld4;
union {
+ BitField<35, 1, u64> ndv_flag;
+ BitField<49, 1, u64> nodep_flag;
+ BitField<50, 1, u64> dc_flag;
+ BitField<33, 2, u64> info;
+ BitField<37, 2, u64> component;
+
+ bool UsesMiscMode(TextureMiscMode mode) const {
+ switch (mode) {
+ case TextureMiscMode::NDV:
+ return ndv_flag != 0;
+ case TextureMiscMode::NODEP:
+ return nodep_flag != 0;
+ case TextureMiscMode::DC:
+ return dc_flag != 0;
+ case TextureMiscMode::AOFFI:
+ return info == 1;
+ case TextureMiscMode::PTP:
+ return info == 2;
+ default:
+ break;
+ }
+ return false;
+ }
+ } tld4_b;
+
+ union {
BitField<49, 1, u64> nodep_flag;
BitField<50, 1, u64> dc_flag;
BitField<51, 1, u64> aoffi_flag;
@@ -1590,7 +1616,8 @@ public:
TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
TLD, // Texture Load
TLDS, // Texture Load with scalar/non-vec4 source/destinations
- TLD4, // Texture Load 4
+ TLD4, // Texture Gather 4
+ TLD4_B, // Texture Gather 4 Bindless
TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
TMML_B, // Texture Mip Map Level
TMML, // Texture Mip Map Level
@@ -1881,6 +1908,7 @@ private:
INST("11011100--11----", Id::TLD, Type::Texture, "TLD"),
INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"),
INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"),
+ INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"),
INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
index e86a7f04a..bc80661d8 100644
--- a/src/video_core/engines/shader_header.h
+++ b/src/video_core/engines/shader_header.h
@@ -38,37 +38,37 @@ struct Header {
BitField<26, 1, u32> does_load_or_store;
BitField<27, 1, u32> does_fp64;
BitField<28, 4, u32> stream_out_mask;
- } common0;
+ } common0{};
union {
BitField<0, 24, u32> shader_local_memory_low_size;
BitField<24, 8, u32> per_patch_attribute_count;
- } common1;
+ } common1{};
union {
BitField<0, 24, u32> shader_local_memory_high_size;
BitField<24, 8, u32> threads_per_input_primitive;
- } common2;
+ } common2{};
union {
BitField<0, 24, u32> shader_local_memory_crs_size;
BitField<24, 4, OutputTopology> output_topology;
BitField<28, 4, u32> reserved;
- } common3;
+ } common3{};
union {
BitField<0, 12, u32> max_output_vertices;
BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
BitField<24, 4, u32> reserved;
BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
- } common4;
+ } common4{};
union {
struct {
- INSERT_PADDING_BYTES(3); // ImapSystemValuesA
- INSERT_PADDING_BYTES(1); // ImapSystemValuesB
- INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
- INSERT_PADDING_BYTES(2); // ImapColor
+ INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
+ INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
+ INSERT_UNION_PADDING_BYTES(16); // ImapGenericVector[32]
+ INSERT_UNION_PADDING_BYTES(2); // ImapColor
union {
BitField<0, 8, u16> clip_distances;
BitField<8, 1, u16> point_sprite_s;
@@ -79,20 +79,20 @@ struct Header {
BitField<14, 1, u16> instance_id;
BitField<15, 1, u16> vertex_id;
};
- INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10]
- INSERT_PADDING_BYTES(1); // ImapReserved
- INSERT_PADDING_BYTES(3); // OmapSystemValuesA
- INSERT_PADDING_BYTES(1); // OmapSystemValuesB
- INSERT_PADDING_BYTES(16); // OmapGenericVector[32]
- INSERT_PADDING_BYTES(2); // OmapColor
- INSERT_PADDING_BYTES(2); // OmapSystemValuesC
- INSERT_PADDING_BYTES(5); // OmapFixedFncTexture[10]
- INSERT_PADDING_BYTES(1); // OmapReserved
+ INSERT_UNION_PADDING_BYTES(5); // ImapFixedFncTexture[10]
+ INSERT_UNION_PADDING_BYTES(1); // ImapReserved
+ INSERT_UNION_PADDING_BYTES(3); // OmapSystemValuesA
+ INSERT_UNION_PADDING_BYTES(1); // OmapSystemValuesB
+ INSERT_UNION_PADDING_BYTES(16); // OmapGenericVector[32]
+ INSERT_UNION_PADDING_BYTES(2); // OmapColor
+ INSERT_UNION_PADDING_BYTES(2); // OmapSystemValuesC
+ INSERT_UNION_PADDING_BYTES(5); // OmapFixedFncTexture[10]
+ INSERT_UNION_PADDING_BYTES(1); // OmapReserved
} vtg;
struct {
- INSERT_PADDING_BYTES(3); // ImapSystemValuesA
- INSERT_PADDING_BYTES(1); // ImapSystemValuesB
+ INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
+ INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
union {
BitField<0, 2, AttributeUse> x;
BitField<2, 2, AttributeUse> y;
@@ -100,10 +100,10 @@ struct Header {
BitField<6, 2, AttributeUse> z;
u8 raw;
} imap_generic_vector[32];
- INSERT_PADDING_BYTES(2); // ImapColor
- INSERT_PADDING_BYTES(2); // ImapSystemValuesC
- INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10]
- INSERT_PADDING_BYTES(2); // ImapReserved
+ INSERT_UNION_PADDING_BYTES(2); // ImapColor
+ INSERT_UNION_PADDING_BYTES(2); // ImapSystemValuesC
+ INSERT_UNION_PADDING_BYTES(10); // ImapFixedFncTexture[10]
+ INSERT_UNION_PADDING_BYTES(2); // ImapReserved
struct {
u32 target;
union {
@@ -139,6 +139,8 @@ struct Header {
return result;
}
} ps;
+
+ std::array<u32, 0xF> raw{};
};
u64 GetLocalMemorySize() const {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index dbca19f35..ecc338ae9 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -207,7 +207,7 @@ public:
union {
struct {
- INSERT_PADDING_WORDS(0x4);
+ INSERT_UNION_PADDING_WORDS(0x4);
struct {
u32 address_high;
u32 address_low;
@@ -220,12 +220,12 @@ public:
u32 semaphore_sequence;
u32 semaphore_trigger;
- INSERT_PADDING_WORDS(0xC);
+ INSERT_UNION_PADDING_WORDS(0xC);
// The puser and the puller share the reference counter, the pusher only has read
// access
u32 reference_count;
- INSERT_PADDING_WORDS(0x5);
+ INSERT_UNION_PADDING_WORDS(0x5);
u32 semaphore_acquire;
u32 semaphore_release;
@@ -234,7 +234,7 @@ public:
BitField<4, 4, u32> operation;
BitField<8, 8, u32> id;
} fence_action;
- INSERT_PADDING_WORDS(0xE2);
+ INSERT_UNION_PADDING_WORDS(0xE2);
// Puller state
u32 acquire_mode;
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
new file mode 100644
index 000000000..b230dcc18
--- /dev/null
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -0,0 +1,63 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <mutex>
+
+#include <boost/icl/interval_map.hpp>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "core/memory.h"
+#include "video_core/rasterizer_accelerated.h"
+
+namespace VideoCore {
+
+namespace {
+
+template <typename Map, typename Interval>
+constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
+ return boost::make_iterator_range(map.equal_range(interval));
+}
+
+} // Anonymous namespace
+
+RasterizerAccelerated::RasterizerAccelerated() = default;
+
+RasterizerAccelerated::~RasterizerAccelerated() = default;
+
+void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
+ std::lock_guard lock{pages_mutex};
+ const u64 page_start{addr >> Memory::PAGE_BITS};
+ const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
+
+ // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
+ // subtract after iterating
+ const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
+ if (delta > 0) {
+ cached_pages.add({pages_interval, delta});
+ }
+
+ for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
+ const auto interval = pair.first & pages_interval;
+ const int count = pair.second;
+
+ const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
+ const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
+ const u64 interval_size = interval_end_addr - interval_start_addr;
+
+ if (delta > 0 && count == delta) {
+ Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
+ } else if (delta < 0 && count == -delta) {
+ Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
+ } else {
+ ASSERT(count >= 0);
+ }
+ }
+
+ if (delta < 0) {
+ cached_pages.add({pages_interval, delta});
+ }
+}
+
+} // namespace VideoCore
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
new file mode 100644
index 000000000..8f7e3547e
--- /dev/null
+++ b/src/video_core/rasterizer_accelerated.h
@@ -0,0 +1,31 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <mutex>
+
+#include <boost/icl/interval_map.hpp>
+
+#include "common/common_types.h"
+#include "video_core/rasterizer_interface.h"
+
+namespace VideoCore {
+
+/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
+class RasterizerAccelerated : public RasterizerInterface {
+public:
+ explicit RasterizerAccelerated();
+ ~RasterizerAccelerated() override;
+
+ void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
+
+private:
+ using CachedPageMap = boost::icl::interval_map<u64, int>;
+ CachedPageMap cached_pages;
+
+ std::mutex pages_mutex;
+};
+
+} // namespace VideoCore
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 35fc094a8..d1e147db8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -68,8 +68,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
ScreenInfo& info)
: texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device},
system{system}, screen_info{info}, buffer_cache{*this, system, STREAM_BUFFER_SIZE} {
- OpenGLState::ApplyDefaultState();
-
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
state.draw.shader_program = 0;
state.Apply();
@@ -342,42 +340,6 @@ std::size_t RasterizerOpenGL::CalculateIndexBufferSize() const {
static_cast<std::size_t>(regs.index_array.FormatSizeInBytes());
}
-template <typename Map, typename Interval>
-static constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
- return boost::make_iterator_range(map.equal_range(interval));
-}
-
-void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
- std::lock_guard lock{pages_mutex};
- const u64 page_start{addr >> Memory::PAGE_BITS};
- const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
-
- // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
- // subtract after iterating
- const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
- if (delta > 0)
- cached_pages.add({pages_interval, delta});
-
- for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
- const auto interval = pair.first & pages_interval;
- const int count = pair.second;
-
- const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS;
- const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS;
- const u64 interval_size = interval_end_addr - interval_start_addr;
-
- if (delta > 0 && count == delta)
- Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
- else if (delta < 0 && count == -delta)
- Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
- else
- ASSERT(count >= 0);
- }
-
- if (delta < 0)
- cached_pages.add({pages_interval, delta});
-}
-
void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) {
shader_cache.LoadDiskCache(stop_loading, callback);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index c24a02d71..bd6fe5c3a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -9,17 +9,16 @@
#include <cstddef>
#include <map>
#include <memory>
-#include <mutex>
#include <optional>
#include <tuple>
#include <utility>
-#include <boost/icl/interval_map.hpp>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/engines/const_buffer_info.h"
#include "video_core/engines/maxwell_3d.h"
+#include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
@@ -52,7 +51,7 @@ namespace OpenGL {
struct ScreenInfo;
struct DrawParameters;
-class RasterizerOpenGL : public VideoCore::RasterizerInterface {
+class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
public:
explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
ScreenInfo& info);
@@ -73,7 +72,6 @@ public:
const Tegra::Engines::Fermi2D::Config& copy_config) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
- void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
void LoadDiskResources(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -228,11 +226,6 @@ private:
AccelDraw accelerate_draw = AccelDraw::Disabled;
OGLFramebuffer clear_framebuffer;
-
- using CachedPageMap = boost::icl::interval_map<u64, int>;
- CachedPageMap cached_pages;
-
- std::mutex pages_mutex;
};
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index bf86b5a0b..f25148362 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <iterator>
#include <glad/glad.h>
#include "common/assert.h"
@@ -69,147 +70,29 @@ void Enable(GLenum cap, GLuint index, bool enable) {
}
void Enable(GLenum cap, bool& current_value, bool new_value) {
- if (UpdateValue(current_value, new_value))
+ if (UpdateValue(current_value, new_value)) {
Enable(cap, new_value);
+ }
}
void Enable(GLenum cap, GLuint index, bool& current_value, bool new_value) {
- if (UpdateValue(current_value, new_value))
+ if (UpdateValue(current_value, new_value)) {
Enable(cap, index, new_value);
-}
-
-} // namespace
-
-OpenGLState::OpenGLState() {
- // These all match default OpenGL values
- framebuffer_srgb.enabled = false;
-
- multisample_control.alpha_to_coverage = false;
- multisample_control.alpha_to_one = false;
-
- cull.enabled = false;
- cull.mode = GL_BACK;
- cull.front_face = GL_CCW;
-
- depth.test_enabled = false;
- depth.test_func = GL_LESS;
- depth.write_mask = GL_TRUE;
-
- primitive_restart.enabled = false;
- primitive_restart.index = 0;
-
- for (auto& item : color_mask) {
- item.red_enabled = GL_TRUE;
- item.green_enabled = GL_TRUE;
- item.blue_enabled = GL_TRUE;
- item.alpha_enabled = GL_TRUE;
}
+}
- const auto ResetStencil = [](auto& config) {
- config.test_func = GL_ALWAYS;
- config.test_ref = 0;
- config.test_mask = 0xFFFFFFFF;
- config.write_mask = 0xFFFFFFFF;
- config.action_depth_fail = GL_KEEP;
- config.action_depth_pass = GL_KEEP;
- config.action_stencil_fail = GL_KEEP;
- };
- stencil.test_enabled = false;
- ResetStencil(stencil.front);
- ResetStencil(stencil.back);
-
- for (auto& item : viewports) {
- item.x = 0;
- item.y = 0;
- item.width = 0;
- item.height = 0;
- item.depth_range_near = 0.0f;
- item.depth_range_far = 1.0f;
- item.scissor.enabled = false;
- item.scissor.x = 0;
- item.scissor.y = 0;
- item.scissor.width = 0;
- item.scissor.height = 0;
- }
-
- for (auto& item : blend) {
- item.enabled = true;
- item.rgb_equation = GL_FUNC_ADD;
- item.a_equation = GL_FUNC_ADD;
- item.src_rgb_func = GL_ONE;
- item.dst_rgb_func = GL_ZERO;
- item.src_a_func = GL_ONE;
- item.dst_a_func = GL_ZERO;
- }
-
- independant_blend.enabled = false;
-
- blend_color.red = 0.0f;
- blend_color.green = 0.0f;
- blend_color.blue = 0.0f;
- blend_color.alpha = 0.0f;
-
- logic_op.enabled = false;
- logic_op.operation = GL_COPY;
-
- draw.read_framebuffer = 0;
- draw.draw_framebuffer = 0;
- draw.vertex_array = 0;
- draw.shader_program = 0;
- draw.program_pipeline = 0;
-
- clip_distance = {};
-
- point.size = 1;
-
- fragment_color_clamp.enabled = false;
-
- depth_clamp.far_plane = false;
- depth_clamp.near_plane = false;
-
- polygon_offset.fill_enable = false;
- polygon_offset.line_enable = false;
- polygon_offset.point_enable = false;
- polygon_offset.factor = 0.0f;
- polygon_offset.units = 0.0f;
- polygon_offset.clamp = 0.0f;
+} // Anonymous namespace
- alpha_test.enabled = false;
- alpha_test.func = GL_ALWAYS;
- alpha_test.ref = 0.0f;
-}
+OpenGLState::OpenGLState() = default;
void OpenGLState::SetDefaultViewports() {
- for (auto& item : viewports) {
- item.x = 0;
- item.y = 0;
- item.width = 0;
- item.height = 0;
- item.depth_range_near = 0.0f;
- item.depth_range_far = 1.0f;
- item.scissor.enabled = false;
- item.scissor.x = 0;
- item.scissor.y = 0;
- item.scissor.width = 0;
- item.scissor.height = 0;
- }
+ viewports.fill(Viewport{});
depth_clamp.far_plane = false;
depth_clamp.near_plane = false;
}
-void OpenGLState::ApplyDefaultState() {
- glEnable(GL_BLEND);
- glDisable(GL_FRAMEBUFFER_SRGB);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_PRIMITIVE_RESTART);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_COLOR_LOGIC_OP);
- glDisable(GL_SCISSOR_TEST);
-}
-
-void OpenGLState::ApplyFramebufferState() const {
+void OpenGLState::ApplyFramebufferState() {
if (UpdateValue(cur_state.draw.read_framebuffer, draw.read_framebuffer)) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
}
@@ -218,52 +101,52 @@ void OpenGLState::ApplyFramebufferState() const {
}
}
-void OpenGLState::ApplyVertexArrayState() const {
+void OpenGLState::ApplyVertexArrayState() {
if (UpdateValue(cur_state.draw.vertex_array, draw.vertex_array)) {
glBindVertexArray(draw.vertex_array);
}
}
-void OpenGLState::ApplyShaderProgram() const {
+void OpenGLState::ApplyShaderProgram() {
if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) {
glUseProgram(draw.shader_program);
}
}
-void OpenGLState::ApplyProgramPipeline() const {
+void OpenGLState::ApplyProgramPipeline() {
if (UpdateValue(cur_state.draw.program_pipeline, draw.program_pipeline)) {
glBindProgramPipeline(draw.program_pipeline);
}
}
-void OpenGLState::ApplyClipDistances() const {
+void OpenGLState::ApplyClipDistances() {
for (std::size_t i = 0; i < clip_distance.size(); ++i) {
Enable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i), cur_state.clip_distance[i],
clip_distance[i]);
}
}
-void OpenGLState::ApplyPointSize() const {
+void OpenGLState::ApplyPointSize() {
if (UpdateValue(cur_state.point.size, point.size)) {
glPointSize(point.size);
}
}
-void OpenGLState::ApplyFragmentColorClamp() const {
+void OpenGLState::ApplyFragmentColorClamp() {
if (UpdateValue(cur_state.fragment_color_clamp.enabled, fragment_color_clamp.enabled)) {
glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
fragment_color_clamp.enabled ? GL_TRUE : GL_FALSE);
}
}
-void OpenGLState::ApplyMultisample() const {
+void OpenGLState::ApplyMultisample() {
Enable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur_state.multisample_control.alpha_to_coverage,
multisample_control.alpha_to_coverage);
Enable(GL_SAMPLE_ALPHA_TO_ONE, cur_state.multisample_control.alpha_to_one,
multisample_control.alpha_to_one);
}
-void OpenGLState::ApplyDepthClamp() const {
+void OpenGLState::ApplyDepthClamp() {
if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
return;
@@ -276,7 +159,7 @@ void OpenGLState::ApplyDepthClamp() const {
Enable(GL_DEPTH_CLAMP, depth_clamp.far_plane || depth_clamp.near_plane);
}
-void OpenGLState::ApplySRgb() const {
+void OpenGLState::ApplySRgb() {
if (cur_state.framebuffer_srgb.enabled == framebuffer_srgb.enabled)
return;
cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled;
@@ -287,7 +170,7 @@ void OpenGLState::ApplySRgb() const {
}
}
-void OpenGLState::ApplyCulling() const {
+void OpenGLState::ApplyCulling() {
Enable(GL_CULL_FACE, cur_state.cull.enabled, cull.enabled);
if (UpdateValue(cur_state.cull.mode, cull.mode)) {
@@ -299,7 +182,12 @@ void OpenGLState::ApplyCulling() const {
}
}
-void OpenGLState::ApplyColorMask() const {
+void OpenGLState::ApplyColorMask() {
+ if (!dirty.color_mask) {
+ return;
+ }
+ dirty.color_mask = false;
+
for (std::size_t i = 0; i < Maxwell::NumRenderTargets; ++i) {
const auto& updated = color_mask[i];
auto& current = cur_state.color_mask[i];
@@ -314,7 +202,7 @@ void OpenGLState::ApplyColorMask() const {
}
}
-void OpenGLState::ApplyDepth() const {
+void OpenGLState::ApplyDepth() {
Enable(GL_DEPTH_TEST, cur_state.depth.test_enabled, depth.test_enabled);
if (cur_state.depth.test_func != depth.test_func) {
@@ -328,7 +216,7 @@ void OpenGLState::ApplyDepth() const {
}
}
-void OpenGLState::ApplyPrimitiveRestart() const {
+void OpenGLState::ApplyPrimitiveRestart() {
Enable(GL_PRIMITIVE_RESTART, cur_state.primitive_restart.enabled, primitive_restart.enabled);
if (cur_state.primitive_restart.index != primitive_restart.index) {
@@ -337,7 +225,12 @@ void OpenGLState::ApplyPrimitiveRestart() const {
}
}
-void OpenGLState::ApplyStencilTest() const {
+void OpenGLState::ApplyStencilTest() {
+ if (!dirty.stencil_state) {
+ return;
+ }
+ dirty.stencil_state = false;
+
Enable(GL_STENCIL_TEST, cur_state.stencil.test_enabled, stencil.test_enabled);
const auto ConfigStencil = [](GLenum face, const auto& config, auto& current) {
@@ -366,7 +259,7 @@ void OpenGLState::ApplyStencilTest() const {
ConfigStencil(GL_BACK, stencil.back, cur_state.stencil.back);
}
-void OpenGLState::ApplyViewport() const {
+void OpenGLState::ApplyViewport() {
for (GLuint i = 0; i < static_cast<GLuint>(Maxwell::NumViewports); ++i) {
const auto& updated = viewports[i];
auto& current = cur_state.viewports[i];
@@ -403,7 +296,7 @@ void OpenGLState::ApplyViewport() const {
}
}
-void OpenGLState::ApplyGlobalBlending() const {
+void OpenGLState::ApplyGlobalBlending() {
const Blend& updated = blend[0];
Blend& current = cur_state.blend[0];
@@ -427,7 +320,7 @@ void OpenGLState::ApplyGlobalBlending() const {
}
}
-void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
+void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) {
const Blend& updated = blend[target];
Blend& current = cur_state.blend[target];
@@ -451,7 +344,12 @@ void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const {
}
}
-void OpenGLState::ApplyBlending() const {
+void OpenGLState::ApplyBlending() {
+ if (!dirty.blend_state) {
+ return;
+ }
+ dirty.blend_state = false;
+
if (independant_blend.enabled) {
const bool force = independant_blend.enabled != cur_state.independant_blend.enabled;
for (std::size_t target = 0; target < Maxwell::NumRenderTargets; ++target) {
@@ -470,7 +368,7 @@ void OpenGLState::ApplyBlending() const {
}
}
-void OpenGLState::ApplyLogicOp() const {
+void OpenGLState::ApplyLogicOp() {
Enable(GL_COLOR_LOGIC_OP, cur_state.logic_op.enabled, logic_op.enabled);
if (UpdateValue(cur_state.logic_op.operation, logic_op.operation)) {
@@ -478,7 +376,12 @@ void OpenGLState::ApplyLogicOp() const {
}
}
-void OpenGLState::ApplyPolygonOffset() const {
+void OpenGLState::ApplyPolygonOffset() {
+ if (!dirty.polygon_offset) {
+ return;
+ }
+ dirty.polygon_offset = false;
+
Enable(GL_POLYGON_OFFSET_FILL, cur_state.polygon_offset.fill_enable,
polygon_offset.fill_enable);
Enable(GL_POLYGON_OFFSET_LINE, cur_state.polygon_offset.line_enable,
@@ -499,7 +402,7 @@ void OpenGLState::ApplyPolygonOffset() const {
}
}
-void OpenGLState::ApplyAlphaTest() const {
+void OpenGLState::ApplyAlphaTest() {
Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled);
if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref),
std::tie(alpha_test.func, alpha_test.ref))) {
@@ -507,19 +410,19 @@ void OpenGLState::ApplyAlphaTest() const {
}
}
-void OpenGLState::ApplyTextures() const {
+void OpenGLState::ApplyTextures() {
if (const auto update = UpdateArray(cur_state.textures, textures)) {
glBindTextures(update->first, update->second, textures.data() + update->first);
}
}
-void OpenGLState::ApplySamplers() const {
+void OpenGLState::ApplySamplers() {
if (const auto update = UpdateArray(cur_state.samplers, samplers)) {
glBindSamplers(update->first, update->second, samplers.data() + update->first);
}
}
-void OpenGLState::ApplyImages() const {
+void OpenGLState::ApplyImages() {
if (const auto update = UpdateArray(cur_state.images, images)) {
glBindImageTextures(update->first, update->second, images.data() + update->first);
}
@@ -535,32 +438,20 @@ void OpenGLState::Apply() {
ApplyPointSize();
ApplyFragmentColorClamp();
ApplyMultisample();
- if (dirty.color_mask) {
- ApplyColorMask();
- dirty.color_mask = false;
- }
+ ApplyColorMask();
ApplyDepthClamp();
ApplyViewport();
- if (dirty.stencil_state) {
- ApplyStencilTest();
- dirty.stencil_state = false;
- }
+ ApplyStencilTest();
ApplySRgb();
ApplyCulling();
ApplyDepth();
ApplyPrimitiveRestart();
- if (dirty.blend_state) {
- ApplyBlending();
- dirty.blend_state = false;
- }
+ ApplyBlending();
ApplyLogicOp();
ApplyTextures();
ApplySamplers();
ApplyImages();
- if (dirty.polygon_offset) {
- ApplyPolygonOffset();
- dirty.polygon_offset = false;
- }
+ ApplyPolygonOffset();
ApplyAlphaTest();
}
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index c358d3b38..cca25206b 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -5,168 +5,146 @@
#pragma once
#include <array>
+#include <type_traits>
#include <glad/glad.h>
#include "video_core/engines/maxwell_3d.h"
namespace OpenGL {
-namespace TextureUnits {
-
-struct TextureUnit {
- GLint id;
- constexpr GLenum Enum() const {
- return static_cast<GLenum>(GL_TEXTURE0 + id);
- }
-};
-
-constexpr TextureUnit MaxwellTexture(int unit) {
- return TextureUnit{unit};
-}
-
-constexpr TextureUnit LightingLUT{3};
-constexpr TextureUnit FogLUT{4};
-constexpr TextureUnit ProcTexNoiseLUT{5};
-constexpr TextureUnit ProcTexColorMap{6};
-constexpr TextureUnit ProcTexAlphaMap{7};
-constexpr TextureUnit ProcTexLUT{8};
-constexpr TextureUnit ProcTexDiffLUT{9};
-
-} // namespace TextureUnits
-
class OpenGLState {
public:
struct {
- bool enabled; // GL_FRAMEBUFFER_SRGB
+ bool enabled = false; // GL_FRAMEBUFFER_SRGB
} framebuffer_srgb;
struct {
- bool alpha_to_coverage; // GL_ALPHA_TO_COVERAGE
- bool alpha_to_one; // GL_ALPHA_TO_ONE
+ bool alpha_to_coverage = false; // GL_ALPHA_TO_COVERAGE
+ bool alpha_to_one = false; // GL_ALPHA_TO_ONE
} multisample_control;
struct {
- bool enabled; // GL_CLAMP_FRAGMENT_COLOR_ARB
+ bool enabled = false; // GL_CLAMP_FRAGMENT_COLOR_ARB
} fragment_color_clamp;
struct {
- bool far_plane;
- bool near_plane;
+ bool far_plane = false;
+ bool near_plane = false;
} depth_clamp; // GL_DEPTH_CLAMP
struct {
- bool enabled; // GL_CULL_FACE
- GLenum mode; // GL_CULL_FACE_MODE
- GLenum front_face; // GL_FRONT_FACE
+ bool enabled = false; // GL_CULL_FACE
+ GLenum mode = GL_BACK; // GL_CULL_FACE_MODE
+ GLenum front_face = GL_CCW; // GL_FRONT_FACE
} cull;
struct {
- bool test_enabled; // GL_DEPTH_TEST
- GLenum test_func; // GL_DEPTH_FUNC
- GLboolean write_mask; // GL_DEPTH_WRITEMASK
+ bool test_enabled = false; // GL_DEPTH_TEST
+ GLboolean write_mask = GL_TRUE; // GL_DEPTH_WRITEMASK
+ GLenum test_func = GL_LESS; // GL_DEPTH_FUNC
} depth;
struct {
- bool enabled;
- GLuint index;
+ bool enabled = false;
+ GLuint index = 0;
} primitive_restart; // GL_PRIMITIVE_RESTART
struct ColorMask {
- GLboolean red_enabled;
- GLboolean green_enabled;
- GLboolean blue_enabled;
- GLboolean alpha_enabled;
+ GLboolean red_enabled = GL_TRUE;
+ GLboolean green_enabled = GL_TRUE;
+ GLboolean blue_enabled = GL_TRUE;
+ GLboolean alpha_enabled = GL_TRUE;
};
std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
color_mask; // GL_COLOR_WRITEMASK
struct {
- bool test_enabled; // GL_STENCIL_TEST
+ bool test_enabled = false; // GL_STENCIL_TEST
struct {
- GLenum test_func; // GL_STENCIL_FUNC
- GLint test_ref; // GL_STENCIL_REF
- GLuint test_mask; // GL_STENCIL_VALUE_MASK
- GLuint write_mask; // GL_STENCIL_WRITEMASK
- GLenum action_stencil_fail; // GL_STENCIL_FAIL
- GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL
- GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS
+ GLenum test_func = GL_ALWAYS; // GL_STENCIL_FUNC
+ GLint test_ref = 0; // GL_STENCIL_REF
+ GLuint test_mask = 0xFFFFFFFF; // GL_STENCIL_VALUE_MASK
+ GLuint write_mask = 0xFFFFFFFF; // GL_STENCIL_WRITEMASK
+ GLenum action_stencil_fail = GL_KEEP; // GL_STENCIL_FAIL
+ GLenum action_depth_fail = GL_KEEP; // GL_STENCIL_PASS_DEPTH_FAIL
+ GLenum action_depth_pass = GL_KEEP; // GL_STENCIL_PASS_DEPTH_PASS
} front, back;
} stencil;
struct Blend {
- bool enabled; // GL_BLEND
- GLenum rgb_equation; // GL_BLEND_EQUATION_RGB
- GLenum a_equation; // GL_BLEND_EQUATION_ALPHA
- GLenum src_rgb_func; // GL_BLEND_SRC_RGB
- GLenum dst_rgb_func; // GL_BLEND_DST_RGB
- GLenum src_a_func; // GL_BLEND_SRC_ALPHA
- GLenum dst_a_func; // GL_BLEND_DST_ALPHA
+ bool enabled = false; // GL_BLEND
+ GLenum rgb_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_RGB
+ GLenum a_equation = GL_FUNC_ADD; // GL_BLEND_EQUATION_ALPHA
+ GLenum src_rgb_func = GL_ONE; // GL_BLEND_SRC_RGB
+ GLenum dst_rgb_func = GL_ZERO; // GL_BLEND_DST_RGB
+ GLenum src_a_func = GL_ONE; // GL_BLEND_SRC_ALPHA
+ GLenum dst_a_func = GL_ZERO; // GL_BLEND_DST_ALPHA
};
std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend;
struct {
- bool enabled;
+ bool enabled = false;
} independant_blend;
struct {
- GLclampf red;
- GLclampf green;
- GLclampf blue;
- GLclampf alpha;
+ GLclampf red = 0.0f;
+ GLclampf green = 0.0f;
+ GLclampf blue = 0.0f;
+ GLclampf alpha = 0.0f;
} blend_color; // GL_BLEND_COLOR
struct {
- bool enabled; // GL_LOGIC_OP_MODE
- GLenum operation;
+ bool enabled = false; // GL_LOGIC_OP_MODE
+ GLenum operation = GL_COPY;
} logic_op;
- std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{};
- std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{};
- std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{};
+ std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures = {};
+ std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers = {};
+ std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images = {};
struct {
- GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
- GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
- GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING
- GLuint shader_program; // GL_CURRENT_PROGRAM
- GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
+ GLuint read_framebuffer = 0; // GL_READ_FRAMEBUFFER_BINDING
+ GLuint draw_framebuffer = 0; // GL_DRAW_FRAMEBUFFER_BINDING
+ GLuint vertex_array = 0; // GL_VERTEX_ARRAY_BINDING
+ GLuint shader_program = 0; // GL_CURRENT_PROGRAM
+ GLuint program_pipeline = 0; // GL_PROGRAM_PIPELINE_BINDING
} draw;
- struct viewport {
- GLint x;
- GLint y;
- GLint width;
- GLint height;
- GLfloat depth_range_near; // GL_DEPTH_RANGE
- GLfloat depth_range_far; // GL_DEPTH_RANGE
+ struct Viewport {
+ GLint x = 0;
+ GLint y = 0;
+ GLint width = 0;
+ GLint height = 0;
+ GLfloat depth_range_near = 0.0f; // GL_DEPTH_RANGE
+ GLfloat depth_range_far = 1.0f; // GL_DEPTH_RANGE
struct {
- bool enabled; // GL_SCISSOR_TEST
- GLint x;
- GLint y;
- GLsizei width;
- GLsizei height;
+ bool enabled = false; // GL_SCISSOR_TEST
+ GLint x = 0;
+ GLint y = 0;
+ GLsizei width = 0;
+ GLsizei height = 0;
} scissor;
};
- std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
+ std::array<Viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
struct {
- float size; // GL_POINT_SIZE
+ float size = 1.0f; // GL_POINT_SIZE
} point;
struct {
- bool point_enable;
- bool line_enable;
- bool fill_enable;
- GLfloat units;
- GLfloat factor;
- GLfloat clamp;
+ bool point_enable = false;
+ bool line_enable = false;
+ bool fill_enable = false;
+ GLfloat units = 0.0f;
+ GLfloat factor = 0.0f;
+ GLfloat clamp = 0.0f;
} polygon_offset;
struct {
- bool enabled; // GL_ALPHA_TEST
- GLenum func; // GL_ALPHA_TEST_FUNC
- GLfloat ref; // GL_ALPHA_TEST_REF
+ bool enabled = false; // GL_ALPHA_TEST
+ GLenum func = GL_ALWAYS; // GL_ALPHA_TEST_FUNC
+ GLfloat ref = 0.0f; // GL_ALPHA_TEST_REF
} alpha_test;
- std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE
+ std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE
OpenGLState();
@@ -179,34 +157,31 @@ public:
/// Apply this state as the current OpenGL state
void Apply();
- void ApplyFramebufferState() const;
- void ApplyVertexArrayState() const;
- void ApplyShaderProgram() const;
- void ApplyProgramPipeline() const;
- void ApplyClipDistances() const;
- void ApplyPointSize() const;
- void ApplyFragmentColorClamp() const;
- void ApplyMultisample() const;
- void ApplySRgb() const;
- void ApplyCulling() const;
- void ApplyColorMask() const;
- void ApplyDepth() const;
- void ApplyPrimitiveRestart() const;
- void ApplyStencilTest() const;
- void ApplyViewport() const;
- void ApplyTargetBlending(std::size_t target, bool force) const;
- void ApplyGlobalBlending() const;
- void ApplyBlending() const;
- void ApplyLogicOp() const;
- void ApplyTextures() const;
- void ApplySamplers() const;
- void ApplyImages() const;
- void ApplyDepthClamp() const;
- void ApplyPolygonOffset() const;
- void ApplyAlphaTest() const;
-
- /// Set the initial OpenGL state
- static void ApplyDefaultState();
+ void ApplyFramebufferState();
+ void ApplyVertexArrayState();
+ void ApplyShaderProgram();
+ void ApplyProgramPipeline();
+ void ApplyClipDistances();
+ void ApplyPointSize();
+ void ApplyFragmentColorClamp();
+ void ApplyMultisample();
+ void ApplySRgb();
+ void ApplyCulling();
+ void ApplyColorMask();
+ void ApplyDepth();
+ void ApplyPrimitiveRestart();
+ void ApplyStencilTest();
+ void ApplyViewport();
+ void ApplyTargetBlending(std::size_t target, bool force);
+ void ApplyGlobalBlending();
+ void ApplyBlending();
+ void ApplyLogicOp();
+ void ApplyTextures();
+ void ApplySamplers();
+ void ApplyImages();
+ void ApplyDepthClamp();
+ void ApplyPolygonOffset();
+ void ApplyAlphaTest();
/// Resets any references to the given resource
OpenGLState& UnbindTexture(GLuint handle);
@@ -253,5 +228,6 @@ private:
bool color_mask;
} dirty{};
};
+static_assert(std::is_trivially_copyable_v<OpenGLState>);
} // namespace OpenGL
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 8d3d962c7..ca690b58b 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -96,6 +96,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
}
break;
}
+ case OpCode::Id::TLD4_B: {
+ is_bindless = true;
+ [[fallthrough]];
+ }
case OpCode::Id::TLD4: {
ASSERT(instr.tld4.array == 0);
UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV),
@@ -108,11 +112,14 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
}
const auto texture_type = instr.tld4.texture_type.Value();
- const bool depth_compare = instr.tld4.UsesMiscMode(TextureMiscMode::DC);
+ const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC)
+ : instr.tld4.UsesMiscMode(TextureMiscMode::DC);
const bool is_array = instr.tld4.array != 0;
- const bool is_aoffi = instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
+ const bool is_aoffi = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::AOFFI)
+ : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
WriteTexInstructionFloat(
- bb, instr, GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi));
+ bb, instr,
+ GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless));
break;
}
case OpCode::Id::TLD4S: {
@@ -586,7 +593,7 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type,
}
Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare,
- bool is_array, bool is_aoffi) {
+ bool is_array, bool is_aoffi, bool is_bindless) {
const std::size_t coord_count = GetCoordCount(texture_type);
// If enabled arrays index is always stored in the gpr8 field
@@ -600,6 +607,12 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
}
u64 parameter_register = instr.gpr20.Value();
+
+ const auto& sampler =
+ is_bindless
+ ? GetBindlessSampler(parameter_register++, {{texture_type, is_array, depth_compare}})
+ : GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
+
std::vector<Node> aoffi;
if (is_aoffi) {
aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true);
@@ -610,12 +623,14 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
dc = GetRegister(parameter_register++);
}
- const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
+ const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component))
+ : Immediate(static_cast<u32>(instr.tld4.component));
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
auto coords_copy = coords;
- MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, element};
+ MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component,
+ element};
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 5243644e8..26c8fde22 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -341,7 +341,7 @@ private:
bool is_array);
Node4 GetTld4Code(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type,
- bool depth_compare, bool is_array, bool is_aoffi);
+ bool depth_compare, bool is_array, bool is_aoffi, bool is_bindless);
Node4 GetTldCode(Tegra::Shader::Instruction instr);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d6bb18d24..160613ee1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1839,6 +1839,10 @@ void GMainWindow::OnLoadAmiibo() {
return;
}
+ LoadAmiibo(filename);
+}
+
+void GMainWindow::LoadAmiibo(const QString& filename) {
Core::System& system{Core::System::GetInstance()};
Service::SM::ServiceManager& sm = system.ServiceManager();
auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user");
@@ -2189,10 +2193,19 @@ static bool IsSingleFileDropEvent(QDropEvent* event) {
}
void GMainWindow::dropEvent(QDropEvent* event) {
- if (IsSingleFileDropEvent(event) && ConfirmChangeGame()) {
- const QMimeData* mimeData = event->mimeData();
- QString filename = mimeData->urls().at(0).toLocalFile();
- BootGame(filename);
+ if (!IsSingleFileDropEvent(event)) {
+ return;
+ }
+
+ const QMimeData* mime_data = event->mimeData();
+ const QString filename = mime_data->urls().at(0).toLocalFile();
+
+ if (emulation_running && QFileInfo(filename).suffix() == QStringLiteral("bin")) {
+ LoadAmiibo(filename);
+ } else {
+ if (ConfirmChangeGame()) {
+ BootGame(filename);
+ }
}
}
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index fd4b9ccf5..7f46bea2b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -142,6 +142,7 @@ private:
void ShowTelemetryCallout();
void SetDiscordEnabled(bool state);
+ void LoadAmiibo(const QString& filename);
void SelectAndSetCurrentUser();