Rebranded to Sudachi (RIP Yoozoo) and updated some more dependencies
This commit is contained in:
parent
169fe4fabc
commit
3fd22b8781
158
CMakeLists.txt
158
CMakeLists.txt
|
@ -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()
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,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 "$@"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2018 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<context>
|
||||
<name>GMainWindow < /name>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/main.cpp" line="2322"/>
|
||||
<location filename="../../src/sudachi/main.cpp" line = "2322" />
|
||||
<source>% n file(s) remaining < /source>
|
||||
< translation >
|
||||
<numerusform>% n file remaining < /numerusform>
|
||||
|
@ -12,7 +12,7 @@
|
|||
< /translation>
|
||||
< /message>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/main.cpp" line="2377"/>
|
||||
<location filename="../../src/sudachi/main.cpp" line = "2377" />
|
||||
<source>% n file(s) were newly installed
|
||||
< /source>
|
||||
< translation >
|
||||
|
@ -23,7 +23,7 @@
|
|||
< /translation>
|
||||
< /message>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/main.cpp" line="2380"/>
|
||||
<location filename="../../src/sudachi/main.cpp" line = "2380" />
|
||||
<source>% n file(s) were overwritten
|
||||
< /source>
|
||||
< translation >
|
||||
|
@ -34,7 +34,7 @@
|
|||
< /translation>
|
||||
< /message>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/main.cpp" line="2382"/>
|
||||
<location filename="../../src/sudachi/main.cpp" line = "2382" />
|
||||
<source>% n file(s) failed to install
|
||||
< /source>
|
||||
< translation >
|
||||
|
@ -45,7 +45,7 @@
|
|||
< /translation>
|
||||
< /message>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/main.cpp" line="3264"/>
|
||||
<location filename="../../src/sudachi/main.cpp" line = "3264" />
|
||||
<source>Building: % n shader(s) < /source>
|
||||
< translation >
|
||||
<numerusform>Building: % n shader < /numerusform>
|
||||
|
@ -56,7 +56,7 @@
|
|||
< context >
|
||||
<name>GameListSearchField < /name>
|
||||
< message numerus = "yes" >
|
||||
<location filename="../../src/yuzu/game_list.cpp" line="87"/>
|
||||
<location filename="../../src/sudachi/game_list.cpp" line = "87" />
|
||||
<source>% 1 of % n result(s) < /source>
|
||||
< translation >
|
||||
<numerusform>% 1 of % n result < /numerusform>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2020 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2021 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2021 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2019 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2019 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2019 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||
SPDX-FileCopyrightText: 2020 sudachi Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
|
|
|
@ -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 |
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 256 KiB |
|
@ -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;
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
|
@ -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 +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 |
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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} "")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 yuzu Emulator Project
|
||||
* SPDX-FileCopyrightText: 2020 sudachi Emulator Project
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue