Rebranded to Sudachi (RIP Yoozoo) and updated some more dependencies

This commit is contained in:
Jarrod Norwell 2024-03-13 03:26:56 +08:00
parent 169fe4fabc
commit 3fd22b8781
3246 changed files with 236720 additions and 321912 deletions

View File

@ -1,9 +1,9 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2018 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
cmake_minimum_required(VERSION 3.22)
project(yuzu)
project(sudachi)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
@ -15,9 +15,9 @@ include(CTest)
# Set bundled sdl2/qt as dependent options.
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF)
@ -28,45 +28,45 @@ option(ENABLE_QT6 "Allow usage of Qt6 to be attempted" OFF)
set(QT6_LOCATION "" CACHE PATH "Additional Location to search for Qt6 libraries like C:/Qt/6.3.1/msvc2019_64/")
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(SUDACHI_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(SUDACHI_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(SUDACHI_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(SUDACHI_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
option(SUDACHI_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
option(SUDACHI_TESTS "Compile tests" "${BUILD_TESTING}")
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
option(SUDACHI_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON)
option(SUDACHI_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON)
CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
option(SUDACHI_USE_BUNDLED_VCPKG "Use vcpkg for sudachi dependencies" "${MSVC}")
option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON)
option(SUDACHI_CHECK_SUBMODULES "Check if submodules are present" ON)
option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF)
option(SUDACHI_ENABLE_LTO "Enable link-time optimization" OFF)
option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
option(SUDACHI_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
option(YUZU_ENABLE_PORTABLE "Allow yuzu to enable portable mode if a user folder is found in the CWD" ON)
option(SUDACHI_ENABLE_PORTABLE "Allow sudachi to enable portable mode if a user folder is found in the CWD" ON)
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
CMAKE_DEPENDENT_OPTION(SUDACHI_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
@ -82,7 +82,7 @@ if (ANDROID OR WIN32 OR APPLE)
endif()
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
if (ANDROID AND SUDACHI_DOWNLOAD_ANDROID_VVL)
set(vvl_version "sdk-1.3.261.1")
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
if (NOT EXISTS "${vvl_zip_file}")
@ -104,7 +104,7 @@ if (ANDROID)
set(CMAKE_SKIP_INSTALL_RULES ON)
endif()
if (YUZU_USE_BUNDLED_VCPKG)
if (SUDACHI_USE_BUNDLED_VCPKG)
if (ANDROID)
set(ENV{ANDROID_NDK_HOME} "${ANDROID_NDK}")
list(APPEND VCPKG_MANIFEST_FEATURES "android")
@ -138,8 +138,8 @@ if (YUZU_USE_BUNDLED_VCPKG)
endif()
endif()
if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
if (SUDACHI_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "sudachi-tests")
endif()
if (ENABLE_WEB_SERVICE)
list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
@ -155,16 +155,16 @@ elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
include("$ENV{VCPKG_TOOLCHAIN_FILE}")
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
if (SUDACHI_USE_PRECOMPILED_HEADERS)
if (MSVC AND CCACHE)
# buildcache does not properly cache PCH files, leading to compilation errors.
# See https://github.com/mbitsnbites/buildcache/discussions/230
message(WARNING "buildcache does not properly support Precompiled Headers. Disabling PCH")
set(DYNARMIC_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
set(YUZU_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
set(SUDACHI_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
endif()
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
if (SUDACHI_USE_PRECOMPILED_HEADERS)
message(STATUS "Using Precompiled Headers.")
set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON)
endif()
@ -199,7 +199,7 @@ function(check_submodules_present)
endforeach()
endfunction()
if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules AND YUZU_CHECK_SUBMODULES)
if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules AND SUDACHI_CHECK_SUBMODULES)
check_submodules_present()
endif()
configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc
@ -211,9 +211,9 @@ if (EXISTS ${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.json
COPYONLY)
endif()
if (ENABLE_COMPATIBILITY_LIST_DOWNLOAD AND NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
message(STATUS "Downloading compatibility list for yuzu...")
message(STATUS "Downloading compatibility list for sudachi...")
file(DOWNLOAD
https://api.yuzu-emu.org/gamedb/
https://api.sudachi-emu.org/gamedb/
"${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json" SHOW_PROGRESS)
endif()
if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
@ -262,7 +262,7 @@ endif()
message(STATUS "Target architecture: ${ARCHITECTURE}")
if (UNIX)
add_definitions(-DYUZU_UNIX=1)
add_definitions(-DSUDACHI_UNIX=1)
endif()
if (ARCHITECTURE_arm64 AND (ANDROID OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
@ -306,11 +306,11 @@ find_package(VulkanMemoryAllocator CONFIG)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED)
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
if (NOT SUDACHI_USE_EXTERNAL_VULKAN_HEADERS)
find_package(VulkanHeaders 1.3.274 REQUIRED)
endif()
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
if (NOT SUDACHI_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
find_package(VulkanUtilityLibraries REQUIRED)
endif()
@ -343,7 +343,7 @@ if (ENABLE_WEB_SERVICE)
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
endif()
if (YUZU_TESTS)
if (SUDACHI_TESTS)
find_package(Catch2 3.0.1 REQUIRED)
endif()
@ -365,26 +365,26 @@ if(ENABLE_QT6 AND Qt6_LOCATION)
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
endif()
function(set_yuzu_qt_components)
function(set_sudachi_qt_components)
# Best practice is to ask for all components at once, so they are from the same version
set(YUZU_QT_COMPONENTS2 Core Widgets Concurrent)
set(SUDACHI_QT_COMPONENTS2 Core Widgets Concurrent)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
list(APPEND YUZU_QT_COMPONENTS2 DBus)
list(APPEND SUDACHI_QT_COMPONENTS2 DBus)
endif()
if (YUZU_USE_QT_MULTIMEDIA)
list(APPEND YUZU_QT_COMPONENTS2 Multimedia)
if (SUDACHI_USE_QT_MULTIMEDIA)
list(APPEND SUDACHI_QT_COMPONENTS2 Multimedia)
endif()
if (YUZU_USE_QT_WEB_ENGINE)
list(APPEND YUZU_QT_COMPONENTS2 WebEngineCore WebEngineWidgets)
if (SUDACHI_USE_QT_WEB_ENGINE)
list(APPEND SUDACHI_QT_COMPONENTS2 WebEngineCore WebEngineWidgets)
endif()
if (ENABLE_QT_TRANSLATION)
list(APPEND YUZU_QT_COMPONENTS2 LinguistTools)
list(APPEND SUDACHI_QT_COMPONENTS2 LinguistTools)
endif()
if (USE_DISCORD_PRESENCE)
list(APPEND YUZU_QT_COMPONENTS2 Network)
list(APPEND SUDACHI_QT_COMPONENTS2 Network)
endif()
set(YUZU_QT_COMPONENTS ${YUZU_QT_COMPONENTS2} PARENT_SCOPE)
endfunction(set_yuzu_qt_components)
set(SUDACHI_QT_COMPONENTS ${SUDACHI_QT_COMPONENTS2} PARENT_SCOPE)
endfunction(set_sudachi_qt_components)
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
if(ENABLE_QT)
@ -393,29 +393,29 @@ if(ENABLE_QT)
set(QT5_VERSION 5.15)
set(QT6_VERSION 6.3.1)
set_yuzu_qt_components()
set_sudachi_qt_components()
if (ENABLE_QT6)
find_package(Qt6 ${QT6_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS})
find_package(Qt6 ${QT6_VERSION} COMPONENTS ${SUDACHI_QT_COMPONENTS})
endif()
if (Qt6_FOUND)
message(STATUS "yuzu/CMakeLists.txt: Qt6Widgets_VERSION ${Qt6Widgets_VERSION}, setting QT_VERSION")
message(STATUS "sudachi/CMakeLists.txt: Qt6Widgets_VERSION ${Qt6Widgets_VERSION}, setting QT_VERSION")
set(QT_VERSION ${Qt6Widgets_VERSION})
set(QT_MAJOR_VERSION 6)
# Qt6 sets cxx_std_17 and we need to undo that
set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "")
else()
message(STATUS "yuzu/CMakeLists.txt: Qt6 not found/not selected, trying for Qt5")
message(STATUS "sudachi/CMakeLists.txt: Qt6 not found/not selected, trying for Qt5")
# When Qt6 partially found, need this set to use Qt5 when not specifying version
set(QT_DEFAULT_MAJOR_VERSION 5)
set(QT_MAJOR_VERSION 5)
set(YUZU_USE_QT_MULTIMEDIA ON)
set(SUDACHI_USE_QT_MULTIMEDIA ON)
# Check for system Qt on Linux, fallback to bundled Qt
if (UNIX AND NOT APPLE)
if (NOT YUZU_USE_BUNDLED_QT)
if (NOT SUDACHI_USE_BUNDLED_QT)
find_package(Qt5 ${QT5_VERSION} COMPONENTS Widgets DBus Multimedia)
endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT))
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR SUDACHI_USE_BUNDLED_QT))
# Check for dependencies, then enable bundled Qt download
# Check that the system GLIBCXX version is compatible
@ -489,23 +489,23 @@ if(ENABLE_QT)
message(FATAL_ERROR "Bundled Qt package missing required dependencies: ${UNRESOLVED_QT_DEPS}")
endif()
set(YUZU_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE)
set(SUDACHI_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE)
endif()
if (YUZU_USE_BUNDLED_QT)
if (SUDACHI_USE_BUNDLED_QT)
# Binary package currently does not support Qt webengine, so make sure it's disabled
set(YUZU_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE)
set(SUDACHI_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE)
endif()
endif()
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH)
set(SUDACHI_QT_NO_CMAKE_SYSTEM_PATH)
if(YUZU_USE_BUNDLED_QT)
if(SUDACHI_USE_BUNDLED_QT)
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
set(QT_BUILD qt-5.15.2-msvc2019_64)
elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64)
set(QT_BUILD qt5_5_15_2)
else()
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable SUDACHI_USE_BUNDLED_QT and provide your own.")
endif()
if (DEFINED QT_BUILD)
@ -514,25 +514,25 @@ if(ENABLE_QT)
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
# Binary package for Qt5 has Qt Multimedia
set(YUZU_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE)
set(SUDACHI_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
# Binary package for Qt6 has Qt Multimedia
set(SUDACHI_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE)
endif()
set_yuzu_qt_components()
find_package(Qt5 ${QT5_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS} ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
set_sudachi_qt_components()
find_package(Qt5 ${QT5_VERSION} COMPONENTS ${SUDACHI_QT_COMPONENTS} ${QT_PREFIX_HINT} ${SUDACHI_QT_NO_CMAKE_SYSTEM_PATH})
endif()
endif()
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the sudachi_find_package
if (ENABLE_SDL2)
if (YUZU_USE_BUNDLED_SDL2)
if (SUDACHI_USE_BUNDLED_SDL2)
# Detect toolchain and platform
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
set(SDL2_VER "SDL2-2.28.2")
else()
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.")
message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable SUDACHI_USE_BUNDLED_SDL2 and provide your own.")
endif()
if (DEFINED SDL2_VER)
@ -547,7 +547,7 @@ if (ENABLE_SDL2)
add_library(SDL2::SDL2 INTERFACE IMPORTED)
target_link_libraries(SDL2::SDL2 INTERFACE "${SDL2_LIBRARY}")
target_include_directories(SDL2::SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
elseif (YUZU_USE_EXTERNAL_SDL2)
elseif (SUDACHI_USE_EXTERNAL_SDL2)
message(STATUS "Using SDL2 from externals.")
else()
find_package(SDL2 2.26.4 REQUIRED)
@ -565,12 +565,12 @@ if (UNIX AND NOT APPLE AND NOT ANDROID)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)
if (NOT SUDACHI_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
endif()
if (WIN32 AND YUZU_CRASH_DUMPS)
if (WIN32 AND SUDACHI_CRASH_DUMPS)
set(BREAKPAD_VER "breakpad-c89f9dd")
download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX)
@ -685,7 +685,7 @@ if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
)
endif()
if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (SUDACHI_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default.
# Try to pick a faster linker.
find_program(LLD lld)
@ -703,11 +703,11 @@ endif()
add_subdirectory(externals)
add_subdirectory(src)
# Set yuzu project or yuzu-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
# Set sudachi project or sudachi-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not
if(ENABLE_QT)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT yuzu)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT sudachi)
else()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT yuzu-cmd)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT sudachi-cmd)
endif()
@ -720,13 +720,13 @@ endif()
# https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
# https://www.freedesktop.org/software/appstream/docs/
if(ENABLE_QT AND UNIX AND NOT APPLE)
install(FILES "dist/org.yuzu_emu.yuzu.desktop"
install(FILES "dist/org.sudachi_emu.sudachi.desktop"
DESTINATION "share/applications")
install(FILES "dist/yuzu.svg"
install(FILES "dist/sudachi.svg"
DESTINATION "share/icons/hicolor/scalable/apps"
RENAME "org.yuzu_emu.yuzu.svg")
install(FILES "dist/org.yuzu_emu.yuzu.xml"
RENAME "org.sudachi_emu.sudachi.svg")
install(FILES "dist/org.sudachi_emu.sudachi.xml"
DESTINATION "share/mime/packages")
install(FILES "dist/org.yuzu_emu.yuzu.metainfo.xml"
install(FILES "dist/org.sudachi_emu.sudachi.metainfo.xml"
DESTINATION "share/metainfo")
endif()

View File

@ -1,10 +0,0 @@
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_yuzu_FFmpeg_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
file(READ "${FFmpeg_PATH}/requirements.txt" FFmpeg_REQUIRED_DLLS)
string(STRIP "${FFmpeg_REQUIRED_DLLS}" FFmpeg_REQUIRED_DLLS)
windows_copy_files(${target_dir} ${FFmpeg_LIBRARY_DIR} ${DLL_DEST} ${FFmpeg_REQUIRED_DLLS})
endfunction(copy_yuzu_FFmpeg_deps)

View File

@ -1,125 +0,0 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_yuzu_Qt5_deps target_dir)
include(WindowsCopyFiles)
if (MSVC)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
else()
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/")
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../lib/")
endif()
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_PLATFORMTHEMES_DIR "${Qt5_DIR}/../../../plugins/platformthemes/")
set(Qt5_PLATFORMINPUTCONTEXTS_DIR "${Qt5_DIR}/../../../plugins/platforminputcontexts/")
set(Qt5_MEDIASERVICE_DIR "${Qt5_DIR}/../../../plugins/mediaservice/")
set(Qt5_XCBGLINTEGRATIONS_DIR "${Qt5_DIR}/../../../plugins/xcbglintegrations/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
set(MEDIASERVICE ${DLL_DEST}mediaservice/)
set(STYLES ${DLL_DEST}plugins/styles/)
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
if (MSVC)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Core$<$<CONFIG:Debug>:d>.*
Qt5Gui$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
Qt5Network$<$<CONFIG:Debug>:d>.*
)
if (YUZU_USE_QT_MULTIMEDIA)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Multimedia$<$<CONFIG:Debug>:d>.*
)
endif()
if (YUZU_USE_QT_WEB_ENGINE)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Network$<$<CONFIG:Debug>:d>.*
Qt5Positioning$<$<CONFIG:Debug>:d>.*
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
Qt5Qml$<$<CONFIG:Debug>:d>.*
Qt5QmlModels$<$<CONFIG:Debug>:d>.*
Qt5Quick$<$<CONFIG:Debug>:d>.*
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST}
icudtl.dat
qtwebengine_devtools_resources.pak
qtwebengine_resources.pak
qtwebengine_resources_100p.pak
qtwebengine_resources_200p.pak
)
endif ()
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qjpeg$<$<CONFIG:Debug>:d>.*
qgif$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(yuzu ${Qt5_MEDIASERVICE_DIR} ${MEDIASERVICE}
dsengine$<$<CONFIG:Debug>:d>.*
wmfengine$<$<CONFIG:Debug>:d>.*
)
else()
set(Qt5_DLLS
"${Qt5_DLL_DIR}libQt5Core.so.5"
"${Qt5_DLL_DIR}libQt5DBus.so.5"
"${Qt5_DLL_DIR}libQt5Gui.so.5"
"${Qt5_DLL_DIR}libQt5Widgets.so.5"
"${Qt5_DLL_DIR}libQt5XcbQpa.so.5"
"${Qt5_DLL_DIR}libicudata.so.60"
"${Qt5_DLL_DIR}libicui18n.so.60"
"${Qt5_DLL_DIR}libicuuc.so.60"
)
set(Qt5_IMAGEFORMAT_DLLS
"${Qt5_IMAGEFORMATS_DIR}libqjpeg.so"
"${Qt5_IMAGEFORMATS_DIR}libqgif.so"
"${Qt5_IMAGEFORMATS_DIR}libqico.so"
)
set(Qt5_PLATFORMTHEME_DLLS
"${Qt5_PLATFORMTHEMES_DIR}libqgtk3.so"
"${Qt5_PLATFORMTHEMES_DIR}libqxdgdesktopportal.so"
)
set(Qt5_PLATFORM_DLLS
"${Qt5_PLATFORMS_DIR}libqxcb.so"
)
set(Qt5_PLATFORMINPUTCONTEXT_DLLS
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libcomposeplatforminputcontextplugin.so"
"${Qt5_PLATFORMINPUTCONTEXTS_DIR}libibusplatforminputcontextplugin.so"
)
set(Qt5_XCBGLINTEGRATION_DLLS
"${Qt5_XCBGLINTEGRATIONS_DIR}libqxcb-glx-integration.so"
)
foreach(LIB ${Qt5_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}/lib" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_IMAGEFORMAT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/imageformats/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMTHEME_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platformthemes/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORM_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforms/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMINPUTCONTEXT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforminputcontexts/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_XCBGLINTEGRATION_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/xcbglintegrations/" FOLLOW_SYMLINK_CHAIN)
endforeach()
endif()
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
# This way it'll look for plugins in the root/plugins/ folder
add_custom_command(TARGET yuzu POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
)
endfunction(copy_yuzu_Qt5_deps)

View File

@ -1,8 +0,0 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
function(copy_yuzu_SDL_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "$<TARGET_FILE_DIR:${target_dir}>/")
windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll)
endfunction(copy_yuzu_SDL_deps)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2017 yuzu Emulator Project
# SPDX-FileCopyrightText: 2017 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# This function downloads a binary library package from our external repo.

View File

@ -19,7 +19,7 @@ if (LLVM_FOUND AND LLVM_Demangle_FOUND AND NOT TARGET LLVM::Demangle)
target_include_directories(LLVM::Demangle INTERFACE ${LLVM_INCLUDE_DIRS})
# prefer shared LLVM: https://github.com/llvm/llvm-project/issues/34593
# but use ugly hack because llvm_config doesn't support interface library
add_library(_dummy_lib SHARED EXCLUDE_FROM_ALL src/yuzu/main.cpp)
add_library(_dummy_lib SHARED EXCLUDE_FROM_ALL src/sudachi/main.cpp)
llvm_config(_dummy_lib USE_SHARED demangle)
get_target_property(LLVM_LIBRARIES _dummy_lib LINK_LIBRARIES)
target_link_libraries(LLVM::Demangle INTERFACE ${LLVM_LIBRARIES})

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
# SPDX-FileCopyrightText: 2019 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Gets a UTC timestamp and sets the provided variable to it
@ -27,7 +27,7 @@ set(BUILD_VERSION "0")
set(BUILD_ID ${DISPLAY_VERSION})
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
string(REGEX MATCH "sudachi-emu/sudachi-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# buildcache wrapper

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2018 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# This file provides the function windows_copy_files.

View File

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Allow systemd-logind to manage user access to hidraw with this file
# On most systems, this file should be installed to /etc/udev/rules.d/72-yuzu-input.rules
# Consult your distro if this is not the case
# Switch Pro Controller (USB/Bluetooth)
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="2009", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", KERNELS=="*057e:2009*", MODE="0660", TAG+="uaccess"
# Joy-Con L (Bluetooth)
KERNEL=="hidraw*", KERNELS=="*057e:2006*", MODE="0660", TAG+="uaccess"
# Joy-Con R (Bluetooth)
KERNEL=="hidraw*", KERNELS=="*057e:2007*", MODE="0660", TAG+="uaccess"
# Joy-Con Charging Grip (USB)
KERNEL=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="200e", MODE="0660", TAG+="uaccess"

4
dist/AppRun vendored
View File

@ -4,7 +4,7 @@
# From: https://github.com/darealshinji/AppImageKit-checkrt
# add your command to execute here
exec=yuzu
exec=sudachi
cd "$(dirname "$0")"
if [ "x$exec" = "x" ]; then
@ -24,5 +24,5 @@ export SSL_CERT_FILE="$PWD/ca-certificates.pem"
#echo ">>>>> LD_LIBRARY_PATH $LD_LIBRARY_PATH"
#echo ">>>>> LD_PRELOAD $LD_PRELOAD"
exec ./usr/bin/yuzu "$@"
exec ./usr/bin/sudachi "$@"

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-FileCopyrightText: 2018 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -10,7 +10,7 @@ Qt has "Translation Rules for Plurals", small example
// i = 2:
Building: 2 shaders
For yuzu the source language used is English, for all other languages handling of plurals is handled by Qt and the translation collaboration site. Handling plurals in the source language (English) requires special consideration.
For sudachi the source language used is English, for all other languages handling of plurals is handled by Qt and the translation collaboration site. Handling plurals in the source language (English) requires special consideration.
With CMake flag GENERATE_QT_TRANSLATION a generated_en.ts file is created from the source. It ignored by git (`.gitignore` in the project root). It is placed in this directory so that the relative refrences with the source code is correct.

View File

@ -1,67 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US" sourcelanguage="en_US">
<context>
<name>GMainWindow</name>
<message numerus="yes">
<location filename="../../src/yuzu/main.cpp" line="2322"/>
<source>%n file(s) remaining</source>
<translation>
<numerusform>%n file remaining</numerusform>
<numerusform>%n files remaining</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../src/yuzu/main.cpp" line="2377"/>
<source>%n file(s) were newly installed
</source>
<translation>
<numerusform>%n file was newly installed
</numerusform>
<numerusform>%n files were newly installed
</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../src/yuzu/main.cpp" line="2380"/>
<source>%n file(s) were overwritten
</source>
<translation>
<numerusform>%n file was overwritten
</numerusform>
<numerusform>%n were overwritten
</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../src/yuzu/main.cpp" line="2382"/>
<source>%n file(s) failed to install
</source>
<translation>
<numerusform>%n file failed to install
</numerusform>
<numerusform>%n files failed to install
</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../src/yuzu/main.cpp" line="3264"/>
<source>Building: %n shader(s)</source>
<translation>
<numerusform>Building: %n shader</numerusform>
<numerusform>Building: %n shaders</numerusform>
</translation>
</message>
</context>
<context>
<name>GameListSearchField</name>
<message numerus="yes">
<location filename="../../src/yuzu/game_list.cpp" line="87"/>
<source>%1 of %n result(s)</source>
<translation>
<numerusform>%1 of %n result</numerusform>
<numerusform>%1 of %n results</numerusform>
</translation>
</message>
</context>
</TS>
<?xml version="1.0" encoding = "utf-8" ?>
<!DOCTYPE TS >
<TS version="2.1" language = "en_US" sourcelanguage = "en_US" >
<context>
<name>GMainWindow < /name>
< message numerus = "yes" >
<location filename="../../src/sudachi/main.cpp" line = "2322" />
<source>% n file(s) remaining < /source>
< translation >
<numerusform>% n file remaining < /numerusform>
<numerusform> % n files remaining < /numerusform>
< /translation>
< /message>
< message numerus = "yes" >
<location filename="../../src/sudachi/main.cpp" line = "2377" />
<source>% n file(s) were newly installed
< /source>
< translation >
<numerusform>% n file was newly installed
< /numerusform>
<numerusform> % n files were newly installed
< /numerusform>
< /translation>
< /message>
< message numerus = "yes" >
<location filename="../../src/sudachi/main.cpp" line = "2380" />
<source>% n file(s) were overwritten
< /source>
< translation >
<numerusform>% n file was overwritten
< /numerusform>
<numerusform> % n were overwritten
< /numerusform>
< /translation>
< /message>
< message numerus = "yes" >
<location filename="../../src/sudachi/main.cpp" line = "2382" />
<source>% n file(s) failed to install
< /source>
< translation >
<numerusform>% n file failed to install
< /numerusform>
<numerusform> % n files failed to install
< /numerusform>
< /translation>
< /message>
< message numerus = "yes" >
<location filename="../../src/sudachi/main.cpp" line = "3264" />
<source>Building: % n shader(s) < /source>
< translation >
<numerusform>Building: % n shader < /numerusform>
< numerusform > Building: % n shaders < /numerusform>
< /translation>
< /message>
< /context>
< context >
<name>GameListSearchField < /name>
< message numerus = "yes" >
<location filename="../../src/sudachi/game_list.cpp" line = "87" />
<source>% 1 of % n result(s) < /source>
< translation >
<numerusform>% 1 of % n result < /numerusform>
<numerusform> % 1 of % n results < /numerusform>
< /translation>
< /message>
< /context>
< /TS>

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
SPDX-FileCopyrightText: 2020 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2021 yuzu Emulator Project
SPDX-FileCopyrightText: 2021 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -1,13 +1,13 @@
[main]
host = https://www.transifex.com
[o:yuzu-emulator:p:yuzu:r:emulator]
[o:sudachi-emulator:p:sudachi:r:emulator]
file_filter = <lang>.ts
source_file = en.ts
source_lang = en
type = QT
[o:yuzu-emulator:p:yuzu:r:yuzu-android]
[o:sudachi-emulator:p:sudachi:r:sudachi-android]
file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml
source_file = ../../src/android/app/src/main/res/values/strings.xml
type = ANDROID

View File

@ -1,3 +1,3 @@
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu), so you can update the translation by executing `tx pull -t -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically.
This directory stores translation patches (TS files) for sudachi Qt frontend. This directory is linked with [sudachi project on transifex](https://www.transifex.com/sudachi-emulator/sudachi), so you can update the translation by executing `tx pull -t -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically.
Do not directly open PRs on github to modify the translation.

