diff --git a/.ci/pack.sh b/.ci/pack.sh index 3609f38446..2aedbd4df1 100755 --- a/.ci/pack.sh +++ b/.ci/pack.sh @@ -7,13 +7,6 @@ REV_NAME="citra-${OS}-${TARGET}-${GITDATE}-${GITREV}" # Find out what release we are building if [[ "$GITHUB_REF_NAME" =~ ^canary- ]] || [[ "$GITHUB_REF_NAME" =~ ^nightly- ]]; then RELEASE_NAME=$(echo $GITHUB_REF_NAME | cut -d- -f1) - # For compatibility with existing installs, use mingw/osx in the archive and target names. - if [ "$TARGET" = "msys2" ]; then - REV_NAME="citra-${OS}-mingw-${GITDATE}-${GITREV}" - RELEASE_NAME="${RELEASE_NAME}-mingw" - elif [ "$OS" = "macos" ]; then - REV_NAME="citra-osx-${TARGET}-${GITDATE}-${GITREV}" - fi else RELEASE_NAME=head fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdd05d4b0c..4e418689d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -161,9 +161,16 @@ jobs: - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 if: ${{ matrix.target == 'msvc' }} - - name: Install MSVC extra tools + - name: Install extra tools (MSVC) run: choco install ccache ninja wget if: ${{ matrix.target == 'msvc' }} + - name: Set up Vulkan SDK (MSVC) + uses: humbletim/setup-vulkan-sdk@v1.2.0 + if: ${{ matrix.target == 'msvc' }} + with: + vulkan-query-version: latest + vulkan-components: Glslang + vulkan-use-cache: true - name: Set up MSYS2 uses: msys2/setup-msys2@v2 if: ${{ matrix.target == 'msys2' }} @@ -172,16 +179,10 @@ jobs: update: true install: git make p7zip pacboy: >- - toolchain:p ccache:p cmake:p ninja:p + toolchain:p ccache:p cmake:p ninja:p glslang:p qt6-base:p qt6-multimedia:p qt6-multimedia-wmf:p qt6-tools:p qt6-translations:p - - name: Setup Vulkan SDK - uses: humbletim/setup-vulkan-sdk@v1.2.0 - with: - vulkan-query-version: latest - vulkan-components: Glslang - vulkan-use-cache: true - - name: Test glslangValidator - run: glslangValidator --version + - name: Test glslang + run: glslang --version || glslangValidator --version - name: Disable line ending translation run: git config --global core.autocrlf input - name: Build diff --git a/CMakeLists.txt b/CMakeLists.txt index 12c511b052..64b42a09ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) +option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON) CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF) option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON) @@ -68,6 +69,8 @@ option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_MF "Use Media Foundation decoder (preferred over FFmpeg)" ON "WIN32" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_AUDIOTOOLBOX "Use AudioToolbox decoder (preferred over FFmpeg)" ON "APPLE" OFF) +CMAKE_DEPENDENT_OPTION(CITRA_ENABLE_BUNDLE_TARGET "Enable the distribution bundling target." ON "NOT ANDROID AND NOT IOS" OFF) + # Compile options CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ${IS_DEBUG_BUILD} "MINGW" OFF) option(ENABLE_LTO "Enable link time optimization" OFF) @@ -219,7 +222,7 @@ find_package(Threads REQUIRED) if (ENABLE_QT) if (NOT USE_SYSTEM_QT) - download_qt(6.5.0) + download_qt(6.5.1) endif() find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent) @@ -341,13 +344,6 @@ function(get_timestamp _var) set(${_var} "${timestamp}" PARENT_SCOPE) endfunction() -# Prevent boost from linking against libs when building -add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY - -DBOOST_SYSTEM_NO_LIB - -DBOOST_DATE_TIME_NO_LIB - -DBOOST_REGEX_NO_LIB -) - # generate git/build information include(GetGitRevisionDescription) get_git_head_revision(GIT_REF_SPEC GIT_REV) @@ -355,17 +351,23 @@ git_describe(GIT_DESC --always --long --dirty) git_branch_name(GIT_BRANCH) get_timestamp(BUILD_DATE) -if (NOT USE_SYSTEM_BOOST) - add_definitions( -DBOOST_ALL_NO_LIB ) +# Boost +# Prevent boost from linking against libs when building +add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY + -DBOOST_SYSTEM_NO_LIB + -DBOOST_DATE_TIME_NO_LIB + -DBOOST_REGEX_NO_LIB +) +if (USE_SYSTEM_BOOST) + find_package(Boost 1.70.0 COMPONENTS container locale serialization iostreams REQUIRED) endif() enable_testing() add_subdirectory(externals) -# Boost -if (USE_SYSTEM_BOOST) - find_package(Boost 1.70.0 COMPONENTS serialization iostreams REQUIRED) -else() +# Boost (bundled) +if (NOT USE_SYSTEM_BOOST) + add_definitions( -DBOOST_ALL_NO_LIB ) add_library(Boost::boost ALIAS boost) add_library(Boost::serialization ALIAS boost_serialization) add_library(Boost::iostreams ALIAS boost_iostreams) @@ -397,7 +399,7 @@ else() endif() # Create target for outputting distributable bundles. -if (NOT ANDROID AND NOT IOS) +if (CITRA_ENABLE_BUNDLE_TARGET) include(BundleTarget) if (ENABLE_SDL2_FRONTEND) bundle_target(citra) diff --git a/CMakeModules/BundleTarget.cmake b/CMakeModules/BundleTarget.cmake index a805d4954c..f5b1c06f42 100644 --- a/CMakeModules/BundleTarget.cmake +++ b/CMakeModules/BundleTarget.cmake @@ -189,6 +189,12 @@ else() add_custom_command( TARGET bundle COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/") + add_custom_command( + TARGET bundle + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/dist/") + add_custom_command( + TARGET bundle + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dist/icon.png" "${CMAKE_BINARY_DIR}/bundle/dist/citra.png") add_custom_command( TARGET bundle COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/license.txt" "${CMAKE_BINARY_DIR}/bundle/") diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 6448e1f251..7ec6c75702 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -54,7 +54,8 @@ function(download_qt target) set(host_flag "--autodesktop") set(host_prefix "${base_path}/${target}/${host_arch_path}") endif() - set(install_args install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} ${host_flag} -m qtmultimedia) + set(install_args install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} ${host_flag} + -m qtmultimedia --archives qttranslations qttools qtsvg qtbase) endif() if (NOT EXISTS "${prefix}") diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake index f0c8e7da63..ee077cbbd9 100644 --- a/CMakeModules/GenerateSCMRev.cmake +++ b/CMakeModules/GenerateSCMRev.cmake @@ -12,8 +12,16 @@ set(HASH_FILES "${VIDEO_CORE}/renderer_opengl/gl_shader_gen.h" "${VIDEO_CORE}/renderer_opengl/gl_shader_util.cpp" "${VIDEO_CORE}/renderer_opengl/gl_shader_util.h" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_gen.cpp" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_gen.h" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_gen_spv.cpp" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_gen_spv.h" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_util.cpp" + "${VIDEO_CORE}/renderer_vulkan/vk_shader_util.h" "${VIDEO_CORE}/shader/shader.cpp" "${VIDEO_CORE}/shader/shader.h" + "${VIDEO_CORE}/shader/shader_uniforms.cpp" + "${VIDEO_CORE}/shader/shader_uniforms.h" "${VIDEO_CORE}/pica.cpp" "${VIDEO_CORE}/pica.h" "${VIDEO_CORE}/regs_framebuffer.h" diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 7d6df72b68..238a411824 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -298,6 +298,11 @@ QAbstractItemView:read-only { alternate-background-color: #232629; } +/* Workaround for https://bugreports.qt.io/browse/QTBUG-115529 */ +QAbstractItemView:item { + border: 0px; +} + QWidget:focus { border: 1px solid #3daee9; } diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index c200819c55..12d05d7bff 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -481,6 +481,11 @@ QAbstractItemView QLineEdit { padding: 2px; } +/* Workaround for https://bugreports.qt.io/browse/QTBUG-115529 */ +QAbstractItemView:item { + border: 0px; +} + /* QAbstractScrollArea ---------------------------------------------------- https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 4d79bd78b9..1d1df84050 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -12,27 +12,29 @@ include(DownloadExternals) include(ExternalProject) # Boost -set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") -set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") -set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "") -add_library(boost INTERFACE) -target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR}) +if (NOT USE_SYSTEM_BOOST) + message(STATUS "Including vendored Boost library") + set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") + set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") + set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "") + add_library(boost INTERFACE) + target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR}) -# Boost::serialization -file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp") -add_library(boost_serialization STATIC ${boost_serialization_SRC}) -target_link_libraries(boost_serialization PUBLIC boost) - -# Boost::iostreams -add_library( - boost_iostreams - STATIC - ${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp - ${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp -) -target_link_libraries(boost_iostreams PUBLIC boost) + # Boost::serialization + file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp") + add_library(boost_serialization STATIC ${boost_serialization_SRC}) + target_link_libraries(boost_serialization PUBLIC boost) + # Boost::iostreams + add_library( + boost_iostreams + STATIC + ${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp + ${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp + ) + target_link_libraries(boost_iostreams PUBLIC boost) # Add additional boost libs here; remember to ALIAS them in the root CMakeLists! +endif() # Catch2 set(CATCH_INSTALL_DOCS OFF CACHE BOOL "") @@ -95,6 +97,7 @@ set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "") set(ENABLE_SPVREMAPPER OFF CACHE BOOL "") set(ENABLE_CTEST OFF CACHE BOOL "") set(ENABLE_HLSL OFF CACHE BOOL "") +set(BUILD_EXTERNAL OFF CACHE BOOL "") add_subdirectory(glslang) # inih @@ -171,37 +174,39 @@ endif() add_library(json-headers INTERFACE) target_include_directories(json-headers INTERFACE ./json) +# OpenSSL +if (USE_SYSTEM_OPENSSL) + find_package(OpenSSL 1.1) + if (OPENSSL_FOUND) + set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) + endif() +endif() + +if (NOT OPENSSL_FOUND) + # LibreSSL + set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") + set(OPENSSLDIR "/etc/ssl/") + add_subdirectory(libressl EXCLUDE_FROM_ALL) + target_include_directories(ssl INTERFACE ./libressl/include) + target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP) + get_directory_property(OPENSSL_LIBRARIES + DIRECTORY libressl + DEFINITION OPENSSL_LIBS) +endif() + +# httplib +add_library(httplib INTERFACE) +target_include_directories(httplib INTERFACE ./httplib) +target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT -DCPPHTTPLIB_NO_DEFAULT_USER_AGENT) +target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES}) + +if(ANDROID) + add_subdirectory(android-ifaddrs) + target_link_libraries(httplib INTERFACE ifaddrs) +endif() + +# cpp-jwt if (ENABLE_WEB_SERVICE) - if (USE_SYSTEM_OPENSSL) - find_package(OpenSSL 1.1) - if (OPENSSL_FOUND) - set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) - endif() - endif() - - if (NOT OPENSSL_FOUND) - # LibreSSL - set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") - set(OPENSSLDIR "/etc/ssl/") - add_subdirectory(libressl EXCLUDE_FROM_ALL) - target_include_directories(ssl INTERFACE ./libressl/include) - target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP) - get_directory_property(OPENSSL_LIBRARIES - DIRECTORY libressl - DEFINITION OPENSSL_LIBS) - endif() - - if(ANDROID) - add_subdirectory(android-ifaddrs) - endif() - - # httplib - add_library(httplib INTERFACE) - target_include_directories(httplib INTERFACE ./httplib) - target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT -DCPPHTTPLIB_NO_DEFAULT_USER_AGENT) - target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES}) - - # cpp-jwt add_library(cpp-jwt INTERFACE) target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include) target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON) diff --git a/externals/boost b/externals/boost index 700ae2eff3..3c27c785ad 160000 --- a/externals/boost +++ b/externals/boost @@ -1 +1 @@ -Subproject commit 700ae2eff3134792f09cea2b051666688b1d5b97 +Subproject commit 3c27c785ad0f8a742af02e620dc225673f3a12d8 diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 4385cdf5fb..fddcc866d4 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -47,7 +47,7 @@ add_library(audio_core STATIC create_target_directory_groups(audio_core) -target_link_libraries(audio_core PUBLIC citra_common) +target_link_libraries(audio_core PUBLIC citra_common citra_core) target_link_libraries(audio_core PRIVATE SoundTouch teakra) set_target_properties(audio_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) add_definitions(-DSOUNDTOUCH_INTEGER_SAMPLES) diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index ecb9448c11..e04b71783b 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -342,7 +342,7 @@ if (USE_DISCORD_PRESENCE) endif() if (ENABLE_WEB_SERVICE) - target_compile_definitions(citra-qt PRIVATE -DENABLE_WEB_SERVICE) + target_link_libraries(citra-qt PRIVATE web_service) endif() if(UNIX AND NOT APPLE) diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index 300a2736d8..3951728e96 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -13,6 +13,7 @@ ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent) ui->setupUi(this); ui->toggle_vsync_new->setEnabled(!is_powered_on); + ui->graphics_api_combo->setEnabled(!is_powered_on); // Set the index to -1 to ensure the below lambda is called with setCurrentIndex ui->graphics_api_combo->setCurrentIndex(-1); @@ -28,9 +29,10 @@ ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent) }); connect(ui->toggle_hw_shader, &QCheckBox::toggled, this, [this] { + const bool enabled = ui->toggle_hw_shader->isEnabled(); const bool checked = ui->toggle_hw_shader->isChecked(); - ui->hw_shader_group->setEnabled(checked); - ui->toggle_disk_shader_cache->setEnabled(checked); + ui->hw_shader_group->setEnabled(checked && enabled); + ui->toggle_disk_shader_cache->setEnabled(checked && enabled); }); SetupPerGameUI(); diff --git a/src/citra_qt/configuration/configure_input.ui b/src/citra_qt/configuration/configure_input.ui index 3e3e8e4f91..2d199e6673 100644 --- a/src/citra_qt/configuration/configure_input.ui +++ b/src/citra_qt/configuration/configure_input.ui @@ -13,7 +13,7 @@ ConfigureInput - + @@ -63,654 +63,665 @@ - - - - - Face Buttons - - - false - - - false - - - - - - - - Y: - - - - - - - - - - - - - - - - - - X: - - - - - - - - - - - - - - - - - - B: - - - - - - - - - - - - - - - - - - A: - - - - - - - - - - - - - - - - - - - Directional Pad - - - false - - - false - - - - - - - - Up: - - - - - - - - - - - - - - - - - - Down: - - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - - - - - - - - - Right: - - - - - - - - - - - - - - - - - - - Misc. - - - false - - - false - - - - - - - - Start: - - - - - - - - - - - - - - - - - - Select: - - - - - - - - - - - - - - - - - - Home: - - - - - - - - - - - - - - - - - - Power: - - - - - - - - - - - - - - - - - - Circle Mod: - - - - - - - - - - - - - - - - - - GPIO14: - - - - - - - - - - - - - - - - - - Debug: - - - - - - - - - - - - - - - - - - - Circle Pad - - - false - - - false - - - - - - - - Up: - - - - - - - - - - - - - - - - - - Right: - - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - - - - - - - Set Analog Stick - - - - - - - - - Down: - - - - - - - - - - - - - - - - - - QLayout::SetDefaultConstraint - - - + + + true + + + + + + + + + Face Buttons + + + false + + + false + + + + + + + + Y: + + + + + + + + + + + + + + + + + + X: + + + + + + + + + + + + + + + + + + B: + + + + + + + + + + + + + + + + + + A: + + + + + + + + + + + + + + + + + + + Directional Pad + + + false + + + false + + + + + + + + Up: + + + + + + + + + + + + + + + + + + Down: + + + + + + + + + + + + + + + + + + Left: + + + + + + + + + + + + + + + + + + Right: + + + + + + + + + + + + + + + + + + + Misc. + + + false + + + false + + + + + + + + Start: + + + + + + + + + + + + + + + + + + Select: + + + + + + + + + + + + + + + + + + Home: + + + + + + + + + + + + + + + + + + Power: + + + + + + + + + + + + + + + + + + Circle Mod: + + + + + + + + + + + + + + + + + + GPIO14: + + + + + + + + + + + + + + + + + + Debug: + + + + + + + + + + + + + + + + + + + Circle Pad + + + false + + + false + + + + + + + + Up: + + + + + + + + + + + + + + + + + + Right: + + + + + + + + + + + + + + + + + + Left: + + + + + + + + + + + + + + - Deadzone: 0 - - - Qt::AlignHCenter + Set Analog Stick + + + + + + Down: + + + + + + + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + + + Deadzone: 0 + + + Qt::AlignHCenter + + + + + + + + + Qt::Horizontal + + + + + - - - - - Qt::Horizontal - - - - - - - - - - - - C-Stick - - - false - - - false - - - - - - - - Right: - - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - - - - - - - - - Up: - - - - - - - - - - - - - - - - Set Analog Stick - - - - - - - - - Down: - - - - - - - - - - - - - - - - QLayout::SetDefaultConstraint - - - - - + + + + + + C-Stick + + + false + + + false + + + + + + + + Right: + + + + + + + + + + + + + + + + + + Left: + + + + + + + + + + + + + + + + + + Up: + + + + + + + + + + + + + + - Deadzone: 0 - - - Qt::AlignHCenter + Set Analog Stick + + + + + + Down: + + + + + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + + Deadzone: 0 + + + Qt::AlignHCenter + + + + + + + + + Qt::Horizontal + + + + + - - - - - Qt::Horizontal - - - - - - - - - - - - Shoulder Buttons - - - false - - - false - - - - - - - - ZR: - - - - - - - - - - - - - - - - - - ZL: - - - - - - - - - - - - - - - - - - L: - - - - - - - - - - - - - - - - - - R: - - - - - - - - - - - - - - - - + + + + + + Shoulder Buttons + + + false + + + false + + + + + + + + ZR: + + + + + + + + + + + + + + + + + + ZL: + + + + + + + + + + + + + + + + + + L: + + + + + + + + + + + + + + + + + + R: + + + + + + + + + + + + + + + + + + + + diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp index 0a5c14a846..e63f5399ed 100644 --- a/src/citra_qt/configuration/configure_system.cpp +++ b/src/citra_qt/configuration/configure_system.cpp @@ -551,7 +551,6 @@ void ConfigureSystem::SetupPerGameUI() { } void ConfigureSystem::DownloadFromNUS() { -#ifdef ENABLE_WEB_SERVICE ui->button_start_download->setEnabled(false); const auto mode = @@ -590,5 +589,4 @@ void ConfigureSystem::DownloadFromNUS() { } ui->button_start_download->setEnabled(true); -#endif } diff --git a/src/citra_qt/debugger/graphics/graphics.cpp b/src/citra_qt/debugger/graphics/graphics.cpp index 1a3c0157c0..674b831001 100644 --- a/src/citra_qt/debugger/graphics/graphics.cpp +++ b/src/citra_qt/debugger/graphics/graphics.cpp @@ -64,15 +64,22 @@ void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_co } GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) - : QDockWidget(tr("Graphics Debugger"), parent) { + : QDockWidget(tr("Graphics Debugger"), parent), model(this) { setObjectName(QStringLiteral("GraphicsDebugger")); - GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this); - g_debugger.RegisterObserver(command_model); - - QListView* command_list = new QListView; - command_list->setModel(command_model); + auto* command_list = new QListView; + command_list->setModel(&model); command_list->setFont(GetMonospaceFont()); setWidget(command_list); } + +void GPUCommandStreamWidget::showEvent(QShowEvent* event) { + g_debugger.RegisterObserver(&model); + QDockWidget::showEvent(event); +} + +void GPUCommandStreamWidget::hideEvent(QHideEvent* event) { + g_debugger.UnregisterObserver(&model); + QDockWidget::hideEvent(event); +} diff --git a/src/citra_qt/debugger/graphics/graphics.h b/src/citra_qt/debugger/graphics/graphics.h index 8837fb7922..9193c28219 100644 --- a/src/citra_qt/debugger/graphics/graphics.h +++ b/src/citra_qt/debugger/graphics/graphics.h @@ -37,5 +37,10 @@ class GPUCommandStreamWidget : public QDockWidget { public: GPUCommandStreamWidget(QWidget* parent = nullptr); +protected: + void showEvent(QShowEvent* event) override; + void hideEvent(QHideEvent* event) override; + private: + GPUCommandStreamItemModel model; }; diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index 6711644e62..aaf733a7db 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -16,6 +16,7 @@ #include "citra_qt/debugger/graphics/graphics_cmdlists.h" #include "citra_qt/util/util.h" #include "common/vector_math.h" +#include "core/core.h" #include "core/memory.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/pica_state.h" @@ -166,7 +167,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { const auto format = texture.format; const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format); - const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress()); + const u8* src = system.Memory().GetPhysicalPointer(config.GetPhysicalAddress()); new_info_widget = new TextureInfoWidget(src, info); } if (command_info_widget) { @@ -180,8 +181,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { } #undef COMMAND_IN_RANGE -GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent) - : QDockWidget(tr("Pica Command List"), parent), memory{memory_} { +GPUCommandListWidget::GPUCommandListWidget(Core::System& system_, QWidget* parent) + : QDockWidget(tr("Pica Command List"), parent), system{system_} { setObjectName(QStringLiteral("Pica Command List")); GPUCommandListModel* model = new GPUCommandListModel(this); diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.h b/src/citra_qt/debugger/graphics/graphics_cmdlists.h index 5ea4d125b3..4bd562a48f 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.h +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.h @@ -11,8 +11,8 @@ class QPushButton; class QTreeView; -namespace Memory { -class MemorySystem; +namespace Core { +class System; } class GPUCommandListModel : public QAbstractListModel { @@ -42,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget { Q_OBJECT public: - explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr); + explicit GPUCommandListWidget(Core::System& system, QWidget* parent = nullptr); public slots: void OnToggleTracing(); @@ -57,7 +57,7 @@ signals: private: std::unique_ptr pica_trace; - Memory::MemorySystem& memory; + Core::System& system; QTreeView* list_widget; QWidget* command_info_widget; QPushButton* toggle_tracing; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index b447af3234..202be08c3b 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() { graphicsWidget->hide(); debug_menu->addAction(graphicsWidget->toggleViewAction()); - graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this); + graphicsCommandsWidget = new GPUCommandListWidget(system, this); addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); graphicsCommandsWidget->hide(); debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); @@ -1071,8 +1071,10 @@ bool GMainWindow::LoadROM(const QString& filename) { ShutdownGame(); } - render_window->InitRenderTarget(); - secondary_window->InitRenderTarget(); + if (!render_window->InitRenderTarget() || !secondary_window->InitRenderTarget()) { + LOG_CRITICAL(Frontend, "Failed to initialize render targets!"); + return false; + } const auto scope = render_window->Acquire(); @@ -1420,10 +1422,17 @@ void GMainWindow::UpdateSaveStates() { actions_save_state[i]->setText(tr("Slot %1").arg(i + 1)); } for (const auto& savestate : savestates) { - const auto text = tr("Slot %1 - %2") - .arg(savestate.slot) - .arg(QDateTime::fromSecsSinceEpoch(savestate.time) - .toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"))); + const bool display_name = + savestate.status == Core::SaveStateInfo::ValidationStatus::RevisionDismatch && + !savestate.build_name.empty(); + const auto text = + tr("Slot %1 - %2 %3") + .arg(savestate.slot) + .arg(QDateTime::fromSecsSinceEpoch(savestate.time) + .toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"))) + .arg(display_name ? QString::fromStdString(savestate.build_name) : QLatin1String()) + .trimmed(); + actions_load_state[savestate.slot - 1]->setEnabled(true); actions_load_state[savestate.slot - 1]->setText(text); actions_save_state[savestate.slot - 1]->setText(text); diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 18e4be6296..acbf79bfff 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -16,6 +16,7 @@ #include "common/common_paths.h" #include "common/file_util.h" #include "common/logging/log.h" +#include "common/scope_exit.h" #include "common/string_util.h" #ifdef _WIN32 @@ -324,31 +325,32 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { return AndroidStorage::CopyFile(srcFilename, std::string(GetParentPath(destFilename)), std::string(GetFilename(destFilename))); #else - using CFilePointer = std::unique_ptr; // Open input file - CFilePointer input{fopen(srcFilename.c_str(), "rb"), std::fclose}; + FILE* input = fopen(srcFilename.c_str(), "rb"); if (!input) { LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename, destFilename, GetLastErrorMsg()); return false; } + SCOPE_EXIT({ fclose(input); }); // open output file - CFilePointer output{fopen(destFilename.c_str(), "wb"), std::fclose}; + FILE* output = fopen(destFilename.c_str(), "wb"); if (!output) { LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename, destFilename, GetLastErrorMsg()); return false; } + SCOPE_EXIT({ fclose(output); }); // copy loop std::array buffer; - while (!feof(input.get())) { + while (!feof(input)) { // read input - std::size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input.get()); + std::size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input); if (rnum != buffer.size()) { - if (ferror(input.get()) != 0) { + if (ferror(input) != 0) { LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", srcFilename, destFilename, GetLastErrorMsg()); return false; @@ -356,7 +358,7 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) { } // write output - std::size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output.get()); + std::size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output); if (wnum != rnum) { LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename, destFilename, GetLastErrorMsg()); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f507b5dc4b..b25a8c3883 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -458,19 +458,14 @@ add_library(citra_core STATIC mmio.h movie.cpp movie.h + nus_download.cpp + nus_download.h perf_stats.cpp perf_stats.h precompiled_headers.h - rpc/packet.cpp - rpc/packet.h - rpc/rpc_server.cpp - rpc/rpc_server.h - rpc/server.cpp - rpc/server.h - rpc/udp_server.cpp - rpc/udp_server.h savestate.cpp savestate.h + savestate_data.h system_titles.cpp system_titles.h telemetry_session.cpp @@ -483,16 +478,26 @@ add_library(citra_core STATIC create_target_directory_groups(citra_core) target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core) -target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams) +target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams httplib) target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives) set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) if (ENABLE_WEB_SERVICE) - target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT) - target_link_libraries(citra_core PRIVATE web_service ${OPENSSL_LIBS} httplib) - if (ANDROID) - target_link_libraries(citra_core PRIVATE ifaddrs) - endif() + target_link_libraries(citra_core PRIVATE web_service) +endif() + +if (ENABLE_SCRIPTING) + target_compile_definitions(citra_core PUBLIC -DENABLE_SCRIPTING) + target_sources(citra_core PRIVATE + rpc/packet.cpp + rpc/packet.h + rpc/rpc_server.cpp + rpc/rpc_server.h + rpc/server.cpp + rpc/server.h + rpc/udp_server.cpp + rpc/udp_server.h + ) endif() if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) diff --git a/src/core/core.cpp b/src/core/core.cpp index 97f71d7d65..de239fe21a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -45,7 +45,9 @@ #include "core/hw/lcd.h" #include "core/loader/loader.h" #include "core/movie.h" +#ifdef ENABLE_SCRIPTING #include "core/rpc/server.h" +#endif #include "core/telemetry_session.h" #include "network/network.h" #include "video_core/custom_textures/custom_tex_manager.h" @@ -418,7 +420,9 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, telemetry_session = std::make_unique(); +#ifdef ENABLE_SCRIPTING rpc_server = std::make_unique(*this); +#endif service_manager = std::make_unique(*this); archive_manager = std::make_unique(*this); @@ -555,7 +559,9 @@ void System::Shutdown(bool is_deserializing) { } custom_tex_manager.reset(); telemetry_session.reset(); +#ifdef ENABLE_SCRIPTING rpc_server.reset(); +#endif archive_manager.reset(); service_manager.reset(); dsp_core.reset(); diff --git a/src/core/core.h b/src/core/core.h index 4c401b736d..ae3310ca72 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -405,8 +405,10 @@ private: /// Image interface std::shared_ptr registered_image_interface; +#ifdef ENABLE_SCRIPTING /// RPC Server for scripting support std::unique_ptr rpc_server; +#endif std::unique_ptr archive_manager; diff --git a/src/core/hle/service/ac/ac.cpp b/src/core/hle/service/ac/ac.cpp index c1a61126bf..84c989642b 100644 --- a/src/core/hle/service/ac/ac.cpp +++ b/src/core/hle/service/ac/ac.cpp @@ -151,6 +151,17 @@ void Module::Interface::RegisterDisconnectEvent(Kernel::HLERequestContext& ctx) LOG_WARNING(Service_AC, "(STUBBED) called"); } +void Module::Interface::GetConnectingProxyEnable(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx); + constexpr bool proxy_enabled = false; + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(proxy_enabled); + + LOG_WARNING(Service_AC, "(STUBBED) called"); +} + void Module::Interface::IsConnected(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); u32 unk = rp.Pop(); diff --git a/src/core/hle/service/ac/ac.h b/src/core/hle/service/ac/ac.h index 4203b0a934..38761150b9 100644 --- a/src/core/hle/service/ac/ac.h +++ b/src/core/hle/service/ac/ac.h @@ -120,6 +120,14 @@ public: */ void RegisterDisconnectEvent(Kernel::HLERequestContext& ctx); + /** + * AC::GetConnectingProxyEnable service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : bool, is proxy enabled + */ + void GetConnectingProxyEnable(Kernel::HLERequestContext& ctx); + /** * AC::IsConnected service function * Outputs: diff --git a/src/core/hle/service/ac/ac_i.cpp b/src/core/hle/service/ac/ac_i.cpp index 84a643e8bc..f7766b3249 100644 --- a/src/core/hle/service/ac/ac_i.cpp +++ b/src/core/hle/service/ac/ac_i.cpp @@ -27,6 +27,7 @@ AC_I::AC_I(std::shared_ptr ac) : Module::Interface(std::move(ac), "ac:i" {0x0027, &AC_I::GetInfraPriority, "GetInfraPriority"}, {0x002D, &AC_I::SetRequestEulaVersion, "SetRequestEulaVersion"}, {0x0030, &AC_I::RegisterDisconnectEvent, "RegisterDisconnectEvent"}, + {0x0036, &AC_I::GetConnectingProxyEnable, "GetConnectingProxyEnable"}, {0x003C, nullptr, "GetAPSSIDList"}, {0x003E, &AC_I::IsConnected, "IsConnected"}, {0x0040, &AC_I::SetClientVersion, "SetClientVersion"}, diff --git a/src/core/hle/service/ac/ac_u.cpp b/src/core/hle/service/ac/ac_u.cpp index d6d0a68679..12506962c5 100644 --- a/src/core/hle/service/ac/ac_u.cpp +++ b/src/core/hle/service/ac/ac_u.cpp @@ -27,6 +27,7 @@ AC_U::AC_U(std::shared_ptr ac) : Module::Interface(std::move(ac), "ac:u" {0x0027, &AC_U::GetInfraPriority, "GetInfraPriority"}, {0x002D, &AC_U::SetRequestEulaVersion, "SetRequestEulaVersion"}, {0x0030, &AC_U::RegisterDisconnectEvent, "RegisterDisconnectEvent"}, + {0x0036, &AC_U::GetConnectingProxyEnable, "GetConnectingProxyEnable"}, {0x003C, nullptr, "GetAPSSIDList"}, {0x003E, &AC_U::IsConnected, "IsConnected"}, {0x0040, &AC_U::SetClientVersion, "SetClientVersion"}, diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 855deebd6c..8a7939ea10 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -31,9 +31,7 @@ #include "core/hle/service/fs/fs_user.h" #include "core/loader/loader.h" #include "core/loader/smdh.h" -#ifdef ENABLE_WEB_SERVICE -#include "web_service/nus_download.h" -#endif +#include "core/nus_download.h" namespace Service::AM { @@ -463,7 +461,6 @@ InstallStatus InstallCIA(const std::string& path, } InstallStatus InstallFromNus(u64 title_id, int version) { -#ifdef ENABLE_WEB_SERVICE LOG_DEBUG(Service_AM, "Downloading {:X}", title_id); CIAFile install_file{GetTitleMediaType(title_id)}; @@ -472,7 +469,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) { if (version != -1) { path += fmt::format(".{}", version); } - auto tmd_response = WebService::NUS::Download(path); + auto tmd_response = Core::NUS::Download(path); if (!tmd_response) { LOG_ERROR(Service_AM, "Failed to download tmd for {:016X}", title_id); return InstallStatus::ErrorFileNotFound; @@ -481,7 +478,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) { tmd.Load(*tmd_response); path = fmt::format("/ccs/download/{:016X}/cetk", title_id); - auto cetk_response = WebService::NUS::Download(path); + auto cetk_response = Core::NUS::Download(path); if (!cetk_response) { LOG_ERROR(Service_AM, "Failed to download cetk for {:016X}", title_id); return InstallStatus::ErrorFileNotFound; @@ -492,7 +489,7 @@ InstallStatus InstallFromNus(u64 title_id, int version) { for (std::size_t i = 0; i < content_count; ++i) { const std::string filename = fmt::format("{:08x}", tmd.GetContentIDByIndex(i)); path = fmt::format("/ccs/download/{:016X}/{}", title_id, filename); - const auto temp_response = WebService::NUS::Download(path); + const auto temp_response = Core::NUS::Download(path); if (!temp_response) { LOG_ERROR(Service_AM, "Failed to download content for {:016X}", title_id); return InstallStatus::ErrorFileNotFound; @@ -550,9 +547,6 @@ InstallStatus InstallFromNus(u64 title_id, int version) { return result; } return InstallStatus::Success; -#else - return InstallStatus::ErrorFileNotFound; -#endif } u64 GetTitleUpdateId(u64 title_id) { diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index c1e0d446a6..2daa1116c3 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -620,9 +620,9 @@ void Module::Interface::SetData(Kernel::HLERequestContext& ctx) { void Module::Interface::ReadData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); - const u32 dest_buffer_size = rp.Pop(); - const CecSystemInfoType info_type = rp.PopEnum(); - const u32 param_buffer_size = rp.Pop(); + const auto dest_buffer_size = rp.Pop(); + const auto info_type = rp.PopEnum(); + const auto param_buffer_size = rp.Pop(); auto& param_buffer = rp.PopMappedBuffer(); auto& dest_buffer = rp.PopMappedBuffer(); @@ -631,22 +631,23 @@ void Module::Interface::ReadData(Kernel::HLERequestContext& ctx) { std::vector buffer; switch (info_type) { case CecSystemInfoType::EulaVersion: { - auto cfg = Service::CFG::GetModule(cecd->system); - Service::CFG::EULAVersion version = cfg->GetEULAVersion(); - dest_buffer.Write(&version, 0, sizeof(version)); + const auto cfg = Service::CFG::GetModule(cecd->system); + const auto version = cfg->GetEULAVersion(); + buffer = {version.minor, version.major}; break; } case CecSystemInfoType::Eula: - buffer = {0x01}; // Eula agreed - dest_buffer.Write(buffer.data(), 0, buffer.size()); + buffer = {true}; // Eula agreed break; case CecSystemInfoType::ParentControl: - buffer = {0x00}; // No parent control - dest_buffer.Write(buffer.data(), 0, buffer.size()); + buffer = {false}; // No parent control break; default: LOG_ERROR(Service_CECD, "Unknown system info type={:#x}", info_type); + buffer = {}; } + dest_buffer.Write(buffer.data(), 0, + std::min(static_cast(dest_buffer_size), buffer.size())); rb.Push(RESULT_SUCCESS); rb.PushMappedBuffer(param_buffer); diff --git a/src/core/hle/service/http/http_c.cpp b/src/core/hle/service/http/http_c.cpp index c0db50f5c8..c24767bcc4 100644 --- a/src/core/hle/service/http/http_c.cpp +++ b/src/core/hle/service/http/http_c.cpp @@ -314,6 +314,7 @@ void HTTP_C::ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout) { } else { LOG_WARNING(Service_HTTP, "(STUBBED) called"); } + [[maybe_unused]] Kernel::MappedBuffer& buffer = rp.PopMappedBuffer(); Kernel::MappedBuffer& buffer = rp.PopMappedBuffer(); diff --git a/src/core/hle/service/http/http_c.h b/src/core/hle/service/http/http_c.h index 0e08aa7dff..41fb2183fc 100644 --- a/src/core/hle/service/http/http_c.h +++ b/src/core/hle/service/http/http_c.h @@ -17,12 +17,10 @@ #include #include #include -#ifdef ENABLE_WEB_SERVICE #if defined(__ANDROID__) #include #endif #include -#endif #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/service.h" @@ -214,7 +212,6 @@ public: bool uses_default_client_cert{}; #ifdef ENABLE_WEB_SERVICE httplib::Response response; -#endif }; struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase { diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 62f82d8ba3..f1e2801fb3 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -316,7 +316,7 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) { if (nfc->nfc_mode == CommunicationMode::TrainTag) { LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode); - IPC::RequestBuilder rb = rp.MakeBuilder(26, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(25, 0); rb.Push(RESULT_SUCCESS); rb.PushRaw({}); return; @@ -324,7 +324,7 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) { TagInfo2 tag_info{}; const auto result = nfc->device->GetTagInfo2(tag_info); - IPC::RequestBuilder rb = rp.MakeBuilder(26, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(25, 0); rb.Push(result); rb.PushRaw(tag_info); } @@ -383,10 +383,14 @@ void Module::Interface::OpenApplicationArea(Kernel::HLERequestContext& ctx) { void Module::Interface::CreateApplicationArea(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); u32 access_id = rp.Pop(); - [[maybe_unused]] u32 size = rp.Pop(); + u32 size = rp.Pop(); std::vector buffer = rp.PopStaticBuffer(); - LOG_CRITICAL(Service_NFC, "called, size={}", size); + LOG_INFO(Service_NFC, "called, size={}", size); + + if (buffer.size() > size) { + buffer.resize(size); + } if (nfc->nfc_mode != CommunicationMode::Amiibo) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -402,8 +406,9 @@ void Module::Interface::CreateApplicationArea(Kernel::HLERequestContext& ctx) { void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); + u32 size = rp.Pop(); - LOG_INFO(Service_NFC, "called"); + LOG_INFO(Service_NFC, "called, size={}", size); nfc->device->RescheduleTagRemoveEvent(); @@ -413,7 +418,7 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) { return; } - std::vector buffer(sizeof(ApplicationArea)); + std::vector buffer(size); const auto result = nfc->device->GetApplicationArea(buffer); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); @@ -423,11 +428,15 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) { void Module::Interface::WriteApplicationArea(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx); - [[maybe_unused]] u32 size = rp.Pop(); + u32 size = rp.Pop(); std::vector tag_uuid_info = rp.PopStaticBuffer(); std::vector buffer = rp.PopStaticBuffer(); - LOG_CRITICAL(Service_NFC, "called, size={}", size); + LOG_INFO(Service_NFC, "called, size={}", size); + + if (buffer.size() > size) { + buffer.resize(size); + } if (nfc->nfc_mode != CommunicationMode::Amiibo) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -540,7 +549,7 @@ void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) { ModelInfo model_info{}; const auto result = nfc->device->GetModelInfo(model_info); - IPC::RequestBuilder rb = rp.MakeBuilder(0x1F, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(14, 0); rb.Push(result); rb.PushRaw(model_info); } diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp index 18ac135cc2..107ff8101c 100644 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ b/src/core/hle/service/nfc/nfc_device.cpp @@ -1101,8 +1101,8 @@ void NfcDevice::BuildAmiiboWithoutKeys() { } void NfcDevice::RescheduleTagRemoveEvent() { - /// The interval at which the amiibo will be removed automatically 1.5s - static constexpr u64 amiibo_removal_interval = nsToCycles(1500 * 1000 * 1000); + /// The interval at which the amiibo will be removed automatically 3s + static constexpr u64 amiibo_removal_interval = msToCycles(3 * 1000); system.CoreTiming().UnscheduleEvent(remove_amiibo_event, 0); diff --git a/src/web_service/nus_download.cpp b/src/core/nus_download.cpp similarity index 93% rename from src/web_service/nus_download.cpp rename to src/core/nus_download.cpp index af7a068a69..d9d79ae2bb 100644 --- a/src/web_service/nus_download.cpp +++ b/src/core/nus_download.cpp @@ -5,9 +5,9 @@ #include #include #include "common/logging/log.h" -#include "web_service/nus_download.h" +#include "core/nus_download.h" -namespace WebService::NUS { +namespace Core::NUS { std::optional> Download(const std::string& path) { constexpr auto HOST = "http://nus.cdn.c.shop.nintendowifi.net"; @@ -46,4 +46,4 @@ std::optional> Download(const std::string& path) { return std::vector(response.body.begin(), response.body.end()); } -} // namespace WebService::NUS +} // namespace Core::NUS diff --git a/src/web_service/nus_download.h b/src/core/nus_download.h similarity index 85% rename from src/web_service/nus_download.h rename to src/core/nus_download.h index 34633b7677..8953906bf6 100644 --- a/src/web_service/nus_download.h +++ b/src/core/nus_download.h @@ -8,8 +8,8 @@ #include #include "common/common_types.h" -namespace WebService::NUS { +namespace Core::NUS { std::optional> Download(const std::string& path); -} +} // namespace Core::NUS diff --git a/src/core/savestate.cpp b/src/core/savestate.cpp index ecf8b9d4dd..e0ed958df1 100644 --- a/src/core/savestate.cpp +++ b/src/core/savestate.cpp @@ -15,18 +15,21 @@ #include "core/core.h" #include "core/movie.h" #include "core/savestate.h" +#include "core/savestate_data.h" #include "network/network.h" namespace Core { #pragma pack(push, 1) struct CSTHeader { - std::array filetype; /// Unique Identifier to check the file type (always "CST"0x1B) - u64_le program_id; /// ID of the ROM being executed. Also called title_id - std::array revision; /// Git hash of the revision this savestate was created with - u64_le time; /// The time when this save state was created + std::array filetype; /// Unique Identifier to check the file type (always "CST"0x1B) + u64_le program_id; /// ID of the ROM being executed. Also called title_id + std::array revision; /// Git hash of the revision this savestate was created with + u64_le time; /// The time when this save state was created + std::array build_name; /// The build name (Canary/Nightly) with the version number + u32_le zero = 0; /// Should be zero, just in case. - std::array reserved{}; /// Make heading 256 bytes so it has consistent size + std::array reserved{}; /// Make heading 256 bytes so it has consistent size }; static_assert(sizeof(CSTHeader) == 256, "CSTHeader should be 256 bytes"); #pragma pack(pop) @@ -58,11 +61,26 @@ static bool ValidateSaveState(const CSTHeader& header, SaveStateInfo& info, u64 return false; } const std::string revision = fmt::format("{:02x}", fmt::join(header.revision, "")); + const std::string build_name = + header.zero == 0 ? reinterpret_cast(header.build_name.data()) : ""; + if (revision == Common::g_scm_rev) { info.status = SaveStateInfo::ValidationStatus::OK; } else { - LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, - revision); + if (!build_name.empty()) { + info.build_name = build_name; + } else if (hash_to_version.find(revision) != hash_to_version.end()) { + info.build_name = hash_to_version.at(revision); + } + if (info.build_name.empty()) { + LOG_WARNING(Core, "Save state file {} created from a different revision {}", path, + revision); + } else { + LOG_WARNING(Core, + "Save state file {} created from a different build {} with revision {}", + path, info.build_name, revision); + } + info.status = SaveStateInfo::ValidationStatus::RevisionDismatch; } return true; @@ -134,6 +152,10 @@ void System::SaveState(u32 slot) const { header.time = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); + const std::string build_fullname = Common::g_build_fullname; + std::memset(header.build_name.data(), 0, sizeof(header.build_name)); + std::memcpy(header.build_name.data(), build_fullname.c_str(), + std::min(build_fullname.length(), sizeof(header.build_name) - 1)); if (file.WriteBytes(&header, sizeof(header)) != sizeof(header) || file.WriteBytes(buffer.data(), buffer.size()) != buffer.size()) { diff --git a/src/core/savestate.h b/src/core/savestate.h index 84daf47789..2962cce864 100644 --- a/src/core/savestate.h +++ b/src/core/savestate.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "common/common_types.h" @@ -16,6 +17,7 @@ struct SaveStateInfo { OK, RevisionDismatch, } status; + std::string build_name; }; constexpr u32 SaveStateSlotCount = 10; // Maximum count of savestate slots diff --git a/src/core/savestate_data.h b/src/core/savestate_data.h new file mode 100644 index 0000000000..5ae9346b90 --- /dev/null +++ b/src/core/savestate_data.h @@ -0,0 +1,1427 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +namespace Core { + +std::map hash_to_version = { + {"c605bb42dbb364cc0977c417aed0630d74b05c25", "nightly-1481"}, + {"47829ee095aa398494f4068919ca83ea2a32caee", "nightly-1482"}, + {"8967b403b984134fddf99a8c2a5158af177d5fba", "nightly-1483"}, + {"79a0cbbba8603becb2c14b57aa9bf6475936aae9", "nightly-1484"}, + {"c8a503b10fe05784ed18a2488bc8fe10569ceac9", "nightly-1485"}, + {"75c9784239215cdf21367137a049cca52b84597a", "nightly-1486"}, + {"397bd1bb7381eaa34ed7c3bcf18661bd3f66fcbb", "nightly-1487"}, + {"b96b7ab3f6bd48ef86dcd3cf37c15f1ba0a4ac4b", "nightly-1488"}, + {"e54b640e0ba77b0126e928aa5fe6ed318cb927de", "nightly-1489"}, + {"8014c67faa11e6d2daa402724679170a4a7f32f6", "nightly-1490"}, + {"182aa1e39d65fc81d1fbd04465a6179600eece5e", "nightly-1491"}, + {"08dddbac4c462ece8554d302a655b5e1de89707f", "nightly-1492"}, + {"1856752b6171368101768cc37029c36ffd13f9a2", "nightly-1493"}, + {"362956a69bc3a31c9ec7a42ae8ff6bf2dee12cce", "nightly-1494"}, + {"ca722f1bb13ce33e1e848c994e7dcdd109fa1ab3", "nightly-1495"}, + {"0f72dd6d85b1d4e6cc49f47d6be68d8a38f9b51d", "nightly-1496"}, + {"df92b37bbff02e4a1d132df48b5210700a62af6d", "nightly-1497"}, + {"acf18ce4dd699ab93140ce91b3aab36edea5641d", "nightly-1498"}, + {"1469ad339c4d3848eef742aa4a1247c963c1a248", "nightly-1499"}, + {"bcc80d08712191a9485c63fd74570877245c340a", "nightly-1500"}, + {"3597921ec5745cd20255aa210c5292eace69949c", "nightly-1501"}, + {"d5a962cb8101fdc0bb9722a1be1a9b8d2f77e2e9", "nightly-1502"}, + {"b82d4315fefb4fc8803e2b65e0dc9252548bd402", "nightly-1503"}, + {"db5b8b9c88512f86327740a0b609057a3b08cbab", "nightly-1504"}, + {"8b43dff8493f797604d28e3a779edfa8dd381144", "nightly-1505"}, + {"38c3c9c74b704050d72e397feb290db2e616209a", "nightly-1506"}, + {"39463f1f6d25164d433a347ef85b95ec1577cdc9", "nightly-1507"}, + {"77ffe37c46af8a91f34e973971042948792a7790", "nightly-1508"}, + {"bc14f485c41311c8d4bc7d830a963ca45b9b9b25", "nightly-1509"}, + {"f18aef0579c7ac42bc4d82a38ea954510667fa14", "nightly-1510"}, + {"ed304e28779511c88c413af1fcab2ff2aec3b88b", "nightly-1511"}, + {"8a0b0c2fc7883a45492a3248b04a4ca48585a427", "nightly-1512"}, + {"9dc0f38ffd40b80f27366aa6b61cfbdba7c1665c", "nightly-1513"}, + {"96832a2c82807876925126bc7a0e3b546a952c74", "nightly-1514"}, + {"98fe5f82c58f76dbc9730f9b82257993c8e77cc9", "nightly-1515"}, + {"c937876935d50edf6ec98f2a9b7a15f1efbd92dd", "nightly-1516"}, + {"64694b0f114e4709ccb3e9b62ff061518fe8cca9", "nightly-1517"}, + {"4a677e83fee0c1cb620f650ce0ab6a9c9d84d3fc", "nightly-1518"}, + {"85d37c99943817e3f41346127c3633ad59a8b716", "nightly-1519"}, + {"fd1b254635cef6ac3393a960423d4388ed6e8cc9", "nightly-1520"}, + {"1bb9a71a0142747ba6dd0899f139d0d527f1263d", "nightly-1521"}, + {"2eacb11c5390b42da1369ef82155451ecf950750", "nightly-1522"}, + {"6a0636d631077487e1039652300e2e20b78301d2", "nightly-1523"}, + {"017f0c469e778ffd1c5b6e3b12739362261fa562", "nightly-1524"}, + {"037c857bd6153c415f61eec21199541a39ab10d7", "nightly-1525"}, + {"4d7487bd34024f7a5be6b909827934041524caf3", "nightly-1526"}, + {"59984df6032befcaec0dbd520b2fe7455d0f46fa", "nightly-1527"}, + {"69075680344f37bf6bb9a615a39d3a7837f5ff6e", "nightly-1528"}, + {"5a008a74fa61f0d363e9112f5afe139f6e4d69f3", "nightly-1529"}, + {"8e7abecf7eca9e22b596c3db0c1808b8cc4ac91a", "nightly-1530"}, + {"70a43be714bf251505670f8bd865bcf2b8a4c9f8", "nightly-1531"}, + {"e212dc3a1f1c6038a75a14bd059e77636180cee9", "nightly-1532"}, + {"2476532f216c0a3d32981600bbcfa465f46eb20f", "nightly-1533"}, + {"eb996f046d402fe4a3cca31476d0c3a9e8aad6aa", "nightly-1534"}, + {"41bff0e3b780072acc9c5fabff8d026b2f97c7af", "nightly-1535"}, + {"36809b2e2edf49ef1211180908b2a1ea0cc63066", "nightly-1536"}, + {"e959d44f0024d65bca587b8fc77ddcf7e807402a", "nightly-1537"}, + {"96ebd534669644d6d1eac778678234abe2c1fc9c", "nightly-1538"}, + {"8a691725706ced0488e1b609aa7a7992c397cd84", "nightly-1539"}, + {"007fb63e47f1e0ea30ebce9c87017b1a34d6d636", "nightly-1540"}, + {"4892d37309d01c5f6457359ee268b8333e51992e", "nightly-1541"}, + {"8d27b0714dc6dfcfb8fda3fa482b391fd9fa4c2d", "nightly-1542"}, + {"d11d600b61e44599a3b7379727263396e51b6ef4", "nightly-1543"}, + {"57aa18f52ea35ca74cd1a6c406a4abf04049b44e", "nightly-1544"}, + {"63c86f24177e779b859eb897d6968df69a2ab276", "nightly-1545"}, + {"307b8f923b36c4e6dc7632f888e895f632654558", "nightly-1546"}, + {"213c956b7ce15a2ceabceef7539b881b1934467c", "nightly-1547"}, + {"51dfc46d3f00c33e4ddf884da7581c5982f34546", "nightly-1548"}, + {"c4ba7b362696ff424044856974d9ae8e2263dd73", "nightly-1549"}, + {"028609d548fe672302fe307bcc4c33ddc52c4c1c", "nightly-1550"}, + {"61c8ea3fe9df8a1a4b75f10c4d864ef3f53f394e", "nightly-1551"}, + {"7dc472a3a78f31039b49bc058682d90a565c8398", "nightly-1552"}, + {"81a1e5680f93189d6029f579b4b261b2aa552818", "nightly-1553"}, + {"76253063a37e70733ac3ede712cd18cfcdff5bd6", "nightly-1554"}, + {"dbd1a389ef14e2b51f9f90ecf706327366b203d4", "nightly-1555"}, + {"0b307a86a6ea5dfb3a35ec2bb8397fab71a70dac", "nightly-1556"}, + {"1643cf5b86f64d9700ad0654b1639ec819dc2b67", "nightly-1557"}, + {"edb5977fba8109521e127ff7fc5d7b320fd56ce8", "nightly-1558"}, + {"e6ad0d390ef9fae9360fb783907d0ffba9d38326", "nightly-1559"}, + {"565e5988efa79cf1072700b8d5d24ff78803145c", "nightly-1560"}, + {"2632b421c2dbae05cdcf2d7a010dc36db1860889", "nightly-1561"}, + {"9b20ff0369c2f305a6bdcbb7658027cec101ea38", "nightly-1562"}, + {"5b245aafd32c9aa8c35d00cf4a197f070e3ed0f6", "nightly-1563"}, + {"16913feb4441ffba1a57347953a8a6aa0103e5c5", "nightly-1564"}, + {"2e24183e53e5343f24f5e3cb630235ceac762ee2", "nightly-1565"}, + {"1504018a566e99967191f6ecf5c5fce3caf4a403", "nightly-1566"}, + {"f7aaa37bf2bfdc3480fbbd398900b199a110b566", "nightly-1567"}, + {"8ce81b19be1a9161c829aec4e0a9521fa8aef57d", "nightly-1568"}, + {"353780e1c9ad5326cdd4b8019234413e3c51911d", "nightly-1569"}, + {"902cc1eb495953274360914c016320e62a971c91", "nightly-1570"}, + {"cb44e4408d5e3fd6ec4f7c39c51aa094389408ba", "nightly-1571"}, + {"8a080146c92bf95336025306481f2d056c504499", "nightly-1572"}, + {"8a080146c92bf95336025306481f2d056c504499", "nightly-1573"}, + {"3090f840a87b5fde58e53f0576d1f7e523514f54", "nightly-1574"}, + {"6d65319c85a7bc032d27f93841ab1e27dd6d93be", "nightly-1575"}, + {"485d64ae7396ede1a37c6fa46185976c0cf0cd2c", "nightly-1576"}, + {"372c653ec33a770fb4fda0969c3a87b12e54e63c", "nightly-1577"}, + {"7444c95132e40098ea4a5166b717f7af813cc385", "nightly-1578"}, + {"e79de3107e0b8e36e5565b615efbf5e15f3aa861", "nightly-1579"}, + {"c4a4b40b2d51a60af3c0450074580a65906ba57a", "nightly-1580"}, + {"c4a4b40b2d51a60af3c0450074580a65906ba57a", "nightly-1581"}, + {"c4a4b40b2d51a60af3c0450074580a65906ba57a", "nightly-1582"}, + {"c4a4b40b2d51a60af3c0450074580a65906ba57a", "nightly-1583"}, + {"910cc9efc18fa3cb1fbc897715afcdd5e8b12f23", "nightly-1584"}, + {"835efd321e2ee361ad76cb4bb077efefe7396dcf", "nightly-1585"}, + {"bd7ee8c315760b3e91a490254370bd3ccfb24bdc", "nightly-1586"}, + {"bd7ee8c315760b3e91a490254370bd3ccfb24bdc", "nightly-1587"}, + {"f4e727cc19f9b6fe56fe54673217425e29bc036a", "nightly-1588"}, + {"96fa75fb93a3dea4a8fbe72bde23b16979057a43", "nightly-1589"}, + {"a83f81916046f673482b522d695874220eb5faf0", "nightly-1590"}, + {"897e473da4e1d5771a5eee021842e427336d623d", "nightly-1591"}, + {"1722701c07088593f1db605ff97d9d6865899f5e", "nightly-1592"}, + {"f6ced5def024192257667b8c21322fb2eb654890", "nightly-1593"}, + {"d88d22080da40fcfcbc88fb3aa3e4cbc7d1e791f", "nightly-1594"}, + {"a34888804b3eb0c150dcd78514a72834075b37fd", "nightly-1595"}, + {"a34888804b3eb0c150dcd78514a72834075b37fd", "nightly-1596"}, + {"c3673ac9cd342839e1b5a41408e7867f50b3c9fc", "nightly-1597"}, + {"b4ec50ba217591d24f25a7765c275b86044fd04f", "nightly-1598"}, + {"b94f21eacdd41d321c9b62730e119cd5495eb2c1", "nightly-1599"}, + {"57da84ba63f0ba0ae6979e5ff27b13e2f4c80ef6", "nightly-1600"}, + {"f72be7af2dd1706cbbd80a9baae417e17752a1b0", "nightly-1601"}, + {"2a676858be6cb384a5473472861d71add9941598", "nightly-1602"}, + {"f2d26eb73b5361490b9aa78e2b1ad2a5941587d4", "nightly-1603"}, + {"69f4aacccf2b35c1bb618e1cf7eaa4b22b08cb78", "nightly-1604"}, + {"550cc859b5ad537f0098233869918539101295c3", "nightly-1605"}, + {"88c0288cb1d1fa029c55fbb8ba7ced384f97c699", "nightly-1606"}, + {"855dc9f0fce8b768c6f468febe3c6772f2f776ef", "nightly-1607"}, + {"a5fd11c213b374b47b07f4fa445a297da881fce7", "nightly-1608"}, + {"08e508e846d04652a9e3bd12872b9fef1dee4712", "nightly-1609"}, + {"4135a12cb5121ce45a565c90efc6869b8391f371", "nightly-1610"}, + {"e48110bdf4f97fd43b940f9394964ab0e0ad3654", "nightly-1611"}, + {"f6b543886c42def34369451927be6dbf8d3e1b4f", "nightly-1612"}, + {"f4be7333556e6c6a12f77276dc5bef1895a44bff", "nightly-1613"}, + {"a39e0ea3b16d254dc2f9fa5eeb697ca1f6c2642b", "nightly-1614"}, + {"2f01046f77180c649c7508c6f7cd8e4a8624fcd5", "nightly-1615"}, + {"66846836bc7017a0c5a34f7718b4e0dcdfe2472c", "nightly-1616"}, + {"6a77547bdee43ee67e3199354dd3de22f3b4a232", "nightly-1617"}, + {"316a64961c3809e0feaa9fb362c49467a22c58ab", "nightly-1618"}, + {"e97ecdc2b838b83fe018a76a73292a7c0ae6d1f0", "nightly-1619"}, + {"df83449d2115922e0651697e70a79f8c818913fa", "nightly-1620"}, + {"df9e230d63970a379c31d9be64d39a127ef3618c", "nightly-1621"}, + {"017631e51b1977ac69e905613cbae0385fd9ede0", "nightly-1622"}, + {"a576eb633fbe55619f8728dab15df143b451143a", "nightly-1623"}, + {"a26b466ac819cd710b6cfcdcbdcb8905c83e7bff", "nightly-1624"}, + {"ff9c3b0531dc84f7b32a852416b7e88f7dce2162", "nightly-1625"}, + {"1032b60d9bb41f24dfa693896ad827f9c7df4d60", "nightly-1626"}, + {"aced133a3d80de3b58bf3c9c8ef555ede79b6c1c", "nightly-1627"}, + {"1c8461fdea1106c68729643525c365afc93f5621", "nightly-1628"}, + {"1bb20571b1b21ad5c61b1cfce4cbd6244c24ad8a", "nightly-1629"}, + {"2e0ce86c9ef82b92f98695e8ab49e5485e796513", "nightly-1630"}, + {"0133ebe0bcbe867eb7f45f58b7826b583ec6fb2c", "nightly-1631"}, + {"045efe8268a7429ada9054ce5dd7c31c4f247287", "nightly-1632"}, + {"bf03fb83aef1b4eb13b11dd6523940d096b9fa49", "nightly-1633"}, + {"80c9f9abbba054dfb59e252bf57a75924ace4488", "nightly-1634"}, + {"de3d7cf49feaa3ac2b2e50cce2e819f3364e043c", "nightly-1635"}, + {"23b67849d5de6cb6536c05c58878db5e9823b188", "nightly-1636"}, + {"a89261d3975f48f035a91e14061fa2df18f7956d", "nightly-1637"}, + {"7a8d5761647cd7d038881f07a15c37396aec54d8", "nightly-1638"}, + {"6772e46153c4ec5dfbb1843c343adda2d4cdc55f", "nightly-1639"}, + {"3115529be7e8a974254bce2a945486bdf904d4c0", "nightly-1640"}, + {"02d6032afb1069b1ea908c3ec14cf1a715bd6867", "nightly-1641"}, + {"1aaec7938fbe7b00652b3e9d9823c625c1e5e23d", "nightly-1642"}, + {"4efeace8eeea982dd21a0d8b43dee8cf2958a509", "nightly-1643"}, + {"2d972f91b28d03aa3939ed956a5d998bf0fda3cc", "nightly-1644"}, + {"4f058c04e8f57148b55330e1bffdcefb6c79e360", "nightly-1645"}, + {"3fa12d43f584b9b0d5ec473f151d3725d1310ad1", "nightly-1646"}, + {"182ffa4243fd1f5dc0627df9f1755384ce8f7f48", "nightly-1647"}, + {"21fb9d63f45c2bafcc02996097028c55024f35db", "nightly-1648"}, + {"a13a23051140aa29e8e8c40999651020df84b2b1", "nightly-1649"}, + {"7ae0fc73385730d53a645306396b50a30b47f418", "nightly-1650"}, + {"2f5eec3576a961ec1a21368166cab676e9db3043", "nightly-1651"}, + {"36780040a621170107f6a927280fde75f238b7ec", "nightly-1652"}, + {"664f5da105f763d2a40680d64e537ead60d2b3a3", "nightly-1653"}, + {"6f45b402e751ba7bcaed6ee5c7afbd79f7f4f875", "nightly-1654"}, + {"4888a14c12f5923f9974423370b24b1e392ff973", "nightly-1655"}, + {"c557b290afd3f93b2ff1653701b110022c2a28f7", "nightly-1656"}, + {"702af87f0dedf9d369d9f91e13f9529b9c49721b", "nightly-1657"}, + {"f0e3637c7a133021a33def8694d712605cc46e81", "nightly-1658"}, + {"3f13e1cc2419fac837952c44d7be9db78b054a2f", "nightly-1659"}, + {"94d1f695eed6c34d7687e89405cd42e9c72fa56a", "nightly-1660"}, + {"94013c8e00ccf1bde9d02c2d86630e0df900c8e3", "nightly-1661"}, + {"26e8b755f0709dc6bce5715837652aca134bda83", "nightly-1662"}, + {"3c1211e9fef2c4447dbf6e21ad2a99828b53a82a", "nightly-1663"}, + {"39e0644993739d01c91c4dfbc0eefff59e5243ac", "nightly-1664"}, + {"987f910a86f3b43ccb5d77ceb4805102031e262c", "nightly-1665"}, + {"ab6c605e59be18e952e5de90640f4d926fc4ae23", "nightly-1666"}, + {"820c288236047f7d9df7bd484567a2f133bdc566", "nightly-1667"}, + {"e6ef00b41ddd75326c4a1337aeebe14b8fa34bbb", "nightly-1668"}, + {"5f1eb7146d6ad4d7cfefff43d36f96b35388c55e", "nightly-1669"}, + {"6f2bbbcced474363d23e6e6ed7a1564cbaab7679", "nightly-1670"}, + {"ce16653cc81a1298a34741a7af4808da988a190f", "nightly-1671"}, + {"1265c37babe0cee93e68c5c866a8be600602c6da", "nightly-1672"}, + {"f00c4a4cf53c665b8d30ba12f99923500a106c3a", "nightly-1673"}, + {"9c76120a132a65301fac8e283096ab5b8863f6f0", "nightly-1674"}, + {"755393da9045047bc96b0ffda66ecba3991dd2f5", "nightly-1675"}, + {"c1d7ba4d60da30e0dffe763c0d654763c98895a3", "nightly-1676"}, + {"50eb63458320ed5fc8e8268b3457d719e72df927", "nightly-1677"}, + {"e33677b021836d8f28cea69ced807cfa208d4e17", "nightly-1678"}, + {"7c6d7905a4958fa7856821b97ecf84d134184485", "nightly-1679"}, + {"8df502a6883c231c1318f7cb3b29509bed12ddd0", "nightly-1680"}, + {"2539215f1824828e19a70799a7a9c5b973d8646b", "nightly-1681"}, + {"2461f67a98800547105a1c239b56878e51e2d33c", "nightly-1682"}, + {"2461f67a98800547105a1c239b56878e51e2d33c", "nightly-1683"}, + {"a1d6396a900473c35a7f34bf86c73713d26a3345", "nightly-1684"}, + {"e2adb514942f5737225c07597db14cf3919b07b4", "nightly-1685"}, + {"6b2e7b77cccf718e99152597aef1f77b87c1920e", "nightly-1686"}, + {"2e3834f880d6c3ebeea24e2374e2beb2a471a2e6", "nightly-1687"}, + {"e770fd6e95e55528ef24085dc3e4279c20e22f32", "nightly-1688"}, + {"5776bdda827787a1f91ae76f4131683626df7658", "nightly-1689"}, + {"2ddecf35d261e5765ccb1f1dc6646241684cc237", "nightly-1690"}, + {"5c58620618810cdcccb05381fa7e11020e5cfd2a", "nightly-1691"}, + {"e6c479f497612a0ae1c00ad9c85d5af715495d46", "nightly-1692"}, + {"e6c479f497612a0ae1c00ad9c85d5af715495d46", "nightly-1693"}, + {"e6c479f497612a0ae1c00ad9c85d5af715495d46", "nightly-1694"}, + {"c2d36cde9fa175950d7eeb61320802ffed0cb32d", "nightly-1695"}, + {"8e3c7674d82df8db66e9cdf6a5d8b0e678a7f720", "nightly-1696"}, + {"b3cab3c4507dc1b28e2f15b2e0c9f473f6e1959f", "nightly-1697"}, + {"b9d7181a63ddfd40e8f94e83177737872cf3a985", "nightly-1698"}, + {"33e5d16c89d9bbc451f30a526821f69f8ff1f9da", "nightly-1699"}, + {"71b8ddb8a9b83655dccdb2d1a4d4cf7127259bb7", "nightly-1700"}, + {"78b8dfc808378214857de148ad00d06a19b51ca0", "nightly-1701"}, + {"24086d05bbdc4c4ae7daaa076b2c8566da6bf09c", "nightly-1702"}, + {"9ff97270cf128f5ce91449ab7d4ad7b62d201b40", "nightly-1703"}, + {"86b775bd8f3e1ab5f3a6e6546ae888a6907a641e", "nightly-1704"}, + {"edbd6dfe8aad7dd1b626aaf20037d8ede6127bb6", "nightly-1705"}, + {"6e16081b6a606f6ba3dd946f9fff247b51433a16", "nightly-1706"}, + {"a2f34ea82b5a31a7e842d0099921b85b8bce403f", "nightly-1707"}, + {"e7671d93b296c1f17040d4dd423cb8b710d67677", "nightly-1708"}, + {"7325f58763dea2de5838f21da860300b63ad220c", "nightly-1709"}, + {"82aedb9900ee0b204550140a8935ca801a811cdd", "nightly-1710"}, + {"842031a2eb0b4bac4a351db914530296812962d1", "nightly-1711"}, + {"324e88d6e08ab8bc95671e6ba8011fc8812ac2c9", "nightly-1712"}, + {"3d8555236fb18fa90c07b47897a790fbb174c34d", "nightly-1713"}, + {"5241032fc58b322e0ede29966dd28490ef0c3cb8", "nightly-1714"}, + {"afed4953bccfb9b39558cf196492c2558ca1f109", "nightly-1715"}, + {"62236b725760bdbc9087894ad4496e9a7d942951", "nightly-1716"}, + {"647a6f8d821d7cb0e0855fecb7fa3bfd5414c600", "nightly-1717"}, + {"dd31ed60c009e2977f746a591ff063d6a921970b", "nightly-1718"}, + {"dfd7926681ce073ee3625b15f85db4278a2a2b7d", "nightly-1719"}, + {"c40871f126a5942b16b8b240d256b59e25b5e7ae", "nightly-1720"}, + {"89410c164ad023d2dd24961b435733123e538d9d", "nightly-1721"}, + {"a1b4daa9d4b97c0afc173c8cbb737387edd7a8d4", "nightly-1722"}, + {"4817b008434e2122679568d1223af4c656f0d2fd", "nightly-1723"}, + {"19617f7edbbc0d709508045770877a85d586ab9a", "nightly-1724"}, + {"7bf0f10305a39a478a1fec8b3581a064a0ccbebc", "nightly-1725"}, + {"d4e85e2bb5cd9678eb648c414e30adaad58e1fad", "nightly-1726"}, + {"6183b5d76c30f62c09fc0940838f32458addfe28", "nightly-1727"}, + {"90192124cc644248c5b192e08e96a6bbbe7e0eae", "nightly-1728"}, + {"ec96ee4371a9b166b0cd9fcec1e44295981418b6", "nightly-1729"}, + {"a5d01c0c1543be2a51aa9f9e8d9d06f67ff92c0d", "nightly-1730"}, + {"219eaabbcf9fbad968a15bb3873eda721a0e9298", "nightly-1731"}, + {"5a7d80172dd115ad9bc6e8e85cee6ed9511c48d0", "nightly-1732"}, + {"8dfd9d344563d9f9c9120318350499f560383650", "nightly-1733"}, + {"64b502aad36a22a98e7adf69a1293b524e571125", "nightly-1734"}, + {"6dfb74a8b976063591caa5d4cda52c4df44f1dce", "nightly-1735"}, + {"83913e68f360209f34d120b525b8592ac00c4b44", "nightly-1736"}, + {"d6356f5e9f9a1ef73e83c28d742a6d6ae44770cd", "nightly-1737"}, + {"60d1def6f8923cdc7ee64e087b15461f3723157f", "nightly-1738"}, + {"60d1def6f8923cdc7ee64e087b15461f3723157f", "nightly-1739"}, + {"2670b951e13eab51e47e45263cd3ac4e44fa1ff5", "nightly-1740"}, + {"67f1e4111dc81c562228aa158b01beaff61d732e", "nightly-1741"}, + {"67f1e4111dc81c562228aa158b01beaff61d732e", "nightly-1742"}, + {"45a4a56264b3d26b4dd1a16b13feda4f9fd5fe37", "nightly-1743"}, + {"45a4a56264b3d26b4dd1a16b13feda4f9fd5fe37", "nightly-1744"}, + {"45a4a56264b3d26b4dd1a16b13feda4f9fd5fe37", "nightly-1745"}, + {"45a4a56264b3d26b4dd1a16b13feda4f9fd5fe37", "nightly-1746"}, + {"45a4a56264b3d26b4dd1a16b13feda4f9fd5fe37", "nightly-1747"}, + {"4e15823db236feeee0f43a9c41434e8489146758", "nightly-1748"}, + {"2fc7def6f67be153e3bb81116209f233e75d9ec2", "nightly-1749"}, + {"2fc7def6f67be153e3bb81116209f233e75d9ec2", "nightly-1750"}, + {"2fc7def6f67be153e3bb81116209f233e75d9ec2", "nightly-1751"}, + {"bae1c31406874294cfcc819945d3d317105a2fdf", "nightly-1752"}, + {"cdbd72e79c9f91fd8261fd3bc2fa25b883a17fbe", "nightly-1753"}, + {"54a36bc54f066ca3f8b578e95bb80e8f176a68d6", "nightly-1754"}, + {"db5edf549e3013a0d8862d56c52f6ed0ea522561", "nightly-1755"}, + {"25ad002e6e7301b5c62bbde129a273e53027e9be", "nightly-1756"}, + {"ac98458e0b234e13936a9c2a98a413408d0f08c9", "nightly-1757"}, + {"b5ac9e494615444f5b7144e7c818bee52cacbaee", "nightly-1758"}, + {"3df43f9505505fbe2abb543c795f791615541cd4", "nightly-1759"}, + {"593b0b2d8fe8c7bde82f53e58520c12b2d567d48", "nightly-1760"}, + {"4a9995ab9f7db6441804084e5d70fb3db8e33e8d", "nightly-1761"}, + {"1382035d4de5ada310c7f4fd00f1836b16ab74fb", "nightly-1762"}, + {"856b3d6c9567d3a37f90c7d0b7418b20e6bb2aba", "nightly-1763"}, + {"44e1f2319facc30a5625c525811546ab2be5c76b", "nightly-1764"}, + {"46c6e5c4c0d79b3343042fd22bea1c48b8283da6", "nightly-1765"}, + {"a6e7a81de949883adf4f654ad773a80eb0931d00", "nightly-1766"}, + {"6f6a9357c26eccf09bf0c993f159d69bbe472f49", "nightly-1767"}, + {"b7c1c21019dc54f7ad647989e0e3d912584cf455", "nightly-1768"}, + {"3bb027ac12ddedec42f4ada49b7e9dbfcf8d3933", "nightly-1769"}, + {"88a475970240e1dbade1720b02f9e5338647b1b8", "nightly-1770"}, + {"84d5d62cf59da7e001bad6b7298e45faac37fbeb", "nightly-1771"}, + {"355933218d00603c910cd0a9daead0b1cd72a3c3", "nightly-1772"}, + {"353aaaf665d70999f7ee524b3b84914944627a45", "nightly-1773"}, + {"2d95b9946f207987cd4f3b4c3a1eb58b17c99767", "nightly-1774"}, + {"357025dfdf2b08204b0a3ae38330dc5fe3f05103", "nightly-1775"}, + {"6764264488488a97ddb60be07f59c0750cc173a7", "nightly-1776"}, + {"bf6e4a41d79d3bbee96d90bab32ddb20e20968eb", "nightly-1777"}, + {"a51b1cd3cd0122110a31d17d8b84d7d2c50b1f7e", "nightly-1778"}, + {"58d0705f0f00db4edb09d178083b9fbca5d0b57e", "nightly-1779"}, + {"ec7dc8803f195cc4d35545d588a8d57e929c93c0", "nightly-1780"}, + {"141471e38fc2b0f6295f28c65f815968f3e9f564", "nightly-1781"}, + {"d38098051d74d19b4b198fcaef7465cedb984fd4", "nightly-1782"}, + {"746609f35fae6ba174848d2ffa42e52b140bcbd1", "nightly-1783"}, + {"47c4f31c8db86b043a1802a65f1df08aeec8e772", "nightly-1784"}, + {"baecc18d8c5365af0dddb231bc8c0a9c03850bf6", "nightly-1785"}, + {"cbd5d1c15c6ec7b182110e0ab264c0de6c2b9730", "nightly-1786"}, + {"e5da8897cdeb24b9830e8e252051d2731de91ec6", "nightly-1787"}, + {"030ecaa83c825bf4c91915d629adca2dadb9aaac", "nightly-1788"}, + {"7d18e36566c949de835c106375eb591a6e1683cd", "nightly-1789"}, + {"c6153bb32ef15c0e7245fdf5bbf3af51104dfa35", "nightly-1790"}, + {"bc6e45ab3b3847bd87f44aa0c8a203deb5ef005a", "nightly-1791"}, + {"a427a804468942b8e86af6d5e5ab2eee34f1ab00", "nightly-1792"}, + {"2c40b2aa7232df9ba201d6d616d3663d1fc31967", "nightly-1793"}, + {"e24e2a8f8b62973cf446792b1dad0e61ae2da449", "nightly-1794"}, + {"1759e2afc2b966e79d7cff5bc3ff848d43b74ae2", "nightly-1795"}, + {"b05b5b3bd8b973846b62dfe51b84952da756232b", "nightly-1796"}, + {"ea26f46b0dfc53b45c53887cef3394b2a7951a6d", "nightly-1797"}, + {"67c4b87184fb4df7bb3d1e68794ecdc183cf692a", "nightly-1798"}, + {"9626bdf3854b2a430dff9425e25cff73e009d508", "nightly-1799"}, + {"a2daef29857e7f64a4f5dc7c196a5bbe8e11367b", "nightly-1800"}, + {"4d684174e04119c57c77bd27aec9d9080cae5c2b", "nightly-1801"}, + {"a93d7a8d3ab02e3ba72013cbf92d5cae84d555d3", "nightly-1802"}, + {"1ddea27ac8fbc2240b961016ec0f6ff20a6ccd6a", "nightly-1803"}, + {"78019072883b1f97140be2d67a8ac0566028976f", "nightly-1804"}, + {"92ad651890f0f15ce81fb414ca0c8305ae2a411c", "nightly-1805"}, + {"c7e259366d69c3818cbe56602e1e89a058515d6b", "nightly-1806"}, + {"bb05d8c12a3498939b10b9bfe3a34fd0dcce0686", "nightly-1807"}, + {"f6320c8de98fd4598c88e9827556859588d0313c", "nightly-1808"}, + {"94d0399876cde32e1b56411e5a0ab3e590a40044", "nightly-1809"}, + {"2967068b87bc2d0285140851dca1b7b1ddd225a3", "nightly-1810"}, + {"4f715b6718f65ebd0141d74411940fe9d5f04afc", "nightly-1811"}, + {"f44c95d6384e4bcda79efe0b3b2ddd8413bfb496", "nightly-1812"}, + {"3b6ffd9c27f7c36ace2804fbd279455771918d1c", "nightly-1813"}, + {"64062162c6b087f2cc043c2038b9bb604f26b492", "nightly-1814"}, + {"d09f6d97f6c573bc9b33e547304828bdc10c641b", "nightly-1815"}, + {"d1171328c9a6b6daceb6747a9359f697b3d3b650", "nightly-1816"}, + {"0fc177e26809461afb13b273a6a7f3879bbcd83c", "nightly-1817"}, + {"48ee112cebfebf74ecb0013bd2ac557d808fa48f", "nightly-1818"}, + {"016ce6c286412cf1e5fc13f251ccd37779ade06a", "nightly-1819"}, + {"84eada8c50afd26145e170b7341e2eb2833a1641", "nightly-1820"}, + {"06a9f69d88253c916b1fc4e8b62ca50f9e04f032", "nightly-1821"}, + {"ae3d50f71f6feee0e5a2c17fe1cb565c255b7b51", "nightly-1822"}, + {"b588d6181bcae7b6886e3b3116c9475a59836c2d", "nightly-1823"}, + {"f18437e59fc2e8bc8388e88b4848c871be24faf0", "nightly-1824"}, + {"f5ed7c775d47379695bf96cefb210b881b09d66f", "nightly-1825"}, + {"e60a816d896332e3a3f7e47efae144a9d5db860c", "nightly-1826"}, + {"ad2cbe2b26f4424acba4f28cc4982d4d8ddcd9b5", "nightly-1827"}, + {"9c6035f254642fd569370efc5ffafc79cca4fc7f", "nightly-1828"}, + {"9b20bcea0fd6eaa753d53d63601db0c4d44f5fb9", "nightly-1829"}, + {"84e54a52a6402928f0cda4bbce24d930546f9842", "nightly-1830"}, + {"0f6478a928195cb9e2c157bc2c9e586aded302c7", "nightly-1831"}, + {"bb8cb3ff820338f58dbedf9c8f0eb729cf900aa9", "nightly-1832"}, + {"3a6a17c708bf694c08ec47141f5ddf9ea638b25a", "nightly-1833"}, + {"9b49d9464444d59b090b2d6c6eda459bb207ee8a", "nightly-1834"}, + {"f66d03dd48ac81ce0cc0f1d0616d2f07093a59a3", "nightly-1835"}, + {"5eb72e948901012a4f6c2fe8a97b9d01cfa87fdd", "nightly-1836"}, + {"a40cde7f765c61c15e7861b5a8fc0666c27ef4a5", "nightly-1837"}, + {"849d795f0ea80587b521283807031146e3833305", "nightly-1838"}, + {"1ab9b60a605dc27db5d754719b60d5b16ff698fa", "nightly-1839"}, + {"ab8d1c7d8bd8de830098da2472ec7ad93877cfa8", "nightly-1840"}, + {"5215468ff61cc7e1f1773db4068aa84303e2f298", "nightly-1841"}, + {"5aa80873e2c24719ef0081d638179e4e52ed04b3", "nightly-1842"}, + {"bb8dde848078280c627af16152885e25ad8674fc", "nightly-1843"}, + {"cda358443fa632b5e27dbe6272882d33d68bb529", "nightly-1844"}, + {"d8c9335ef0801927b7d3ab8e0d809ffa7dcf3189", "nightly-1845"}, + {"286f750c6c6b70b48e3fb2fb579e5bfafbf51a69", "nightly-1846"}, + {"8b116aaa04031d5815fc52773453aa0b4654ba8a", "nightly-1847"}, + {"c961ecb9a45695352e35afe58647877fce0cda09", "nightly-1848"}, + {"8f2a5374c326eb75491eb2ac28add6a71b5b9b69", "nightly-1849"}, + {"455a0198d9961b148053fb5cc73be069f091c90b", "nightly-1850"}, + {"07e02a1acf8f48c3379dfa17aaea46cef2c9136f", "nightly-1851"}, + {"976995ba08e6441689c2ff9aa3db286a07c083b6", "nightly-1852"}, + {"27be16ee315dfb6b28ecd2715075c0bafe4321f2", "nightly-1853"}, + {"2cbf6fbb171086d6fd890bb0e6ea8e2fddaa3811", "nightly-1854"}, + {"6fbc54b0c5178dfb6aa05278c80a43d08445ec5f", "nightly-1855"}, + {"e18e30a8ccd3aaa4b2dcbd67d06bf986ea8636e8", "nightly-1856"}, + {"27c280534d6ed9cc4c41bba01c5bdcc9bf024235", "nightly-1857"}, + {"a2fd43deaba82a95010c767e2ca613d9470d621c", "nightly-1858"}, + {"a2fd43deaba82a95010c767e2ca613d9470d621c", "nightly-1859"}, + {"0c3fe272b6f9640134b4897b0ec1970bf2864b0d", "nightly-1860"}, + {"8c12eb4905d09bc2c1eb0fdd61b05f7cb8d9f7a8", "nightly-1861"}, + {"54385a54eb441ff7691644c98c887086178fd410", "nightly-1862"}, + {"54385a54eb441ff7691644c98c887086178fd410", "nightly-1863"}, + {"5317c00c45ad6b128a2649f3b1b399bd323a1ed4", "nightly-1864"}, + {"d9d0fc63ec965b60d99895f31cd751a3a51466c4", "nightly-1865"}, + {"9ef42040afc83789671580c02f428c96804f3215", "nightly-1866"}, + {"b5d6f645bd67633f54b96aa0bd500ca750d17e1e", "nightly-1867"}, + {"b5d6f645bd67633f54b96aa0bd500ca750d17e1e", "nightly-1868"}, + {"5346ca27b521cd7fdcfcafad978137dde2d9586c", "nightly-1869"}, + {"ffc95eb59b950a3e0404c928e8676a68899634c2", "nightly-1870"}, + {"f96047f18229e257297593e68cbbdf29b72b1e9b", "nightly-1871"}, + {"f96047f18229e257297593e68cbbdf29b72b1e9b", "nightly-1872"}, + {"215a099c4fdbcfd82f7009b4c173dc3720e60ac0", "nightly-1873"}, + {"041252ba368e476d924089096acacd6536842828", "nightly-1874"}, + {"9cbefa468a7a8989b13cf8a943c2a171c995fedd", "nightly-1875"}, + {"31cd8120b6956f7aa869eebf8002be10f9cb0e7f", "nightly-1876"}, + {"495e5dadd76d56d5fd94003794c14617a9583390", "nightly-1877"}, + {"8b93db0841bc35ec2f3057172385929c885acc05", "nightly-1878"}, + {"563c77154ed2e41d3e916dfe4d62a68cdb47e80e", "nightly-1879"}, + {"cdb157f58af55e3f9728bc3ea10e71e83a299e7a", "nightly-1880"}, + {"2a2ee8bc968232058fe77a06e95d4f3fa1b851e7", "nightly-1881"}, + {"5f81940e632103ecd3b7f9760dc0ba2b5f361e2b", "nightly-1882"}, + {"89db2e323adb8e577fcdeef6e4a0ac40f03f187f", "nightly-1883"}, + {"9414db4f65ac777dbfdf54421681a230f9c3bd43", "nightly-1884"}, + {"c9b2bd9077aef1238ddde75e1ee781bf7ff13fbd", "nightly-1885"}, + {"1b944f3255589bf886343289ebf9c48d343f7f97", "nightly-1886"}, + {"9ba6a901936bb40e1b724dc3792c1bd2da80ec4c", "nightly-1887"}, + {"2c74ed1a6d15fb1dd12ad4a5841811c841d1413c", "nightly-1888"}, + {"d16dce6d991547e92bf1ac664e36a94eaeb9195a", "nightly-1889"}, + {"06f3c90cfb7ffd5e535c779afaa122694fbbed8a", "nightly-1890"}, + {"06f3c90cfb7ffd5e535c779afaa122694fbbed8a", "nightly-1891"}, + {"06f3c90cfb7ffd5e535c779afaa122694fbbed8a", "nightly-1892"}, + {"9bd8c9290bd4bc32bc1fd3dc1dea8674ebbc1d8c", "nightly-1893"}, + {"ea649263b752f9b73f1627ef9784ced19fe245bb", "nightly-1894"}, + {"9dc71e33478f4a9cfeac0b263ea6ddd8e8b7b1df", "nightly-1895"}, + {"41f13456c0a2b341229e61a31f3bf3144404cfa4", "nightly-1896"}, + {"34de77d4291dc078d7e3e15415d784966d423adf", "nightly-1897"}, + {"70335a7f4d50c092fb04749ac8d45ebeff1814a3", "nightly-1898"}, + {"2273df4d70e2745853e661dcf676373518fb04fb", "nightly-1899"}, + {"b4db9aebf2b4ac53b6a24ce360bb23e0b8b0f0fa", "nightly-1900"}, + {"f9ab0b3042a47fb535470c7d8792306c02526128", "nightly-1901"}, + {"d8e74a9ff4ea88e1b8810b86ea1d20637cba29cc", "nightly-1902"}, + {"7677ace5ea9a23138a2359fee43f560c38dd7b8e", "nightly-1903"}, + {"dc39eac91677e793e248d60ae01d2735f601751e", "nightly-1904"}, + {"0768bd8ce0d2f322c6e859f579beca89fdf2dcf6", "nightly-1905"}, + {"a12058ea37ea6e545985e6a8784cc1c776b0bc21", "nightly-1906"}, + {"a12058ea37ea6e545985e6a8784cc1c776b0bc21", "nightly-1907"}, + {"110063aa56e53f039fbe142640b8a24f14a588fa", "nightly-1908"}, + {"110063aa56e53f039fbe142640b8a24f14a588fa", "nightly-1909"}, + {"fa8c530e1088d85b3edb5ee22ffeb2d5ee27a87a", "nightly-1910"}, + {"2281bf5b0bd8cf5eb7bffb52145ce75cae3611e0", "nightly-1911"}, + {"72b82ef6edc53259e8b358107160864621701983", "nightly-1912"}, + {"848116b5be6be6c7d24ac099a579e19fc21f2c27", "nightly-1913"}, + {"b45c7188c7d37062e9567aef94edf68813aa7a00", "nightly-1914"}, + {"723b662604e8a4ba57d8c9d2f6865775726bbc23", "nightly-1915"}, + {"c67c648c1a2de1be3e1ca0d9c7d6f9ee2521e9c6", "nightly-1916"}, + {"c67c648c1a2de1be3e1ca0d9c7d6f9ee2521e9c6", "nightly-1917"}, + {"52f88f8fb49154cf6389981c8d208de6019702ae", "nightly-1918"}, + {"54c499ed5b840102f5d25321d7015d25e6bf0ba2", "nightly-1919"}, + {"238a574645e428dcff17b74ea8e80ada77987aa2", "nightly-1920"}, + {"38435e9b3e9b0502d6dbc2b8f2f665bb291c1da5", "nightly-1921"}, + {"06db4ffb17466d11cfbd274b0cab664c9e31fdad", "nightly-1922"}, + {"06db4ffb17466d11cfbd274b0cab664c9e31fdad", "nightly-1923"}, + {"4c8a98a321f744d5935a9b864549b550942d1b83", "nightly-1924"}, + {"7c11b9b6891c17e09bda4aed5b32bcb57535cdd7", "nightly-1925"}, + {"7c11b9b6891c17e09bda4aed5b32bcb57535cdd7", "nightly-1926"}, + {"70225e92f717523754ddaf7e641c7971cc36c5ee", "nightly-1927"}, + {"89663e0db82a1a246e4b133d64589f3f401a17ab", "nightly-1928"}, + {"89663e0db82a1a246e4b133d64589f3f401a17ab", "nightly-1929"}, + {"9b82de6b24ea06496846a5fa211a23879b0ff644", "nightly-1930"}, + {"7edc86a9bc817f8d88fe261aafa6d5c87340b267", "nightly-1931"}, + {"2e479fcec5288e5243f6e6988d22065c0fd9bfaf", "nightly-1932"}, + {"2d6aca45635ffcafd28cf6ccf26018edf85c4651", "nightly-1933"}, + {"0d516f6da5258e6b19d7a062ef3b28848f745b40", "nightly-1934"}, + {"d26dcc8e31bc713dafd1a4ff552ae626351f58f5", "nightly-1935"}, + {"ca2d87e5e38f84a1f4336c995fa71fb0e235e667", "nightly-1936"}, + {"3d0a3c2c45cb6322ca9ae3a4fa570918339770c0", "nightly-1937"}, + {"2126c240cdf89d1d0035cd5ad4d4d1cf95697f8e", "nightly-1938"}, + {"df9cc1b84cff00e3e44de4efa63e08644c8fa6a1", "nightly-1939"}, + {"df9cc1b84cff00e3e44de4efa63e08644c8fa6a1", "nightly-1940"}, + {"e5310b25d4977eac7a23b4acaa4ded853b4c9360", "nightly-1941"}, + {"662bb9ba7787dd580b922c6a9962a10ccc6ab77d", "nightly-1942"}, + {"b738584832615d759a5d5768c99ff1101b98ffc7", "nightly-1943"}, + {"a94af8ea62abb481b356813be2a3dd7aabf69c7f", "nightly-1944"}, + {"bbf833bceb23aa4185b11042357b04b1733b4418", "nightly-1945"}, + {"0bedb28bdc5084a504aeb5a95da3221f8170c6ec", "nightly-1946"}, + {"8b6b58a36481b910acf31e2576166bd2fbb2c059", "nightly-1947"}, + {"700c00f021dbe7674a42971d7ca3c3916d3b6b41", "nightly-1948"}, + {"e783b0d4a97a67eb3380c64f3fc6d65d41a51872", "nightly-1949"}, + {"e783b0d4a97a67eb3380c64f3fc6d65d41a51872", "nightly-1950"}, + {"71582a72a46a2f9dc63365559ff10871f45b498e", "nightly-1951"}, + {"b5e1a27a7e779a05ffb1cdfbf144e203fc774691", "nightly-1952"}, + {"a537f56766b4523cb2bedfc3324cd935217d6961", "nightly-1953"}, + {"8b21b902f2fa6fd94dd1b6fe9155dd4fb3a068cb", "nightly-1954"}, + {"539a1a0b6e0d9d9b7967101c0baa29984cad4468", "nightly-1955"}, + {"51996c54f03c554b8126cd7242801879be292f7c", "nightly-1956"}, + {"964f9ee3cf3f0196a4eadb94cf2f0405d6abb9f3", "nightly-1957"}, + {"335fb78c5cfeedfe0e285a475b31ee8158e703da", "nightly-1958"}, + {"3fedc68230bad234694fc8dd8270c019fdb100a0", "nightly-1959"}, + {"88ea66053e23bfd984d0ecb50f46bcc9c3668f7c", "nightly-1960"}, + {"ebac2e49786bcdb24cf876afb64c7573a165ed61", "nightly-1961"}, + {"aaeba6759e6d57968ce0b12f6245f45836dec546", "nightly-1962"}, + {"5b52849f901fbdfbdbb8a81728b3233307445d0c", "nightly-1963"}, + {"6d0cd5b00e80bdea60d7e0e6caed81f7cd5fbd40", "nightly-1964"}, + {"ac78b74c45569ab5460d5458b75a1c817dbaa9bb", "nightly-1965"}, + {"33a2113b7108908605f6a5e946cdb83078c80f68", "nightly-1966"}, + {"d4bac5d837b15062087feed654236800c68ecd5f", "canary-1655"}, + {"d1b6fe70c3838584f9f5c0d1f6887b4613ebbef0", "canary-1656"}, + {"7ad3b72632182f0041e5a75dbe69b37784be474f", "canary-1657"}, + {"6417392a020365519dc2d61f8eb3612727137acb", "canary-1658"}, + {"95aa356c73d8f799756257d6770c62ccf7051de7", "canary-1659"}, + {"337433b53fddfbcfcfed314f259a76d5cb1b34b6", "canary-1660"}, + {"a80076c01c692866fa85b95c04f68506a5ca82c9", "canary-1661"}, + {"ea258dee21ed515bcea8a76738149f4ede17fdea", "canary-1662"}, + {"dcb3c4f01b0c88159cdc94578f18cf378a3d2dca", "canary-1663"}, + {"b5b949672d295feeb666cc48225a4a522bbff61e", "canary-1664"}, + {"395374c0ed7e8acb5c7c28ac3dc218c5120f59bb", "canary-1665"}, + {"4c00e4dca0f0251117ce03e254d2a735a4e4f63d", "canary-1666"}, + {"db43a83f1608dbc772f73c3c9ca839b9ce1a0178", "canary-1667"}, + {"fbcab9ff5d7383e498ef9e785f4b386c23dc1674", "canary-1668"}, + {"ccbe5ea8ee14e5389be064a834b64edf4ff569cb", "canary-1669"}, + {"5494d4fd553151402bee8f616251726758409bdd", "canary-1670"}, + {"f5d7369d9dac9747487b3f90cab8b95796d678fa", "canary-1671"}, + {"d63c5f8a493412fa91696d07ef3caf658dbdfc01", "canary-1672"}, + {"7c26be6a09bffdcebe2bde5a6452ab1bdde61c7b", "canary-1673"}, + {"dfd021fe9005e4ea37520fe142d5f5aaa467336b", "canary-1674"}, + {"25ad5899a65724e597ff75cbffd7489e3760cdba", "canary-1675"}, + {"df56dabdb7bbad548e1b3ed13f125464c7ec954b", "canary-1676"}, + {"98ce9e5f05f60376de11245a6c9535b46a56e3d5", "canary-1677"}, + {"769809c4fa59f174b92520ef9fa475e6055e4b8e", "canary-1678"}, + {"28e251647b70774d80b8aaa2c6a778c855f20c05", "canary-1679"}, + {"50cbbdccb87e2c2530f3e17d2c879ee4a1adf70d", "canary-1680"}, + {"603e8745a6401b337b05ed20fb1c259268ffd38e", "canary-1681"}, + {"e0acd5a60e4cb0167681e90ef03ec1f1951d025a", "canary-1682"}, + {"86cfbf8daa5f129743e249f5dade7ffb8f316fa1", "canary-1683"}, + {"a47b54dc9e3e193a081023a1bd49aae7e9c7d106", "canary-1684"}, + {"f8ea290abf2f500cda78af9393d2e0d8e4e35779", "canary-1685"}, + {"da20fed4b78ed36eb0135ee73d8c4df7d6b6ac2f", "canary-1686"}, + {"ac0338d55d34ca036ee8a82c4f0e65e38da88b19", "canary-1687"}, + {"a33eaef0ad6ebf869b5d0f024e22a38aed85d1d1", "canary-1688"}, + {"afe573ab93e7fa91e1f0c9226f572c428345a4ba", "canary-1689"}, + {"48690c71b53e996f8fb1095558140cf115c6106e", "canary-1690"}, + {"89a2d7c0f04a901ba4883621d28e9b557c3eea55", "canary-1691"}, + {"26e598f80e4577e4b42ca5be2146f50f1264b649", "canary-1692"}, + {"bc7e243ea49a1be6353aa4ca9bb63388490a6c85", "canary-1693"}, + {"33870e458a245fe11c453bebf118dc62b3aa313b", "canary-1694"}, + {"874091b5e773600e0417f26e789c9726a1bd5974", "canary-1695"}, + {"6c89cbdb5d75bf505dd7aeebce288ac01f48a927", "canary-1696"}, + {"918e9e1aa979e71d05f4f10685770a3cfe30fa46", "canary-1697"}, + {"3427820b6869d86e2cdb2cf23ba8ef754a17c771", "canary-1698"}, + {"4a10f1785cf5e376c60087cf1dabe74379462f4f", "canary-1699"}, + {"e7d8221e216a68d8c2b12f1700bbf9b88c8c8531", "canary-1700"}, + {"d39c0469f83883d9782d771b6bb9e5294d14954c", "canary-1701"}, + {"55b7c3f08ee44048256fc98f7f9477d1d5037cef", "canary-1702"}, + {"00f53130b7bdce5ef414daaa65333da8ab67633c", "canary-1703"}, + {"d6f4c63f5065832cae86822eee2c8513fc725d8d", "canary-1704"}, + {"2ca80a5120408a466b70da397dc1c1c638304c36", "canary-1705"}, + {"bfb6db55f97e69efb548d328d094b7422a8f2988", "canary-1706"}, + {"8da0661c56ab1373756a313905d8e186e3c9f0f6", "canary-1707"}, + {"4a2a2f67c50270848088f9510aa9d36e642b423a", "canary-1708"}, + {"0b142cfe10cee28e6b9c4306c6f1d81a883fec1e", "canary-1709"}, + {"6f500b13cbca57d7a92aff3f759b6714b2fff646", "canary-1710"}, + {"c0b37ec9b522efa465dc7ed83d645d1cdd754653", "canary-1711"}, + {"e8378e0c8b08ae111fff96e93108f2a9d38c16be", "canary-1712"}, + {"e3cf770f224a9c5e9e400879c980cf110c8e470c", "canary-1713"}, + {"2994a850331b02127a9e4b48008e3eb7cb027530", "canary-1714"}, + {"e239a0a445df3a7de6d25a938485ed264c8cbcc8", "canary-1715"}, + {"9fe240a0fd917779852fe6152d6d5972b782b1aa", "canary-1716"}, + {"e6a180eb2ab01dc16b2a437a778ec1c61556a0c4", "canary-1717"}, + {"20477b1124b794faaf30d915d88981e829295ada", "canary-1718"}, + {"02856b012285c6c16ab87b5fba492051adf960e2", "canary-1719"}, + {"feff6500f298dfb566239684ba87debf1c073a57", "canary-1720"}, + {"f2150db83d6513694e1f883d302ebca5b18be898", "canary-1721"}, + {"3023be433aa58714f636ed5e73d850565f93dcb2", "canary-1722"}, + {"d8b73e7409f8118da83675c391ab91449d17171d", "canary-1723"}, + {"a40953a2f2195726ff397088192008143bec043c", "canary-1724"}, + {"2d436a01454d8e32a92def33d96c6619d9cceea5", "canary-1725"}, + {"ce609a8b8811079738151b65c0925d2e97628f94", "canary-1726"}, + {"c3bf506721e7d814d55c618141c674f5409028ce", "canary-1727"}, + {"a310e63721c41beb9036d4fb860346a1ddc316ff", "canary-1728"}, + {"2e2a4acb54e72247d20c4ea231fb4d3b293e6a11", "canary-1729"}, + {"114a9a094f5f80d51397a773da1cab0084406ccb", "canary-1730"}, + {"50aa5af1c38499b9b4ade34b11d61f9f12def81c", "canary-1731"}, + {"10eee0730e3a57ef36d6e1e92d3b6689d8af0f84", "canary-1732"}, + {"ea36ba153294462e5ed548a6ee8eecb3a670cb8d", "canary-1733"}, + {"7aafad1d206a445626133343041dece1a2e2cb5d", "canary-1734"}, + {"21bfc5d0cb2b29b78b0ea22f0486522923d71fa3", "canary-1735"}, + {"a04a0adc58c62c5a33f2a9e86cfc80da758898f2", "canary-1736"}, + {"a76ed4fc98d85bc4fafde7bb6f0a39159f89ce63", "canary-1737"}, + {"f26630628b9aae40f25ef3d09c4fe8ecb9560ea6", "canary-1738"}, + {"35ae86d53d02f68b1414c54355994c621fb9df25", "canary-1739"}, + {"b0745a05acb9737d58d00ca088411cfb4b0af5a4", "canary-1740"}, + {"2927215a15b1e26d537e1fedddcc95ddaf6eadff", "canary-1741"}, + {"4b9816ea0405c269acb8443f3b41ce7367c8460e", "canary-1742"}, + {"ec93fb8e48255617b352747aac913119381378af", "canary-1743"}, + {"8e9fce90ea802a3f25d477ed45ac513a7e20632e", "canary-1744"}, + {"5f118ec69703ff9e3c758584d4dbbe0161bd3d04", "canary-1745"}, + {"12471d3c17a6b61dbe67907f331fe850eea211b8", "canary-1746"}, + {"cae107e5ce0d588963c135871543b07b3f6bb64c", "canary-1747"}, + {"3009ec486ea762ef519c143d215e719c607e0cd1", "canary-1748"}, + {"b78d27fad6e2bc5c9a5e5cd62421196d441919e2", "canary-1749"}, + {"fecdb7e9e933a644c80992b476ed0002a2b119b9", "canary-1750"}, + {"a7e85228c70562e0782b213b1e9417884677011a", "canary-1751"}, + {"786c033f3d0fce82677b5ca575800b798b4f67fc", "canary-1752"}, + {"4117a8df36fc669f5e371b99211a8953ae916583", "canary-1753"}, + {"0ef6ba8e60056ac0e28cc22c156c7aa0c3106fe8", "canary-1754"}, + {"41dc0b7e9620de885c147bc063046fe15847d9dd", "canary-1755"}, + {"e185ce826be8defd23e6ef08a0fe545dd313f6bf", "canary-1756"}, + {"7f9bd7a8e3b70e3ee40334b07a4061c7d60421a3", "canary-1757"}, + {"9b0a1d178fbae4ede686895a8b1ba995654f29a4", "canary-1758"}, + {"7180c4a55276a2c9ac2665d5ae198d0a9c63f4fa", "canary-1759"}, + {"a9574d49011b4cbc061c14fa90cbea4a7e407333", "canary-1760"}, + {"20dfa5c9ad0650b417f8703dd8098fd52a79bd4f", "canary-1761"}, + {"d0ca49baa9c75a925fd373cc95124fb11a8674a6", "canary-1762"}, + {"777c13f6d9532ea6dea582f786a9a174df5368a5", "canary-1763"}, + {"dd8e082c55c4db763946a2759745e0b703f1f286", "canary-1764"}, + {"27630ea1557df1ee0d946b1b2ca498482cd63106", "canary-1765"}, + {"5e5d6db8e5dfac9e65ac029c730d88f99d9b49d1", "canary-1766"}, + {"4fa68e30abd28d20eec38983b3598ea5bd31634b", "canary-1767"}, + {"c83a2f2e983b803355f0fe97eb28a5412c120ae8", "canary-1768"}, + {"f40be3ac452809698c6a152e349ce6faab2ac982", "canary-1769"}, + {"44db15625fd58a2b6498a361448734750de48e73", "canary-1770"}, + {"4c04c75d2a3ce639bd5a1c357916bb40350a0a04", "canary-1771"}, + {"65fae8c989378bbc708339d149720519c282907a", "canary-1772"}, + {"d2993552027f9a8cffaa645873305a6f536e9991", "canary-1773"}, + {"5442e61a6c3b46ad6e2acc515ad6724660a352bd", "canary-1774"}, + {"f004b111c0eed5080080da54237bcc948b14093c", "canary-1775"}, + {"30d15091c952322db553eb05d10a3cb707c549f1", "canary-1776"}, + {"3d6669d9fd1c5edc766bcebab0c67a24e20f69f5", "canary-1777"}, + {"900c6bdde2f5519e09c6b8fbfcbf76943e3f83d2", "canary-1778"}, + {"a5348655ebb8fe00f3b1dfba46cc90c5d5c7a294", "canary-1779"}, + {"e733d99c6d5ca4c833668da799edf68cacd3505a", "canary-1780"}, + {"d0c61b606a305a895b9763b7eb53c5eac75fbd4b", "canary-1781"}, + {"08b26ba1121ea24727fb27fc017ecfcb0e93312a", "canary-1782"}, + {"d66aab1d24ac6e1d21e01989c008b0d90fc6768b", "canary-1783"}, + {"6cff89369ac8560533049672f26238bdb0403699", "canary-1784"}, + {"6758fab4f5b9bfd4b2c54888bc1635bbe00d5991", "canary-1785"}, + {"6ebf5e00e5d0107f5997ef74ef22bf7650971d18", "canary-1786"}, + {"408778ad499ea3909b1d2d332a377e461fb1d3d9", "canary-1787"}, + {"894d7f5a819e8ea6075a743800a595efe6afb760", "canary-1788"}, + {"1eaa5ae3ad10a93cb9b3e3aa8b74f563e21fb30f", "canary-1789"}, + {"ba9ecd4c2f0ed534f25d717858185b3bbd20903b", "canary-1790"}, + {"0e9198ee233753f75dda80dd5abe9423ed8337e9", "canary-1791"}, + {"4093bd25ef44a31f9ca1198a626ac8664c0feff7", "canary-1792"}, + {"3a96164b710b6db0d940a29ba5ffc1d5d7af0544", "canary-1793"}, + {"7e9145c892575663012a5f06bfdbd8d75642b28a", "canary-1794"}, + {"61f0e5221d5414b01b36233e6338ff069efb69ad", "canary-1795"}, + {"ff61700097cce1789700d1cda3521f1a72c2428a", "canary-1796"}, + {"697ea32d5a892da6b5d65a64b54002649f5fa59d", "canary-1797"}, + {"fb15c4b8914ab7036c5fac8a5ecd4e6738b9a41c", "canary-1798"}, + {"22d22815ca7bd1fea11a761cd03df68b9997e14b", "canary-1799"}, + {"a7a04ec06629329ee73354692efac85006768cb3", "canary-1800"}, + {"25a841d3e2b02d2daa6f881fc831dce35cfbbff9", "canary-1801"}, + {"750c0a5d880deec799eaef78042a6141a40195d9", "canary-1802"}, + {"1cfba094a94eedb8353709e2e6a90821f7f60d3e", "canary-1803"}, + {"c8b2c89fe5b5bd3502baef3239fefba9a27a7408", "canary-1804"}, + {"3ee981ec7119e7d83bd279fe18d703cb72f36162", "canary-1805"}, + {"e9c481cc253960dec4452dde06034ed8e1b9cef7", "canary-1806"}, + {"b1b24d827f75d1ff9f8fd637d4393fc21a81806e", "canary-1807"}, + {"234300db243bbf01d95b20a1e6609a765efe2f32", "canary-1808"}, + {"bb4e341f214bbd99c8d479a04d1951f0c58fed23", "canary-1809"}, + {"d8b1c8cc4b6797d1f70f3c8da8f5dece5ed3112c", "canary-1810"}, + {"7c650f6b3316e00536c23b585fcf37bb65e73964", "canary-1811"}, + {"bbf3a64e534f42e6235bfd53a062f944423b3562", "canary-1812"}, + {"71521bb195151222d74f5e2df4db012d61bd7f39", "canary-1813"}, + {"d3e12d29c4305ef1b5e22f92ed2ca71d11c15e56", "canary-1814"}, + {"5f153e2919481937162fba27b3edde281b5a79e2", "canary-1815"}, + {"c13db937fc90243d171dff3ad8d71a3e8e43123c", "canary-1816"}, + {"26679095ed6b36412f8de2da93d7192d90dbdf92", "canary-1817"}, + {"bdf2d786fd2f56d7619ece94dc6914e801840663", "canary-1818"}, + {"94758cf85dfc3c1aed9e9e569d0785977a6b7145", "canary-1819"}, + {"506f1dc9ce3f75999213fb32ac6ff69d1c393749", "canary-1820"}, + {"a7fa0b2cdf2e06d582fe5c7e34a68d1be5746996", "canary-1821"}, + {"8858cc8c3eb6897b87da98f87fe932ec38ecffe0", "canary-1822"}, + {"e78b73004d1bf8860673358ee2d43b191d046885", "canary-1823"}, + {"44728606cb405b4e0728aa4c83db70678bfe112b", "canary-1824"}, + {"e1eca222b484a96765bbc0e9a21eb58c8e4917ff", "canary-1825"}, + {"9b81c6cc54d32ce275d0e1224d7f0a0d45c083c3", "canary-1826"}, + {"92c4ca3533d86bb944aa2e7bdd33f4699d1e1d35", "canary-1827"}, + {"07a65a5ee1c92210bb3b27b74d294faf4b4ceacd", "canary-1828"}, + {"6c7a01c0a79330b57dbbd9c216448bdaa0f02e40", "canary-1829"}, + {"55b529b6f817e3d17088e4b1df374f61bccf1f84", "canary-1830"}, + {"d0ec7c09a471f93b402e0d288298b42bb9fb5973", "canary-1831"}, + {"f3f2ea7b077c3472cb96d9ee6338b0e5b84e2b6c", "canary-1832"}, + {"4a6ed6d8beb0cfdf059cfcc2028f37303cd6e2bc", "canary-1833"}, + {"dad352fb3b7ab213bed3b24c35b70a6339f11268", "canary-1834"}, + {"a65f1a093d5b80d1725b732741c04e77f97ce35d", "canary-1835"}, + {"16973a813c839f72186d09b0c17deab6402484ea", "canary-1836"}, + {"037d1abae5367a3a7de911fa8ec852d75fc601f3", "canary-1837"}, + {"317cf7aef19a1abe8e8c43b1cbf2abcdef1e9953", "canary-1838"}, + {"7c77583ddfa5cb553355a1cb1fa460bfbaea8789", "canary-1839"}, + {"f629b8cd72a246edbcba8fa7f047a03037c0f9ca", "canary-1840"}, + {"f55ab9374bc83fdd678f10e34426e11b0198eec5", "canary-1841"}, + {"745532a6172fa2b08dbf699e707322f361a027ee", "canary-1842"}, + {"67126e301b2cbf3e88b8fe988022cfb5646a37f5", "canary-1843"}, + {"70374c8ebaf6f7fa820dcdb85e7a592332c659fb", "canary-1844"}, + {"964cb0671c4e41e84cd1dcf0ab5affc73b3cb179", "canary-1845"}, + {"058afda8b0c6bfbb1f251cff8b3f88ec6e843328", "canary-1846"}, + {"2f53020cd9f79de8ada0cc7d424cab1168a62a6b", "canary-1847"}, + {"c99734738452f18a1c9e800968e092d74a102fea", "canary-1848"}, + {"af5b0283abb85e51c91e938855ecfc4c33c6fbf6", "canary-1849"}, + {"063cae9dd4c5e51eaeb4a979c075bd51861adb34", "canary-1850"}, + {"e44a132f6c8ef6ce5a1bb52d72c60bcecfab8b77", "canary-1851"}, + {"af546de70d88fa0612b4eb847aa4aaa7a5d023a8", "canary-1852"}, + {"cce7bdb24d9d495c6e62f5f1cd31962d81673544", "canary-1853"}, + {"367907780ee73ded585eeaa3c916cc5a2c00f323", "canary-1854"}, + {"79b5bcc01ea4c14486849995fb15f017b6929275", "canary-1855"}, + {"ee9df1448b9ca2c8082c31e8166de4e921b594d0", "canary-1856"}, + {"f9e7514b3577af873234395e1551993132a58009", "canary-1857"}, + {"a34b8e81d94497a3b55bbcd1bcb2a33fc7fd773d", "canary-1858"}, + {"10aa692432fbf6b8dfc67e7b0b058dc10c4866f8", "canary-1859"}, + {"3a37d6cc81513acbcd89ff1437a1d3c23bb07c2d", "canary-1860"}, + {"9c0666d42d642ae681bb68f2928efa5e077b0ce9", "canary-1861"}, + {"64fcc113e7a9738d7a20c77173bd98b88b104aac", "canary-1862"}, + {"55f5cbb0f8cb821060ee4e1ed252717f794a69c9", "canary-1863"}, + {"69ad9ddbc56bc4a6e3c2c52fb5d063b70309e812", "canary-1864"}, + {"6cc34687b1f02d9c528cd4ad5b56f975637b21e4", "canary-1865"}, + {"d35532496681addfbf0a046f54beb33f845e9cf3", "canary-1866"}, + {"ec4251d9fa66bae1f43c29f974c73d55b2d3ed76", "canary-1867"}, + {"288baa78526187cc9a8482cb12b1b912b8b561d8", "canary-1868"}, + {"f63770cbc9698f5c09713676743774ec80722687", "canary-1869"}, + {"385ab4a043a11b22a776d263081ac12fc38a24ec", "canary-1870"}, + {"6701a95ff4b4c6f695ea383606723b82585221f3", "canary-1871"}, + {"f24ddd7963c053cfac6e2aa20953dc396ce95475", "canary-1872"}, + {"16f16affe8cefbee71bee5687f2741b584e5fda6", "canary-1873"}, + {"99c95859156f2f2b9b0e9d47ddb72e944c6d2ff5", "canary-1874"}, + {"dba62cdba3b87d4990c1819fa9eaf2fd09266f4b", "canary-1875"}, + {"be309e3f992231046ca1b6c9a5432508d9c63b68", "canary-1876"}, + {"15ba28aaecbb7b8791754bdaf32f76de49d449bf", "canary-1877"}, + {"b95aa95df5ef33e38bb8931c278af1aadc2a9afc", "canary-1878"}, + {"eca2c7286fabedbafaaabc8cb81f8b1a942c686d", "canary-1879"}, + {"cffc3a8b3dc3ce5f78a56ec54cf599f19d7e574b", "canary-1880"}, + {"019fded9f0f4734239afa6f0428d103dc7426867", "canary-1881"}, + {"3d5527c8813450fac0b8bae967ab08586bcf05cd", "canary-1882"}, + {"570304092f34b014cdc640e42e136fa5ccce9ce9", "canary-1883"}, + {"30dcf3ba09a7eaa12ad0bc232a1fb5bff66af9c4", "canary-1884"}, + {"95ec695301d81b76aa716f1932de7c855c0a056f", "canary-1885"}, + {"6f8ea3cef0da61c5ca7292905f352da40d53d3d8", "canary-1886"}, + {"4df6a3f706c6403ce98356647c7e9c3197dd6163", "canary-1887"}, + {"ddc274d593c71ee14bdffbee13b9c6b0b032a2e9", "canary-1888"}, + {"3b76c8a8312a7e10755bbe544863dfcb664c42b6", "canary-1889"}, + {"d439c8ec9c9841286317447e1597b12f5dff6dc0", "canary-1890"}, + {"020505a1c069d05df5166b18f1d47b5e9c4c3dbc", "canary-1891"}, + {"7c3bf1703946208ebd08105e3d6177e369aef331", "canary-1892"}, + {"519fdba8f7e9a409fa42083db9f8c953e0295247", "canary-1893"}, + {"711aab0b97efc7e6db24ea18866b7a3dc7ff8937", "canary-1894"}, + {"fe69cc656ad640735a4b5e96be50d2319f38e3fc", "canary-1895"}, + {"5bcd21b36c3931245bb11f7f11fa66fbe415cabc", "canary-1896"}, + {"ec5978773356a175b045a76b4acaa0a908b7b45a", "canary-1897"}, + {"97a028178f8cbff53276eb674b05b818b346a56f", "canary-1898"}, + {"aad9aefaf5cd5f745bbaa6a82fc72ec4a21c1081", "canary-1899"}, + {"7c8884ca2fd552342d047a0bc77236231c239062", "canary-1900"}, + {"91935ce74394d34e0ff36a02694f6b490dfab48c", "canary-1901"}, + {"e97e9e4f509f72f72be133b1eb42f4488a34965f", "canary-1902"}, + {"6385727a3afd3f16aabb3306b5d8d44acd28c918", "canary-1903"}, + {"b9ce98c36fc209fc7f1e79926a1f97c1e6e84332", "canary-1904"}, + {"9043f8dd556c58e8dcedc166c497c695b46ba510", "canary-1905"}, + {"607907ce55dc7d3ac7c2a47028286f435e890c4f", "canary-1906"}, + {"e489b84e88a424822d75254200fb0409e37c626a", "canary-1907"}, + {"f6cc24e0647f38e4dfaa820b6ef35f748d14ffbe", "canary-1908"}, + {"de929d2f7d7a587e951f99c274c39b9d6d66307a", "canary-1909"}, + {"a258d9c6feacc1c17bebf2ec14d9f83f9c38b32a", "canary-1910"}, + {"8a763cdb888c036f065b464aba00bf6f00adc998", "canary-1911"}, + {"0048cade152bf7e5d7a0403409335c2f2c15e316", "canary-1912"}, + {"5ab7a22ab5672bffef236f7791bf4c33dbee6291", "canary-1913"}, + {"58b0f996eed8fac307896c1f5353cf5e6dc6d9a8", "canary-1914"}, + {"3813c23074582d9c7352ea3453eeb2231774c283", "canary-1915"}, + {"e3df6f3ca3438e26cecc385183999e7434c2a2c6", "canary-1916"}, + {"778b2679f1f740cb83c03c161373b08862f2f207", "canary-1917"}, + {"7c5bbf3121f54058d2a6e4b9217ac94e2517460d", "canary-1918"}, + {"7328bd95b464cb95b2af5faaf04fae0b1f434a79", "canary-1919"}, + {"327e813c6737354bef560b8960657b2f818fcec8", "canary-1920"}, + {"b1b83ae3a972e52f967bc9f655da12fe4d50d99c", "canary-1921"}, + {"adb0c6723e87dab48261aeb63ed20e309a51d47d", "canary-1922"}, + {"b64a0fb5e5aac67f9798af74b3c881431118afa3", "canary-1923"}, + {"eed14ff2966ede81bac066460a2ca68644ce9dff", "canary-1924"}, + {"4e7630d1719f9feb3279b1200db73ef0213248db", "canary-1925"}, + {"9b29fa3d51b79bf1d4e2f8ddf298d2e9884d4853", "canary-1926"}, + {"0fff4f891f1f417692cec4e8fae8eba56684d778", "canary-1927"}, + {"625639a53da4226f07fb4c57a32e7d807fc0968f", "canary-1928"}, + {"dd2d5c32a4ca4205082a193b1ea1a0960ec01147", "canary-1929"}, + {"6ace34c92b3bd64a3c46a1e701919c148b53e30b", "canary-1930"}, + {"fbebbdd295cdccfb229deb25cb793fad90f71c2b", "canary-1931"}, + {"ad7212ecc25ff94cd12567f61593768cbe53ffe0", "canary-1932"}, + {"ff22387f58baad9cdac6ca991d7c188f510aa29a", "canary-1933"}, + {"2ea07124aef3d927ba1e2ac5c758a070ec1a975b", "canary-1934"}, + {"ee699b24ea71a19960aa9fd724f1cb756d4ce1a8", "canary-1935"}, + {"fbf379a3408a3ef731b1d31067cf010e525cbc7b", "canary-1936"}, + {"8c887f09e8fb80ab0ce03bfd07f34fcf80d71e01", "canary-1937"}, + {"1d5dbf1a3c2be3ecbf737be9d9ff2cf4bcc33491", "canary-1938"}, + {"8bb1c4960bab8cf13ae0fe13ab86201fbacd24d2", "canary-1939"}, + {"50f093f30f10d0d199c99431e097b9d637de82b6", "canary-1940"}, + {"2ae47cc3f74c2dc0187f974020e87c41f6ad16d0", "canary-1941"}, + {"e172afb23d87dff773fe386d9175c39e9000109b", "canary-1942"}, + {"e2402bcc375ae17aa495e5dd342c0e8a1f3dde1e", "canary-1943"}, + {"82db62a3f8fdc27fabe0f75f906e88fedab6ab5b", "canary-1944"}, + {"3934131240ecf9924c84b741fdf76dd9bc5040cf", "canary-1945"}, + {"74ba307cb54c91172c9fefd37844ff24bd1f0382", "canary-1946"}, + {"c2cfab82b55aa340958bc06c33f3ed3fe45a8b62", "canary-1947"}, + {"6bbd080f2693e9a028712eaaad78c3a43554a025", "canary-1948"}, + {"54dca2754a0a6076fd685eca278653a1714d132f", "canary-1949"}, + {"b2b4fedf93b493747dd6b8647bbb41353142d94c", "canary-1950"}, + {"3354b2738bb316d1306a600bf1c2e8219bbd6b67", "canary-1951"}, + {"1d1f601c4a6d9c65fc9959b760c08167dad20ebe", "canary-1952"}, + {"09100ece382760fd39be6668fa73e181f5b64880", "canary-1953"}, + {"90ce055b029d06a41bf5bf91763d1f74ac208e06", "canary-1954"}, + {"88ac3d3a4697150b04db5016efc581e5c332b112", "canary-1955"}, + {"7a60d461c23b5e8273585ef1baba7c1c25ec8d72", "canary-1956"}, + {"efdcb840cd65b62cbff33daf378381d1042c7a9c", "canary-1957"}, + {"bff20a0b4af389429ca73205c46d7728552101ee", "canary-1958"}, + {"651c9d0d69749bdb33e4a271dbb154c2c065b18f", "canary-1959"}, + {"bc3718a9c90aefa81e27ad98e2b5cfc4a95796c2", "canary-1960"}, + {"64ac2c94a07ce444fbf66e61dabc44919f74c176", "canary-1961"}, + {"5e2c6e1a5d9b7d501e72627a025776d2d3f0e615", "canary-1962"}, + {"c9d6de5568bafea422dcac7c0aa6de2a13f6d730", "canary-1963"}, + {"c9104c8ed9ce2007b7ab2804f790b2d9f773e36e", "canary-1964"}, + {"85a2b701ef72df2d70bc817eccf64230c680090d", "canary-1965"}, + {"966f680d9ad9d6d3e596da386e5196d25025031c", "canary-1966"}, + {"ecdf2ed8f05e06e9e4dc7bb01a6129e16fb88515", "canary-1967"}, + {"e25fc4db6577dc7ade64f85e5938d0cd9bea8f5e", "canary-1968"}, + {"311b2d53307bcfae1b4786e8854d5868c8a92d0a", "canary-1969"}, + {"7ee5bf952faaf95f10e01033b734724b6c89807d", "canary-1970"}, + {"523b29e5e1b3287d227cddbdf5bb31b16199aba0", "canary-1971"}, + {"173deaccf415ec7c55476dd338c0786e3a42ad7f", "canary-1972"}, + {"6e7fae86648f69dade661632726a696c36a1cabd", "canary-1973"}, + {"4bf7e28070609d9b7a8d26b118659a51fdb7df08", "canary-1974"}, + {"cd67f6338f8c750236d3bb0458594c6559f58bc6", "canary-1975"}, + {"39265312b4ad9f2f311e47dbda8970b0b2b3e3c5", "canary-1976"}, + {"6c8837ba3dda8bb1af2f01be2ca9b55838d44826", "canary-1977"}, + {"4ca36e5c2dedd024a3e329ba02c1d0c380f02e01", "canary-1978"}, + {"3a9b3691af1f44d509221172af1c886cddde8db0", "canary-1979"}, + {"ffe9bf47349142cd5dd9fe2780158488fc07db08", "canary-1980"}, + {"0cfc5f6460035388ec1b37ec504c7bcc5bd09b86", "canary-1981"}, + {"40f8fcf59d17cb1cab052ad689622b186824c013", "canary-1982"}, + {"23796db11a3d2ee1b6b86dc47a3c43f9cd88beb6", "canary-1983"}, + {"1bc889a67b3db0645c375eb7bffe37e0ae75bba1", "canary-1984"}, + {"f6ddea22fca8372c0049af256290d334a3d50b04", "canary-1985"}, + {"f083b3a16c7d7f55a94216c5a60e5d52db5c58ae", "canary-1986"}, + {"250e15fcfbd4d66d6362492f413767e199cc567d", "canary-1987"}, + {"085788ea5b1311d5df1ed153b93779d446dda2d6", "canary-1988"}, + {"fe7e1633461f65cb1fab44826d58403070425ce7", "canary-1989"}, + {"2eb3e59f855241aa410d28227dbe68bd8bf45e30", "canary-1990"}, + {"1e4cf0dbfeb65756abe9c2fc9b1c8f331df78c87", "canary-1991"}, + {"9a40f51551f6774a0ec868b0b0bdf9e51a4aa2fc", "canary-1992"}, + {"11d556a749d2dbb5a58013e45ead493872885ea2", "canary-1993"}, + {"0827616ef431432c7e0c57feb263766209856fc4", "canary-1994"}, + {"5daaab6025d69970d77cd0b30d6ee04c55ca38a1", "canary-1995"}, + {"02f0cf89a1ac033fe899fadb6a880427f6b63270", "canary-1996"}, + {"ff250859bc2072ac6af8574ed555a9638abbee53", "canary-1997"}, + {"569b5fa268e54492e6d128ed6fe6c2cb9630be38", "canary-1998"}, + {"a0434e363806fe94d2a25d49970b26004d971dd1", "canary-1999"}, + {"c0aa6b4ab30fce3aa79c68d375088eefe2a0b003", "canary-2000"}, + {"5a0c4bf8ea639282c4da31dd4df6a0851ba93163", "canary-2001"}, + {"ed640fe14016cb17ef477a5aed54170430c865b6", "canary-2002"}, + {"c2ae29257751f6d96e6e8e37dadc4ac76e110886", "canary-2003"}, + {"4ed0d398147c845e509a95336f03a3ed063fed78", "canary-2004"}, + {"356dc310137e5de8f19752ed52747c2b6a005425", "canary-2005"}, + {"be99088228cacdbb29e1dbae03103f40978fe139", "canary-2006"}, + {"ecbb434d63db92fba837eec1709ac54bee371ea8", "canary-2007"}, + {"1cabff2e3eb25326a48e5ecec8db5ee378fe3fe2", "canary-2008"}, + {"19274fa9419eb490174f89ce602ce14a4948d745", "canary-2009"}, + {"94a04ff6f1144b3d1d4b13540b35fafadc7f202a", "canary-2010"}, + {"ee20a4a4e074d5267e18283b40df1210ae7304ca", "canary-2011"}, + {"48c3b2b0bb824b7256b4fd12151c97c3ee306920", "canary-2012"}, + {"089b5388364f9439eb44fb079fa46ea3af8d4bdc", "canary-2013"}, + {"fede559f374055baeded955de12590d7a3e42ef0", "canary-2014"}, + {"7b05612011ea08e363ab3b0e50c3d9e2b2ed2166", "canary-2015"}, + {"c14f7dbf7358cea668e2f9c7acb65297b9e73926", "canary-2016"}, + {"b3e8e0ad7c029d81e7f2dd6268f262d0669ac61f", "canary-2017"}, + {"6989669937a5f46560456ffc7c92c1a6a44db663", "canary-2018"}, + {"b2596771c0047b594e59ac8532b004ba05a838b9", "canary-2019"}, + {"9ee270ff0ba9dfc934d218ae8da32dc6c98598f8", "canary-2020"}, + {"0a585c14673ea19c10b45952db504ca7c48456dc", "canary-2021"}, + {"f5979074d530a5f203585716bc564762f1a289e0", "canary-2022"}, + {"1709cec298e05138f664badeffd02185fc773770", "canary-2023"}, + {"2c912da7e5587e406c25f92fe5def8ff4c51c2f0", "canary-2024"}, + {"047544f1297b47e1d2964655afde5b8528c6b45a", "canary-2025"}, + {"53cc251ac60a25b3ea374eb969ce7cabf7db7060", "canary-2026"}, + {"45afd1494885f6113b5c2e93fa12208851003f40", "canary-2027"}, + {"3043e4373219da9a7901f5df438ea9d14da73125", "canary-2028"}, + {"ef118fbf27ac4dfd5fcd357325698ac78918c16c", "canary-2029"}, + {"72e38f2453e6d7dbc6e061344247809abb9db8c2", "canary-2030"}, + {"d1107edac7037fed58baeb5bb7d1bc74f90c3085", "canary-2031"}, + {"259587795363684e51235be8252c5f1f6cf3c8bc", "canary-2032"}, + {"cffb2a74c1dae07c965ae86c9dcc01530c72feca", "canary-2033"}, + {"64c9fde24fb117ae87ddaa348bbf9ba272240afe", "canary-2034"}, + {"5fb77b2f493a4f2ee6b7112f2423778e4d10147e", "canary-2035"}, + {"c5220092bbd16ab162bf19da32acad71b5cc1537", "canary-2036"}, + {"0a10560f6525b39ee0e27e39f56495341124d531", "canary-2037"}, + {"288968b7040836717d8f8a7158180984d19bfdce", "canary-2038"}, + {"d0bc9988e9de499f981da66565f6b0b897d8e322", "canary-2039"}, + {"09a8d9f462e4dadd12eb5088dc10c56c62e148ac", "canary-2040"}, + {"bcf9ca41bcc3dbd020add947bcb9cd17681561d7", "canary-2041"}, + {"018ac98cb8adbb5895e7a9f24aec1f18738cef74", "canary-2042"}, + {"b292d2965a0ca561b7268f55bc855f5937d47777", "canary-2043"}, + {"e40e5a10536c3ca8de9604423acb75a1672837dd", "canary-2044"}, + {"86a7cef21cca10255b3755d80ea554943a9830b7", "canary-2045"}, + {"a773f3899a98c3b7fe1151c254d3c8aebc5459a3", "canary-2046"}, + {"bd941b991e0a4a1d2f09468da721ba8a957d9f77", "canary-2047"}, + {"286c6fbaa94492a300d8ca2bda032e0e136e3bc5", "canary-2048"}, + {"26e3be682fa2807aab7389ce8f472214b029104b", "canary-2049"}, + {"05d2c273ed660721fb2fe4b6af2f4994e1399a4c", "canary-2050"}, + {"8ed72b8596d8a8b1fcd5e9ffaf675039699624d9", "canary-2051"}, + {"c57ccfd01a7983f2ea413820ab07a3672516a3fb", "canary-2052"}, + {"55a72789fdd2b644439f89bb0ea418326a897cf3", "canary-2053"}, + {"364a24336ce9fc7abea421e98c996f23553fe407", "canary-2054"}, + {"b208941acf1652a69e0f7058726e83d7e481547f", "canary-2055"}, + {"f2456a79ef85be22a7fbfceb05d172efbae1c8aa", "canary-2056"}, + {"4f324051f1b45f975ec35dec4c7c6d43f7f97c0e", "canary-2057"}, + {"b856c987585e922410a206a6bc7d8cde7c1a72f7", "canary-2058"}, + {"c48376533e05baa839f72200334ac0618d13788b", "canary-2059"}, + {"ae6c86e534ee5ae30a6dce9028c2d5f2674d25b1", "canary-2060"}, + {"891c89136918c0c22f1989e20d7e5e4c7258b423", "canary-2061"}, + {"fa4f761383e9b01fbbba9964a8cd6830f9d577fd", "canary-2062"}, + {"250f7061c28b7922592d75222e4f90aaf181312f", "canary-2063"}, + {"892913efab41bf7c20508974485e2c893032d530", "canary-2064"}, + {"10fd1c5cbe04187a9afb1c1c1ce499fc0177657c", "canary-2065"}, + {"a6187481e9c85f60f981d5237a2e59faa7f18877", "canary-2066"}, + {"ce95013f8e7e0bc470f9aac54344ba62aeda7adb", "canary-2067"}, + {"1f96a31b70d5334845d7e07529ced9731e494c2c", "canary-2068"}, + {"d3ccf18362dcc86f728fd7887a1573c799df9adb", "canary-2069"}, + {"6f73b314dcfc28b8d3659f6b172d9df601fc8682", "canary-2070"}, + {"e38e3e0a877a40669baea291fadc47bff413dd96", "canary-2071"}, + {"8aa6f206f0a018d98e7387900045f72ea81babcf", "canary-2072"}, + {"5744a83c5247b56f40aa4ea37e16530322d49d2e", "canary-2073"}, + {"5484be2ed8c5ec937a2969d519695fc3253e6979", "canary-2074"}, + {"b8504cbf36d4d1035883e4ca7247695eb9d7b86d", "canary-2075"}, + {"6de1df1bf493e0fcb933e720b53b867eb932d00a", "canary-2076"}, + {"b3dde3c37895c029c0735d52519852e73ceaf3bd", "canary-2077"}, + {"68e99d8f4f1d2a2d1704026b9ebd17333743f22f", "canary-2078"}, + {"5e224adf8dc2fbdee82f02a2e8b8ac34f0036a84", "canary-2079"}, + {"06e916d4e1b9867e2d70684739fb2a88fb997bd5", "canary-2080"}, + {"aa0c2da77983f611fb9f426b994ac1a0b4251b90", "canary-2081"}, + {"4bab204f9cce7ccd4e73461524df5e6418dfef57", "canary-2082"}, + {"e211c662571eadf9ba98efcfb5266188711de5e3", "canary-2083"}, + {"be34f1fec6855899ae7f4c756ab0df201a95137f", "canary-2084"}, + {"ba0bc9e58252d9df51576b09af91f9e3e7c9e35b", "canary-2085"}, + {"bcaa6084e61a48005ffdb014bc76b6586cd5567c", "canary-2086"}, + {"95a101f86cc96bd47fe1c6489de28d2178678ab9", "canary-2087"}, + {"66156194c4762104a3f3d06b028e93242e36d9ac", "canary-2088"}, + {"960dddb23f68e2ccd6c96a71b6e90432139bf30d", "canary-2089"}, + {"403ea18f8ca2b9cac29702c9787d988c9848a934", "canary-2090"}, + {"307675fa4405cd8c885c29114454ecffb8ae60a1", "canary-2091"}, + {"4d8bc2c2c7cb94eef0c6ba129876097706005090", "canary-2092"}, + {"0ab4fda53fe47e731564814e071b22b9f06d6503", "canary-2093"}, + {"7135378321cc4d62f1d4d2fc35ce5db9046302aa", "canary-2094"}, + {"82df460203f0b430884cef45fe17e6532bd152c5", "canary-2095"}, + {"d9e64330cb1852446d6d739d9b6d712cdd696876", "canary-2096"}, + {"17a444c98c55d125957095c70f4aab1a8b1322b8", "canary-2097"}, + {"d4b55cbb36cf10b05ed626bd0bb789c891919404", "canary-2098"}, + {"dd41795f116031e85cb5b15bdd46843396638e31", "canary-2099"}, + {"7c806996ce6c62c35790ae3d9dc7777746f28521", "canary-2100"}, + {"4b1cd0979a4b896fedb5093e97ed369643334b05", "canary-2101"}, + {"83f7f6317a58477825f58440ae62abd303f059fd", "canary-2102"}, + {"ee0e618273cfce9e170c47713b73fca2129b313c", "canary-2103"}, + {"f616fb335329bd0d5b675a8f434038a3bb2f8044", "canary-2104"}, + {"d99acc204737fff6d570bf702c6b4d5965fdc654", "canary-2105"}, + {"b571b99a54ed3b92fc1cdae13efc0be70eb06542", "canary-2106"}, + {"93f25598bedbbd1faad7914986843fe3fde0416a", "canary-2107"}, + {"2732efcba37aab2c7c0b90f8a8ff2045a161293c", "canary-2108"}, + {"de9ad8b328d3fb638aa94fed13be259140265586", "canary-2109"}, + {"df8f2f627f31afd75dd508e57008f7140efe7ef0", "canary-2110"}, + {"ecf9e171496db7b9633a1db71159c81354ff7f7a", "canary-2111"}, + {"8fcdc9d66e6fda8dc16a856410cf4fa2011fc00b", "canary-2112"}, + {"cc36e0f54d0253a7eb4382502d7b961eeb8a1b62", "canary-2113"}, + {"c59ad7917654cd4ee0af71b4105a6dcc8189a043", "canary-2114"}, + {"df4aa4a601fd32fd32109b06b0b2f63ccb022f6c", "canary-2115"}, + {"5aa1987d55b2e3e258c7ac0e8a2e812f9b72b862", "canary-2116"}, + {"a8b5bd30a8b0d5fd905980d49dd49ac23f578711", "canary-2117"}, + {"17630edcd3662b88919c0d72cae401ea50712f74", "canary-2118"}, + {"b3f246ce099d6ff3aad30fe2fbe28761a446ddeb", "canary-2119"}, + {"b6df6cd62d04bf25173f516bcc11d8abda837704", "canary-2120"}, + {"4ad3eac947ffc1b643fac4357a4741724d5dbb52", "canary-2121"}, + {"3d62fefb8bf992bd8267ec83105ebd7e6ed95bee", "canary-2122"}, + {"12b1a2dbcc196961f7b012d42ae38fbff979f7ea", "canary-2123"}, + {"d8537cc3f540eeede5aa34ab7625c6833ecf20fc", "canary-2124"}, + {"0c754fdd8ca5ec3311b6d3f648270b967c2f531f", "canary-2125"}, + {"26ff8e7bfe1707053ae194e4cdf61c7146e23abe", "canary-2126"}, + {"c32995347d859bbc6353524a3afe2974df6d56f8", "canary-2127"}, + {"fe4841425158424693846df59e311e3b5e99d4a5", "canary-2128"}, + {"3174fe02570394d64a23da7839729cd0065502d2", "canary-2129"}, + {"9c96c145f3b36df0e58be398ea81283b7ec7c5ca", "canary-2130"}, + {"efffbd7f82f8df63aee15ad9cfa181e1fdc511bc", "canary-2131"}, + {"42c77b58f7afb3001b532690e388ef1b04a09a6c", "canary-2132"}, + {"0cae5f586d4832104f5db5820c968e830a623505", "canary-2133"}, + {"8afade060cf826e133022eb655dbe1259b78cd5f", "canary-2134"}, + {"57891c04443d0db1be5b29817d8c85ad8e1fcce5", "canary-2135"}, + {"49cc29e990ea680ffaaaf444f5e0ffffcb2645ec", "canary-2136"}, + {"d0d0afdb18b20f68a5d4027daecbee683e3cac24", "canary-2137"}, + {"fbe7fbdb7fb8ce22a661dee955d76a984d716acf", "canary-2138"}, + {"77edcd97d16d733b42ec7e3daa12f3163fc16d50", "canary-2139"}, + {"c4069c7362c0abb88108a4481efd5490c89aa99e", "canary-2140"}, + {"55ed4c0409d59438ba4710638c50ae4c8773b04f", "canary-2141"}, + {"fedf9a9b31443b64a71bf26747ac900694e4b017", "canary-2142"}, + {"e5b9c950828bef6830bd94e4742fcf4fd3739aa8", "canary-2143"}, + {"743e610494cfb047265ac52c61c98d8af06e84a1", "canary-2144"}, + {"ce6ae36a45a599cf2fef82e79c07cbad562b6864", "canary-2145"}, + {"605fd45fd2ebb1389698fd834fefde1c23a69c35", "canary-2146"}, + {"ead203fad1c64765dde993def4dcfee9384dadc5", "canary-2147"}, + {"1a5462b37490609be2fec0b3beb33c1ed3284a9b", "canary-2148"}, + {"1132311449b0366dae77acd3a63aa5723145fc9b", "canary-2149"}, + {"08ca904f094d340f6b4cc7e5208c63c23610bdf4", "canary-2150"}, + {"76f59efc357209fd8711a88b008b640522d675a7", "canary-2151"}, + {"da3788aa9a26b8518ddd3f97f874f6f019e657bd", "canary-2152"}, + {"4c6d6f5d6defebfcbe257b3770f6bfff9b852672", "canary-2153"}, + {"9a93fe978cf810b564411c354888c20771179fd8", "canary-2154"}, + {"469f2786530ccb03361dee0261228b7aab17ede2", "canary-2155"}, + {"1736232c88b63cd1b6345d4b835aaee167bd2947", "canary-2156"}, + {"e252af9e8cfa3fcf7226eb939d6ff152fa814bab", "canary-2157"}, + {"3e150456570a7081c530b7ec0bcd8e163b02af23", "canary-2158"}, + {"56adea1074ea1b784217210150f38f745714504f", "canary-2159"}, + {"e6f9f18db0c3efb2772b2695efa87a410dfcce5d", "canary-2160"}, + {"bf3496820d9fbf363369bd80712172797f178e24", "canary-2161"}, + {"33ee3902bc80ad67fe895b449f01fc5dca5dbcb5", "canary-2162"}, + {"5b3b5aa3e4369f3c3272f71ce9621787fa78a5a7", "canary-2163"}, + {"862c3eb0569677a156693c824f521aaa3222bdae", "canary-2164"}, + {"27431c7e79e26ea93bc9c300c5c84da76a25d10f", "canary-2165"}, + {"b9b66af246366a5221acde92cb01c42c756bd626", "canary-2166"}, + {"06eadacf6e375f5270d3be00e5ee5f93579dcdad", "canary-2167"}, + {"48f6c9e95aff2cc8fc1a9cbcb19ac128d17041c1", "canary-2168"}, + {"9840c2defc936dba7afd3424923fb42516b7c034", "canary-2169"}, + {"1a23026b5759cb3c0499732c2c8c8490e5640d05", "canary-2170"}, + {"47d89f0a8cc266e2ac44a5777657800941e33414", "canary-2171"}, + {"1fb57cabb71d3a48b007c54a48afb990e9eb7418", "canary-2172"}, + {"d0cf14f99598913a6dca96a2c5d6c96bc9d53128", "canary-2173"}, + {"14f9b973999f2888252181fa1d3ffb6cb55fb5d5", "canary-2174"}, + {"3353aa4175a68f3a1c7304cb5d644b25cff520a1", "canary-2175"}, + {"db7598416e9651c39b676ea3928fa3bc8235e3b0", "canary-2176"}, + {"57e5ccef7738973b967c92b7c5ed309694571bb7", "canary-2177"}, + {"a4009657e16f1aaf9aed40c906c8be5f712bebbc", "canary-2178"}, + {"f30873d99be6a9e33c35bd4dcaf5f95b62789713", "canary-2179"}, + {"479beb279079aa675ff8c5771d1c02e40857b923", "canary-2180"}, + {"4207e97b3881a8d41a3ea8b39ba5e20f2e7d7904", "canary-2181"}, + {"ae14756c62c8034e92e4d52c01645fd660d4897f", "canary-2182"}, + {"d9302742ed77d33f4e407afc73386f3a607c8f78", "canary-2183"}, + {"f4d60a043f064e748db00afeddd8ba01811a8adf", "canary-2184"}, + {"27db4a5a63e9a09af62d917fc97fc7092b218486", "canary-2185"}, + {"740c6a8c9c6a59d460de3ee9d2b687bd70215d81", "canary-2186"}, + {"4bc95e08bd05a16a555d70fd8326dd364596f593", "canary-2187"}, + {"3e5094a65ea2b8423937909fa6c7581d8d2abc1a", "canary-2188"}, + {"1d9485c5a14d1a5e4f5ab3224e372d4952df2e6d", "canary-2189"}, + {"546a8da7b78857ffe3df48257afb9bab34b60ebd", "canary-2190"}, + {"06a951ddcd713de0f1098b173f2c993779496e8f", "canary-2191"}, + {"7574727d1ec36d8654447f3091ae7eff4ad060b1", "canary-2192"}, + {"b3f5a847a4cd5e2b991cf59af65c3ee95440a0d1", "canary-2193"}, + {"f1899d3ea2f434bbd7af8c1b2a97208b16123c6d", "canary-2194"}, + {"a77a99d457bcfc0b440694ea2352826628071770", "canary-2195"}, + {"0725dde769e08be0c9500563a16038b40dac068f", "canary-2196"}, + {"eef32fb41e7483a7d4f88b2661f116f6118739fc", "canary-2197"}, + {"17ac375c67656b1ef21953fdebcc4f2d48a4a353", "canary-2198"}, + {"39584f2ca3872e0c021c67664881fdfc1dadbbee", "canary-2199"}, + {"9eef83c433ca8672cd748ba3fd05cff1ada17b4d", "canary-2200"}, + {"8d2a97d840e553938b226871d5878db2eddde925", "canary-2201"}, + {"e1674808b94e610e3cb4cb8fcb778111a1f9e005", "canary-2202"}, + {"d81837472b2f68c057bf6c5c78c8029b39b2c1ac", "canary-2203"}, + {"7e1cd897e6ef900979ba5ff35111dd53e794bf95", "canary-2204"}, + {"21ce2b4c4c1949e718f267c0019a99de58db8923", "canary-2205"}, + {"98a2aaa16b7c83ccd67a24d88df8ab5446cc7d54", "canary-2206"}, + {"190471340506131ad41b6e8b287cc02c51dd0c42", "canary-2207"}, + {"fe87ff36de4213bdb8f7cecab6e7f373cfd46aca", "canary-2208"}, + {"1275a417c95a78cd22104c4ccb6dacb0482f3978", "canary-2209"}, + {"9a21b19e56cf30ca688cf25995c5503215ae2eec", "canary-2210"}, + {"ceea63d0f3348c55ba65e6eef67bda41e87b82d4", "canary-2211"}, + {"3498dfce191a3738a51991e5ae20b923d3075083", "canary-2212"}, + {"72fb90522059ccf7517837225c8ddbb78bd65176", "canary-2213"}, + {"14115e175109ad8c3786aaea2372382009ac0be3", "canary-2214"}, + {"dffe8e231417cb36925b892898bd001602b43dd8", "canary-2215"}, + {"986173342504b2dbbf183031e92ba5d9422da1ab", "canary-2216"}, + {"5af8b582547bb8da62e1dd100b76787f3e24d291", "canary-2217"}, + {"cc3e9a84256cf58c29ec91aa816209ccff59ab97", "canary-2218"}, + {"e115fd17d1f5b0da6aae9390fe56d02e02997284", "canary-2219"}, + {"247ff064766d986c45e87ae2690cb2c5061badc9", "canary-2220"}, + {"8063c6eda2cfed8b07260fab81d1fecba347d2f6", "canary-2221"}, + {"9500f382569912732a47306309192fe3835aff92", "canary-2222"}, + {"dd60b9bc65e46de5b833835831fe31ed81a67cac", "canary-2223"}, + {"dc62a7b77caf0c34c890aee4a5c9ae0216d8ce76", "canary-2224"}, + {"500e93cee72e05c3551dbc5c9668b374e478dc88", "canary-2225"}, + {"77dcb704d859d321cae38b01bb3f4fcbda73f050", "canary-2226"}, + {"a634dcee69928c3f94463e8fae1d3cacd20cf264", "canary-2227"}, + {"b9fd8a8c3c4640bca852196596cf4e1a3e28ae62", "canary-2228"}, + {"dd58cdc3a78517bf634d533b216518f7dd107b80", "canary-2229"}, + {"5eeba8722b49f0f2369ba8c376c10b37145e0b14", "canary-2230"}, + {"a72d785b20d6f300e1b5fd3f589728fb7280fbb8", "canary-2231"}, + {"c8a0161a21e45c2f320dc014adaf60d832610703", "canary-2232"}, + {"0e4bdbf57c156d01d14fc720e68c4afb566ecd10", "canary-2233"}, + {"4e39a8d3e5a291b3111de14dea6a513e2c56c7f5", "canary-2234"}, + {"159f73477857c7c56830d9109ee9be52439e4787", "canary-2235"}, + {"976fa35e2a3b44e9e9b671239657d6ca3a00a7fe", "canary-2236"}, + {"cde88be7a11d79b3903e6e58e78345865145559a", "canary-2237"}, + {"6d388d0d0b85ae38d18b505e5aa49600335a2841", "canary-2238"}, + {"82179e1caff53e7a1a93bc32b963e8894d04810c", "canary-2239"}, + {"d427733092d8a9b5724e30883ee2684894cf40cc", "canary-2240"}, + {"9b58b2ee28baca31687799109d3daecd6169af6e", "canary-2241"}, + {"f0917f5a420ea577ab859b08da78d43a9db02e0b", "canary-2242"}, + {"58cb375e83ce050792d8bedbd997efaa5d53719c", "canary-2243"}, + {"c65d7140671b106daceb165de60d99f1e8fa8538", "canary-2244"}, + {"fad6a3ba2f6786584ae8034e711497cd6ce29f87", "canary-2245"}, + {"6127aa49ff3968f04691365625a3b7b90fe18b99", "canary-2246"}, + {"a402381ff3ffbf8a581e25eb0da0e8ab56335bcb", "canary-2247"}, + {"1a1852f4ba786bf46d1e80a1212c279f31190dfc", "canary-2248"}, + {"02c74c878c1c0b382203ee0b1b3efb52f63e9e3d", "canary-2249"}, + {"4daabe3dcfeb814aff779d1e437bbeb517b9ae21", "canary-2250"}, + {"c80d81bed5d7bf6e23be3bc45b16f756b061217a", "canary-2251"}, + {"0f87d01c9fb05997ae5c73b55fb6bc8f65e28124", "canary-2252"}, + {"6dd51b32bf895906c053091fa63987966c659be2", "canary-2253"}, + {"2df04fa1c608c22e2b55b6df0ecaac34092f4255", "canary-2254"}, + {"68e131be11858ddbfdb954ba5c21518228ddca1f", "canary-2255"}, + {"6e5db49acfa95d7105262dbf25710634db504ec1", "canary-2256"}, + {"81ed9f9e850b17ae9061b9bc24ce9f263bb0ced4", "canary-2257"}, + {"b9ea1619b9ba06edd5c31cf5f7cd4ce43e3da2c5", "canary-2258"}, + {"9d4d5fba50a8f4e399b2b51578a941371c705a30", "canary-2259"}, + {"44b85365b428f0061ec06f824e4e0fe480b86b44", "canary-2260"}, + {"bd3ae3ad1cfedd7dd92e4c2ee96c6695675109a0", "canary-2261"}, + {"e5a133e3898a9875fb4e4d55e95e98009c77dd94", "canary-2262"}, + {"e0b7932195ca0b6ee1f10e52fa25526c1ebbdd7a", "canary-2263"}, + {"1f65fa68bf5f060e32b4c996c0ab93b52519c403", "canary-2264"}, + {"51c0d446c0e4b9958d8141247d5735e16cf5a61b", "canary-2265"}, + {"baeff6eddb8cefee4650173feb607eabf7127a82", "canary-2266"}, + {"d947e71f0719d5463d74108be734d22d69e232bb", "canary-2267"}, + {"8a1c8c53f246aff24268d5fd185efc68229591e8", "canary-2268"}, + {"b02d9c4a4e7bd4ac77b575157675377604c8052e", "canary-2269"}, + {"1cb8bb700876fadbfb987f41b3fd208af4111cd5", "canary-2270"}, + {"58a6502a16a99f5957d2744c7589b98ed3f866c0", "canary-2271"}, + {"ac3ef658e212a62c0934d82fe562fd08bc84bc08", "canary-2272"}, + {"aa36a3c0da8dc97b84ea79331bab6995e190f9c6", "canary-2273"}, + {"96df489edff20d423aef5b6de7caf504e3b3ee71", "canary-2274"}, + {"f3006178da3fe313d6d0f76c9b8fa524e1b8d31c", "canary-2275"}, + {"071f7de6f75af2417f0a63aa7b81b2f76a333650", "canary-2276"}, + {"ea7eb4062ce2f7fa8ce22aeabea7b8e24bf9bf7a", "canary-2277"}, + {"c0e95440d14c7c27da386abb8031cf759082ba2a", "canary-2278"}, + {"96cdf4cbc92b87e9fbac2b11e6df2a98820f3563", "canary-2279"}, + {"fccf0982da29d723ef979671f752c8bd9de6ebf7", "canary-2280"}, + {"bd172dd147e188e41c39b7459abf561f679dff88", "canary-2281"}, + {"626c9dec254e8b3030f7e3d7f7f9d95fe11983b5", "canary-2282"}, + {"8e53f6cbd527b5b9822999982dca046d9ffc6ec7", "canary-2283"}, + {"8be213872f827cb4f2a77705cd189057f8316cec", "canary-2284"}, + {"d937b05ba541da2b7ae34e0c933faa749b756d2a", "canary-2285"}, + {"c2533f8fdb533ae2a3d1473b3544a85bee03f672", "canary-2286"}, + {"c15eeee714e8c1d46c5d371a32c03af67ba76514", "canary-2287"}, + {"c74049d76ab8e2f12836d8547bfd9cd9a0b0e30c", "canary-2288"}, + {"b505cb5a21e3b73edccfe9dc3a2108f8960db3c8", "canary-2289"}, + {"638c8c37717589520efb0c603a1f3b53e197a187", "canary-2290"}, + {"f963aea4a1b270f5d8666e0c7a8fc9886f93652b", "canary-2291"}, + {"3fe9ac1ee5c3777fdcc1efd49998a5222d06b15c", "canary-2292"}, + {"702fa0098dd8724383e4ea09c0b11b3eb97e2996", "canary-2293"}, + {"fee5f03c003a5904837887ceb714ec30c1570505", "canary-2294"}, + {"0fbef6b0fc796a118fb255dbfb109b7c49b4de47", "canary-2295"}, + {"c67d61a57bfeeec0b6a695af942c210c265b9b69", "canary-2296"}, + {"7e93a7320250cc7ae11f58221ccddacdc1da0df5", "canary-2297"}, + {"7d4074cf16a76eff5b6e3b4de33dd379b22773d5", "canary-2298"}, + {"6a6f652baccd31c21e7b96e4a62086f8ab5eca04", "canary-2299"}, + {"cd6855a653edf7982bae89bb6d23719f1b3ffcfb", "canary-2300"}, + {"ca9d924edd34af4dc9cfb59c50fa3d79b7d64510", "canary-2301"}, + {"ef7b48e25c5bd52ab7de0954dd296b5ea917e70c", "canary-2302"}, + {"1fd334deed8450f687f527a2ffa0c948a7a180b9", "canary-2303"}, + {"80a06ce823d9aba4a5a6dd5054f77fe8eacb2f5d", "canary-2304"}, + {"f4099df0fc8d3571fa2a4e09585c5bc6e242e110", "canary-2305"}, + {"0f8f1f9f1e58e7965d59e96b7722c1d620647a0e", "canary-2306"}, + {"6669110544b72510392c30fb2e1bf0ac38f72364", "canary-2307"}, + {"78608bf033d55e7729db434957df3960a705b12f", "canary-2308"}, + {"b08517e2caa6de694f74d14c0184873050341d29", "canary-2309"}, + {"12c9b5b0b7e86600e885214aae4c88de0c74dc8f", "canary-2310"}, + {"55c4e61a1b8aba133dcf069df4c2a624ca836289", "canary-2311"}, + {"62507595fddc6fafd2b64891163c50cd1e789652", "canary-2312"}, + {"6e8d7b6d3ad4dfaef3798785609fb4615aab0219", "canary-2313"}, + {"3b9afe36cadce455972674c5a8e4bffdefab8f6a", "canary-2314"}, + {"b100f5e64b8fed3501b0535202971861a1caf3b0", "canary-2315"}, + {"7b3bd2073c4479003ae4112743901c0b8ed86a8c", "canary-2316"}, + {"ba7cdc41ffa9392d1774e3e15357af36df80d813", "canary-2317"}, + {"bccef5e54410e76c8612876fe18a377ba8d8b351", "canary-2318"}, + {"12c57dfffaabf48a440dee6a6cdc417b191f6748", "canary-2319"}, + {"996ab19430fd6f05f4423697e6b1aaf3c5f5c0e4", "canary-2320"}, + {"eadac48d56d373d5229041bcc085f4b4f2ea135d", "canary-2321"}, + {"536a27a639c2927652550dc38be2afbc0f7bb63d", "canary-2322"}, + {"31b894ce96267660227a67b0296389b46aae8e56", "canary-2323"}, + {"e608d0fd5700539432a372bbe8c15de75d735789", "canary-2324"}, + {"68680807a92896ebb23cdf63f6687dafdb6da9a5", "canary-2325"}, + {"54a01c33bd1ab0cbe68261cdbbf3e422144b2501", "canary-2326"}, + {"35b1ffaa3b9e081d633cc61eb6c9cd50dc76462a", "canary-2327"}, + {"048deca412a5706d9c80d2f02962d5c3adc67bbd", "canary-2328"}, + {"75cca0724adc3b9cbb181b3ffa3baf2255d68196", "canary-2329"}, + {"bf469e328ef8dc5c0bf5811b3eb4dcb8c83e0f39", "canary-2330"}, + {"5b9d126727d72c40a57a4138a36fa64024fb8c2c", "canary-2331"}, + {"db0a13ddcf9931555f9a2b409430f0478592fb85", "canary-2332"}, + {"21447152b9e2cc07dc421afad8e43b399fbe8fda", "canary-2333"}, + {"a1159c0814a41e6789fd39acb1129fc3c6bc0b48", "canary-2334"}, + {"18ba11250bb6fa5c850109307e6393895da6c7e3", "canary-2335"}, + {"3e0d5df13c1d337dc022c3d67c73bc5fa0ea2de8", "canary-2336"}, + {"009656592df7bb39b7fdb9e5e6fc78bbf3bc15f0", "canary-2337"}, + {"7075be3b19654d7a337c531530d515de2a03cd95", "canary-2338"}, + {"6c83402ed8d4e8656285c4cf486cd387a539cc97", "canary-2339"}, + {"062c8927e7b117a4df5c8f056cda305d026054fd", "canary-2340"}, + {"ac6ddf4aabfad72e10271ff0efdbd12e8494c852", "canary-2341"}, + {"3b092dc9587193766ec5013ad48f26ec5da4b1a9", "canary-2342"}, + {"cef48915d0e3cc862663537539af2777164deab0", "canary-2343"}, + {"ca590eff7e45d9ded5b79c3c61e8b948b05f38a8", "canary-2344"}, + {"93e5c657651b61d40a7700aa65d47abdc63de1da", "canary-2345"}, + {"f61cf3a2db825f2f7972d79911f352b4d14469f9", "canary-2346"}, + {"ae0abf49f0885c0fc936ae7b9a14b62d8728d25b", "canary-2347"}, + {"4f9be7d7e0ef2ce224194c30214a30c07585db5a", "canary-2348"}, + {"6142c04092733782182eeaf332219caa0aba6821", "canary-2349"}, + {"6013af93f82988f846d8b85463d1c8b51e636dad", "canary-2350"}, + {"1bec32697ba1f7dbd2da91e4cac0b17492e87f46", "canary-2351"}, + {"3ab70c7539d44842f5870bc8aaae776549229aeb", "canary-2352"}, + {"945a897acf17b7139422304de4f2644961335a1d", "canary-2353"}, + {"c4026dc03ea71fd1274be4f5d5388b598bd903cb", "canary-2354"}, + {"775dbc553f305ec655ccadbe7f9883a273311cac", "canary-2355"}, + {"e45133b0fd466e4d510609fdd31055206039f07d", "canary-2356"}, + {"be4fb8ecb71d52bc8432a06e64e31fb67c4b0efe", "canary-2357"}, + {"dd96fc5dbb7731c3d7a6bf23116296eeb20acf29", "canary-2358"}, + {"185cc6b428d51df2e98042234676eb43edf73e86", "canary-2359"}, + {"95aa4457ab1837e0e7b6b8573a47f2f1742db4b5", "canary-2360"}, + {"f119f19fd06a71ceb06077a9c362456b7385c4de", "canary-2361"}, + {"f16706288e107670c2a469f67f41d162d6be0d3e", "canary-2362"}, + {"cae7c105eeb5f31b697fe588ea53c588a3c467bf", "canary-2363"}, + {"1a7c6f9daea11749523958f32efe129194341b0b", "canary-2364"}, + {"af76af2a4de0f9bdfdddaf7c73546ebfd5724876", "canary-2365"}, + {"0bbf367392616c53a18e469e4d82282ee9fccaec", "canary-2366"}, + {"91e7576ca88b42fc640fb21209dc9ce584d8bbb2", "canary-2367"}, + {"61c4859f773425e21b8789868e8fc480ae26a6c0", "canary-2368"}, + {"f6c184f506ac576f68bf0a2a23b7295dda2f4198", "canary-2369"}, + {"cb65b6ed9f943a74a24a95adcafa82e7692f3cc7", "canary-2370"}, + {"66afc941fa0b4f3bfb577a1d4ec3ee04148c8532", "canary-2371"}, + {"75c1f306794947a2ce9513b0371ef703621292c0", "canary-2372"}, + {"d8ec62512b5fb38eb21e3812a89c214d11ab43e6", "canary-2373"}, + {"60d583c68a91e77406f8bf7eb54f4f0d0a7289f2", "canary-2374"}, + {"d4abf9e447586bea635c0816a581b005b4513434", "canary-2375"}, + {"47d7e7ca22d832d5d505725bb4bd0347dd55420a", "canary-2376"}, + {"e10a727a0a616a1465e7adbb2666361afefc3e5e", "canary-2377"}, + {"36dcdf6a28495733b3485df5b9e770be8abfc395", "canary-2378"}, + {"33aa5de88570085d77e0d3efa62527d6ba5333b2", "canary-2379"}, + {"61789f19ae7afac351d33367fddd6ab7c300f45b", "canary-2380"}, + {"7168317abc2d10396a7ee3ab9e3cdd78a8181d99", "canary-2381"}, + {"26613b182647a7630d4ad6d58094014f347bd227", "canary-2382"}, + {"7d479d089129314c80a1ff70e148cdf9a4df85eb", "canary-2383"}, + {"8f02c57757cf7eb9c1ed2d13271f5852fd6086ba", "canary-2384"}, + {"67421ff0c0e722c7738bd8ba74282b7d2eaeb78b", "canary-2385"}, + {"76c947ffdfdd3e03012f7d80912d63fb71b4d1e5", "canary-2386"}, + {"897fae3a33fd96dbf3e27a049867745bdae1d9d0", "canary-2387"}, + {"7666bfc037cca0cdb11a0111f5650e53969bfe4b", "canary-2388"}, + {"b9c5b95db5f9ec98c12ee83a6e845986d4cd2209", "canary-2389"}, + {"a5a13128b4769cf8dfcfc5289707c6eb8ac13c61", "canary-2390"}, + {"5bd0047b513dd29f446e3ae29b6283a0b70e7f60", "canary-2391"}, + {"2807d3e2fec27518976a50bdaf3f837560ae290a", "canary-2392"}, + {"25e44b4d02c830a390acd6262976a48622fc5eed", "canary-2393"}, + {"373786e5be9948d0f4a25a83fc939df43ede423f", "canary-2394"}, + {"183fcc32d52a640a4c0de1ae2721c4ed410bdae9", "canary-2395"}, + {"27dcd6dc4ec34ca65722f501b83c1d08947140d1", "canary-2396"}, + {"eb79a2a1612f6b339fbd18b695d7f579642bb1e6", "canary-2397"}, + {"ec1934d23a0f2791d812c10bc9ca7797308fc24a", "canary-2398"}, + {"0daab8b7ff793947ebca48595a70d6a88df66d58", "canary-2399"}, + {"4e9fae5020d244808b9fc9ccd6bf07d810f6d9d3", "canary-2400"}, + {"1ef395f4f00fa567c82ec1611c9fc07707da4970", "canary-2401"}, + {"5ed7a3c1a980993dd94f2f8e0497053e5285f758", "canary-2402"}, + {"7eabe1a79bf70e975b4e1f3e813d9566522b15c4", "canary-2403"}, + {"b879b864620af3a52e067c8b82832b40354ae7af", "canary-2404"}, + {"fe18c662054c15a3f4cbccacefea3c504ff86cd7", "canary-2405"}, + {"726c74840775b8b6f3c2f860a86c12019c9231ea", "canary-2406"}, + {"c93abdeae44be27ccd691d82d74f9959bd6b74aa", "canary-2407"}, + {"f8fc54154750c036d62cecf9f2b504bc13347a52", "canary-2408"}, + {"8d4dd0cd1f47adddea0b3027b88680ca4e964911", "canary-2409"}, + {"01b3a00b9c5b07ddb603be5d342a28d21526f04f", "canary-2410"}, + {"c621e5887d866b20aa3c1f449d438045207e4f5f", "canary-2411"}, + {"3402c4f105664e813752162e9f955617ab16a70a", "canary-2412"}, + {"c7a27f8789fb07e8edf34ef49ecd9d2723650a90", "canary-2413"}, + {"9946596523c6e62ad7a8187f0c82e3e46ed97e44", "canary-2414"}, + {"e509bf96a3cdece9ab7babb61a7279af799ff39b", "canary-2415"}, + {"f5dba7be36b44a9bc7ed8fe3b854981a8ff42983", "canary-2416"}, + {"68ec5d2d59b283633e0ae5ea7ea9960d6d9fc0f4", "canary-2417"}, + {"34e696544ce2774a0bfe1f7f4ebca7509c9d9fca", "canary-2418"}, + {"1a2e04a5da17b36d600db4950e5b638c6681fd31", "canary-2419"}, + {"6853081f306e932f0aa2e041b0d4c29475f8b9da", "canary-2420"}, + {"83eee44f180c134368801d60f6ad39423aa32d1f", "canary-2421"}, + {"4e6725464574729f40880fdf6b22c7d99f26c55a", "canary-2422"}, + {"ae6f757258eb5cad6da8b282378e61d991c004b3", "canary-2423"}, + {"37dcc2c8dd5a49de5dfb24f8151ef55806dd820d", "canary-2424"}, + {"61fdf0553097c56c836246092979c77bcaee00ad", "canary-2425"}, + {"c218d30390e507706643d0814c283789706de2b3", "canary-2426"}, + {"97b5cb539cec9f52f308e1fdbf880aff9fe07955", "canary-2427"}, + {"2036a8f8d646eb519aca3461ad7633c1b8c37925", "canary-2428"}, + {"c59d34fedb80830bd45b41270696eb74d18a3a77", "canary-2429"}, + {"76d8035c7c8d4cdc4f4c3eb5e8f58db9e8ae2850", "canary-2430"}, + {"ec968319fbfe725b5c4330b4cf7051b121607675", "canary-2431"}, + {"aec48b6422c1a385c95118cd3869b00db28944cd", "canary-2432"}, + {"51cbd53c02726a283a27242f6ed4d51e171bb2fd", "canary-2433"}, + {"c5b836d6d96a52243fad812e4b54e587176cd65c", "canary-2434"}, + {"ef5fba91640c10ca2a8b0b7e6e6e25da4bf2de74", "canary-2435"}, + {"1db9c74f737414365881f8c5c15d623fb8b204d8", "canary-2436"}, + {"daf0b9069cd4d4574e0a0503bb57b15462ed8cca", "canary-2437"}, + {"dd426d73c9a1795d6d5b425cc1698f7d1f523706", "canary-2438"}, + {"ddbe932d7aebf5c226d403be44c485c1d75bb507", "canary-2439"}, + {"494cab41a4860d80306657b648297039f488f17e", "canary-2440"}, + {"2b40cc5db3d357752d62c998610c213cdd5d6769", "canary-2441"}, + {"3e1cdfcc198d5992de3e220d7ed1419f4e0282ed", "canary-2442"}, + {"325890d5da808e47b8c81e7e6f0baba6f4a4d2ba", "canary-2443"}, + {"eb65e3037de14be165bde2580b8c88e46bfc5266", "canary-2444"}, + {"b68f5893cb8b25d72595ad47cb6046351daef2b5", "canary-2445"}, + {"37442ca8e2db36a4a8a72016667ce9f4786a3522", "canary-2446"}, + {"6a48182f745773ae305d2205170d5fd01b100697", "canary-2447"}, + {"054278a903561db287294d125b6afa7412c91994", "canary-2448"}, + {"550f653df51f2b070a9f37f6b023e2deba703e20", "canary-2449"}, + {"ddde883a5610e3e0a36f9867024249dc598f5c78", "canary-2450"}, + {"da8c25cfa766f3c61781b2dadd1a78419aa80185", "canary-2451"}, + {"761d29b2d20612244e7bd0a5af32e308887e1513", "canary-2452"}, + {"11a99d3fbf20e769be84a6f073c4bd067e603f1f", "canary-2453"}, + {"48d3739c861acb0563432eec3569edca68288b12", "canary-2454"}, + {"f12b48c6f22deb5a015021cf71e0541689d01849", "canary-2455"}, + {"60414674db6e46a55c1faafbf8de8ee2429708a5", "canary-2456"}, + {"325150d7d766043e5316593726a2bce494b586ce", "canary-2457"}, + {"40d6b80ea1473e10c33e003d79be58d0e8776ada", "canary-2458"}, + {"a5ec92f2ad698bc46b4db2d05c8acb7308262c58", "canary-2459"}, + {"a74c448cacf59fd016739bee2befd8ae25f39851", "canary-2460"}, + {"7a191051c8554238837919839c783c80f142714b", "canary-2461"}, + {"631c3f66a0401aaba48b28d0aee037e5071e9b9c", "canary-2462"}, + {"2bc03b1e04a248da094c3bfbaab828020c391558", "canary-2463"}, + {"123a2f37268250e5bb53a1c332248d657bf32731", "canary-2464"}, + {"5d043164581ce63ab7095344974d08ba9db1f721", "canary-2465"}, + {"2b2133e20e2aa21d6411439a1df9628ec8a377ce", "canary-2466"}, + {"c8c2a90e46dffe585aaf5f75f9a4e42ee0a82c67", "canary-2467"}, + {"419926afaca11ed2d297e1012943971e03c0b106", "canary-2468"}, + {"c327be0c191df7c56e6bc0d69fedeb516bb83f31", "canary-2469"}, + {"cdcd487d379baf6ad70dc33444722f551370602d", "canary-2470"}, + {"a8d8fdbceaf07f6588d915f5e458ba1a64415e04", "canary-2471"}, + {"1e6cd354b80eafde38971d898f27614d75b0383c", "canary-2472"}, + {"1be12ac6c0c31b80c041588e8a5c2e8b27bb8722", "canary-2473"}, + {"1529e316a6678db7e3cc33eb4d640e5e3a1cbf54", "canary-2474"}, + {"3ee62c4f65b0a5d2e83857aa7d933f40a2a55f1e", "canary-2475"}, + {"b43c06653f17ce83a3d627d51c9e4c65a9cd62ae", "canary-2476"}, + {"e0e394f48974a6352aacf66e742b0298dea552ac", "canary-2477"}, + {"9ab82a11e23d722e741490052ca300e723fac650", "canary-2478"}, + {"bfd715cf8fe3d7d1f29f609f5cb4d8b862161510", "canary-2479"}, + {"851bcfdab6958b93ce273b3e4e183757ed724352", "canary-2480"}, + {"aa4e3e367dab18c52041dffb6b00e570cb129da1", "canary-2481"}, + {"858c4d9d86a1c1d64a072a44455daf8740b32150", "canary-2482"}, + {"0b96b1147d0396ad649528764a595c27528dd791", "canary-2483"}, + {"c987a45b56e51c7367ac40be90a6f622c3d027b8", "canary-2484"}, + {"391fbec3ed339a94c078c6aff6686649a918aaea", "canary-2485"}, + {"0311e3eb22885ef4ef1160f890de3495697a1e44", "canary-2486"}, + {"45b11a4467490ccbb3b49d6619631e5cb56d199f", "canary-2487"}, + {"1b984f8930fd5e19fdbad2d978e112074bec4257", "canary-2488"}, + {"d1b74644c9af7bf148df8bc1499638dae507c98e", "canary-2489"}, + {"4ab64484e710954916cdff98f2c4017ca470690b", "canary-2490"}, + {"ff02694ddadf2ca7fffb5769caa51541e22a4b15", "canary-2491"}, + {"d8b4012b476a17046187ef6aeacd7c756a1ba609", "canary-2492"}, + {"87144004438ae12bbe2491551641aed7eef75701", "canary-2493"}, + {"5f01661e762a569baa33694bd2162ef17573d5b9", "canary-2494"}, + {"84fd965394e169a3a4dba4b91c87ad124dcbbcc8", "canary-2495"}, + {"399ed10f30617b4ca02fc3d136453969ffbb8ba9", "canary-2496"}, + {"e8bfb9991add79d2f47810f8d9a8f3a03318f038", "canary-2497"}, + {"c71f31b0034ba2d9ca737727d832207b9e9027b2", "canary-2498"}, + {"e63fe1eb194d3f084afa118545d89d549b33d364", "canary-2499"}, + {"37a696dd041a3becc4cf91a293563bfdf6cc893c", "canary-2500"}, + {"da564ca624c9a23005a1aaeeccfaefbcb49e19e3", "canary-2501"}, + {"af2db7328886d104f79ee218c0743647d685bee5", "canary-2502"}, + {"2fd5b184814034eb5cff474b54900e59cc884af6", "canary-2503"}, + {"8b61c9bb1ac60cb0f1c82863c89ffe7545ed2a02", "canary-2504"}, + {"2e5377c127f096fce7ff0228ce86056e3e9ced17", "canary-2505"}, + {"27c009e36d285e7c9c94d64ccb4c5bc758d0bff7", "canary-2506"}, + {"83748c04b9b5f7a99d742ddd4c30946568472b5a", "canary-2507"}, + {"4e9604ac1d32bf67d189483f1ca37c57076fbab0", "canary-2508"}, + {"e52b7e655c4263ebee887b9a7f1900c6d4d5c1c9", "canary-2509"}, + {"14290bc2fa2b73687c5e43000eeb6f9365fe5dc7", "canary-2510"}, + {"eae26a9359d8b5a8081509e03eca55abe5131b5c", "canary-2511"}, + {"2f01abf9080285465a16f2e468dd60e3bfe041db", "canary-2512"}, + {"bf49a6b2d0dfb5c55245804890d19859423c5846", "canary-2513"}, + {"b5ab621a1014386cd85e16db8b9a60de0d236b5d", "canary-2514"}, + {"d3ba6078b8a1730ce2c42f69136767646f31f5c4", "canary-2515"}, + {"04c5f04cbdfbdabbba317de902bbaed507793c71", "canary-2516"}, + {"b2f7814b172c81f01ad2bab86c0a523696a3948d", "canary-2517"}, + {"7dda646b52f942432e65b5700ba3b8e29ec634fc", "canary-2518"}, + {"fa011fc4967620d4fa6fcaa73e38c275316bc0e8", "canary-2519"}, + {"4a2a73d87adf338e28442ec2f893674a39327b55", "canary-2520"}, + {"61d28b3d358a5b53456326a565d9ac40843684d8", "canary-2521"}, + {"17436144e4ff79f915c9540f35aeff225d74a5c6", "canary-2522"}, + {"1ec747e83a23b97875ee6fe0f05c455cdb8781ba", "canary-2523"}, + {"190968c458496861359c64a7a2fd9a0edf2a0eae", "canary-2524"}, + {"2c494c74b02c45988389baab959e65a973172c2e", "canary-2525"}, + {"1d94d2058f795959555d4953818855025bbdacff", "canary-2526"}, + {"fdfc868e2e20a143f5e668df160c5c2a8c1dd550", "canary-2527"}, + {"b221e73aadace0260a304e3cc19aa84630f447ef", "canary-2528"}, + {"fe5e2fbd5ef47f495164f200ca2c26a8529f1d54", "canary-2529"}, + {"7fb3648dfa744c62d5ae683705f2447368c2fc2d", "canary-2530"}, + {"721b7a719979e3db405babd83eefd240ae24d502", "canary-2531"}, + {"bd4c0fb32cf46f737e036856561c875224e82779", "canary-2532"}, + {"0bd28cbd67358ba92754d6ea0725f62d1685d88c", "canary-2533"}, + {"80acb73faa30e85192bb3c33d0feec9841a0d180", "canary-2534"}, + {"3d33319fe18d74c768c39cd008ed1de4a88fa06f", "canary-2535"}, + {"7b55223d9291613857e07eaf622c161212186a5e", "canary-2536"}, + {"cc251a3bfb5d17563ae0fac6bf82827e1564adc6", "canary-2537"}, + {"4ec3b43672d44410df34ef4535ee0709c83b3d6f", "canary-2538"}, + {"b4458640591ddb3fa9338ae7012114161defbbe4", "canary-2539"}, + {"9e79cbe503fdbef8d385e294e1e5efd2008d0e69", "canary-2540"}, + {"3bfb605e85cf70497037a66cc1ce801734006190", "canary-2541"}, + {"6dc61e18b1e3a5e81a83bd286f4307a133e28aea", "canary-2542"}, + {"3c6566fdb92b5f7b1e80ddba91b9bd6b891b1544", "canary-2543"}, + {"3812bf653b47f3983422a3e8fee2c9eb01385809", "canary-2544"}, + {"1872ada841a0b8166a167d4333572433ed733521", "canary-2545"}, + {"2b3fb8da5f31455f07e785a58eff05bd6f00410d", "canary-2546"}, + {"db15a46df09656047cb4ad17e04f2009ab9044de", "canary-2547"}, + {"79f72b90925e00dfeb85b2c1194c14b525768fd2", "canary-2548"}, + {"6d9fa46d4dc0d1ac7ba6d57e96fa322fd5ef9607", "canary-2549"}, + {"56d6addd66f57dcbf454066174dcf1a0527825bc", "canary-2550"}, + {"f0d164e12826cc61eb6441920d94369978d0fd64", "canary-2551"}, + {"08decc47d38eea9e50cd9e76d56c03ecfcf9edc9", "canary-2552"}, + {"d528d07f1130eb2d7368963e0dc4713d69a00ccf", "canary-2553"}, + {"f5f60952ce13ffc1aef38120ca66be4d05f68f97", "canary-2554"}, + {"c3f23f374355637712878b4e24bf50ddfbde2ac4", "canary-2555"}, + {"de746b574acff63b8c6fb859630e86f8744fc2b6", "canary-2556"}, + {"da979398400ee91db5cfb75edfea44874be18cfb", "canary-2557"}, + {"ae697e0c79253c5c483d79145bae43baff935e88", "canary-2558"}, + {"9d492c84db35925b042dd30321538a62340eaafe", "canary-2559"}, + {"5cd20ee78790631b462cd990170debdbbea6ea15", "canary-2560"}, + {"c2f54595c6ee1edb818d266faf579acebcf82601", "canary-2561"}, + {"0b5c899ecb8bda89b4a4b5adeb4466a787d3156b", "canary-2562"}, + {"4327d1219d36d5563bc7369c62bc323f6ed0fa16", "canary-2563"}, + {"4b299f3ecde1160648a3b9f29d3e09c4a848b129", "canary-2564"}, + {"0c0967e517b926fb83b141c4fb1a939ca520ed11", "canary-2565"}, + {"1ae4365a314bfa5eca57d685fc3f3f3e68632f26", "canary-2566"}, + {"052251edfab9716a699a436b6e408fe3d7cb541e", "canary-2567"}, + {"bfcce2f98838e884a8421d82c7457c452ad0dd10", "canary-2568"}, + {"a2cda5ce2c4e5c349b19001b47ea39c0dc666bb6", "canary-2569"}, + {"63a467a465be01b1dc9d6c339fd07c79c58b6728", "canary-2570"}, + {"1e557a46e3ac713354443ceae7d0132c2258114d", "canary-2571"}, + {"aaf177267b8a7bdb86d3f5e41430b11798caff95", "canary-2572"}, + {"68f20dd4f79d9eea15deb33e0b11292575939cfd", "canary-2573"}, + {"0b24ce88b522064e7ac533fa91d2021c81e0a452", "canary-2574"}, + {"64f26948fe2c2076857731621934be82a6ea3e93", "canary-2575"}, + {"57cc95b0c07ac92ff76a9e1b1de676e1e5deae5a", "canary-2576"}, + {"b65bfc57c71cc5b970046499dc480dc5ddf07928", "canary-2577"}, + {"95d26f48446351cea6323897625297eb16b7d221", "canary-2578"}, + {"82d498c75de034323817c58901f595a4120db630", "canary-2579"}, + {"068fecb8e56c49557fc41e8934a57d2d4538d8ae", "canary-2580"}, + {"11e0ddb870455811a221016c745f1c58ca46d027", "canary-2581"}, + {"4e4ac3d054235476794eb1ecb9a31128f43b7ffc", "canary-2582"}}; +} diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 01dc51a6cd..8209f47ebc 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt @@ -10,7 +10,6 @@ create_target_directory_groups(citra-room) target_link_libraries(citra-room PRIVATE citra_common network) if (ENABLE_WEB_SERVICE) - target_compile_definitions(citra-room PRIVATE -DENABLE_WEB_SERVICE) target_link_libraries(citra-room PRIVATE web_service) endif() diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 23deb2ff20..d9f0fdc220 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -21,14 +21,10 @@ add_library(network STATIC create_target_directory_groups(network) if (ENABLE_WEB_SERVICE) - target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT) - target_link_libraries(network PRIVATE web_service httplib) - if (ANDROID) - target_link_libraries(network PRIVATE ifaddrs) - endif() + target_link_libraries(network PRIVATE web_service) endif() -target_link_libraries(network PRIVATE citra_common enet Boost::serialization cryptopp) +target_link_libraries(network PRIVATE citra_common enet Boost::serialization cryptopp httplib) set_target_properties(network PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) if (CITRA_USE_PRECOMPILED_HEADERS) diff --git a/src/video_core/custom_textures/custom_tex_manager.cpp b/src/video_core/custom_textures/custom_tex_manager.cpp index b8bb214389..18d69e129e 100644 --- a/src/video_core/custom_textures/custom_tex_manager.cpp +++ b/src/video_core/custom_textures/custom_tex_manager.cpp @@ -170,9 +170,13 @@ bool CustomTexManager::ParseFilename(const FileUtil::FSTEntry& file, CustomTextu } void CustomTexManager::PrepareDumping(u64 title_id) { - // If a pack exists in the load folder that uses the old hash - // dump textures using the old hash. - ReadConfig(title_id, true); + // If a pack exists in the load folder that uses the old hash, dump textures using the old hash. + // This occurs either if a configuration file doesn't exist or that file sets the old hash. + const std::string load_path = + fmt::format("{}textures/{:016X}/", GetUserPath(FileUtil::UserPath::LoadDir), title_id); + if (FileUtil::Exists(load_path) && !ReadConfig(title_id, true)) { + use_new_hash = false; + } // Write template config file const std::string dump_path = diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 1c054978fb..8acc71c03d 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -27,9 +27,12 @@ set(SHADER_FILES vulkan_blit_depth_stencil.frag ) -find_program(GLSLANGVALIDATOR "glslangValidator") -if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND") - message(FATAL_ERROR "Required program `glslangValidator` not found.") +find_program(GLSLANG "glslang") +if ("${GLSLANG}" STREQUAL "GLSLANG-NOTFOUND") + find_program(GLSLANG "glslangValidator") + if ("${GLSLANG}" STREQUAL "GLSLANG-NOTFOUND") + message(FATAL_ERROR "Required program `glslang` (or `glslangValidator`) not found.") + endif() endif() set(MACROS "-Dgl_VertexID=gl_VertexIndex") @@ -42,11 +45,11 @@ set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) -# Check if `--quiet` is available on host's glslangValidator version -# glslangValidator prints to STDERR iff an unrecognized flag is passed to it +# Check if `--quiet` is available on host's glslang version +# glslang prints to STDERR iff an unrecognized flag is passed to it execute_process( COMMAND - ${GLSLANGVALIDATOR} ${QUIET_FLAG} + ${GLSLANG} ${QUIET_FLAG} ERROR_VARIABLE GLSLANG_ERROR # STDOUT variable defined to silence unnecessary output during CMake configuration @@ -55,7 +58,7 @@ execute_process( ) if (NOT GLSLANG_ERROR STREQUAL "") - message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`") + message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANG}`") set(QUIET_FLAG "") endif() @@ -87,7 +90,7 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES}) OUTPUT ${SPIRV_HEADER_FILE} COMMAND - ${GLSLANGVALIDATOR} --target-env vulkan1.1 --glsl-version 450 ${QUIET_FLAG} ${MACROS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} + ${GLSLANG} --target-env vulkan1.1 --glsl-version 450 ${QUIET_FLAG} ${MACROS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} MAIN_DEPENDENCY ${SOURCE_FILE} ) diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 2dcae06f8a..bcd40354dd 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp @@ -599,6 +599,17 @@ void RasterizerAccelerated::NotifyPicaRegisterChanged(u32 id) { SyncTextureLodBias(2); break; + // Texture borders + case PICA_REG_INDEX(texturing.texture0.border_color): + SyncTextureBorderColor(0); + break; + case PICA_REG_INDEX(texturing.texture1.border_color): + SyncTextureBorderColor(1); + break; + case PICA_REG_INDEX(texturing.texture2.border_color): + SyncTextureBorderColor(2); + break; + // Clipping plane case PICA_REG_INDEX(rasterizer.clip_coef[0]): case PICA_REG_INDEX(rasterizer.clip_coef[1]): @@ -821,6 +832,16 @@ void RasterizerAccelerated::SyncTextureLodBias(int tex_index) { } } +void RasterizerAccelerated::SyncTextureBorderColor(int tex_index) { + const auto pica_textures = regs.texturing.GetTextures(); + const auto params = pica_textures[tex_index].config; + const Common::Vec4f border_color = ColorRGBA8(params.border_color.raw); + if (border_color != uniform_block_data.data.tex_border_color[tex_index]) { + uniform_block_data.data.tex_border_color[tex_index] = border_color; + uniform_block_data.dirty = true; + } +} + void RasterizerAccelerated::SyncClipCoef() { const auto raw_clip_coef = regs.rasterizer.GetClipCoef(); const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(), diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index d9191226be..2ad11ee32a 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h @@ -97,6 +97,9 @@ protected: /// Syncs the texture LOD bias to match the PICA register void SyncTextureLodBias(int tex_index); + /// Syncs the texture border color to match the PICA registers + void SyncTextureBorderColor(int tex_index); + /// Syncs the clip coefficients to match the PICA register void SyncClipCoef(); diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 81e44504e0..37abcae144 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -127,6 +127,29 @@ void RasterizerCache::RemoveFramebuffers(SurfaceId surface_id) { } } +template +void RasterizerCache::RemoveTextureCubeFace(SurfaceId surface_id) { + if (False(slot_surfaces[surface_id].flags & SurfaceFlagBits::Tracked)) { + return; + } + + for (auto it = texture_cube_cache.begin(); it != texture_cube_cache.end();) { + TextureCube& cube = it->second; + for (SurfaceId& face_id : cube.face_ids) { + if (face_id == surface_id) { + face_id = SurfaceId{}; + } + } + if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(), + [](SurfaceId id) { return id; })) { + sentenced.emplace_back(cube.surface_id, frame_tick); + it = texture_cube_cache.erase(it); + } else { + it++; + } + } +} + template bool RasterizerCache::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) { const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 1.f, 1.f}, @@ -866,39 +889,6 @@ SurfaceId RasterizerCache::FindMatch(const SurfaceParams& params, ScaleMatch return match_id; } -template -void RasterizerCache::DuplicateSurface(SurfaceId src_id, SurfaceId dst_id) { - Surface& src_surface = slot_surfaces[src_id]; - Surface& dst_surface = slot_surfaces[dst_id]; - ASSERT(dst_surface.addr <= src_surface.addr && dst_surface.end >= src_surface.end); - - const auto src_rect = src_surface.GetScaledRect(); - const auto dst_rect = dst_surface.GetScaledSubRect(src_surface); - ASSERT(src_rect.GetWidth() == dst_rect.GetWidth()); - - const TextureCopy copy = { - .src_level = 0, - .dst_level = 0, - .src_offset = {src_rect.left, src_rect.bottom}, - .dst_offset = {dst_rect.left, dst_rect.bottom}, - .extent = {src_rect.GetWidth(), src_rect.GetHeight()}, - }; - runtime.CopyTextures(src_surface, dst_surface, copy); - - dst_surface.invalid_regions -= src_surface.GetInterval(); - dst_surface.invalid_regions += src_surface.invalid_regions; - - SurfaceRegions regions; - for (const auto& pair : RangeFromInterval(dirty_regions, src_surface.GetInterval())) { - if (pair.second == src_id) { - regions += pair.first; - } - } - for (const auto& interval : regions) { - dirty_regions.set({interval, dst_id}); - } -} - template void RasterizerCache::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 size) { if (size == 0) [[unlikely]] { @@ -1051,15 +1041,16 @@ bool RasterizerCache::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv surface.flags |= SurfaceFlagBits::Custom; const auto upload = [this, level, surface_id, material]() -> bool { - Surface& surface = slot_surfaces[surface_id]; - ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom), + ASSERT_MSG(True(slot_surfaces[surface_id].flags & SurfaceFlagBits::Custom), "Surface is not suitable for custom upload, aborting!"); - if (!surface.IsCustom()) { - const SurfaceBase old_surface{surface}; + if (!slot_surfaces[surface_id].IsCustom()) { + const SurfaceBase old_surface{slot_surfaces[surface_id]}; const SurfaceId old_id = slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material); + slot_surfaces[old_id].flags &= ~SurfaceFlagBits::Registered; sentenced.emplace_back(old_id, frame_tick); } + Surface& surface = slot_surfaces[surface_id]; surface.UploadCustom(material, level); if (custom_tex_manager.SkipMipmaps()) { runtime.GenerateMipmaps(surface); @@ -1203,7 +1194,6 @@ void RasterizerCache::ClearAll(bool flush) { cached_pages -= flush_interval; dirty_regions.clear(); page_table.clear(); - remove_surfaces.clear(); } template @@ -1232,7 +1222,7 @@ void RasterizerCache::FlushRegion(PAddr addr, u32 size, SurfaceId flush_surfa interval.lower(), interval.upper()}; SCOPE_EXIT({ flushed_intervals += interval; }); - if (surface.IsFill()) { + if (surface.type == SurfaceType::Fill) { DownloadFillSurface(surface, interval); continue; } @@ -1274,6 +1264,7 @@ void RasterizerCache::InvalidateRegion(PAddr addr, u32 size, SurfaceId region region_owner.MarkValid(invalid_interval); } + boost::container::small_vector remove_surfaces; ForEachSurfaceInRegion(addr, size, [&](SurfaceId surface_id, Surface& surface) { if (surface_id == region_owner_id) { return; @@ -1301,13 +1292,12 @@ void RasterizerCache::InvalidateRegion(PAddr addr, u32 size, SurfaceId region for (const SurfaceId surface_id : remove_surfaces) { UnregisterSurface(surface_id); - if (!slot_surfaces[surface_id].IsFill()) { + if (slot_surfaces[surface_id].type != SurfaceType::Fill) { sentenced.emplace_back(surface_id, frame_tick); } else { slot_surfaces.erase(surface_id); } } - remove_surfaces.clear(); } template @@ -1316,14 +1306,17 @@ SurfaceId RasterizerCache::CreateSurface(const SurfaceParams& params) { const auto it = std::find_if(sentenced.begin(), sentenced.end(), [&](const auto& pair) { return slot_surfaces[pair.first] == params; }); - if (it != sentenced.end()) { - const SurfaceId surface_id = it->first; - sentenced.erase(it); - return surface_id; + if (it == sentenced.end()) { + return slot_surfaces.insert(runtime, params); } - return slot_surfaces.insert(runtime, params); + const SurfaceId surface_id = it->first; + sentenced.erase(it); + return surface_id; }(); Surface& surface = slot_surfaces[surface_id]; + if (params.res_scale > surface.res_scale) { + surface.ScaleUp(params.res_scale); + } surface.MarkInvalid(surface.GetInterval()); return surface_id; } @@ -1364,24 +1357,7 @@ void RasterizerCache::UnregisterSurface(SurfaceId surface_id) { surfaces.erase(vector_it); }); - if (False(surface.flags & SurfaceFlagBits::Tracked)) { - return; - } - - std::erase_if(texture_cube_cache, [&](auto& pair) { - TextureCube& cube = pair.second; - for (SurfaceId& face_id : cube.face_ids) { - if (face_id == surface_id) { - face_id = SurfaceId{}; - } - } - if (std::none_of(cube.face_ids.begin(), cube.face_ids.end(), - [](SurfaceId id) { return id; })) { - sentenced.emplace_back(cube.surface_id, frame_tick); - return true; - } - return false; - }); + RemoveTextureCubeFace(surface_id); } template @@ -1393,7 +1369,6 @@ void RasterizerCache::UnregisterAll() { } } texture_cube_cache.clear(); - remove_surfaces.clear(); } template diff --git a/src/video_core/rasterizer_cache/rasterizer_cache_base.h b/src/video_core/rasterizer_cache/rasterizer_cache_base.h index daed5f2532..c8553e2704 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache_base.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache_base.h @@ -165,8 +165,8 @@ private: /// Removes any framebuffers that reference the provided surface_id. void RemoveFramebuffers(SurfaceId surface_id); - /// Transfers ownership of a memory region from src_surface to dest_surface - void DuplicateSurface(SurfaceId src_id, SurfaceId dst_id); + /// Removes any references of the provided surface id from cached texture cubes. + void RemoveTextureCubeFace(SurfaceId surface_id); /// Computes the hash of the provided texture data. u64 ComputeHash(const SurfaceParams& load_info, std::span upload_data); @@ -224,7 +224,6 @@ private: Common::SlotVector slot_framebuffers; SurfaceMap dirty_regions; PageMap cached_pages; - std::vector remove_surfaces; u32 resolution_scale_factor; u64 frame_tick{}; FramebufferParams fb_params; diff --git a/src/video_core/rasterizer_cache/surface_base.h b/src/video_core/rasterizer_cache/surface_base.h index c3bd7b4320..19c0959dab 100644 --- a/src/video_core/rasterizer_cache/surface_base.h +++ b/src/video_core/rasterizer_cache/surface_base.h @@ -46,10 +46,6 @@ public: /// Returns true if the surface contains a custom material with a normal map. bool HasNormalMap() const noexcept; - bool IsFill() const noexcept { - return type == SurfaceType::Fill; - } - bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept { const PAddr overlap_end = overlap_addr + static_cast(overlap_size); return addr < overlap_end && overlap_addr < end; diff --git a/src/video_core/rasterizer_cache/surface_params.cpp b/src/video_core/rasterizer_cache/surface_params.cpp index 2f14961935..74ae8205c1 100644 --- a/src/video_core/rasterizer_cache/surface_params.cpp +++ b/src/video_core/rasterizer_cache/surface_params.cpp @@ -227,4 +227,11 @@ std::string SurfaceParams::DebugName(bool scaled, bool custom) const noexcept { custom ? "custom," : "", scaled ? "scaled" : "unscaled"); } +bool SurfaceParams::operator==(const SurfaceParams& other) const noexcept { + return std::tie(addr, end, width, height, stride, levels, is_tiled, texture_type, pixel_format, + custom_format) == + std::tie(other.addr, other.end, other.width, other.height, other.stride, other.levels, + other.is_tiled, other.texture_type, other.pixel_format, other.custom_format); +} + } // namespace VideoCore diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h index 89aff60431..23e4db7e20 100644 --- a/src/video_core/rasterizer_cache/surface_params.h +++ b/src/video_core/rasterizer_cache/surface_params.h @@ -53,9 +53,7 @@ public: /// Returns a string identifier of the params object std::string DebugName(bool scaled, bool custom = false) const noexcept; - bool operator==(const SurfaceParams& other) const noexcept { - return std::memcmp(this, &other, sizeof(SurfaceParams)) == 0; - } + bool operator==(const SurfaceParams& other) const noexcept; [[nodiscard]] SurfaceInterval GetInterval() const noexcept { return SurfaceInterval{addr, end}; diff --git a/src/video_core/renderer_opengl/frame_dumper_opengl.cpp b/src/video_core/renderer_opengl/frame_dumper_opengl.cpp index dd8720b101..7c9a52e071 100644 --- a/src/video_core/renderer_opengl/frame_dumper_opengl.cpp +++ b/src/video_core/renderer_opengl/frame_dumper_opengl.cpp @@ -5,6 +5,9 @@ #include #include + +#include "core/core.h" +#include "core/dumping/backend.h" #include "core/frontend/emu_window.h" #include "video_core/renderer_opengl/frame_dumper_opengl.h" #include "video_core/renderer_opengl/gl_texture_mailbox.h" @@ -12,13 +15,9 @@ namespace OpenGL { FrameDumperOpenGL::FrameDumperOpenGL(Core::System& system_, Frontend::EmuWindow& emu_window) - : system(system_), context(emu_window.CreateSharedContext()) {} + : system{system_}, context{emu_window.CreateSharedContext()} {} -FrameDumperOpenGL::~FrameDumperOpenGL() { - if (present_thread.joinable()) { - present_thread.join(); - } -} +FrameDumperOpenGL::~FrameDumperOpenGL() = default; bool FrameDumperOpenGL::IsDumping() const { auto video_dumper = system.GetVideoDumper(); @@ -35,19 +34,19 @@ void FrameDumperOpenGL::StartDumping() { present_thread.join(); } - present_thread = std::thread(&FrameDumperOpenGL::PresentLoop, this); + present_thread = std::jthread([this](std::stop_token stop_token) { PresentLoop(stop_token); }); } void FrameDumperOpenGL::StopDumping() { - stop_requested.store(true, std::memory_order_relaxed); + present_thread.request_stop(); } -void FrameDumperOpenGL::PresentLoop() { +void FrameDumperOpenGL::PresentLoop(std::stop_token stop_token) { const auto scope = context->Acquire(); InitializeOpenGLObjects(); const auto& layout = GetLayout(); - while (!stop_requested.exchange(false)) { + while (!stop_token.stop_requested()) { auto frame = mailbox->TryGetPresentFrame(200); if (!frame) { continue; diff --git a/src/video_core/renderer_opengl/frame_dumper_opengl.h b/src/video_core/renderer_opengl/frame_dumper_opengl.h index bcd4980941..7b02315bcb 100644 --- a/src/video_core/renderer_opengl/frame_dumper_opengl.h +++ b/src/video_core/renderer_opengl/frame_dumper_opengl.h @@ -6,9 +6,8 @@ #include #include -#include -#include "core/core.h" -#include "core/dumping/backend.h" + +#include "common/polyfill_thread.h" #include "core/frontend/framebuffer_layout.h" #include "video_core/renderer_opengl/gl_resource_manager.h" @@ -18,6 +17,10 @@ class GraphicsContext; class TextureMailbox; } // namespace Frontend +namespace Core { +class System; +} + namespace OpenGL { class RendererOpenGL; @@ -42,12 +45,12 @@ public: private: void InitializeOpenGLObjects(); void CleanupOpenGLObjects(); - void PresentLoop(); + void PresentLoop(std::stop_token stop_token); +private: Core::System& system; std::unique_ptr context; - std::thread present_thread; - std::atomic_bool stop_requested{false}; + std::jthread present_thread; // PBOs used to dump frames faster std::array pbos; diff --git a/src/video_core/renderer_opengl/gl_driver.cpp b/src/video_core/renderer_opengl/gl_driver.cpp index c0b8c2fe4e..d9778393a9 100644 --- a/src/video_core/renderer_opengl/gl_driver.cpp +++ b/src/video_core/renderer_opengl/gl_driver.cpp @@ -188,6 +188,10 @@ void Driver::FindBugs() { if (vendor == Vendor::AMD || (vendor == Vendor::Intel && !is_linux)) { bugs |= DriverBug::BrokenTextureView; } + + if (vendor == Vendor::Intel && !is_linux) { + bugs |= DriverBug::BrokenClearTexture; + } } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_driver.h b/src/video_core/renderer_opengl/gl_driver.h index 40044b1812..1e1b5e2469 100644 --- a/src/video_core/renderer_opengl/gl_driver.h +++ b/src/video_core/renderer_opengl/gl_driver.h @@ -38,6 +38,8 @@ enum class DriverBug { VertexArrayOutOfBound = 1 << 1, // On AMD and Intel drivers on Windows glTextureView produces incorrect results BrokenTextureView = 1 << 2, + // On Haswell and Broadwell Intel drivers glClearTexSubImage produces a black screen + BrokenClearTexture = 1 << 3, }; /** diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 128137d52c..d8a1ed1145 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -109,76 +109,100 @@ PicaFSConfig PicaFSConfig::BuildFromRegs(const Pica::Regs& regs, bool use_normal << 4; // Fragment lighting - state.lighting.enable = !regs.lighting.disable; - state.lighting.src_num = regs.lighting.max_light_index + 1; + if (state.lighting.enable) { + state.lighting.src_num = regs.lighting.max_light_index + 1; - for (unsigned light_index = 0; light_index < state.lighting.src_num; ++light_index) { - unsigned num = regs.lighting.light_enable.GetNum(light_index); - const auto& light = regs.lighting.light[num]; - state.lighting.light[light_index].num = num; - state.lighting.light[light_index].directional = light.config.directional != 0; - state.lighting.light[light_index].two_sided_diffuse = light.config.two_sided_diffuse != 0; - state.lighting.light[light_index].geometric_factor_0 = light.config.geometric_factor_0 != 0; - state.lighting.light[light_index].geometric_factor_1 = light.config.geometric_factor_1 != 0; - state.lighting.light[light_index].dist_atten_enable = - !regs.lighting.IsDistAttenDisabled(num); - state.lighting.light[light_index].spot_atten_enable = - !regs.lighting.IsSpotAttenDisabled(num); - state.lighting.light[light_index].shadow_enable = !regs.lighting.IsShadowDisabled(num); + for (unsigned light_index = 0; light_index < state.lighting.src_num; ++light_index) { + unsigned num = regs.lighting.light_enable.GetNum(light_index); + const auto& light = regs.lighting.light[num]; + state.lighting.light[light_index].num = num; + state.lighting.light[light_index].directional = light.config.directional != 0; + state.lighting.light[light_index].two_sided_diffuse = + light.config.two_sided_diffuse != 0; + state.lighting.light[light_index].geometric_factor_0 = + light.config.geometric_factor_0 != 0; + state.lighting.light[light_index].geometric_factor_1 = + light.config.geometric_factor_1 != 0; + state.lighting.light[light_index].dist_atten_enable = + !regs.lighting.IsDistAttenDisabled(num); + state.lighting.light[light_index].spot_atten_enable = + !regs.lighting.IsSpotAttenDisabled(num); + state.lighting.light[light_index].shadow_enable = !regs.lighting.IsShadowDisabled(num); + } + + state.lighting.lut_d0.enable = regs.lighting.config1.disable_lut_d0 == 0; + if (state.lighting.lut_d0.enable) { + state.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0; + state.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value(); + state.lighting.lut_d0.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); + } + + state.lighting.lut_d1.enable = regs.lighting.config1.disable_lut_d1 == 0; + if (state.lighting.lut_d1.enable) { + state.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0; + state.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value(); + state.lighting.lut_d1.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); + } + + // this is a dummy field due to lack of the corresponding register + state.lighting.lut_sp.enable = true; + state.lighting.lut_sp.abs_input = regs.lighting.abs_lut_input.disable_sp == 0; + state.lighting.lut_sp.type = regs.lighting.lut_input.sp.Value(); + state.lighting.lut_sp.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.sp); + + state.lighting.lut_fr.enable = regs.lighting.config1.disable_lut_fr == 0; + if (state.lighting.lut_fr.enable) { + state.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0; + state.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value(); + state.lighting.lut_fr.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); + } + + state.lighting.lut_rr.enable = regs.lighting.config1.disable_lut_rr == 0; + if (state.lighting.lut_rr.enable) { + state.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0; + state.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value(); + state.lighting.lut_rr.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); + } + + state.lighting.lut_rg.enable = regs.lighting.config1.disable_lut_rg == 0; + if (state.lighting.lut_rg.enable) { + state.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0; + state.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value(); + state.lighting.lut_rg.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); + } + + state.lighting.lut_rb.enable = regs.lighting.config1.disable_lut_rb == 0; + if (state.lighting.lut_rb.enable) { + state.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0; + state.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value(); + state.lighting.lut_rb.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); + } + + state.lighting.config = regs.lighting.config0.config; + state.lighting.enable_primary_alpha = regs.lighting.config0.enable_primary_alpha; + state.lighting.enable_secondary_alpha = regs.lighting.config0.enable_secondary_alpha; + state.lighting.bump_mode = regs.lighting.config0.bump_mode; + state.lighting.bump_selector = regs.lighting.config0.bump_selector; + state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; + state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 0; + + state.lighting.enable_shadow = regs.lighting.config0.enable_shadow != 0; + if (state.lighting.enable_shadow) { + state.lighting.shadow_primary = regs.lighting.config0.shadow_primary != 0; + state.lighting.shadow_secondary = regs.lighting.config0.shadow_secondary != 0; + state.lighting.shadow_invert = regs.lighting.config0.shadow_invert != 0; + state.lighting.shadow_alpha = regs.lighting.config0.shadow_alpha != 0; + state.lighting.shadow_selector = regs.lighting.config0.shadow_selector; + } } - state.lighting.lut_d0.enable = regs.lighting.config1.disable_lut_d0 == 0; - state.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0; - state.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value(); - state.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); - - state.lighting.lut_d1.enable = regs.lighting.config1.disable_lut_d1 == 0; - state.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0; - state.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value(); - state.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); - - // this is a dummy field due to lack of the corresponding register - state.lighting.lut_sp.enable = true; - state.lighting.lut_sp.abs_input = regs.lighting.abs_lut_input.disable_sp == 0; - state.lighting.lut_sp.type = regs.lighting.lut_input.sp.Value(); - state.lighting.lut_sp.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.sp); - - state.lighting.lut_fr.enable = regs.lighting.config1.disable_lut_fr == 0; - state.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0; - state.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value(); - state.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); - - state.lighting.lut_rr.enable = regs.lighting.config1.disable_lut_rr == 0; - state.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0; - state.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value(); - state.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); - - state.lighting.lut_rg.enable = regs.lighting.config1.disable_lut_rg == 0; - state.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0; - state.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value(); - state.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); - - state.lighting.lut_rb.enable = regs.lighting.config1.disable_lut_rb == 0; - state.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0; - state.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value(); - state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); - - state.lighting.config = regs.lighting.config0.config; - state.lighting.enable_primary_alpha = regs.lighting.config0.enable_primary_alpha; - state.lighting.enable_secondary_alpha = regs.lighting.config0.enable_secondary_alpha; - state.lighting.bump_mode = regs.lighting.config0.bump_mode; - state.lighting.bump_selector = regs.lighting.config0.bump_selector; - state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; - state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 0; - - state.lighting.enable_shadow = regs.lighting.config0.enable_shadow != 0; - state.lighting.shadow_primary = regs.lighting.config0.shadow_primary != 0; - state.lighting.shadow_secondary = regs.lighting.config0.shadow_secondary != 0; - state.lighting.shadow_invert = regs.lighting.config0.shadow_invert != 0; - state.lighting.shadow_alpha = regs.lighting.config0.shadow_alpha != 0; - state.lighting.shadow_selector = regs.lighting.config0.shadow_selector; - state.proctex.enable = regs.texturing.main_config.texture3_enable; if (state.proctex.enable) { state.proctex.coord = regs.texturing.main_config.texture3_coordinates; @@ -1246,13 +1270,13 @@ float LookupLightingLUT(int lut_index, int index, float delta) { } float LookupLightingLUTUnsigned(int lut_index, float pos) { - int index = clamp(int(pos * 256.0), 0, 255); + int index = int(clamp(floor(pos * 256.0), 0.f, 255.f)); float delta = pos * 256.0 - float(index); return LookupLightingLUT(lut_index, index, delta); } float LookupLightingLUTSigned(int lut_index, float pos) { - int index = clamp(int(pos * 128.0), -128, 127); + int index = int(clamp(floor(pos * 128.0), -128.f, 127.f)); float delta = pos * 128.0 - float(index); if (index < 0) index += 256; return LookupLightingLUT(lut_index, index, delta); diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index e7ca8179fb..a45ecc5702 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -187,7 +187,41 @@ bool TextureRuntime::Reinterpret(Surface& source, Surface& dest, return true; } -bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClear& clear) { +bool TextureRuntime::ClearTextureWithoutFbo(Surface& surface, + const VideoCore::TextureClear& clear) { + if (!driver.HasArbClearTexture() || driver.HasBug(DriverBug::BrokenClearTexture)) { + return false; + } + GLenum format{}; + GLenum type{}; + switch (surface.type) { + case SurfaceType::Color: + case SurfaceType::Texture: + format = GL_RGBA; + type = GL_FLOAT; + break; + case SurfaceType::Depth: + format = GL_DEPTH_COMPONENT; + type = GL_FLOAT; + break; + case SurfaceType::DepthStencil: + format = GL_DEPTH_STENCIL; + type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + break; + default: + UNREACHABLE_MSG("Unknown surface type {}", surface.type); + } + glClearTexSubImage(surface.Handle(), clear.texture_level, clear.texture_rect.left, + clear.texture_rect.bottom, 0, clear.texture_rect.GetWidth(), + clear.texture_rect.GetHeight(), 1, format, type, &clear.value); + return true; +} + +void TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClear& clear) { + if (ClearTextureWithoutFbo(surface, clear)) { + return; + } + OpenGLState state = OpenGLState::GetCurState(); state.scissor.enabled = true; state.scissor.x = clear.texture_rect.left; @@ -222,10 +256,7 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea break; default: UNREACHABLE_MSG("Unknown surface type {}", surface.type); - return false; } - - return true; } bool TextureRuntime::CopyTextures(Surface& source, Surface& dest, diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h index 02914624b5..b9a971c2d5 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.h +++ b/src/video_core/renderer_opengl/gl_texture_runtime.h @@ -59,7 +59,7 @@ public: bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit); /// Fills the rectangle of the texture with the clear value provided - bool ClearTexture(Surface& surface, const VideoCore::TextureClear& clear); + void ClearTexture(Surface& surface, const VideoCore::TextureClear& clear); /// Copies a rectangle of source to another rectange of dest bool CopyTextures(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy); @@ -76,6 +76,9 @@ private: return driver; } + /// Fills the rectangle of the surface with the value provided, without an fbo. + bool ClearTextureWithoutFbo(Surface& surface, const VideoCore::TextureClear& clear); + private: const Driver& driver; BlitHelper blit_helper; diff --git a/src/video_core/renderer_opengl/post_processing_opengl.cpp b/src/video_core/renderer_opengl/post_processing_opengl.cpp index 1e479b65fc..3f26ee3cbb 100644 --- a/src/video_core/renderer_opengl/post_processing_opengl.cpp +++ b/src/video_core/renderer_opengl/post_processing_opengl.cpp @@ -41,9 +41,9 @@ constexpr char dolphin_shader_header[] = R"( #define lerp mix // Output variable -out float4 color; +layout (location = 0) out float4 color; // Input coordinates -in float2 frag_tex_coord; +layout (location = 0) in float2 frag_tex_coord; // Resolution uniform float4 i_resolution; uniform float4 o_resolution; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 2388032a85..9d1b1935e0 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -409,7 +409,9 @@ bool Instance::CreateDevice() { const bool has_extended_dynamic_state = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, is_arm || is_qualcomm, "it is broken on Qualcomm and ARM drivers"); - const bool has_custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); + const bool has_custom_border_color = + add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, is_qualcomm, + "it is broken on most Qualcomm driver versions"); const bool has_index_type_uint8 = add_extension(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME); const bool has_pipeline_creation_cache_control = add_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME); diff --git a/src/video_core/renderer_vulkan/vk_shader_gen.cpp b/src/video_core/renderer_vulkan/vk_shader_gen.cpp index 555b17b5b1..6f1dc412b3 100644 --- a/src/video_core/renderer_vulkan/vk_shader_gen.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_gen.cpp @@ -69,6 +69,17 @@ PicaFSConfig::PicaFSConfig(const Pica::Regs& regs, const Instance& instance) { state.texture2_use_coord1.Assign(regs.texturing.main_config.texture2_use_coord1 != 0); + const auto pica_textures = regs.texturing.GetTextures(); + for (u32 tex_index = 0; tex_index < 3; tex_index++) { + const auto config = pica_textures[tex_index].config; + state.texture_border_color[tex_index].enable_s.Assign( + !instance.IsCustomBorderColorSupported() && + config.wrap_s == TexturingRegs::TextureConfig::WrapMode::ClampToBorder); + state.texture_border_color[tex_index].enable_t.Assign( + !instance.IsCustomBorderColorSupported() && + config.wrap_t == TexturingRegs::TextureConfig::WrapMode::ClampToBorder); + } + // Emulate logic op in the shader if not supported. This is mostly for mobile GPUs const bool emulate_logic_op = instance.NeedsLogicOpEmulation() && !Pica::g_state.regs.framebuffer.output_merger.alphablend_enable; @@ -101,80 +112,101 @@ PicaFSConfig::PicaFSConfig(const Pica::Regs& regs, const Instance& instance) { regs.texturing.tev_combiner_buffer_input.update_mask_a.Value() << 4); // Fragment lighting - state.lighting.enable.Assign(!regs.lighting.disable); - state.lighting.src_num.Assign(regs.lighting.max_light_index + 1); + if (state.lighting.enable) { + state.lighting.src_num.Assign(regs.lighting.max_light_index + 1); - for (u32 light_index = 0; light_index < state.lighting.src_num; ++light_index) { - const u32 num = regs.lighting.light_enable.GetNum(light_index); - const auto& light = regs.lighting.light[num]; - state.lighting.light[light_index].num.Assign(num); - state.lighting.light[light_index].directional.Assign(light.config.directional != 0); - state.lighting.light[light_index].two_sided_diffuse.Assign(light.config.two_sided_diffuse != - 0); - state.lighting.light[light_index].geometric_factor_0.Assign( - light.config.geometric_factor_0 != 0); - state.lighting.light[light_index].geometric_factor_1.Assign( - light.config.geometric_factor_1 != 0); - state.lighting.light[light_index].dist_atten_enable.Assign( - !regs.lighting.IsDistAttenDisabled(num)); - state.lighting.light[light_index].spot_atten_enable.Assign( - !regs.lighting.IsSpotAttenDisabled(num)); - state.lighting.light[light_index].shadow_enable.Assign( - !regs.lighting.IsShadowDisabled(num)); + for (u32 light_index = 0; light_index < state.lighting.src_num; ++light_index) { + const u32 num = regs.lighting.light_enable.GetNum(light_index); + const auto& light = regs.lighting.light[num]; + state.lighting.light[light_index].num.Assign(num); + state.lighting.light[light_index].directional.Assign(light.config.directional != 0); + state.lighting.light[light_index].two_sided_diffuse.Assign( + light.config.two_sided_diffuse != 0); + state.lighting.light[light_index].geometric_factor_0.Assign( + light.config.geometric_factor_0 != 0); + state.lighting.light[light_index].geometric_factor_1.Assign( + light.config.geometric_factor_1 != 0); + state.lighting.light[light_index].dist_atten_enable.Assign( + !regs.lighting.IsDistAttenDisabled(num)); + state.lighting.light[light_index].spot_atten_enable.Assign( + !regs.lighting.IsSpotAttenDisabled(num)); + state.lighting.light[light_index].shadow_enable.Assign( + !regs.lighting.IsShadowDisabled(num)); + } + + state.lighting.lut_d0.enable.Assign(regs.lighting.config1.disable_lut_d0 == 0); + if (state.lighting.lut_d0.enable) { + state.lighting.lut_d0.abs_input.Assign(regs.lighting.abs_lut_input.disable_d0 == 0); + state.lighting.lut_d0.type.Assign(regs.lighting.lut_input.d0.Value()); + state.lighting.lut_d0.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); + } + + state.lighting.lut_d1.enable.Assign(regs.lighting.config1.disable_lut_d1 == 0); + if (state.lighting.lut_d1.enable) { + state.lighting.lut_d1.abs_input.Assign(regs.lighting.abs_lut_input.disable_d1 == 0); + state.lighting.lut_d1.type.Assign(regs.lighting.lut_input.d1.Value()); + state.lighting.lut_d1.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); + } + + // this is a dummy field due to lack of the corresponding register + state.lighting.lut_sp.enable.Assign(1); + state.lighting.lut_sp.abs_input.Assign(regs.lighting.abs_lut_input.disable_sp == 0); + state.lighting.lut_sp.type.Assign(regs.lighting.lut_input.sp.Value()); + state.lighting.lut_sp.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.sp); + + state.lighting.lut_fr.enable.Assign(regs.lighting.config1.disable_lut_fr == 0); + if (state.lighting.lut_fr.enable) { + state.lighting.lut_fr.abs_input.Assign(regs.lighting.abs_lut_input.disable_fr == 0); + state.lighting.lut_fr.type.Assign(regs.lighting.lut_input.fr.Value()); + state.lighting.lut_fr.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); + } + + state.lighting.lut_rr.enable.Assign(regs.lighting.config1.disable_lut_rr == 0); + if (state.lighting.lut_rr.enable) { + state.lighting.lut_rr.abs_input.Assign(regs.lighting.abs_lut_input.disable_rr == 0); + state.lighting.lut_rr.type.Assign(regs.lighting.lut_input.rr.Value()); + state.lighting.lut_rr.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); + } + + state.lighting.lut_rg.enable.Assign(regs.lighting.config1.disable_lut_rg == 0); + if (state.lighting.lut_rg.enable) { + state.lighting.lut_rg.abs_input.Assign(regs.lighting.abs_lut_input.disable_rg == 0); + state.lighting.lut_rg.type.Assign(regs.lighting.lut_input.rg.Value()); + state.lighting.lut_rg.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); + } + + state.lighting.lut_rb.enable.Assign(regs.lighting.config1.disable_lut_rb == 0); + if (state.lighting.lut_rb.enable) { + state.lighting.lut_rb.abs_input.Assign(regs.lighting.abs_lut_input.disable_rb == 0); + state.lighting.lut_rb.type.Assign(regs.lighting.lut_input.rb.Value()); + state.lighting.lut_rb.scale = + regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); + } + + state.lighting.config.Assign(regs.lighting.config0.config); + state.lighting.enable_primary_alpha.Assign(regs.lighting.config0.enable_primary_alpha); + state.lighting.enable_secondary_alpha.Assign(regs.lighting.config0.enable_secondary_alpha); + state.lighting.bump_mode.Assign(regs.lighting.config0.bump_mode); + state.lighting.bump_selector.Assign(regs.lighting.config0.bump_selector); + state.lighting.bump_renorm.Assign(regs.lighting.config0.disable_bump_renorm == 0); + state.lighting.clamp_highlights.Assign(regs.lighting.config0.clamp_highlights != 0); + + state.lighting.enable_shadow.Assign(regs.lighting.config0.enable_shadow != 0); + if (state.lighting.enable_shadow) { + state.lighting.shadow_primary.Assign(regs.lighting.config0.shadow_primary != 0); + state.lighting.shadow_secondary.Assign(regs.lighting.config0.shadow_secondary != 0); + state.lighting.shadow_invert.Assign(regs.lighting.config0.shadow_invert != 0); + state.lighting.shadow_alpha.Assign(regs.lighting.config0.shadow_alpha != 0); + state.lighting.shadow_selector.Assign(regs.lighting.config0.shadow_selector); + } } - state.lighting.lut_d0.enable.Assign(regs.lighting.config1.disable_lut_d0 == 0); - state.lighting.lut_d0.abs_input.Assign(regs.lighting.abs_lut_input.disable_d0 == 0); - state.lighting.lut_d0.type.Assign(regs.lighting.lut_input.d0.Value()); - state.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); - - state.lighting.lut_d1.enable.Assign(regs.lighting.config1.disable_lut_d1 == 0); - state.lighting.lut_d1.abs_input.Assign(regs.lighting.abs_lut_input.disable_d1 == 0); - state.lighting.lut_d1.type.Assign(regs.lighting.lut_input.d1.Value()); - state.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); - - // this is a dummy field due to lack of the corresponding register - state.lighting.lut_sp.enable.Assign(1); - state.lighting.lut_sp.abs_input.Assign(regs.lighting.abs_lut_input.disable_sp == 0); - state.lighting.lut_sp.type.Assign(regs.lighting.lut_input.sp.Value()); - state.lighting.lut_sp.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.sp); - - state.lighting.lut_fr.enable.Assign(regs.lighting.config1.disable_lut_fr == 0); - state.lighting.lut_fr.abs_input.Assign(regs.lighting.abs_lut_input.disable_fr == 0); - state.lighting.lut_fr.type.Assign(regs.lighting.lut_input.fr.Value()); - state.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); - - state.lighting.lut_rr.enable.Assign(regs.lighting.config1.disable_lut_rr == 0); - state.lighting.lut_rr.abs_input.Assign(regs.lighting.abs_lut_input.disable_rr == 0); - state.lighting.lut_rr.type.Assign(regs.lighting.lut_input.rr.Value()); - state.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); - - state.lighting.lut_rg.enable.Assign(regs.lighting.config1.disable_lut_rg == 0); - state.lighting.lut_rg.abs_input.Assign(regs.lighting.abs_lut_input.disable_rg == 0); - state.lighting.lut_rg.type.Assign(regs.lighting.lut_input.rg.Value()); - state.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); - - state.lighting.lut_rb.enable.Assign(regs.lighting.config1.disable_lut_rb == 0); - state.lighting.lut_rb.abs_input.Assign(regs.lighting.abs_lut_input.disable_rb == 0); - state.lighting.lut_rb.type.Assign(regs.lighting.lut_input.rb.Value()); - state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); - - state.lighting.config.Assign(regs.lighting.config0.config); - state.lighting.enable_primary_alpha.Assign(regs.lighting.config0.enable_primary_alpha); - state.lighting.enable_secondary_alpha.Assign(regs.lighting.config0.enable_secondary_alpha); - state.lighting.bump_mode.Assign(regs.lighting.config0.bump_mode); - state.lighting.bump_selector.Assign(regs.lighting.config0.bump_selector); - state.lighting.bump_renorm.Assign(regs.lighting.config0.disable_bump_renorm == 0); - state.lighting.clamp_highlights.Assign(regs.lighting.config0.clamp_highlights != 0); - - state.lighting.enable_shadow.Assign(regs.lighting.config0.enable_shadow != 0); - state.lighting.shadow_primary.Assign(regs.lighting.config0.shadow_primary != 0); - state.lighting.shadow_secondary.Assign(regs.lighting.config0.shadow_secondary != 0); - state.lighting.shadow_invert.Assign(regs.lighting.config0.shadow_invert != 0); - state.lighting.shadow_alpha.Assign(regs.lighting.config0.shadow_alpha != 0); - state.lighting.shadow_selector.Assign(regs.lighting.config0.shadow_selector); - state.proctex.enable.Assign(regs.texturing.main_config.texture3_enable); if (state.proctex.enable) { state.proctex.coord.Assign(regs.texturing.main_config.texture3_coordinates); @@ -284,54 +316,6 @@ static bool IsPassThroughTevStage(const TevStageConfig& stage) { stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1); } -static std::string SampleTexture(const PicaFSConfig& config, unsigned texture_unit) { - const auto& state = config.state; - switch (texture_unit) { - case 0: - // Only unit 0 respects the texturing type - switch (state.texture0_type) { - case TexturingRegs::TextureConfig::Texture2D: - return "textureLod(tex0, texcoord0, getLod(texcoord0 * " - "vec2(textureSize(tex0, 0))) + tex_lod_bias[0])"; - case TexturingRegs::TextureConfig::Projection2D: - // TODO (wwylele): find the exact LOD formula for projection texture - return "textureProj(tex0, vec3(texcoord0, texcoord0_w))"; - case TexturingRegs::TextureConfig::TextureCube: - return "texture(tex_cube, vec3(texcoord0, texcoord0_w))"; - case TexturingRegs::TextureConfig::Shadow2D: - return "shadowTexture(texcoord0, texcoord0_w)"; - case TexturingRegs::TextureConfig::ShadowCube: - return "shadowTextureCube(texcoord0, texcoord0_w)"; - case TexturingRegs::TextureConfig::Disabled: - return "vec4(0.0)"; - default: - LOG_CRITICAL(HW_GPU, "Unhandled texture type {:x}", state.texture0_type); - UNIMPLEMENTED(); - return "texture(tex0, texcoord0)"; - } - case 1: - return "textureLod(tex1, texcoord1, getLod(texcoord1 * " - "vec2(textureSize(tex1, 0))) + tex_lod_bias[1])"; - case 2: - if (state.texture2_use_coord1) - return "textureLod(tex2, texcoord1, getLod(texcoord1 * " - "vec2(textureSize(tex2, 0))) + tex_lod_bias[2])"; - else - return "textureLod(tex2, texcoord2, getLod(texcoord2 * " - "vec2(textureSize(tex2, 0))) + tex_lod_bias[2])"; - case 3: - if (state.proctex.enable) { - return "ProcTex()"; - } else { - LOG_DEBUG(Render_OpenGL, "Using Texture3 without enabling it"); - return "vec4(0.0)"; - } - default: - UNREACHABLE(); - return ""; - } -} - /// Writes the specified TEV stage source component(s) static void AppendSource(std::string& out, const PicaFSConfig& config, TevStageConfig::Source source, std::string_view index_name) { @@ -347,16 +331,16 @@ static void AppendSource(std::string& out, const PicaFSConfig& config, out += "secondary_fragment_color"; break; case Source::Texture0: - out += SampleTexture(config, 0); + out += "sampleTexUnit0()"; break; case Source::Texture1: - out += SampleTexture(config, 1); + out += "sampleTexUnit1()"; break; case Source::Texture2: - out += SampleTexture(config, 2); + out += "sampleTexUnit2()"; break; case Source::Texture3: - out += SampleTexture(config, 3); + out += "sampleTexUnit3()"; break; case Source::PreviousBuffer: out += "combiner_buffer"; @@ -656,7 +640,7 @@ static void WriteLighting(std::string& out, const PicaFSConfig& config) { // Compute fragment normals and tangents const auto perturbation = [&] { - return fmt::format("2.0 * ({}).rgb - 1.0", SampleTexture(config, lighting.bump_selector)); + return fmt::format("2.0 * (sampleTexUnit{}()).rgb - 1.0", lighting.bump_selector); }; switch (lighting.bump_mode) { @@ -700,7 +684,7 @@ static void WriteLighting(std::string& out, const PicaFSConfig& config) { "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\n"; if (lighting.enable_shadow) { - std::string shadow_texture = SampleTexture(config, lighting.shadow_selector); + std::string shadow_texture = fmt::format("sampleTexUnit{}()", lighting.shadow_selector); if (lighting.shadow_invert) { out += fmt::format("vec4 shadow = vec4(1.0) - {};\n", shadow_texture); } else { @@ -1247,13 +1231,13 @@ float LookupLightingLUT(int lut_index, int index, float delta) { } float LookupLightingLUTUnsigned(int lut_index, float pos) { - int index = clamp(int(pos * 256.0), 0, 255); + int index = int(clamp(floor(pos * 256.0), 0.f, 255.f)); float delta = pos * 256.0 - float(index); return LookupLightingLUT(lut_index, index, delta); } float LookupLightingLUTSigned(int lut_index, float pos) { - int index = clamp(int(pos * 128.0), -128, 127); + int index = int(clamp(floor(pos * 128.0), -128.f, 127.f)); float delta = pos * 128.0 - float(index); if (index < 0) index += 256; return LookupLightingLUT(lut_index, index, delta); @@ -1310,6 +1294,7 @@ float mix2(vec4 s, vec2 a) { vec4 shadowTexture(vec2 uv, float w) { )"; + if (!config.state.shadow_texture_orthographic) { out += "uv /= w;"; } @@ -1344,9 +1329,7 @@ vec4 shadowTextureCube(vec2 uv, float w) { uv = -c.xy; if (c.z > 0.0) uv.x = -uv.x; } -)"; - out += "uint z = uint(max(0, int(min(w, 1.0) * float(0xFFFFFF)) - shadow_texture_bias));"; - out += R"( + uint z = uint(max(0, int(min(w, 1.0) * float(0xFFFFFF)) - shadow_texture_bias)); vec2 coord = vec2(size) * (uv / w * vec2(0.5) + vec2(0.5)) - vec2(0.5); vec2 coord_floor = floor(coord); vec2 f = coord - coord_floor; @@ -1409,10 +1392,92 @@ vec4 shadowTextureCube(vec2 uv, float w) { CompareShadow(pixels.w, z)); return vec4(mix2(s, f)); } -)"; + )"; - if (config.state.proctex.enable) + if (config.state.proctex.enable) { AppendProcTexSampler(out, config); + } + + for (u32 texture_unit = 0; texture_unit < 4; texture_unit++) { + out += fmt::format("vec4 sampleTexUnit{}() {{", texture_unit); + if (texture_unit == 0 && state.texture0_type == TexturingRegs::TextureConfig::Disabled) { + out += "return vec4(0.0);}"; + continue; + } else if (texture_unit == 3) { + if (state.proctex.enable) { + out += "return ProcTex();}"; + } else { + out += "return vec4(0.0);}"; + } + continue; + } + + u32 texcoord_num = texture_unit == 2 && state.texture2_use_coord1 ? 1 : texture_unit; + if (config.state.texture_border_color[texture_unit].enable_s) { + out += fmt::format(R"( + if (texcoord{}.x < 0 || texcoord{}.x > 1) {{ + return tex_border_color[{}]; + }} + )", + texcoord_num, texcoord_num, texture_unit); + } + if (config.state.texture_border_color[texture_unit].enable_t) { + out += fmt::format(R"( + if (texcoord{}.y < 0 || texcoord{}.y > 1) {{ + return tex_border_color[{}]; + }} + )", + texcoord_num, texcoord_num, texture_unit); + } + // TODO: 3D border? + + switch (texture_unit) { + case 0: + // Only unit 0 respects the texturing type + switch (state.texture0_type) { + case TexturingRegs::TextureConfig::Texture2D: + out += "return textureLod(tex0, texcoord0, getLod(texcoord0 * " + "vec2(textureSize(tex0, 0))) + tex_lod_bias[0]);"; + break; + case TexturingRegs::TextureConfig::Projection2D: + // TODO (wwylele): find the exact LOD formula for projection texture + out += "return textureProj(tex0, vec3(texcoord0, texcoord0_w));"; + break; + case TexturingRegs::TextureConfig::TextureCube: + out += "return texture(tex_cube, vec3(texcoord0, texcoord0_w));"; + break; + case TexturingRegs::TextureConfig::Shadow2D: + out += "return shadowTexture(texcoord0, texcoord0_w);"; + break; + case TexturingRegs::TextureConfig::ShadowCube: + out += "return shadowTextureCube(texcoord0, texcoord0_w);"; + break; + default: + LOG_CRITICAL(HW_GPU, "Unhandled texture type {:x}", state.texture0_type); + UNIMPLEMENTED(); + out += "return texture(tex0, texcoord0);"; + break; + } + case 1: + out += "return textureLod(tex1, texcoord1, getLod(texcoord1 * vec2(textureSize(tex1, " + "0))) + tex_lod_bias[1]);"; + break; + case 2: + if (state.texture2_use_coord1) { + out += "return textureLod(tex2, texcoord1, getLod(texcoord1 * " + "vec2(textureSize(tex2, 0))) + tex_lod_bias[1]);"; + } else { + out += "return textureLod(tex2, texcoord2, getLod(texcoord2 * " + "vec2(textureSize(tex2, 0))) + tex_lod_bias[2]);"; + } + break; + default: + UNREACHABLE(); + break; + } + + out += "}"; + } // We round the interpolated primary color to the nearest 1/255th // This maintains the PICA's 8 bits of precision diff --git a/src/video_core/renderer_vulkan/vk_shader_gen.h b/src/video_core/renderer_vulkan/vk_shader_gen.h index bd901b0060..52fa832ff6 100644 --- a/src/video_core/renderer_vulkan/vk_shader_gen.h +++ b/src/video_core/renderer_vulkan/vk_shader_gen.h @@ -57,6 +57,11 @@ struct PicaFSConfigState { BitField<28, 1, u32> shadow_texture_orthographic; }; + union { + BitField<0, 1, u32> enable_s; + BitField<1, 1, u32> enable_t; + } texture_border_color[3]; + std::array tev_stages; struct { diff --git a/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp b/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp index 0b9647e3fa..3320219448 100644 --- a/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_gen_spv.cpp @@ -21,8 +21,8 @@ FragmentModule::FragmentModule(Core::TelemetrySession& telemetry_, const PicaFSC DefineArithmeticTypes(); DefineUniformStructs(); DefineInterface(); - if (config.state.proctex.enable) { - DefineProcTexSampler(); + for (u32 i = 0; i < NUM_TEX_UNITS; i++) { + DefineTexSampler(i); } DefineEntryPoint(); } @@ -225,7 +225,8 @@ void FragmentModule::WriteLighting() { // Compute fragment normals and tangents const auto perturbation = [&]() -> Id { - const Id texel{SampleTexture(lighting.bump_selector)}; + const Id texel{ + OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[lighting.bump_selector])}; const Id texel_rgb{OpVectorShuffle(vec_ids.Get(3), texel, texel, 0, 1, 2)}; const Id rgb_mul_two{OpVectorTimesScalar(vec_ids.Get(3), texel_rgb, ConstF32(2.f))}; return OpFSub(vec_ids.Get(3), rgb_mul_two, ConstF32(1.f, 1.f, 1.f)); @@ -284,23 +285,25 @@ void FragmentModule::WriteLighting() { Id shadow{ConstF32(1.f, 1.f, 1.f, 1.f)}; if (lighting.enable_shadow) { - shadow = SampleTexture(lighting.shadow_selector); + shadow = OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[lighting.shadow_selector]); if (lighting.shadow_invert) { shadow = OpFSub(vec_ids.Get(4), ConstF32(1.f, 1.f, 1.f, 1.f), shadow); } } const auto lookup_lighting_lut_unsigned = [this](Id lut_index, Id pos) -> Id { - const Id pos_int{OpConvertFToS(i32_id, OpFMul(f32_id, pos, ConstF32(256.f)))}; - const Id index{OpSClamp(i32_id, pos_int, ConstS32(0), ConstS32(255))}; + const Id pos_floor{OpFloor(f32_id, OpFMul(f32_id, pos, ConstF32(256.f)))}; + const Id index_float{OpFClamp(f32_id, pos_floor, ConstF32(0.f), ConstF32(255.f))}; + const Id index{OpConvertFToS(i32_id, index_float)}; const Id neg_index{OpFNegate(f32_id, OpConvertSToF(f32_id, index))}; const Id delta{OpFma(f32_id, pos, ConstF32(256.f), neg_index)}; return LookupLightingLUT(lut_index, index, delta); }; const auto lookup_lighting_lut_signed = [this](Id lut_index, Id pos) -> Id { - const Id pos_int{OpConvertFToS(i32_id, OpFMul(f32_id, pos, ConstF32(128.f)))}; - const Id index{OpSClamp(i32_id, pos_int, ConstS32(-128), ConstS32(127))}; + const Id pos_floor{OpFloor(f32_id, OpFMul(f32_id, pos, ConstF32(128.f)))}; + const Id index_float{OpFClamp(f32_id, pos_floor, ConstF32(-128.f), ConstF32(127.f))}; + const Id index{OpConvertFToS(i32_id, index_float)}; const Id neg_index{OpFNegate(f32_id, OpConvertSToF(f32_id, index))}; const Id delta{OpFma(f32_id, pos, ConstF32(128.f), neg_index)}; const Id increment{ @@ -708,89 +711,6 @@ void FragmentModule::WriteAlphaTestCondition(FramebufferRegs::CompareFunc func) } } -Id FragmentModule::SampleTexture(u32 texture_unit) { - const PicaFSConfigState& state = config.state; - const Id zero_vec{ConstF32(0.f, 0.f, 0.f, 0.f)}; - - // PICA's LOD formula for 2D textures. - // This LOD formula is the same as the LOD lower limit defined in OpenGL. - // f(x, y) >= max{m_u, m_v, m_w} - // (See OpenGL 4.6 spec, 8.14.1 - Scale Factor and Level-of-Detail) - const auto sample_lod = [this, texture_unit](Id tex_id, Id texcoord_id) { - const Id sampled_image{OpLoad(TypeSampledImage(image2d_id), tex_id)}; - const Id tex_image{OpImage(image2d_id, sampled_image)}; - const Id tex_size{OpImageQuerySizeLod(ivec_ids.Get(2), tex_image, ConstS32(0))}; - const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id)}; - const Id coord{OpFMul(vec_ids.Get(2), texcoord, OpConvertSToF(vec_ids.Get(2), tex_size))}; - const Id abs_dfdx_coord{OpFAbs(vec_ids.Get(2), OpDPdx(vec_ids.Get(2), coord))}; - const Id abs_dfdy_coord{OpFAbs(vec_ids.Get(2), OpDPdy(vec_ids.Get(2), coord))}; - const Id d{OpFMax(vec_ids.Get(2), abs_dfdx_coord, abs_dfdy_coord)}; - const Id dx_dy_max{ - OpFMax(f32_id, OpCompositeExtract(f32_id, d, 0), OpCompositeExtract(f32_id, d, 1))}; - const Id lod{OpLog2(f32_id, dx_dy_max)}; - const Id lod_bias{GetShaderDataMember(f32_id, ConstS32(28), ConstU32(texture_unit))}; - const Id biased_lod{OpFAdd(f32_id, lod, lod_bias)}; - return OpImageSampleExplicitLod(vec_ids.Get(4), sampled_image, texcoord, - spv::ImageOperandsMask::Lod, biased_lod); - }; - - const auto sample = [this](Id tex_id, bool projection) { - const Id image_type = tex_id.value == tex_cube_id.value ? image_cube_id : image2d_id; - const Id sampled_image{OpLoad(TypeSampledImage(image_type), tex_id)}; - const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)}; - const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)}; - const Id coord{OpCompositeConstruct(vec_ids.Get(3), - OpCompositeExtract(f32_id, texcoord0, 0), - OpCompositeExtract(f32_id, texcoord0, 1), texcoord0_w)}; - if (projection) { - return OpImageSampleProjImplicitLod(vec_ids.Get(4), sampled_image, coord); - } else { - return OpImageSampleImplicitLod(vec_ids.Get(4), sampled_image, coord); - } - }; - - switch (texture_unit) { - case 0: - // Only unit 0 respects the texturing type - switch (state.texture0_type) { - case Pica::TexturingRegs::TextureConfig::Texture2D: - return sample_lod(tex0_id, texcoord0_id); - case Pica::TexturingRegs::TextureConfig::Projection2D: - return sample(tex0_id, true); - case Pica::TexturingRegs::TextureConfig::TextureCube: - return sample(tex_cube_id, false); - case Pica::TexturingRegs::TextureConfig::Shadow2D: - return SampleShadow(); - // case Pica::TexturingRegs::TextureConfig::ShadowCube: - // return "shadowTextureCube(texcoord0, texcoord0_w)"; - case Pica::TexturingRegs::TextureConfig::Disabled: - return zero_vec; - default: - LOG_CRITICAL(Render_Vulkan, "Unhandled texture type {:x}", state.texture0_type); - UNIMPLEMENTED(); - return zero_vec; - } - case 1: - return sample_lod(tex1_id, texcoord1_id); - case 2: - if (state.texture2_use_coord1) { - return sample_lod(tex2_id, texcoord1_id); - } else { - return sample_lod(tex2_id, texcoord2_id); - } - case 3: - if (state.proctex.enable) { - return OpFunctionCall(vec_ids.Get(4), proctex_func); - } else { - LOG_DEBUG(Render_Vulkan, "Using Texture3 without enabling it"); - return zero_vec; - } - default: - UNREACHABLE(); - return void_id; - } -} - Id FragmentModule::CompareShadow(Id pixel, Id z) { const Id pixel_d24{OpShiftRightLogical(u32_id, pixel, ConstS32(8))}; const Id pixel_s8{OpConvertUToF(f32_id, OpBitwiseAnd(u32_id, pixel, ConstU32(255u)))}; @@ -800,7 +720,7 @@ Id FragmentModule::CompareShadow(Id pixel, Id z) { } Id FragmentModule::SampleShadow() { - const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)}; + const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord_id[0])}; const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)}; const Id abs_min_w{OpFMul(f32_id, OpFMin(f32_id, OpFAbs(f32_id, texcoord0_w), ConstF32(1.f)), ConstF32(16777215.f))}; @@ -939,11 +859,145 @@ Id FragmentModule::AppendProcTexCombineAndMap(ProcTexCombiner combiner, Id u, Id return ProcTexLookupLUT(offset, combined); } -void FragmentModule::DefineProcTexSampler() { +void FragmentModule::DefineTexSampler(u32 texture_unit) { + const PicaFSConfigState& state = config.state; + const Id func_type{TypeFunction(vec_ids.Get(4))}; - proctex_func = OpFunction(vec_ids.Get(4), spv::FunctionControlMask::MaskNone, func_type); + sample_tex_unit_func[texture_unit] = + OpFunction(vec_ids.Get(4), spv::FunctionControlMask::MaskNone, func_type); AddLabel(OpLabel()); + const Id zero_vec{ConstF32(0.f, 0.f, 0.f, 0.f)}; + + if (texture_unit == 0 && state.texture0_type == TexturingRegs::TextureConfig::Disabled) { + OpReturnValue(zero_vec); + OpFunctionEnd(); + return; + } + + if (texture_unit == 3) { + if (state.proctex.enable) { + OpReturnValue(ProcTexSampler()); + } else { + OpReturnValue(zero_vec); + } + OpFunctionEnd(); + return; + } + + const Id border_label{OpLabel()}; + const Id not_border_label{OpLabel()}; + + u32 texcoord_num = texture_unit == 2 && state.texture2_use_coord1 ? 1 : texture_unit; + const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id[texcoord_num])}; + + auto& texture_border_color = state.texture_border_color[texture_unit]; + if (texture_border_color.enable_s || texture_border_color.enable_t) { + const Id texcoord_s{OpCompositeExtract(f32_id, texcoord, 0)}; + const Id texcoord_t{OpCompositeExtract(f32_id, texcoord, 1)}; + + const Id s_lt_zero{OpFOrdLessThan(bool_id, texcoord_s, ConstF32(0.0f))}; + const Id s_gt_one{OpFOrdGreaterThan(bool_id, texcoord_s, ConstF32(1.0f))}; + const Id t_lt_zero{OpFOrdLessThan(bool_id, texcoord_t, ConstF32(0.0f))}; + const Id t_gt_one{OpFOrdGreaterThan(bool_id, texcoord_t, ConstF32(1.0f))}; + + Id cond{}; + if (texture_border_color.enable_s && texture_border_color.enable_t) { + cond = OpAny(bool_id, OpCompositeConstruct(bvec_ids.Get(4), s_lt_zero, s_gt_one, + t_lt_zero, t_gt_one)); + } else if (texture_border_color.enable_s) { + cond = OpAny(bool_id, OpCompositeConstruct(bvec_ids.Get(2), s_lt_zero, s_gt_one)); + } else if (texture_border_color.enable_t) { + cond = OpAny(bool_id, OpCompositeConstruct(bvec_ids.Get(2), t_lt_zero, t_gt_one)); + } + + OpSelectionMerge(not_border_label, spv::SelectionControlMask::MaskNone); + OpBranchConditional(cond, border_label, not_border_label); + + AddLabel(border_label); + const Id border_color{ + GetShaderDataMember(vec_ids.Get(4), ConstS32(29), ConstU32(texture_unit))}; + OpReturnValue(border_color); + + AddLabel(not_border_label); + } + + // PICA's LOD formula for 2D textures. + // This LOD formula is the same as the LOD lower limit defined in OpenGL. + // f(x, y) >= max{m_u, m_v, m_w} + // (See OpenGL 4.6 spec, 8.14.1 - Scale Factor and Level-of-Detail) + const auto sample_lod = [&](Id tex_id) { + const Id sampled_image{OpLoad(TypeSampledImage(image2d_id), tex_id)}; + const Id tex_image{OpImage(image2d_id, sampled_image)}; + const Id tex_size{OpImageQuerySizeLod(ivec_ids.Get(2), tex_image, ConstS32(0))}; + const Id coord{OpFMul(vec_ids.Get(2), texcoord, OpConvertSToF(vec_ids.Get(2), tex_size))}; + const Id abs_dfdx_coord{OpFAbs(vec_ids.Get(2), OpDPdx(vec_ids.Get(2), coord))}; + const Id abs_dfdy_coord{OpFAbs(vec_ids.Get(2), OpDPdy(vec_ids.Get(2), coord))}; + const Id d{OpFMax(vec_ids.Get(2), abs_dfdx_coord, abs_dfdy_coord)}; + const Id dx_dy_max{ + OpFMax(f32_id, OpCompositeExtract(f32_id, d, 0), OpCompositeExtract(f32_id, d, 1))}; + const Id lod{OpLog2(f32_id, dx_dy_max)}; + const Id lod_bias{GetShaderDataMember(f32_id, ConstS32(28), ConstU32(texture_unit))}; + const Id biased_lod{OpFAdd(f32_id, lod, lod_bias)}; + return OpImageSampleExplicitLod(vec_ids.Get(4), sampled_image, texcoord, + spv::ImageOperandsMask::Lod, biased_lod); + }; + + const auto sample_3d = [&](Id tex_id, bool projection) { + const Id image_type = tex_id.value == tex_cube_id.value ? image_cube_id : image2d_id; + const Id sampled_image{OpLoad(TypeSampledImage(image_type), tex_id)}; + const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)}; + const Id coord{OpCompositeConstruct(vec_ids.Get(3), OpCompositeExtract(f32_id, texcoord, 0), + OpCompositeExtract(f32_id, texcoord, 1), texcoord0_w)}; + if (projection) { + return OpImageSampleProjImplicitLod(vec_ids.Get(4), sampled_image, coord); + } else { + return OpImageSampleImplicitLod(vec_ids.Get(4), sampled_image, coord); + } + }; + + Id ret_val{void_id}; + switch (texture_unit) { + case 0: + // Only unit 0 respects the texturing type + switch (state.texture0_type) { + case Pica::TexturingRegs::TextureConfig::Texture2D: + ret_val = sample_lod(tex0_id); + break; + case Pica::TexturingRegs::TextureConfig::Projection2D: + ret_val = sample_3d(tex0_id, true); + break; + case Pica::TexturingRegs::TextureConfig::TextureCube: + ret_val = sample_3d(tex_cube_id, false); + break; + case Pica::TexturingRegs::TextureConfig::Shadow2D: + ret_val = SampleShadow(); + // case Pica::TexturingRegs::TextureConfig::ShadowCube: + // return "shadowTextureCube(texcoord0, texcoord0_w)"; + break; + default: + LOG_CRITICAL(Render_Vulkan, "Unhandled texture type {:x}", state.texture0_type); + UNIMPLEMENTED(); + ret_val = zero_vec; + break; + } + break; + case 1: + ret_val = sample_lod(tex1_id); + break; + case 2: + ret_val = sample_lod(tex2_id); + break; + default: + UNREACHABLE(); + break; + } + + OpReturnValue(ret_val); + OpFunctionEnd(); +} + +Id FragmentModule::ProcTexSampler() { // Define noise tables at the beginning of the function if (config.state.proctex.noise_enable) { noise1d_table = @@ -955,24 +1009,11 @@ void FragmentModule::DefineProcTexSampler() { Id uv{}; if (config.state.proctex.coord < 3) { - Id texcoord_id{}; - switch (config.state.proctex.coord.Value()) { - case 0: - texcoord_id = texcoord0_id; - break; - case 1: - texcoord_id = texcoord1_id; - break; - case 2: - texcoord_id = texcoord2_id; - break; - } - - const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id)}; + const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id[config.state.proctex.coord.Value()])}; uv = OpFAbs(vec_ids.Get(2), texcoord); } else { LOG_CRITICAL(Render_Vulkan, "Unexpected proctex.coord >= 3"); - uv = OpFAbs(vec_ids.Get(2), OpLoad(vec_ids.Get(2), texcoord0_id)); + uv = OpFAbs(vec_ids.Get(2), OpLoad(vec_ids.Get(2), texcoord_id[0])); } // This LOD formula is the same as the LOD upper limit defined in OpenGL. @@ -1056,8 +1097,7 @@ void FragmentModule::DefineProcTexSampler() { final_color = OpCompositeInsert(vec_ids.Get(4), final_alpha, final_color, 3); } - OpReturnValue(final_color); - OpFunctionEnd(); + return final_color; } Id FragmentModule::Byteround(Id variable_id, u32 size) { @@ -1224,13 +1264,13 @@ Id FragmentModule::AppendSource(TevStageConfig::Source source, s32 index) { case Source::SecondaryFragmentColor: return secondary_fragment_color; case Source::Texture0: - return SampleTexture(0); + return OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[0]); case Source::Texture1: - return SampleTexture(1); + return OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[1]); case Source::Texture2: - return SampleTexture(2); + return OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[2]); case Source::Texture3: - return SampleTexture(3); + return OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[3]); case Source::PreviousBuffer: return combiner_buffer; case Source::Constant: @@ -1426,9 +1466,9 @@ void FragmentModule::DefineEntryPoint() { const Id main_type{TypeFunction(TypeVoid())}; const Id main_func{OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type)}; - AddEntryPoint(spv::ExecutionModel::Fragment, main_func, "main", primary_color_id, texcoord0_id, - texcoord1_id, texcoord2_id, texcoord0_w_id, normquat_id, view_id, color_id, - gl_frag_coord_id, gl_frag_depth_id); + AddEntryPoint(spv::ExecutionModel::Fragment, main_func, "main", primary_color_id, + texcoord_id[0], texcoord_id[1], texcoord_id[2], texcoord0_w_id, normquat_id, + view_id, color_id, gl_frag_coord_id, gl_frag_depth_id); AddExecutionMode(main_func, spv::ExecutionMode::OriginUpperLeft); AddExecutionMode(main_func, spv::ExecutionMode::DepthReplacing); } @@ -1441,21 +1481,25 @@ void FragmentModule::DefineUniformStructs() { const Id light_src_array_id{TypeArray(light_src_struct_id, ConstU32(NUM_LIGHTS))}; const Id lighting_lut_array_id{TypeArray(ivec_ids.Get(4), ConstU32(NUM_LIGHTING_SAMPLERS / 4))}; const Id const_color_array_id{TypeArray(vec_ids.Get(4), ConstU32(NUM_TEV_STAGES))}; + const Id border_color_array_id{TypeArray(vec_ids.Get(4), ConstU32(NUM_NON_PROC_TEX_UNITS))}; - const Id shader_data_struct_id{TypeStruct( - i32_id, i32_id, f32_id, f32_id, f32_id, f32_id, i32_id, i32_id, i32_id, i32_id, i32_id, - i32_id, i32_id, i32_id, i32_id, i32_id, f32_id, i32_id, u32_id, lighting_lut_array_id, - vec_ids.Get(3), vec_ids.Get(2), vec_ids.Get(2), vec_ids.Get(2), vec_ids.Get(3), - light_src_array_id, const_color_array_id, vec_ids.Get(4), vec_ids.Get(3), vec_ids.Get(4))}; + const Id shader_data_struct_id{ + TypeStruct(i32_id, i32_id, f32_id, f32_id, f32_id, f32_id, i32_id, i32_id, i32_id, i32_id, + i32_id, i32_id, i32_id, i32_id, i32_id, i32_id, f32_id, i32_id, u32_id, + lighting_lut_array_id, vec_ids.Get(3), vec_ids.Get(2), vec_ids.Get(2), + vec_ids.Get(2), vec_ids.Get(3), light_src_array_id, const_color_array_id, + vec_ids.Get(4), vec_ids.Get(3), border_color_array_id, vec_ids.Get(4))}; constexpr std::array light_src_offsets{0u, 16u, 32u, 48u, 64u, 80u, 92u, 96u}; - constexpr std::array shader_data_offsets{ - 0u, 4u, 8u, 12u, 16u, 20u, 24u, 28u, 32u, 36u, 40u, 44u, 48u, 52u, 56u, - 60u, 64u, 68u, 72u, 80u, 176u, 192u, 200u, 208u, 224u, 240u, 1136u, 1232u, 1248u, 1264u}; + constexpr std::array shader_data_offsets{0u, 4u, 8u, 12u, 16u, 20u, 24u, 28u, + 32u, 36u, 40u, 44u, 48u, 52u, 56u, 60u, + 64u, 68u, 72u, 80u, 176u, 192u, 200u, 208u, + 224u, 240u, 1136u, 1232u, 1248u, 1264u, 1312u}; Decorate(lighting_lut_array_id, spv::Decoration::ArrayStride, 16u); Decorate(light_src_array_id, spv::Decoration::ArrayStride, 112u); Decorate(const_color_array_id, spv::Decoration::ArrayStride, 16u); + Decorate(border_color_array_id, spv::Decoration::ArrayStride, 16u); for (u32 i = 0; i < static_cast(light_src_offsets.size()); i++) { MemberDecorate(light_src_struct_id, i, spv::Decoration::Offset, light_src_offsets[i]); } @@ -1473,9 +1517,9 @@ void FragmentModule::DefineUniformStructs() { void FragmentModule::DefineInterface() { // Define interface block primary_color_id = DefineInput(vec_ids.Get(4), 1); - texcoord0_id = DefineInput(vec_ids.Get(2), 2); - texcoord1_id = DefineInput(vec_ids.Get(2), 3); - texcoord2_id = DefineInput(vec_ids.Get(2), 4); + texcoord_id[0] = DefineInput(vec_ids.Get(2), 2); + texcoord_id[1] = DefineInput(vec_ids.Get(2), 3); + texcoord_id[2] = DefineInput(vec_ids.Get(2), 4); texcoord0_w_id = DefineInput(f32_id, 5); normquat_id = DefineInput(vec_ids.Get(4), 6); view_id = DefineInput(vec_ids.Get(3), 7); diff --git a/src/video_core/renderer_vulkan/vk_shader_gen_spv.h b/src/video_core/renderer_vulkan/vk_shader_gen_spv.h index 98631423f5..32bac11c28 100644 --- a/src/video_core/renderer_vulkan/vk_shader_gen_spv.h +++ b/src/video_core/renderer_vulkan/vk_shader_gen_spv.h @@ -30,6 +30,8 @@ class FragmentModule : public Sirit::Module { static constexpr u32 NUM_TEV_STAGES = 6; static constexpr u32 NUM_LIGHTS = 8; static constexpr u32 NUM_LIGHTING_SAMPLERS = 24; + static constexpr u32 NUM_TEX_UNITS = 4; + static constexpr u32 NUM_NON_PROC_TEX_UNITS = 3; public: explicit FragmentModule(Core::TelemetrySession& telemetry, const PicaFSConfig& config); @@ -57,15 +59,15 @@ private: /// Writes the code to emulate the specified TEV stage void WriteTevStage(s32 index); - /// Defines the tex3 proctex sampling function - void DefineProcTexSampler(); + /// Defines the basic texture sampling functions for a unit + void DefineTexSampler(u32 texture_unit); + + /// Function for sampling the procedurally generated texture unit. + Id ProcTexSampler(); /// Writes the if-statement condition used to evaluate alpha testing. void WriteAlphaTestCondition(Pica::FramebufferRegs::CompareFunc func); - /// Samples the current fragment texel from the provided texture unit - [[nodiscard]] Id SampleTexture(u32 texture_unit); - /// Samples the current fragment texel from shadow plane [[nodiscard]] Id SampleShadow(); @@ -237,9 +239,7 @@ private: Id shader_data_id{}; Id primary_color_id{}; - Id texcoord0_id{}; - Id texcoord1_id{}; - Id texcoord2_id{}; + Id texcoord_id[NUM_NON_PROC_TEX_UNITS]{}; Id texcoord0_w_id{}; Id normquat_id{}; Id view_id{}; @@ -276,7 +276,7 @@ private: Id alpha_results_2{}; Id alpha_results_3{}; - Id proctex_func{}; + Id sample_tex_unit_func[NUM_TEX_UNITS]{}; Id noise1d_table{}; Id noise2d_table{}; Id lut_offsets{}; diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp index 681817686b..cbdbfa2a82 100644 --- a/src/video_core/shader/shader_interpreter.cpp +++ b/src/video_core/shader/shader_interpreter.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include "common/assert.h" @@ -26,32 +27,64 @@ using nihstro::SwizzlePattern; namespace Pica::Shader { +struct IfStackElement { + u32 else_address; + u32 end_address; +}; + struct CallStackElement { - u32 final_address; // Address upon which we jump to return_address - u32 return_address; // Where to jump when leaving scope - u8 repeat_counter; // How often to repeat until this call stack element is removed - u8 loop_increment; // Which value to add to the loop counter after an iteration - // TODO: Should this be a signed value? Does it even matter? - u32 loop_address; // The address where we'll return to after each loop iteration + u32 end_address; + u32 return_address; +}; + +struct LoopStackElement { + u32 entry_address; + u32 end_address; + u8 loop_downcounter; + u8 address_increment; + u8 previous_aL; }; template static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData& debug_data, - unsigned offset) { - // TODO: Is there a maximal size for this? - boost::container::static_vector call_stack; - u32 program_counter = offset; + unsigned entry_point) { + boost::circular_buffer if_stack(8); + boost::circular_buffer call_stack(4); + boost::circular_buffer loop_stack(4); + u32 program_counter = entry_point; state.conditional_code[0] = false; state.conditional_code[1] = false; - auto call = [&program_counter, &call_stack](u32 offset, u32 num_instructions, u32 return_offset, - u8 repeat_count, u8 loop_increment) { - // -1 to make sure when incrementing the PC we end up at the correct offset - program_counter = offset - 1; - ASSERT(call_stack.size() < call_stack.capacity()); - call_stack.push_back( - {offset + num_instructions, return_offset, repeat_count, loop_increment, offset}); + const auto do_if = [&](Instruction instr, bool condition) { + if (condition) { + if_stack.push_back({ + .else_address = instr.flow_control.dest_offset, + .end_address = instr.flow_control.dest_offset + instr.flow_control.num_instructions, + }); + } else { + program_counter = instr.flow_control.dest_offset - 1; + } + }; + + const auto do_call = [&](Instruction instr) { + call_stack.push_back({ + .end_address = instr.flow_control.dest_offset + instr.flow_control.num_instructions, + .return_address = program_counter + 1, + }); + program_counter = instr.flow_control.dest_offset - 1; + }; + + const auto do_loop = [&](Instruction instr, const Common::Vec4& loop_param) { + const u8 previous_aL = static_cast(state.address_registers[2]); + loop_stack.push_back({ + .entry_address = program_counter + 1, + .end_address = instr.flow_control.dest_offset + 1, + .loop_downcounter = loop_param.x, + .address_increment = loop_param.z, + .previous_aL = previous_aL, + }); + state.address_registers[2] = loop_param.y; }; auto evaluate_condition = [&state](Instruction::FlowControlType flow_control) { @@ -82,25 +115,11 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData // Placeholder for invalid inputs static f24 dummy_vec4_float24[4]; - unsigned iteration = 0; - bool exit_loop = false; - while (!exit_loop) { - if (!call_stack.empty()) { - auto& top = call_stack.back(); - if (program_counter == top.final_address) { - state.address_registers[2] += top.loop_increment; - - if (top.repeat_counter-- == 0) { - program_counter = top.return_address; - call_stack.pop_back(); - } else { - program_counter = top.loop_address; - } - - // TODO: Is "trying again" accurate to hardware? - continue; - } - } + u32 iteration = 0; + bool should_stop = false; + while (!should_stop) { + bool is_break = false; + const u32 old_program_counter = program_counter; const Instruction instr = {program_code[program_counter]}; const SwizzlePattern swizzle = {swizzle_data[instr.common.operand_desc_id]}; @@ -538,7 +557,7 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData // Handle each instruction on its own switch (instr.opcode.Value()) { case OpCode::Id::END: - exit_loop = true; + should_stop = true; break; case OpCode::Id::JMPC: @@ -559,72 +578,68 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData break; case OpCode::Id::CALL: - call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, - program_counter + 1, 0, 0); + do_call(instr); break; case OpCode::Id::CALLU: Record( debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]); if (uniforms.b[instr.flow_control.bool_uniform_id]) { - call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, - program_counter + 1, 0, 0); + do_call(instr); } break; case OpCode::Id::CALLC: Record(debug_data, iteration, state.conditional_code); if (evaluate_condition(instr.flow_control)) { - call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, - program_counter + 1, 0, 0); + do_call(instr); } break; case OpCode::Id::NOP: break; - case OpCode::Id::IFU: + case OpCode::Id::IFU: { Record( debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]); - if (uniforms.b[instr.flow_control.bool_uniform_id]) { - call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1, - instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, - 0); - } else { - call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, - instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, - 0); - } - + const bool cond = uniforms.b[instr.flow_control.bool_uniform_id]; + do_if(instr, cond); break; + } case OpCode::Id::IFC: { // TODO: Do we need to consider swizzlers here? - Record(debug_data, iteration, state.conditional_code); - if (evaluate_condition(instr.flow_control)) { - call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1, - instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, - 0); - } else { - call(instr.flow_control.dest_offset, instr.flow_control.num_instructions, - instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0, - 0); - } - + const bool cond = evaluate_condition(instr.flow_control); + do_if(instr, cond); break; } case OpCode::Id::LOOP: { - Common::Vec4 loop_param(uniforms.i[instr.flow_control.int_uniform_id].x, - uniforms.i[instr.flow_control.int_uniform_id].y, - uniforms.i[instr.flow_control.int_uniform_id].z, - uniforms.i[instr.flow_control.int_uniform_id].w); + const Common::Vec4& loop_param = uniforms.i[instr.flow_control.int_uniform_id]; state.address_registers[2] = loop_param.y; Record(debug_data, iteration, loop_param); - call(program_counter + 1, instr.flow_control.dest_offset - program_counter, - instr.flow_control.dest_offset + 1, loop_param.x, loop_param.z); + do_loop(instr, loop_param); + Record(debug_data, iteration, + state.address_registers); + break; + } + + case OpCode::Id::BREAK: { + is_break = true; + Record(debug_data, iteration, + state.address_registers); + break; + } + + case OpCode::Id::BREAKC: { + Record(debug_data, iteration, state.conditional_code); + if (evaluate_condition(instr.flow_control)) { + is_break = true; + } + Record(debug_data, iteration, + state.address_registers); break; } @@ -657,6 +672,47 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData ++program_counter; ++iteration; + + // Stacks are checked in the order CALL -> IF -> LOOP. The CALL stack + // can be popped multiple times per instruction. A JMP at the end of a + // scope is never taken, this is why we compare against + // old_program_counter + 1 here. + u32 next_program_counter = old_program_counter + 1; + for (u32 i = 0; i < 4; i++) { + if (call_stack.empty() || call_stack.back().end_address != next_program_counter) + break; + // Hardware bug: when popping four CALL scopes at once, the last + // one doesn't update the program counter + if (i < 3) { + program_counter = call_stack.back().return_address; + next_program_counter = program_counter; + } + call_stack.pop_back(); + } + + // The other two stacks can only pop one entry per instruction. They + // are checked against the original program counter before any CALL + // scopes were closed and they overwrite any previous program counter + // updates. + if (!if_stack.empty() && if_stack.back().else_address == old_program_counter + 1) { + program_counter = if_stack.back().end_address; + if_stack.pop_back(); + } + + if (!loop_stack.empty() && + (loop_stack.back().end_address == old_program_counter + 1 || is_break)) { + auto& loop = loop_stack.back(); + state.address_registers[2] += loop.address_increment; + if (!is_break && loop.loop_downcounter--) { + program_counter = loop.entry_address; + } else { + program_counter = loop.end_address; + // Only restore previous value if there is a surrounding LOOP scope. + if (loop_stack.size() > 1) + state.address_registers[2] = loop.previous_aL; + loop_stack.pop_back(); + } + } } } diff --git a/src/video_core/shader/shader_uniforms.cpp b/src/video_core/shader/shader_uniforms.cpp index 8247d697b3..baa4964744 100644 --- a/src/video_core/shader/shader_uniforms.cpp +++ b/src/video_core/shader/shader_uniforms.cpp @@ -67,6 +67,7 @@ layout ({}std140) uniform shader_data {{ vec4 const_color[NUM_TEV_STAGES]; vec4 tev_combiner_buffer_color; vec3 tex_lod_bias; + vec4 tex_border_color[3]; vec4 clip_coef; }}; )"; diff --git a/src/video_core/shader/shader_uniforms.h b/src/video_core/shader/shader_uniforms.h index 1cc8e574f8..168f3f14c4 100644 --- a/src/video_core/shader/shader_uniforms.h +++ b/src/video_core/shader/shader_uniforms.h @@ -64,10 +64,11 @@ struct UniformData { alignas(16) Common::Vec4f const_color[6]; // A vec4 color for each of the six tev stages alignas(16) Common::Vec4f tev_combiner_buffer_color; alignas(16) Common::Vec3f tex_lod_bias; + alignas(16) Common::Vec4f tex_border_color[3]; alignas(16) Common::Vec4f clip_coef; }; -static_assert(sizeof(UniformData) == 0x500, +static_assert(sizeof(UniformData) == 0x530, "The size of the UniformData does not match the structure in the shader"); static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec"); diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index d030236042..feb158b687 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt @@ -1,8 +1,6 @@ add_library(web_service STATIC announce_room_json.cpp announce_room_json.h - nus_download.cpp - nus_download.h precompiled_headers.h telemetry_json.cpp telemetry_json.h @@ -16,7 +14,7 @@ add_library(web_service STATIC create_target_directory_groups(web_service) -target_compile_definitions(web_service PRIVATE -DCPPHTTPLIB_OPENSSL_SUPPORT) +target_compile_definitions(web_service PUBLIC -DENABLE_WEB_SERVICE) target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt) target_link_libraries(web_service PUBLIC ${OPENSSL_LIBS}) set_target_properties(web_service PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})