17476
dist/languages/ar.ts vendored

File diff suppressed because it is too large Load Diff

17546
dist/languages/ca.ts vendored

File diff suppressed because it is too large Load Diff

17514
dist/languages/cs.ts vendored

File diff suppressed because it is too large Load Diff

17504
dist/languages/da.ts vendored

File diff suppressed because it is too large Load Diff

17564
dist/languages/de.ts vendored

File diff suppressed because it is too large Load Diff

17502
dist/languages/el.ts vendored

File diff suppressed because it is too large Load Diff

17642
dist/languages/es.ts vendored

File diff suppressed because it is too large Load Diff

12436
dist/languages/fi.ts vendored

File diff suppressed because it is too large Load Diff

17640
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load Diff

17594
dist/languages/hu.ts vendored

File diff suppressed because it is too large Load Diff

13134
dist/languages/id.ts vendored

File diff suppressed because it is too large Load Diff

17580
dist/languages/it.ts vendored

File diff suppressed because it is too large Load Diff

17536
dist/languages/ja_JP.ts vendored

File diff suppressed because it is too large Load Diff

17554
dist/languages/ko_KR.ts vendored

File diff suppressed because it is too large Load Diff

17564
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load Diff

17540
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load Diff

17550
dist/languages/pl.ts vendored

File diff suppressed because it is too large Load Diff

17644
dist/languages/pt_BR.ts vendored

File diff suppressed because it is too large Load Diff

17608
dist/languages/pt_PT.ts vendored

File diff suppressed because it is too large Load Diff

17644
dist/languages/ru_RU.ts vendored

File diff suppressed because it is too large Load Diff

17492
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load Diff

17552
dist/languages/tr_TR.ts vendored

File diff suppressed because it is too large Load Diff

17576
dist/languages/uk.ts vendored

File diff suppressed because it is too large Load Diff

17558
dist/languages/vi.ts vendored

File diff suppressed because it is too large Load Diff

17556
dist/languages/vi_VN.ts vendored

File diff suppressed because it is too large Load Diff

17546
dist/languages/zh_CN.ts vendored

File diff suppressed because it is too large Load Diff

17542
dist/languages/zh_TW.ts vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
[Desktop Entry]
Version=1.0
Type=Application
Name=yuzu
GenericName=Switch Emulator
Comment=Nintendo Switch video game console emulator
Icon=org.yuzu_emu.yuzu
TryExec=yuzu
Exec=yuzu %f
Categories=Game;Emulator;Qt;
MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
Keywords=Nintendo;Switch;
StartupWMClass=yuzu

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: 2021 yuzu Emulator Project
SPDX-License-Identifier: CC0-1.0
-->
<component type="desktop-application">
<id>org.yuzu_emu.yuzu</id>
<metadata_license>CC0-1.0</metadata_license>
<name>yuzu</name>
<summary>Nintendo Switch emulator</summary>
<description>
<p>yuzu is the world's most popular, open-source, Nintendo Switch emulator — started by the creators of Citra.</p>
<p>The emulator is capable of running most commercial games at full speed, provided you meet the necessary hardware requirements.</p>
<p>For a full list of games yuzu support, please visit our Compatibility page.</p>
<p>Check out our website for the latest news on exciting features, monthly progress reports, and more!</p>
</description>
<categories>
<category>Game</category>
<category>Emulator</category>
</categories>
<keywords>
<keyword>switch</keyword>
<keyword>emulator</keyword>
</keywords>
<url type="homepage">https://yuzu-emu.org/</url>
<url type="bugtracker">https://github.com/yuzu-emu/yuzu/issues</url>
<url type="faq">https://yuzu-emu.org/wiki/faq/</url>
<url type="help">https://yuzu-emu.org/wiki/home/</url>
<url type="donation">https://yuzu-emu.org/donate/</url>
<url type="translate">https://www.transifex.com/projects/p/yuzu</url>
<url type="contact">https://community.citra-emu.org/</url>
<url type="vcs-browser">https://github.com/yuzu-emu/yuzu</url>
<url type="contribute">https://yuzu-emu.org/wiki/contributing/</url>
<launchable type="desktop-id">org.yuzu_emu.yuzu.desktop</launchable>
<provides>
<binary>yuzu</binary>
<binary>yuzu-cmd</binary>
</provides>
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>gamepad</control>
</supports>
<requires>
<memory>8192</memory>
</requires>
<recommends>
<memory>16384</memory>
</recommends>
<project_license>GPL-3.0-or-later</project_license>
<developer_name>yuzu Emulator Team</developer_name>
<content_rating type="oars-1.0"/>
<screenshots>
<screenshot type="default"><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/001-Super%20Mario%20Odyssey%20.png</image></screenshot>
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/004-The%20Legend%20of%20Zelda%20Skyward%20Sword%20HD.png</image></screenshot>
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/007-Pokemon%20Sword.png</image></screenshot>
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/010-Hyrule%20Warriors%20Age%20of%20Calamity.png</image></screenshot>
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/039-Pok%C3%A9mon%20Mystery%20Dungeon%20Rescue%20Team%20DX.png.png.png</image></screenshot>
</screenshots>
</component>

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-nx-nro">
<comment>Nintendo Switch homebrew executable</comment>
<acronym>NRO</acronym>
<icon name="org.yuzu_emu.yuzu"/>
<glob pattern="*.nro"/>
<magic><match value="NRO" type="string" offset="16"/></magic>
</mime-type>
<mime-type type="application/x-nx-nso">
<comment>Nintendo Switch homebrew executable</comment>
<acronym>NSO</acronym>
<icon name="org.yuzu_emu.yuzu"/>
<glob pattern="*.nso"/>
<magic><match value="NSO" type="string" offset="0"/></magic>
</mime-type>
<mime-type type="application/x-nx-nsp">
<comment>Nintendo Switch Package</comment>
<acronym>NSP</acronym>
<icon name="org.yuzu_emu.yuzu"/>
<glob pattern="*.nsp"/>
<magic><match value="PFS" type="string" offset="0"/></magic>
</mime-type>
<mime-type type="application/x-nx-xci">
<comment>Nintendo Switch Card Image</comment>
<acronym>XCI</acronym>
<icon name="org.yuzu_emu.yuzu"/>
<glob pattern="*.xci"/>
</mime-type>
</mime-info>

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2019 yuzu Emulator Project
SPDX-FileCopyrightText: 2019 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2019 yuzu Emulator Project
SPDX-FileCopyrightText: 2019 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
SPDX-FileCopyrightText: 2020 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-FileCopyrightText: 2018 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->
@ -18,7 +18,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
<file alias="256x256/sudachi.png">icons/256x256/sudachi.png</file>
</qresource>
<qresource prefix="default">
<file>style.qss</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2022 yuzu Emulator Project
SPDX-FileCopyrightText: 2022 sudachi Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->
<RCC>

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018 yuzu Emulator Project
* SPDX-FileCopyrightText: 2018 sudachi Emulator Project
* SPDX-License-Identifier: GPL-2.0-or-later
*/
QAbstractSpinBox {

BIN
dist/yuzu.bmp vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

12
dist/yuzu.desktop vendored
View File

@ -1,12 +0,0 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=yuzu
GenericName=Switch Emulator
Comment=Nintendo Switch video game console emulator
Icon=yuzu
TryExec=yuzu
Exec=yuzu %f
Categories=Game;Emulator;Qt;
MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
Keywords=Switch;Nintendo;

BIN
dist/yuzu.icns vendored

Binary file not shown.

BIN
dist/yuzu.ico vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

58
dist/yuzu.manifest vendored
View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->
<assembly manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<!-- Windows 7/8/8.1/10 -->
<dpiAware
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
true/pm
</dpiAware>
<!-- Windows 10, version 1607 or later -->
<dpiAwareness
xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
PerMonitorV2
</dpiAwareness>
<!-- Windows 10, version 1703 or later -->
<gdiScaling
xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
true
</gdiScaling>
<ws2:longPathAware
xmlns:ws3="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
true
</ws2:longPathAware>
</asmv3:windowsSettings>
</asmv3:application>
<compatibility
xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<trustInfo
xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<!--
UAC settings:
- app should run at same integrity level as calling process
- app does not need to manipulate windows belonging to
higher-integrity-level processes
-->
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"
/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

1
dist/yuzu.svg vendored
View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612.15 680.17"><defs><style>.cls-1{fill:#c6c6c6;}.cls-2{fill:#ffdc00;}</style></defs><title>newAsset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="g823"><g id="right"><g id="g827"><g id="g833"><path id="path835" class="cls-1" d="M340.08,136V680.17c150.26,0,272.07-121.81,272.07-272.07S490.34,136,340.08,136m53.14,59.6a219.06,219.06,0,0,1,0,424.94V195.63"/></g></g></g><g id="left"><g id="g839"><g id="g845"><path id="path847" class="cls-2" d="M272.07,0C121.81,0,0,121.81,0,272.07S121.81,544.13,272.07,544.13ZM218.93,59.6V484.54A219,219,0,0,1,117.26,117.26,217.44,217.44,0,0,1,218.93,59.6"/></g></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 717 B

View File

@ -63,11 +63,11 @@ if (ENABLE_LIBUSB AND NOT TARGET libusb::usb)
endif()
# SDL2
if (YUZU_USE_EXTERNAL_SDL2)
if (SUDACHI_USE_EXTERNAL_SDL2)
if (NOT WIN32)
# Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers
# Sudachi itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers
# Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095)
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
# Sudachi-cmd also needs: Video (depends on Loadso/Dlopen)
# CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809)
set(SDL_UNUSED_SUBSYSTEMS
File Filesystem
@ -142,7 +142,7 @@ if (NOT TARGET Opus::opus)
endif()
# FFMpeg
if (YUZU_USE_BUNDLED_FFMPEG)
if (SUDACHI_USE_BUNDLED_FFMPEG)
add_subdirectory(ffmpeg)
set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
@ -151,12 +151,12 @@ if (YUZU_USE_BUNDLED_FFMPEG)
endif()
# Vulkan-Headers
if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
if (SUDACHI_USE_EXTERNAL_VULKAN_HEADERS)
add_subdirectory(Vulkan-Headers)
endif()
# Vulkan-Utility-Libraries
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
if (SUDACHI_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
add_subdirectory(Vulkan-Utility-Libraries)
endif()
@ -210,7 +210,7 @@ endif()
# Breakpad
# https://github.com/microsoft/vcpkg/blob/master/ports/breakpad/CMakeLists.txt
if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
if (SUDACHI_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
set(BREAKPAD_WIN32_DEFINES
NOMINMAX
UNICODE

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2018 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# This file provides the function windows_copy_files.

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2021 yuzu Emulator Project
# SPDX-FileCopyrightText: 2021 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
if (NOT WIN32 AND NOT ANDROID)
@ -143,7 +143,7 @@ if (NOT WIN32 AND NOT ANDROID)
)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `configure` parameters builds only exactly what sudachi needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
set(FFmpeg_CC ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER})
set(FFmpeg_CXX ${CMAKE_CXX_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER})
@ -222,7 +222,7 @@ if (NOT WIN32 AND NOT ANDROID)
message(FATAL_ERROR "FFmpeg not found")
endif()
elseif(ANDROID)
# Use yuzu FFmpeg binaries
# Use sudachi FFmpeg binaries
if (ARCHITECTURE_arm64)
set(FFmpeg_EXT_NAME "ffmpeg-android-v5.1.LTS-aarch64")
elseif (ARCHITECTURE_x86_64)
@ -253,7 +253,7 @@ elseif(ANDROID)
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
elseif(WIN32)
# Use yuzu FFmpeg binaries
# Use sudachi FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-6.0")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(FindPackageHandleStandardArgs)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
project(gamemode LANGUAGES CXX C)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
# SPDX-FileCopyrightText: 2020 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020 yuzu Emulator Project
* SPDX-FileCopyrightText: 2020 sudachi Emulator Project
* SPDX-License-Identifier: GPL-2.0-or-later
*/

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
set(NX_TZDB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include")
@ -32,7 +32,7 @@ set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
if ((NOT CAN_BUILD_NX_TZDB OR SUDACHI_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
@ -48,7 +48,7 @@ if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_
${NX_TZDB_ARCHIVE}
DESTINATION
${NX_TZDB_ROMFS_DIR})
elseif (CAN_BUILD_NX_TZDB AND NOT YUZU_DOWNLOAD_TIME_ZONE_DATA)
elseif (CAN_BUILD_NX_TZDB AND NOT SUDACHI_DOWNLOAD_TIME_ZONE_DATA)
add_subdirectory(tzdb_to_nx)
add_dependencies(nx_tzdb x80e)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# CMake does not have a way to list the files in a specific directory,

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
set(ZONE_PATH ${CMAKE_ARGV3})

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2023 sudachi Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2023 sudachi Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2023 sudachi Emulator Project
// SPDX-FileCopyrightText: 1996 Arthur David Olson
// SPDX-License-Identifier: BSD-2-Clause

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2023 sudachi Emulator Project
// SPDX-FileCopyrightText: 1996 Arthur David Olson
// SPDX-License-Identifier: BSD-2-Clause

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
# SPDX-FileCopyrightText: 2018 sudachi Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Enable modules to include each other's files
@ -88,7 +88,7 @@ if (MSVC)
/wd4702 # unreachable code (when used with LTO)
)
if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS)
if (USE_CCACHE OR SUDACHI_USE_PRECOMPILED_HEADERS)
# when caching, we need to use /Z7 to downgrade debug info to use an older but more cacheable format
# Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21
add_compile_options(/Z7)
@ -193,20 +193,20 @@ add_subdirectory(input_common)
add_subdirectory(frontend_common)
add_subdirectory(shader_recompiler)
if (YUZU_ROOM)
if (SUDACHI_ROOM)
add_subdirectory(dedicated_room)
endif()
if (YUZU_TESTS)
if (SUDACHI_TESTS)
add_subdirectory(tests)
endif()
if (ENABLE_SDL2)
add_subdirectory(yuzu_cmd)
add_subdirectory(sudachi_cmd)
endif()
if (ENABLE_QT)
add_subdirectory(yuzu)
add_subdirectory(sudachi)
endif()
if (ENABLE_WEB_SERVICE)
@ -215,5 +215,5 @@ endif()
if (ANDROID)
add_subdirectory(android/app/src/main/jni)
target_include_directories(yuzu-android PRIVATE android/app/src/main)
target_include_directories(sudachi-android PRIVATE android/app/src/main)
endif()

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Built application files

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 2023 sudachi Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
import android.annotation.SuppressLint
@ -24,7 +24,7 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn
@Suppress("UnstableApiUsage")
android {
namespace = "org.yuzu.yuzu_emu"
namespace = "org.sudachi.sudachi_emu"
compileSdk = 34
ndkVersion = "26.2.11394342"
@ -53,7 +53,7 @@ android {
defaultConfig {
// TODO If this is ever modified, change application_id in strings.xml
applicationId = "org.yuzu.yuzu_emu"
applicationId = "org.sudachi.sudachi_emu"
minSdk = 30
targetSdk = 34
versionName = getGitVersion()
@ -102,7 +102,7 @@ android {
signingConfigs.getByName("default")
}
resValue("string", "app_name_suffixed", "yuzu")
resValue("string", "app_name_suffixed", "sudachi")
isMinifyEnabled = true
isDebuggable = false
proguardFiles(
@ -115,7 +115,7 @@ android {
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
register("relWithDebInfo") {
isDefault = true
resValue("string", "app_name_suffixed", "yuzu Debug Release")
resValue("string", "app_name_suffixed", "sudachi Debug Release")
signingConfig = signingConfigs.getByName("default")
isMinifyEnabled = true
isDebuggable = true
@ -132,7 +132,7 @@ android {
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
debug {
signingConfig = signingConfigs.getByName("default")
resValue("string", "app_name_suffixed", "yuzu Debug")
resValue("string", "app_name_suffixed", "sudachi Debug")
isDebuggable = true
isJniDebuggable = true
versionNameSuffix = "-debug"
@ -172,9 +172,9 @@ android {
"-DENABLE_WEB_SERVICE=0", // Don't use telemetry
"-DBUNDLE_SPEEX=ON",
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
"-DYUZU_USE_BUNDLED_VCPKG=ON",
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
"-DYUZU_ENABLE_LTO=ON",
"-DSUDACHI_USE_BUNDLED_VCPKG=ON",
"-DSUDACHI_USE_BUNDLED_FFMPEG=ON",
"-DSUDACHI_ENABLE_LTO=ON",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2023 sudachi Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# To get usable stack traces

View File

@ -1,22 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="500"
android:viewportHeight="500">
<path
android:fillColor="#C6C6C6"
android:fillType="nonZero"
android:pathData="M262.66,175.11L262.66,375.05C318.54,375.05 363.85,330.29 363.85,275.08C363.85,219.87 318.54,175.11 262.66,175.11M282.43,197.01C318.67,206 344.09,238.19 344.09,275.11C344.09,312.03 318.67,344.22 282.43,353.2L282.43,197.01"
android:strokeWidth="1.46"
android:strokeColor="#00000000"
android:strokeLineCap="butt"
android:strokeLineJoin="miter" />
<path
android:fillColor="#FFDC00"
android:fillType="nonZero"
android:pathData="M237.31,125.11C181.43,125.11 136.12,169.87 136.12,225.08C136.12,280.29 181.43,325.05 237.31,325.05ZM217.57,147.01L217.57,303.2C189.11,296.16 166.67,274.54 158.84,246.6C151.01,218.65 159,188.71 179.75,168.21C190.16,157.86 203.24,150.53 217.57,147.01"
android:strokeWidth="1.46"
android:strokeColor="#00000000"
android:strokeLineCap="butt"
android:strokeLineJoin="miter" />
</vector>

View File

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="155.3dp"
android:height="172.55dp"
android:viewportWidth="155.3"
android:viewportHeight="172.55">
<path
android:fillColor="#C6C6C6"
android:pathData="M86.28,34.51v138a69,69 0,0 0,0 -138M99.76,49.63a55.57,55.57 0,0 1,0 107.8V49.63" />
<path
android:fillColor="#FFDC00"
android:pathData="M69,0a69,69 0,0 0,0 138ZM55.54,15.12v107.8A55.55,55.55 0,0 1,29.75 29.75,55.1 55.1,0 0,1 55.54,15.12" />
</vector>

View File

@ -1,24 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="340.97dp"
android:height="389.85dp"
android:viewportWidth="340.97"
android:viewportHeight="389.85">
<path
android:fillColor="?attr/colorOnSurface"
android:pathData="M341,268.68v73c0,14.5 -2.24,25.24 -6.83,32.82 -5.92,10.15 -16.21,15.32 -30.54,15.32S279,384.61 273,374.27c-4.56,-7.64 -6.8,-18.42 -6.8,-32.92V268.68a4.52,4.52 0,0 1,4.51 -4.51H273a4.5,4.5 0,0 1,4.5 4.51v72.5c0,33.53 14.88,37.4 26.07,37.4 12.14,0 26.08,-4.17 26.08,-36.71V268.68a4.52,4.52 0,0 1,4.52 -4.51h2.27A4.5,4.5 0,0 1,341 268.68Z" />
<path
android:fillColor="?attr/colorOnSurface"
android:pathData="M246.49,389.85H178.6c-2.35,0 -4.72,-1.88 -4.72,-6.08a8.28,8.28 0,0 1,1.33 -4.48l60.33,-104.47H186a4.51,4.51 0,0 1,-4.51 -4.51v-1.58a4.51,4.51 0,0 1,4.48 -4.51h0.8c58.69,-0.11 59.12,0 59.67,0.07a5.19,5.19 0,0 1,4 5.8,8.69 8.69,0 0,1 -1.33,3.76l-60.6,104.77h58a4.51,4.51 0,0 1,4.51 4.51v2.21A4.51,4.51 0,0 1,246.49 389.85Z" />
<path
android:fillColor="?attr/colorOnSurface"
android:pathData="M73.6,268.68v82.06c0,26 -11.8,38.44 -37.12,39.09h-0.12a4.51,4.51 0,0 1,-4.51 -4.51V383a4.51,4.51 0,0 1,4.48 -4.5c18.49,-0.15 26,-8.23 26,-27.9v-2.37A32.34,32.34 0,0 1,59 351.46c-6.39,5.5 -14.5,8.29 -24.07,8.29C12.09,359.75 0,347.34 0,323.86V268.68a4.52,4.52 0,0 1,4.51 -4.51H6.73a4.52,4.52 0,0 1,4.5 4.51v55c0,7.6 1.82,14.22 5,18.18 3.57,4.56 9.17,6.49 18.75,6.49 10.13,0 17.32,-3.76 22,-11.5 3.61,-5.92 5.43,-13.66 5.43,-23V268.68a4.52,4.52 0,0 1,4.51 -4.51h2.22A4.52,4.52 0,0 1,73.6 268.68Z" />
<path
android:fillColor="?attr/colorOnSurface"
android:pathData="M163.27,268.68v73c0,14.5 -2.24,25.24 -6.84,32.82 -5.92,10.15 -16.2,15.32 -30.53,15.32s-24.62,-5.23 -30.58,-15.57c-4.56,-7.64 -6.79,-18.42 -6.79,-32.92V268.68A4.51,4.51 0,0 1,93 264.17h2.28a4.51,4.51 0,0 1,4.51 4.51v72.5c0,33.53 14.88,37.4 26.07,37.4 12.14,0 26.08,-4.17 26.08,-36.71V268.68a4.51,4.51 0,0 1,4.51 -4.51h2.27A4.51,4.51 0,0 1,163.27 268.68Z" />
<path
android:fillColor="#C6C6C6"
android:pathData="M181.2,42.83V214.17a85.67,85.67 0,0 0,0 -171.34M197.93,61.6a69,69 0,0 1,0 133.8V61.6" />
<path
android:fillColor="#FFDC00"
android:pathData="M159.78,0a85.67,85.67 0,1 0,0 171.33ZM143.05,18.77v133.8A69,69 0,0 1,111 36.92a68.47,68.47 0,0 1,32 -18.15" />
</vector>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2023 yuzu Emulator Project
SPDX-FileCopyrightText: 2023 sudachi Emulator Project
SPDX-License-Identifier: GPL-3.0-or-later
-->
@ -17,7 +17,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name="org.yuzu.yuzu_emu.YuzuApplication"
android:name="org.sudachi.sudachi_emu.SudachiApplication"
android:label="@string/app_name_suffixed"
android:icon="@drawable/ic_launcher"
android:allowBackup="true"
@ -34,9 +34,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:resource="@xml/game_mode_config" />
<activity
android:name="org.yuzu.yuzu_emu.ui.main.MainActivity"
android:name="org.sudachi.sudachi_emu.ui.main.MainActivity"
android:exported="true"
android:theme="@style/Theme.Yuzu.Splash.Main">
android:theme="@style/Theme.Sudachi.Splash.Main">
<!-- This intentfilter marks this Activity as the one that gets launched from Home screen. -->
<intent-filter>
@ -48,13 +48,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
</activity>
<activity
android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity"
android:theme="@style/Theme.Yuzu.Main"
android:name="org.sudachi.sudachi_emu.features.settings.ui.SettingsActivity"
android:theme="@style/Theme.Sudachi.Main"
android:label="@string/preferences_settings"/>
<activity
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
android:theme="@style/Theme.Yuzu.Main"
android:name="org.sudachi.sudachi_emu.activities.EmulationActivity"
android:theme="@style/Theme.Sudachi.Main"
android:launchMode="singleTop"
android:supportsPictureInPicture="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"

View File

@ -1,462 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu
import android.content.DialogInterface
import android.net.Uri
import android.text.Html
import android.text.method.LinkMovementMethod
import android.view.Surface
import android.view.View
import android.widget.TextView
import androidx.annotation.Keep
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.lang.ref.WeakReference
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.fragments.CoreErrorDialogFragment
import org.yuzu.yuzu_emu.utils.DocumentsTree
import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.Log
import org.yuzu.yuzu_emu.model.InstallResult
import org.yuzu.yuzu_emu.model.Patch
import org.yuzu.yuzu_emu.model.GameVerificationResult
/**
* Class which contains methods that interact
* with the native side of the Yuzu code.
*/
object NativeLibrary {
@JvmField
var sEmulationActivity = WeakReference<EmulationActivity?>(null)
init {
try {
System.loadLibrary("yuzu-android")
} catch (ex: UnsatisfiedLinkError) {
error("[NativeLibrary] $ex")
}
}
@Keep
@JvmStatic
fun openContentUri(path: String?, openmode: String?): Int {
return if (DocumentsTree.isNativePath(path!!)) {
YuzuApplication.documentsTree!!.openContentUri(path, openmode)
} else {
FileUtil.openContentUri(path, openmode)
}
}
@Keep
@JvmStatic
fun getSize(path: String?): Long {
return if (DocumentsTree.isNativePath(path!!)) {
YuzuApplication.documentsTree!!.getFileSize(path)
} else {
FileUtil.getFileSize(path)
}
}
@Keep
@JvmStatic
fun exists(path: String?): Boolean {
return if (DocumentsTree.isNativePath(path!!)) {
YuzuApplication.documentsTree!!.exists(path)
} else {
FileUtil.exists(path, suppressLog = true)
}
}
@Keep
@JvmStatic
fun isDirectory(path: String?): Boolean {
return if (DocumentsTree.isNativePath(path!!)) {
YuzuApplication.documentsTree!!.isDirectory(path)
} else {
FileUtil.isDirectory(path)
}
}
@Keep
@JvmStatic
fun getParentDirectory(path: String): String =
if (DocumentsTree.isNativePath(path)) {
YuzuApplication.documentsTree!!.getParentDirectory(path)
} else {
path
}
@Keep
@JvmStatic
fun getFilename(path: String): String =
if (DocumentsTree.isNativePath(path)) {
YuzuApplication.documentsTree!!.getFilename(path)
} else {
FileUtil.getFilename(Uri.parse(path))
}
external fun setAppDirectory(directory: String)
/**
* Installs a nsp or xci file to nand
* @param filename String representation of file uri
* @return int representation of [InstallResult]
*/
external fun installFileToNand(
filename: String,
callback: (max: Long, progress: Long) -> Boolean
): Int
external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean
external fun initializeGpuDriver(
hookLibDir: String?,
customDriverDir: String?,
customDriverName: String?,
fileRedirectDir: String?
)
external fun reloadKeys(): Boolean
external fun initializeSystem(reload: Boolean)
/**
* Begins emulation.
*/
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
// Surface Handling
external fun surfaceChanged(surf: Surface?)
external fun surfaceDestroyed()
/**
* Unpauses emulation from a paused state.
*/
external fun unpauseEmulation()
/**
* Pauses emulation.
*/
external fun pauseEmulation()
/**
* Stops emulation.
*/
external fun stopEmulation()
/**
* Returns true if emulation is running (or is paused).
*/
external fun isRunning(): Boolean
/**
* Returns true if emulation is paused.
*/
external fun isPaused(): Boolean
/**
* Returns the performance stats for the current game
*/
external fun getPerfStats(): DoubleArray
/**
* Returns the current CPU backend.
*/
external fun getCpuBackend(): String
/**
* Returns the current GPU Driver.
*/
external fun getGpuDriver(): String
external fun applySettings()
external fun logSettings()
enum class CoreError {
ErrorSystemFiles,
ErrorSavestate,
ErrorUnknown
}
var coreErrorAlertResult = false
val coreErrorAlertLock = Object()
private fun onCoreErrorImpl(title: String, message: String) {
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present")
return
}
val fragment = CoreErrorDialogFragment.newInstance(title, message)
fragment.show(emulationActivity.supportFragmentManager, "coreError")
}
/**
* Handles a core error.
*
* @return true: continue; false: abort
*/
fun onCoreError(error: CoreError?, details: String): Boolean {
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
Log.error("[NativeLibrary] EmulationActivity not present")
return false
}
val title: String
val message: String
when (error) {
CoreError.ErrorSystemFiles -> {
title = emulationActivity.getString(R.string.system_archive_not_found)
message = emulationActivity.getString(
R.string.system_archive_not_found_message,
details.ifEmpty { emulationActivity.getString(R.string.system_archive_general) }
)
}
CoreError.ErrorSavestate -> {
title = emulationActivity.getString(R.string.save_load_error)
message = details
}
CoreError.ErrorUnknown -> {
title = emulationActivity.getString(R.string.fatal_error)
message = emulationActivity.getString(R.string.fatal_error_message)
}
else -> {
return true
}
}
// Show the AlertDialog on the main thread.
emulationActivity.runOnUiThread { onCoreErrorImpl(title, message) }
// Wait for the lock to notify that it is complete.
synchronized(coreErrorAlertLock) { coreErrorAlertLock.wait() }
return coreErrorAlertResult
}
@Keep
@JvmStatic
fun exitEmulationActivity(resultCode: Int) {
val Success = 0
val ErrorNotInitialized = 1
val ErrorGetLoader = 2
val ErrorSystemFiles = 3
val ErrorSharedFont = 4
val ErrorVideoCore = 5
val ErrorUnknown = 6
val ErrorLoader = 7
val captionId: Int
var descriptionId: Int
when (resultCode) {
ErrorVideoCore -> {
captionId = R.string.loader_error_video_core
descriptionId = R.string.loader_error_video_core_description
}
else -> {
captionId = R.string.loader_error_encrypted
descriptionId = R.string.loader_error_encrypted_roms_description
if (!reloadKeys()) {
descriptionId = R.string.loader_error_encrypted_keys_description
}
}
}
val emulationActivity = sEmulationActivity.get()
if (emulationActivity == null) {
Log.warning("[NativeLibrary] EmulationActivity is null, can't exit.")
return
}
val builder = MaterialAlertDialogBuilder(emulationActivity)
.setTitle(captionId)
.setMessage(
Html.fromHtml(
emulationActivity.getString(descriptionId),
Html.FROM_HTML_MODE_LEGACY
)
)
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
emulationActivity.finish()
}
.setOnDismissListener { emulationActivity.finish() }
emulationActivity.runOnUiThread {
val alert = builder.create()
alert.show()
(alert.findViewById<View>(android.R.id.message) as TextView).movementMethod =
LinkMovementMethod.getInstance()
}
}
fun setEmulationActivity(emulationActivity: EmulationActivity?) {
Log.debug("[NativeLibrary] Registering EmulationActivity.")
sEmulationActivity = WeakReference(emulationActivity)
}
fun clearEmulationActivity() {
Log.debug("[NativeLibrary] Unregistering EmulationActivity.")
sEmulationActivity.clear()
}
@Keep
@JvmStatic
fun onEmulationStarted() {
sEmulationActivity.get()!!.onEmulationStarted()
}
@Keep
@JvmStatic
fun onEmulationStopped(status: Int) {
sEmulationActivity.get()!!.onEmulationStopped(status)
}
@Keep
@JvmStatic
fun onProgramChanged(programIndex: Int) {
sEmulationActivity.get()!!.onProgramChanged(programIndex)
}
/**
* Logs the Yuzu version, Android version and, CPU.
*/
external fun logDeviceInfo()
/**
* Submits inline keyboard text. Called on input for buttons that result text.
* @param text Text to submit to the inline software keyboard implementation.
*/
external fun submitInlineKeyboardText(text: String?)
/**
* Submits inline keyboard input. Used to indicate keys pressed that are not text.
* @param key_code Android Key Code associated with the keyboard input.
*/
external fun submitInlineKeyboardInput(key_code: Int)
/**
* Creates a generic user directory if it doesn't exist already
*/
external fun initializeEmptyUserDirectory()
/**
* Gets the launch path for a given applet. It is the caller's responsibility to also
* set the system's current applet ID before trying to launch the nca given by this function.
*
* @param id The applet entry ID
* @return The applet's launch path
*/
external fun getAppletLaunchPath(id: Long): String
/**
* Sets the system's current applet ID before launching.
*
* @param appletId One of the ids in the Service::AM::Applets::AppletId enum
*/
external fun setCurrentAppletId(appletId: Int)
/**
* Sets the cabinet mode for launching the cabinet applet.
*
* @param cabinetMode One of the modes that corresponds to the enum in Service::NFP::CabinetMode
*/
external fun setCabinetMode(cabinetMode: Int)
/**
* Checks whether NAND contents are available and valid.
*
* @return 'true' if firmware is available
*/
external fun isFirmwareAvailable(): Boolean
/**
* Checks the PatchManager for any addons that are available
*
* @param path Path to game file. Can be a [Uri].
* @param programId String representation of a game's program ID
* @return Array of available patches
*/
external fun getPatchesForFile(path: String, programId: String): Array<Patch>?
/**
* Removes an update for a given [programId]
* @param programId String representation of a game's program ID
*/
external fun removeUpdate(programId: String)
/**
* Removes all DLC for a [programId]
* @param programId String representation of a game's program ID
*/
external fun removeDLC(programId: String)
/**
* Removes a mod installed for a given [programId]
* @param programId String representation of a game's program ID
* @param name The name of a mod as given by [getPatchesForFile]. This corresponds with the name
* of the mod's directory in a game's load folder.
*/
external fun removeMod(programId: String, name: String)
/**
* Verifies all installed content
* @param callback UI callback for verification progress. Return true in the callback to cancel.
* @return Array of content that failed verification. Successful if empty.
*/
external fun verifyInstalledContents(
callback: (max: Long, progress: Long) -> Boolean
): Array<String>
/**
* Verifies the contents of a game
* @param path String path to a game
* @param callback UI callback for verification progress. Return true in the callback to cancel.
* @return Int that is meant to be converted to a [GameVerificationResult]
*/
external fun verifyGameContents(
path: String,
callback: (max: Long, progress: Long) -> Boolean
): Int
/**
* Gets the save location for a specific game
*
* @param programId String representation of a game's program ID
* @return Save data path that may not exist yet
*/
external fun getSavePath(programId: String): String
/**
* Gets the root save directory for the default profile as either
* /user/save/account/<user id raw string> or /user/save/000...000/<user id>
*
* @param future If true, returns the /user/save/account/... directory
* @return Save data path that may not exist yet
*/
external fun getDefaultProfileSaveDataRoot(future: Boolean): String
/**
* Adds a file to the manual filesystem provider in our EmulationSession instance
* @param path Path to the file we're adding. Can be a string representation of a [Uri] or
* a normal path
*/
external fun addFileToFilesystemProvider(path: String)
/**
* Clears all files added to the manual filesystem provider in our EmulationSession instance
*/
external fun clearFilesystemProvider()
/**
* Checks if all necessary keys are present for decryption
*/
external fun areKeysPresent(): Boolean
}

View File

@ -1,55 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import org.yuzu.yuzu_emu.features.input.NativeInput
import java.io.File
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.DocumentsTree
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.Log
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
class YuzuApplication : Application() {
private fun createNotificationChannels() {
val noticeChannel = NotificationChannel(
getString(R.string.notice_notification_channel_id),
getString(R.string.notice_notification_channel_name),
NotificationManager.IMPORTANCE_HIGH
)
noticeChannel.description = getString(R.string.notice_notification_channel_description)
noticeChannel.setSound(null, null)
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(noticeChannel)
}
override fun onCreate() {
super.onCreate()
application = this
documentsTree = DocumentsTree()
DirectoryInitialization.start()
GpuDriverHelper.initializeDriverParameters()
NativeInput.reloadInputDevices()
NativeLibrary.logDeviceInfo()
Log.logDeviceInfo()
createNotificationChannels()
}
companion object {
var documentsTree: DocumentsTree? = null
lateinit var application: YuzuApplication
val appContext: Context
get() = application.applicationContext
}
}

View File

@ -1,509 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.activities
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.PictureInPictureParams
import android.app.RemoteAction
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.drawable.Icon
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Build
import android.os.Bundle
import android.util.Rational
import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.Surface
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.fragment.NavHostFragment
import androidx.preference.PreferenceManager
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.model.EmulationViewModel
import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.Log
import org.yuzu.yuzu_emu.utils.MemoryUtil
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.NfcReader
import org.yuzu.yuzu_emu.utils.ParamPackage
import org.yuzu.yuzu_emu.utils.ThemeHelper
import java.text.NumberFormat
import kotlin.math.roundToInt
class EmulationActivity : AppCompatActivity(), SensorEventListener {
private lateinit var binding: ActivityEmulationBinding
var isActivityRecreated = false
private lateinit var nfcReader: NfcReader
private val gyro = FloatArray(3)
private val accel = FloatArray(3)
private var motionTimestamp: Long = 0
private var flipMotionOrientation: Boolean = false
private val actionPause = "ACTION_EMULATOR_PAUSE"
private val actionPlay = "ACTION_EMULATOR_PLAY"
private val actionMute = "ACTION_EMULATOR_MUTE"
private val actionUnmute = "ACTION_EMULATOR_UNMUTE"
private val emulationViewModel: EmulationViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
Log.gameLaunched = true
ThemeHelper.setTheme(this)
super.onCreate(savedInstanceState)
InputHandler.updateControllerData()
val players = NativeConfig.getInputSettings(true)
var hasConfiguredControllers = false
players.forEach {
if (it.hasMapping()) {
hasConfiguredControllers = true
}
}
if (!hasConfiguredControllers && InputHandler.androidControllers.isNotEmpty()) {
var params: ParamPackage? = null
for (controller in InputHandler.registeredControllers) {
if (controller.get("port", -1) == 0) {
params = controller
break
}
}
if (params != null) {
NativeInput.updateMappingsWithDefault(
0,
params,
params.get("display", getString(R.string.unknown))
)
NativeConfig.saveGlobalConfig()
}
}
binding = ActivityEmulationBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras)
isActivityRecreated = savedInstanceState != null
// Set these options now so that the SurfaceView the game renders into is the right size.
enableFullscreenImmersive()
window.decorView.setBackgroundColor(getColor(android.R.color.black))
nfcReader = NfcReader(this)
nfcReader.initialize()
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.totalMemory)) {
Toast.makeText(
this,
getString(
R.string.device_memory_inadequate,
MemoryUtil.getDeviceRAM(),
getString(
R.string.memory_formatted,
NumberFormat.getInstance().format(MemoryUtil.REQUIRED_MEMORY),
getString(R.string.memory_gigabyte)
)
),
Toast.LENGTH_LONG
).show()
preferences.edit()
.putBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, true)
.apply()
}
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
// Special case, we do not support multiline input, dismiss the keyboard.
val overlayView: View =
this.findViewById(R.id.surface_input_overlay)
val im =
overlayView.context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
im.hideSoftInputFromWindow(overlayView.windowToken, 0)
} else {
val textChar = event.unicodeChar
if (textChar == 0) {
// No text, button input.
NativeLibrary.submitInlineKeyboardInput(keyCode)
} else {
// Text submitted.
NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
}
}
}
return super.onKeyDown(keyCode, event)
}
override fun onResume() {
super.onResume()
nfcReader.startScanning()
startMotionSensorListener()
InputHandler.updateControllerData()
buildPictureInPictureParams()
}
override fun onPause() {
super.onPause()
nfcReader.stopScanning()
stopMotionSensorListener()
}
override fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
nfcReader.onNewIntent(intent)
InputHandler.updateControllerData()
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
) {
return super.dispatchKeyEvent(event)
}
if (emulationViewModel.drawerOpen.value) {
return super.dispatchKeyEvent(event)
}
return InputHandler.dispatchKeyEvent(event)
}
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
) {
return super.dispatchGenericMotionEvent(event)
}
if (emulationViewModel.drawerOpen.value) {
return super.dispatchGenericMotionEvent(event)
}
// Don't attempt to do anything if we are disconnecting a device.
if (event.actionMasked == MotionEvent.ACTION_CANCEL) {
return true
}
return InputHandler.dispatchGenericMotionEvent(event)
}
override fun onSensorChanged(event: SensorEvent) {
val rotation = this.display?.rotation
if (rotation == Surface.ROTATION_90) {
flipMotionOrientation = true
}
if (rotation == Surface.ROTATION_270) {
flipMotionOrientation = false
}
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
if (flipMotionOrientation) {
accel[0] = event.values[1] / SensorManager.GRAVITY_EARTH
accel[1] = -event.values[0] / SensorManager.GRAVITY_EARTH
} else {
accel[0] = -event.values[1] / SensorManager.GRAVITY_EARTH
accel[1] = event.values[0] / SensorManager.GRAVITY_EARTH
}
accel[2] = -event.values[2] / SensorManager.GRAVITY_EARTH
}
if (event.sensor.type == Sensor.TYPE_GYROSCOPE) {
// Investigate why sensor value is off by 6x
if (flipMotionOrientation) {
gyro[0] = -event.values[1] / 6.0f
gyro[1] = event.values[0] / 6.0f
} else {
gyro[0] = event.values[1] / 6.0f
gyro[1] = -event.values[0] / 6.0f
}
gyro[2] = event.values[2] / 6.0f
}
// Only update state on accelerometer data
if (event.sensor.type != Sensor.TYPE_ACCELEROMETER) {
return
}
val deltaTimestamp = (event.timestamp - motionTimestamp) / 1000
motionTimestamp = event.timestamp
NativeInput.onDeviceMotionEvent(
NativeInput.Player1Device,
deltaTimestamp,
gyro[0],
gyro[1],
gyro[2],
accel[0],
accel[1],
accel[2]
)
NativeInput.onDeviceMotionEvent(
NativeInput.ConsoleDevice,
deltaTimestamp,
gyro[0],
gyro[1],
gyro[2],
accel[0],
accel[1],
accel[2]
)
}
override fun onAccuracyChanged(sensor: Sensor, i: Int) {}
private fun enableFullscreenImmersive() {
WindowCompat.setDecorFitsSystemWindows(window, false)
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
private fun PictureInPictureParams.Builder.getPictureInPictureAspectBuilder():
PictureInPictureParams.Builder {
val aspectRatio = when (IntSetting.RENDERER_ASPECT_RATIO.getInt()) {
0 -> Rational(16, 9)
1 -> Rational(4, 3)
2 -> Rational(21, 9)
3 -> Rational(16, 10)
else -> null // Best fit
}
return this.apply { aspectRatio?.let { setAspectRatio(it) } }
}
private fun PictureInPictureParams.Builder.getPictureInPictureActionsBuilder():
PictureInPictureParams.Builder {
val pictureInPictureActions: MutableList<RemoteAction> = mutableListOf()
val pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
if (NativeLibrary.isPaused()) {
val playIcon = Icon.createWithResource(this@EmulationActivity, R.drawable.ic_pip_play)
val playPendingIntent = PendingIntent.getBroadcast(
this@EmulationActivity,
R.drawable.ic_pip_play,
Intent(actionPlay),
pendingFlags
)
val playRemoteAction = RemoteAction(
playIcon,
getString(R.string.play),
getString(R.string.play),
playPendingIntent
)
pictureInPictureActions.add(playRemoteAction)
} else {
val pauseIcon = Icon.createWithResource(this@EmulationActivity, R.drawable.ic_pip_pause)
val pausePendingIntent = PendingIntent.getBroadcast(
this@EmulationActivity,
R.drawable.ic_pip_pause,
Intent(actionPause),
pendingFlags
)
val pauseRemoteAction = RemoteAction(
pauseIcon,
getString(R.string.pause),
getString(R.string.pause),
pausePendingIntent
)
pictureInPictureActions.add(pauseRemoteAction)
}
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
val unmuteIcon = Icon.createWithResource(
this@EmulationActivity,
R.drawable.ic_pip_unmute
)
val unmutePendingIntent = PendingIntent.getBroadcast(
this@EmulationActivity,
R.drawable.ic_pip_unmute,
Intent(actionUnmute),
pendingFlags
)
val unmuteRemoteAction = RemoteAction(
unmuteIcon,
getString(R.string.unmute),
getString(R.string.unmute),
unmutePendingIntent
)
pictureInPictureActions.add(unmuteRemoteAction)
} else {
val muteIcon = Icon.createWithResource(this@EmulationActivity, R.drawable.ic_pip_mute)
val mutePendingIntent = PendingIntent.getBroadcast(
this@EmulationActivity,
R.drawable.ic_pip_mute,
Intent(actionMute),
pendingFlags
)
val muteRemoteAction = RemoteAction(
muteIcon,
getString(R.string.mute),
getString(R.string.mute),
mutePendingIntent
)
pictureInPictureActions.add(muteRemoteAction)
}
return this.apply { setActions(pictureInPictureActions) }
}
fun buildPictureInPictureParams() {
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val isEmulationActive = emulationViewModel.emulationStarted.value &&
!emulationViewModel.isEmulationStopping.value
pictureInPictureParamsBuilder.setAutoEnterEnabled(
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
)
}
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
}
private var pictureInPictureReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
if (intent.action == actionPlay) {
if (NativeLibrary.isPaused()) NativeLibrary.unpauseEmulation()
} else if (intent.action == actionPause) {
if (!NativeLibrary.isPaused()) NativeLibrary.pauseEmulation()
}
if (intent.action == actionUnmute) {
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
BooleanSetting.AUDIO_MUTED.setBoolean(false)
}
} else if (intent.action == actionMute) {
if (!BooleanSetting.AUDIO_MUTED.getBoolean()) {
BooleanSetting.AUDIO_MUTED.setBoolean(true)
}
}
buildPictureInPictureParams()
}
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
if (isInPictureInPictureMode) {
IntentFilter().apply {
addAction(actionPause)
addAction(actionPlay)
addAction(actionMute)
addAction(actionUnmute)
}.also {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(pictureInPictureReceiver, it, RECEIVER_EXPORTED)
} else {
registerReceiver(pictureInPictureReceiver, it)
}
}
} else {
try {
unregisterReceiver(pictureInPictureReceiver)
} catch (ignored: Exception) {
}
// Always resume audio, since there is no UI button
if (BooleanSetting.AUDIO_MUTED.getBoolean()) {
BooleanSetting.AUDIO_MUTED.setBoolean(false)
}
}
}
fun onEmulationStarted() {
emulationViewModel.setEmulationStarted(true)
}
fun onEmulationStopped(status: Int) {
if (status == 0 && emulationViewModel.programChanged.value == -1) {
finish()
}
emulationViewModel.setEmulationStopped(true)
}
fun onProgramChanged(programIndex: Int) {
emulationViewModel.setProgramChanged(programIndex)
}
private fun startMotionSensorListener() {
val sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
val accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_GAME)
sensorManager.registerListener(this, accelSensor, SensorManager.SENSOR_DELAY_GAME)
}
private fun stopMotionSensorListener() {
val sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
val accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.unregisterListener(this, gyroSensor)
sensorManager.unregisterListener(this, accelSensor)
}
companion object {
const val EXTRA_SELECTED_GAME = "SelectedGame"
fun launch(activity: AppCompatActivity, game: Game) {
val launcher = Intent(activity, EmulationActivity::class.java)
launcher.putExtra(EXTRA_SELECTED_GAME, game)
activity.startActivity(launcher)
}
private fun areCoordinatesOutside(view: View?, x: Float, y: Float): Boolean {
if (view == null) {
return true
}
val viewBounds = Rect()
view.getGlobalVisibleRect(viewBounds)
return !viewBounds.contains(x.roundToInt(), y.roundToInt())
}
}
}

View File

@ -1,38 +0,0 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.annotation.SuppressLint
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
import androidx.recyclerview.widget.RecyclerView
/**
* Generic adapter that implements an [AsyncDifferConfig] and covers some of the basic boilerplate
* code used in every [RecyclerView].
* Type assigned to [Model] must inherit from [Object] in order to be compared properly.
* @param exact Decides whether each item will be compared by reference or by their contents
*/
abstract class AbstractDiffAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
exact: Boolean = true
) : ListAdapter<Model, Holder>(AsyncDifferConfig.Builder(DiffCallback<Model>(exact)).build()) {
override fun onBindViewHolder(holder: Holder, position: Int) =
holder.bind(currentList[position])
private class DiffCallback<Model>(val exact: Boolean) : DiffUtil.ItemCallback<Model>() {
override fun areItemsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
if (exact) {
return oldItem === newItem
}
return oldItem == newItem
}
@SuppressLint("DiffUtilEquals")
override fun areContentsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
return oldItem == newItem
}
}
}

View File

@ -1,98 +0,0 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.annotation.SuppressLint
import androidx.recyclerview.widget.RecyclerView
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
/**
* Generic list class meant to take care of basic lists
* @param currentList The list to show initially
*/
abstract class AbstractListAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
open var currentList: List<Model>
) : RecyclerView.Adapter<Holder>() {
override fun onBindViewHolder(holder: Holder, position: Int) =
holder.bind(currentList[position])
override fun getItemCount(): Int = currentList.size
/**
* Adds an item to [currentList] and notifies the underlying adapter of the change. If no parameter
* is passed in for position, [item] is added to the end of the list. Invokes [callback] last.
* @param item The item to add to the list
* @param position Index where [item] will be added
* @param callback Lambda that's called at the end of the list changes and has the added list
* position passed in as a parameter
*/
open fun addItem(item: Model, position: Int = -1, callback: ((position: Int) -> Unit)? = null) {
val newList = currentList.toMutableList()
val positionToUpdate: Int
if (position == -1) {
newList.add(item)
currentList = newList
positionToUpdate = currentList.size - 1
} else {
newList.add(position, item)
currentList = newList
positionToUpdate = position
}
onItemAdded(positionToUpdate, callback)
}
protected fun onItemAdded(position: Int, callback: ((Int) -> Unit)? = null) {
notifyItemInserted(position)
callback?.invoke(position)
}
/**
* Replaces the [item] at [position] in the [currentList] and notifies the underlying adapter
* of the change. Invokes [callback] last.
* @param item New list item
* @param position Index where [item] will replace the existing list item
* @param callback Lambda that's called at the end of the list changes and has the changed list
* position passed in as a parameter
*/
fun changeItem(item: Model, position: Int, callback: ((position: Int) -> Unit)? = null) {
val newList = currentList.toMutableList()
newList[position] = item
currentList = newList
onItemChanged(position, callback)
}
protected fun onItemChanged(position: Int, callback: ((Int) -> Unit)? = null) {
notifyItemChanged(position)
callback?.invoke(position)
}
/**
* Removes the list item at [position] in [currentList] and notifies the underlying adapter
* of the change. Invokes [callback] last.
* @param position Index where the list item will be removed
* @param callback Lambda that's called at the end of the list changes and has the removed list
* position passed in as a parameter
*/
fun removeItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
val newList = currentList.toMutableList()
newList.removeAt(position)
currentList = newList
onItemRemoved(position, callback)
}
protected fun onItemRemoved(position: Int, callback: ((Int) -> Unit)? = null) {
notifyItemRemoved(position)
callback?.invoke(position)
}
/**
* Replaces [currentList] with [newList] and notifies the underlying adapter of the change.
* @param newList The new list to replace [currentList]
*/
@SuppressLint("NotifyDataSetChanged")
open fun replaceList(newList: List<Model>) {
currentList = newList
notifyDataSetChanged()
}
}

View File

@ -1,105 +0,0 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import org.yuzu.yuzu_emu.model.SelectableItem
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
/**
* Generic list class meant to take care of single selection UI updates
* @param currentList The list to show initially
* @param defaultSelection The default selection to use if no list items are selected by
* [SelectableItem.selected] or if the currently selected item is removed from the list
*/
abstract class AbstractSingleSelectionList<
Model : SelectableItem,
Holder : AbstractViewHolder<Model>
>(
final override var currentList: List<Model>,
private val defaultSelection: DefaultSelection = DefaultSelection.Start
) : AbstractListAdapter<Model, Holder>(currentList) {
var selectedItem = getDefaultSelection()
init {
findSelectedItem()
}
/**
* Changes the selection state of the [SelectableItem] that was selected and the previously selected
* item and notifies the underlying adapter of the change for those items. Invokes [callback] last.
* Does nothing if [position] is the same as the currently selected item.
* @param position Index of the item that was selected
* @param callback Lambda that's called at the end of the list changes and has the selected list
* position passed in as a parameter
*/
fun selectItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
if (position == selectedItem) {
return
}
val previouslySelectedItem = selectedItem
selectedItem = position
if (currentList.indices.contains(selectedItem)) {
currentList[selectedItem].onSelectionStateChanged(true)
}
if (currentList.indices.contains(previouslySelectedItem)) {
currentList[previouslySelectedItem].onSelectionStateChanged(false)
}
onItemChanged(previouslySelectedItem)
onItemChanged(selectedItem)
callback?.invoke(position)
}
/**
* Removes a given item from the list and notifies the underlying adapter of the change. If the
* currently selected item was the item that was removed, the item at the position provided
* by [defaultSelection] will be made the new selection. Invokes [callback] last.
* @param position Index of the item that was removed
* @param callback Lambda that's called at the end of the list changes and has the removed and
* selected list positions passed in as parameters
*/
fun removeSelectableItem(
position: Int,
callback: ((removedPosition: Int, selectedPosition: Int) -> Unit)?
) {
removeItem(position)
if (position == selectedItem) {
selectedItem = getDefaultSelection()
currentList[selectedItem].onSelectionStateChanged(true)
onItemChanged(selectedItem)
} else if (position < selectedItem) {
selectedItem--
}
callback?.invoke(position, selectedItem)
}
override fun addItem(item: Model, position: Int, callback: ((Int) -> Unit)?) {
super.addItem(item, position, callback)
if (position <= selectedItem && position != -1) {
selectedItem++
}
}
override fun replaceList(newList: List<Model>) {
super.replaceList(newList)
findSelectedItem()
}
private fun findSelectedItem() {
for (i in currentList.indices) {
if (currentList[i].selected) {
selectedItem = i
break
}
}
}
private fun getDefaultSelection(): Int =
when (defaultSelection) {
DefaultSelection.Start -> currentList.indices.first
DefaultSelection.End -> currentList.indices.last
}
enum class DefaultSelection { Start, End }
}

View File

@ -1,37 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding
import org.yuzu.yuzu_emu.model.Patch
import org.yuzu.yuzu_emu.model.AddonViewModel
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
class AddonAdapter(val addonViewModel: AddonViewModel) :
AbstractDiffAdapter<Patch, AddonAdapter.AddonViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder {
ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
.also { return AddonViewHolder(it) }
}
inner class AddonViewHolder(val binding: ListItemAddonBinding) :
AbstractViewHolder<Patch>(binding) {
override fun bind(model: Patch) {
binding.root.setOnClickListener {
binding.addonCheckbox.isChecked = !binding.addonCheckbox.isChecked
}
binding.title.text = model.name
binding.version.text = model.version
binding.addonCheckbox.setOnCheckedChangeListener { _, checked ->
model.enabled = checked
}
binding.addonCheckbox.isChecked = model.enabled
binding.buttonDelete.setOnClickListener {
addonViewModel.setAddonToDelete(model)
}
}
}
}

View File

@ -1,74 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import org.yuzu.yuzu_emu.HomeNavigationDirections
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.databinding.CardSimpleOutlinedBinding
import org.yuzu.yuzu_emu.model.Applet
import org.yuzu.yuzu_emu.model.AppletInfo
import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
class AppletAdapter(val activity: FragmentActivity, applets: List<Applet>) :
AbstractListAdapter<Applet, AppletAdapter.AppletViewHolder>(applets) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): AppletAdapter.AppletViewHolder {
CardSimpleOutlinedBinding.inflate(LayoutInflater.from(parent.context), parent, false)
.also { return AppletViewHolder(it) }
}
inner class AppletViewHolder(val binding: CardSimpleOutlinedBinding) :
AbstractViewHolder<Applet>(binding) {
override fun bind(model: Applet) {
binding.title.setText(model.titleId)
binding.description.setText(model.descriptionId)
binding.icon.setImageDrawable(
ResourcesCompat.getDrawable(
binding.icon.context.resources,
model.iconId,
binding.icon.context.theme
)
)
binding.root.setOnClickListener { onClick(model) }
}
fun onClick(applet: Applet) {
val appletPath = NativeLibrary.getAppletLaunchPath(applet.appletInfo.entryId)
if (appletPath.isEmpty()) {
Toast.makeText(
binding.root.context,
R.string.applets_error_applet,
Toast.LENGTH_SHORT
).show()
return
}
if (applet.appletInfo == AppletInfo.Cabinet) {
binding.root.findNavController()
.navigate(R.id.action_appletLauncherFragment_to_cabinetLauncherDialogFragment)
return
}
NativeLibrary.setCurrentAppletId(applet.appletInfo.appletId)
val appletGame = Game(
title = YuzuApplication.appContext.getString(applet.titleId),
path = appletPath
)
val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame)
binding.root.findNavController().navigate(action)
}
}
}

View File

@ -1,59 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import org.yuzu.yuzu_emu.HomeNavigationDirections
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.databinding.DialogListItemBinding
import org.yuzu.yuzu_emu.model.CabinetMode
import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter.CabinetModeViewHolder
import org.yuzu.yuzu_emu.model.AppletInfo
import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
class CabinetLauncherDialogAdapter(val fragment: Fragment) :
AbstractListAdapter<CabinetMode, CabinetModeViewHolder>(
CabinetMode.values().copyOfRange(1, CabinetMode.entries.size).toList()
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CabinetModeViewHolder {
DialogListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
.also { return CabinetModeViewHolder(it) }
}
inner class CabinetModeViewHolder(val binding: DialogListItemBinding) :
AbstractViewHolder<CabinetMode>(binding) {
override fun bind(model: CabinetMode) {
binding.icon.setImageDrawable(
ResourcesCompat.getDrawable(
binding.icon.context.resources,
model.iconId,
binding.icon.context.theme
)
)
binding.title.setText(model.titleId)
binding.root.setOnClickListener { onClick(model) }
}
private fun onClick(mode: CabinetMode) {
val appletPath = NativeLibrary.getAppletLaunchPath(AppletInfo.Cabinet.entryId)
NativeLibrary.setCurrentAppletId(AppletInfo.Cabinet.appletId)
NativeLibrary.setCabinetMode(mode.id)
val appletGame = Game(
title = YuzuApplication.appContext.getString(R.string.cabinet_applet),
path = appletPath
)
val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame)
fragment.findNavController().navigate(action)
}
}
}

View File

@ -1,59 +0,0 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.model.Driver
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.utils.ViewUtils.marquee
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
class DriverAdapter(private val driverViewModel: DriverViewModel) :
AbstractSingleSelectionList<Driver, DriverAdapter.DriverViewHolder>(
driverViewModel.driverList.value
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DriverViewHolder {
CardDriverOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false)
.also { return DriverViewHolder(it) }
}
inner class DriverViewHolder(val binding: CardDriverOptionBinding) :
AbstractViewHolder<Driver>(binding) {
override fun bind(model: Driver) {
binding.apply {
radioButton.isChecked = model.selected
root.setOnClickListener {
selectItem(bindingAdapterPosition) {
driverViewModel.onDriverSelected(it)
driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global)
}
}
buttonDelete.setOnClickListener {
removeSelectableItem(
bindingAdapterPosition
) { removedPosition: Int, selectedPosition: Int ->
driverViewModel.onDriverRemoved(removedPosition, selectedPosition)
driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global)
}
}
// Delay marquee by 3s
title.marquee()
version.marquee()
description.marquee()
title.text = model.title
version.text = model.version
description.text = model.description
buttonDelete.setVisible(
model.title != binding.root.context.getString(R.string.system_gpu_driver)
)
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More