Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe13539d72 | |||
| be218cc020 | |||
| c3cbe2d4d0 | |||
| 79b162a37c | |||
| f3fbb3812f | |||
| d8caa74233 | |||
| 17fe74ef11 | |||
| 73713737c6 | |||
| 61f3ce643c | |||
| f7f6a4cde4 | |||
| 65fa1a37e2 | |||
| 41192e6e3d | |||
| d8f2e22bf8 | |||
| 51506ef836 | |||
| 0d3cef65ad | |||
| c2794985b2 | |||
| 2e1af92852 | |||
| b9655669b3 | |||
| 6b01977005 | |||
| 91d41d1c34 | |||
| 2e4ee8d9a4 | |||
| 92274ff280 | |||
| d1ac5b2e50 | |||
| c160d6b752 | |||
| eb2d9ea574 | |||
| 4f389338bd | |||
| 227a007413 | |||
| 74d6eaf721 | |||
| 9807fa02ed | |||
| 7d239df065 | |||
| b690813196 | |||
| b9f54f4979 | |||
| 7e730a121b | |||
| 680384f7b8 | |||
| a27914f0f4 | |||
| 3f226678dd | |||
| e9d84d098d | |||
| 32db6c1877 | |||
| 8eaa7c28ce | |||
| 3edfcabdea | |||
| 450c483de0 | |||
| 66db2613b5 | |||
| 9a046190c7 | |||
| cfbef5c487 | |||
| f51d61e4a4 | |||
| ba9e03a612 | |||
| 7832afc5dd | |||
| 028765867f | |||
| d89df63a28 | |||
| 87c4f658ce | |||
| b7584cb2c3 | |||
| f32f356c40 | |||
| 7ca657d22f | |||
| 7764cdd57e | |||
| 42863027e2 |
@@ -4,7 +4,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# specify full path if dupes may exist
|
# specify full path if dupes may exist
|
||||||
EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder"
|
EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh tools/windows/vcvarsall.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder"
|
||||||
|
|
||||||
# license header constants, please change when needed :))))
|
# license header constants, please change when needed :))))
|
||||||
YEAR=2025
|
YEAR=2025
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: yuzu Discord
|
- name: Eden Discord
|
||||||
url: https://discord.com/invite/u77vRWY
|
url: https://discord.gg/HstXbPch7X
|
||||||
about: If you are experiencing an issue with yuzu, and you need tech support, or if you have a general question, try asking in the official yuzu Discord linked here. Piracy is not allowed.
|
|
||||||
- name: Community forums
|
|
||||||
url: https://community.citra-emu.org
|
|
||||||
about: This is an alternative place for tech support, however helpers there are not as active.
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
name: tx-src
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sources:
|
||||||
|
runs-on: source
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Push New Sources
|
||||||
|
run: |
|
||||||
|
export PATH=/usr/lib/qt6/bin:$PATH
|
||||||
|
./tools/translations/qt-source.sh
|
||||||
|
tx-cli push -s
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
name: Check Strings
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-strings:
|
||||||
|
runs-on: source
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Find Unused Strings
|
||||||
|
run: ./tools/find-unused-strings.sh
|
||||||
|
|
||||||
|
- name: Find Stale Translations
|
||||||
|
run: ./tools/stale-translations.sh
|
||||||
|
|
||||||
|
- name: Diff
|
||||||
|
run: git --no-pager diff --exit-code HEAD
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
name: tx-pull
|
||||||
|
|
||||||
|
on:
|
||||||
|
# monday, wednesday, saturday at 2pm
|
||||||
|
schedule:
|
||||||
|
cron:
|
||||||
|
- '0 14 * * 1,3,6'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tx-update:
|
||||||
|
runs-on: source
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Get New Translations
|
||||||
|
run: tx-cli pull -t -f
|
||||||
|
|
||||||
|
- name: Push branch
|
||||||
|
run: |
|
||||||
|
git config --local user.name "Eden CI"
|
||||||
|
git config --local user.email "ci@eden-emu.dev"
|
||||||
|
git config --local user.signingkey "D57652791BB25D2A"
|
||||||
|
git config --local push.autoSetupRemote true
|
||||||
|
|
||||||
|
git remote set-url origin ci:eden-emu/eden.git
|
||||||
|
|
||||||
|
TIMESTAMP=$(date +"%s")
|
||||||
|
echo "TIMESTAMP=$TIMESTAMP" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
git switch -c update-translations-$TIMESTAMP
|
||||||
|
git add dist src/android/app/src/main/res
|
||||||
|
|
||||||
|
git commit -sS -m "[dist, android] Update translations from Transifex"
|
||||||
|
git push
|
||||||
|
|
||||||
|
- name: Create PR
|
||||||
|
run: |
|
||||||
|
DATE=$(date +"%b %d")
|
||||||
|
TITLE="[dist, android] Update translations from Transifex for $DATE"
|
||||||
|
BODY="Automatic translation update for $DATE"
|
||||||
|
BASE=master
|
||||||
|
HEAD=update-translations-$TIMESTAMP
|
||||||
|
|
||||||
|
cat << EOF > data.json
|
||||||
|
{
|
||||||
|
"base": "$BASE",
|
||||||
|
"body": "$BODY",
|
||||||
|
"head": "$HEAD",
|
||||||
|
"title": "$TITLE"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
curl -X 'POST' \
|
||||||
|
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d "@data.json" --fail
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
# Build directory
|
# Build directory
|
||||||
/[Bb]uild*/
|
/[Bb]uild*/
|
||||||
doc-build/
|
doc-build/
|
||||||
|
out/
|
||||||
AppDir/
|
AppDir/
|
||||||
uruntime
|
uruntime
|
||||||
|
|
||||||
@@ -59,3 +60,4 @@ eden-windows-msvc
|
|||||||
artifacts
|
artifacts
|
||||||
*.AppImage*
|
*.AppImage*
|
||||||
/install*
|
/install*
|
||||||
|
vulkansdk*.exe
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
|||||||
set(PLATFORM_LINUX ON)
|
set(PLATFORM_LINUX ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# dumb heuristic to detect msys2
|
||||||
|
if (CMAKE_COMMAND MATCHES "msys64")
|
||||||
|
set(PLATFORM_MSYS ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(CXX_CLANG ON)
|
set(CXX_CLANG ON)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
@@ -85,6 +90,94 @@ if (PLATFORM_NETBSD)
|
|||||||
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig")
|
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# MSYS2 utilities
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
include(FixMsysPaths)
|
||||||
|
# really, really dumb heuristic to detect what environment we are in
|
||||||
|
macro(system var)
|
||||||
|
if (CMAKE_COMMAND MATCHES ${var})
|
||||||
|
set(MSYSTEM ${var})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
system(mingw64)
|
||||||
|
system(clang64)
|
||||||
|
system(clangarm64)
|
||||||
|
system(ucrt64)
|
||||||
|
|
||||||
|
if (NOT DEFINED MSYSTEM)
|
||||||
|
set(MSYSTEM msys2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# we (generally) want to prioritize environment-specific binaries if possible
|
||||||
|
# some, like autoconf, are not present on environments besides msys2 though
|
||||||
|
set(CMAKE_PROGRAM_PATH C:/msys64/${MSYSTEM}/bin C:/msys64/usr/bin)
|
||||||
|
set(ENV{PKG_CONFIG_PATH} C:/msys64/${MSYSTEM}/lib/pkgconfig)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# static stuff
|
||||||
|
option(YUZU_STATIC_BUILD "Use static libraries and executables if available" OFF)
|
||||||
|
|
||||||
|
if (YUZU_STATIC_BUILD)
|
||||||
|
include(StaticQtLibs)
|
||||||
|
|
||||||
|
# lol
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
|
||||||
|
## find .a libs first (static, usually)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||||
|
|
||||||
|
## some libraries define a Library::Name_static alternative ##
|
||||||
|
set(YUZU_STATIC_SUFFIX _static)
|
||||||
|
|
||||||
|
## some libraries use CMAKE_IMPORT_LIBRARY_SUFFIX e.g. Harfbuzz ##
|
||||||
|
set(CMAKE_IMPORT_LIBRARY_SUFFIX ".a")
|
||||||
|
|
||||||
|
if (MINGW)
|
||||||
|
# simple hook to reject dynamic libs
|
||||||
|
function(find_library var)
|
||||||
|
# also skip previously-found libraries cuz... yaknow
|
||||||
|
# UNLESS they are dll.a :{
|
||||||
|
if (${var} AND NOT ${var} MATCHES "dll\\.a$")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_find_library(${var} ${ARGN})
|
||||||
|
if (${var})
|
||||||
|
get_filename_component(lib_name "${${var}}" NAME)
|
||||||
|
if (lib_name MATCHES "dll\\.a$")
|
||||||
|
unset(${var} CACHE)
|
||||||
|
set(${var} "${var}-NOTFOUND" CACHE INTERNAL "" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# msys2 quazip does not build a static lib
|
||||||
|
set(QuaZip-Qt6_FORCE_BUNDLED ON)
|
||||||
|
|
||||||
|
set(YUZU_USE_BUNDLED_FFMPEG ON)
|
||||||
|
set(YUZU_USE_BUNDLED_SDL2 ON)
|
||||||
|
set(YUZU_USE_BUNDLED_OPENSSL ON)
|
||||||
|
|
||||||
|
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
|
||||||
|
elseif(APPLE)
|
||||||
|
# these libs do not properly provide static libs/let you do it with cmake
|
||||||
|
set(YUZU_USE_CPM ON)
|
||||||
|
|
||||||
|
set(YUZU_USE_BUNDLED_FFMPEG ON)
|
||||||
|
set(YUZU_USE_BUNDLED_SDL2 ON)
|
||||||
|
set(YUZU_USE_BUNDLED_OPENSSL ON)
|
||||||
|
|
||||||
|
# IMPORTED_IMPLIB not set for imported target
|
||||||
|
# TODO(crueter): wtf
|
||||||
|
set(fmt_FORCE_BUNDLED ON)
|
||||||
|
set(SPIRV-Tools_FORCE_BUNDLED ON)
|
||||||
|
set(SPIRV-Headers_FORCE_BUNDLED ON)
|
||||||
|
set(zstd_FORCE_BUNDLED ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Detect current compilation architecture and create standard definitions
|
# Detect current compilation architecture and create standard definitions
|
||||||
# =======================================================================
|
# =======================================================================
|
||||||
|
|
||||||
@@ -219,11 +312,9 @@ endif()
|
|||||||
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
||||||
cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF)
|
cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF)
|
||||||
|
|
||||||
if (ENABLE_SDL2)
|
# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system
|
||||||
# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system
|
cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Build SDL2 from external source" OFF "ENABLE_SDL2;NOT MSVC" OFF)
|
||||||
cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF)
|
cmake_dependent_option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}" "ENABLE_SDL2" OFF)
|
||||||
option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# qt stuff
|
# qt stuff
|
||||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||||
@@ -244,10 +335,14 @@ option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if n
|
|||||||
|
|
||||||
# ffmpeg
|
# ffmpeg
|
||||||
option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT})
|
option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT})
|
||||||
cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF)
|
cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from external source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF)
|
||||||
|
|
||||||
# sirit
|
# sirit
|
||||||
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${EXT_DEFAULT})
|
set(BUNDLED_SIRIT_DEFAULT OFF)
|
||||||
|
if ((MSVC AND NOT (CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo") OR ANDROID))
|
||||||
|
set(BUNDLED_SIRIT_DEFAULT ON)
|
||||||
|
endif()
|
||||||
|
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${BUNDLED_SIRIT_DEFAULT})
|
||||||
|
|
||||||
# Re-allow on FreeBSD once its on mainline ports
|
# Re-allow on FreeBSD once its on mainline ports
|
||||||
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR APPLE" OFF)
|
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR APPLE" OFF)
|
||||||
@@ -284,6 +379,17 @@ if(USE_CCACHE)
|
|||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}")
|
message(FATAL_ERROR "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
# Follow SCCache recommendations:
|
||||||
|
# <https://github.com/mozilla/sccache/blob/main/README.md?plain=1#L144>
|
||||||
|
if(WIN32)
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||||
|
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# TODO(crueter): CI this?
|
# TODO(crueter): CI this?
|
||||||
@@ -318,7 +424,7 @@ if (ANDROID OR WIN32 OR APPLE OR PLATFORM_SUN)
|
|||||||
set(DEFAULT_ENABLE_OPENSSL OFF)
|
set(DEFAULT_ENABLE_OPENSSL OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_WEB_SERVICE)
|
if (ENABLE_WEB_SERVICE OR USE_DISCORD_PRESENCE)
|
||||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
set(DEFAULT_ENABLE_OPENSSL ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -355,13 +461,6 @@ if (ANDROID)
|
|||||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe
|
set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# We need to downgrade debug info (/Zi -> /Z7) to use an older but more cacheable format
|
|
||||||
# See https://github.com/nanoant/CMakePCHCompiler/issues/21
|
|
||||||
if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
|
||||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
|
||||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Default to a Release build
|
# Default to a Release build
|
||||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
|
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
|
||||||
@@ -582,6 +681,7 @@ else()
|
|||||||
find_package(stb MODULE)
|
find_package(stb MODULE)
|
||||||
|
|
||||||
find_package(Opus 1.3 MODULE REQUIRED)
|
find_package(Opus 1.3 MODULE REQUIRED)
|
||||||
|
|
||||||
find_package(ZLIB 1.2 REQUIRED)
|
find_package(ZLIB 1.2 REQUIRED)
|
||||||
find_package(zstd 1.5 REQUIRED MODULE)
|
find_package(zstd 1.5 REQUIRED MODULE)
|
||||||
|
|
||||||
@@ -634,15 +734,15 @@ if (APPLE)
|
|||||||
# Umbrella framework for everything GUI-related
|
# Umbrella framework for everything GUI-related
|
||||||
find_library(COCOA_LIBRARY Cocoa)
|
find_library(COCOA_LIBRARY Cocoa)
|
||||||
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
|
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
|
||||||
find_library(ICONV_LIBRARY iconv REQUIRED)
|
# find_library(ICONV_LIBRARY iconv REQUIRED)
|
||||||
list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY})
|
# list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY})
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
# Target Windows 10
|
# Target Windows 10
|
||||||
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
||||||
set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi)
|
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} winmm iphlpapi ws2_32 wlanapi)
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
# PSAPI is the Process Status API
|
# PSAPI is the Process Status API
|
||||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
|
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
|
||||||
endif()
|
endif()
|
||||||
elseif (PLATFORM_HAIKU)
|
elseif (PLATFORM_HAIKU)
|
||||||
# Haiku is so special :)
|
# Haiku is so special :)
|
||||||
@@ -655,6 +755,8 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
|||||||
set(PLATFORM_LIBRARIES rt)
|
set(PLATFORM_LIBRARIES rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Platform Libraries: ${PLATFORM_LIBRARIES}")
|
||||||
|
|
||||||
add_subdirectory(externals)
|
add_subdirectory(externals)
|
||||||
|
|
||||||
# pass targets from externals
|
# pass targets from externals
|
||||||
|
|||||||
@@ -542,10 +542,11 @@ function(AddCIPackage)
|
|||||||
PACKAGE
|
PACKAGE
|
||||||
EXTENSION
|
EXTENSION
|
||||||
MIN_VERSION
|
MIN_VERSION
|
||||||
DISABLED_PLATFORMS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "" ${ARGN})
|
set(multiValueArgs DISABLED_PLATFORMS)
|
||||||
|
|
||||||
|
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
if(NOT DEFINED PKG_ARGS_VERSION)
|
if(NOT DEFINED PKG_ARGS_VERSION)
|
||||||
message(FATAL_ERROR "[CPMUtil] VERSION is required")
|
message(FATAL_ERROR "[CPMUtil] VERSION is required")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,6 +13,10 @@ find_package_handle_standard_args(Opus
|
|||||||
VERSION_VAR OPUS_VERSION
|
VERSION_VAR OPUS_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
FixMsysPath(PkgConfig::OPUS)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (Opus_FOUND AND NOT TARGET Opus::opus)
|
if (Opus_FOUND AND NOT TARGET Opus::opus)
|
||||||
add_library(Opus::opus ALIAS PkgConfig::OPUS)
|
add_library(Opus::opus ALIAS PkgConfig::OPUS)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,6 +13,10 @@ find_package_handle_standard_args(SPIRV-Tools
|
|||||||
VERSION_VAR SPIRV-Tools_VERSION
|
VERSION_VAR SPIRV-Tools_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
FixMsysPath(PkgConfig::SPIRV-Tools)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (SPIRV-Tools_FOUND AND NOT TARGET SPIRV-Tools::SPIRV-Tools)
|
if (SPIRV-Tools_FOUND AND NOT TARGET SPIRV-Tools::SPIRV-Tools)
|
||||||
if (TARGET SPIRV-Tools)
|
if (TARGET SPIRV-Tools)
|
||||||
add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools)
|
add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools)
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
@@ -11,6 +14,10 @@ find_package_handle_standard_args(enet
|
|||||||
VERSION_VAR ENET_VERSION
|
VERSION_VAR ENET_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
FixMsysPath(PkgConfig::ENET)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (enet_FOUND AND NOT TARGET enet::enet)
|
if (enet_FOUND AND NOT TARGET enet::enet)
|
||||||
add_library(enet::enet ALIAS PkgConfig::ENET)
|
add_library(enet::enet ALIAS PkgConfig::ENET)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
@@ -11,6 +14,10 @@ find_package_handle_standard_args(libusb
|
|||||||
VERSION_VAR LIBUSB_VERSION
|
VERSION_VAR LIBUSB_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
FixMsysPath(PkgConfig::LIBUSB)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
||||||
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -9,6 +12,11 @@ if (lz4_CONSIDERED_CONFIGS)
|
|||||||
else()
|
else()
|
||||||
find_package(PkgConfig QUIET)
|
find_package(PkgConfig QUIET)
|
||||||
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
||||||
|
|
||||||
|
if (PLATFORM_MSYS)
|
||||||
|
FixMsysPath(PkgConfig::LZ4)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package_handle_standard_args(lz4
|
find_package_handle_standard_args(lz4
|
||||||
REQUIRED_VARS LZ4_LINK_LIBRARIES
|
REQUIRED_VARS LZ4_LINK_LIBRARIES
|
||||||
VERSION_VAR LZ4_VERSION
|
VERSION_VAR LZ4_VERSION
|
||||||
|
|||||||
@@ -6,22 +6,34 @@
|
|||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
find_package(zstd QUIET CONFIG)
|
||||||
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
|
if (zstd_CONSIDERED_CONFIGS)
|
||||||
find_package_handle_standard_args(zstd
|
find_package_handle_standard_args(zstd CONFIG_MODE)
|
||||||
REQUIRED_VARS ZSTD_LINK_LIBRARIES
|
else()
|
||||||
VERSION_VAR ZSTD_VERSION
|
find_package(PkgConfig QUIET)
|
||||||
)
|
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
|
||||||
|
find_package_handle_standard_args(zstd
|
||||||
|
REQUIRED_VARS ZSTD_LINK_LIBRARIES
|
||||||
|
VERSION_VAR ZSTD_VERSION
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (zstd_FOUND AND NOT TARGET zstd::zstd)
|
if (zstd_FOUND AND NOT TARGET zstd::zstd)
|
||||||
if (TARGET zstd::libzstd_shared)
|
if (TARGET zstd::libzstd_shared AND NOT YUZU_STATIC_BUILD)
|
||||||
add_library(zstd::zstd ALIAS zstd::libzstd_shared)
|
add_library(zstd::zstd ALIAS zstd::libzstd_shared)
|
||||||
add_library(zstd::libzstd ALIAS zstd::libzstd_shared)
|
|
||||||
elseif (TARGET zstd::libzstd_static)
|
elseif (TARGET zstd::libzstd_static)
|
||||||
add_library(zstd::zstd ALIAS zstd::libzstd_static)
|
add_library(zstd::zstd ALIAS zstd::libzstd_static)
|
||||||
add_library(zstd::libzstd ALIAS zstd::libzstd_static)
|
|
||||||
else()
|
else()
|
||||||
add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
|
add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
|
||||||
add_library(zstd::libzstd ALIAS PkgConfig::ZSTD)
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_target_property(ZSTD_TARGET zstd::zstd ALIASED_TARGET)
|
||||||
|
|
||||||
|
if (NOT TARGET zstd::libzstd)
|
||||||
|
if (ZSTD_TARGET)
|
||||||
|
add_library(zstd::libzstd ALIAS ${ZSTD_TARGET})
|
||||||
|
else()
|
||||||
|
add_library(zstd::libzstd ALIAS zstd::zstd)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
function(FixMsysPath target)
|
||||||
|
get_target_property(include_dir ${target} INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
|
|
||||||
|
if (NOT (include_dir MATCHES "^/"))
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(root_default $ENV{MSYS2_LOCATION})
|
||||||
|
if (root_default STREQUAL "")
|
||||||
|
set(root_default "C:/msys64")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(MSYS_ROOT_PATH ${root_default} CACHE STRING "Location of the MSYS2 root")
|
||||||
|
|
||||||
|
set(include_dir "C:/msys64${include_dir}")
|
||||||
|
set_target_properties(${target} PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${include_dir})
|
||||||
|
endfunction()
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
|
|
||||||
set(CMAKE_SYSTEM_NAME Windows)
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
|
||||||
|
|
||||||
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
|
|
||||||
set(SDL2_PATH ${MINGW_PREFIX})
|
|
||||||
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
|
|
||||||
|
|
||||||
# Specify the cross compiler
|
|
||||||
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}clang)
|
|
||||||
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}clang++)
|
|
||||||
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
|
|
||||||
set(CMAKE_C_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
|
|
||||||
set(CMAKE_CXX_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
|
|
||||||
set(CMAKE_C_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
|
|
||||||
set(CMAKE_CXX_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
|
|
||||||
|
|
||||||
# Mingw tools
|
|
||||||
set(STRIP ${MINGW_TOOL_PREFIX}strip)
|
|
||||||
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
|
|
||||||
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
|
|
||||||
|
|
||||||
# ccache wrapper
|
|
||||||
option(USE_CCACHE "Use ccache for compilation" OFF)
|
|
||||||
if(USE_CCACHE)
|
|
||||||
find_program(CCACHE ccache)
|
|
||||||
if(CCACHE)
|
|
||||||
message(STATUS "Using ccache found in PATH")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
|
|
||||||
else(CCACHE)
|
|
||||||
message(WARNING "USE_CCACHE enabled, but no ccache found")
|
|
||||||
endif(CCACHE)
|
|
||||||
endif(USE_CCACHE)
|
|
||||||
|
|
||||||
# Search for programs in the build host directories
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
|
||||||
|
|
||||||
|
|
||||||
# Echo modified cmake vars to screen for debugging purposes
|
|
||||||
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
|
|
||||||
message("")
|
|
||||||
message("Custom cmake vars: (blank = system default)")
|
|
||||||
message("-----------------------------------------")
|
|
||||||
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
|
|
||||||
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
|
|
||||||
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
|
|
||||||
message("* WINDRES : ${WINDRES}")
|
|
||||||
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
|
|
||||||
message("* STRIP : ${STRIP}")
|
|
||||||
message("* USE_CCACHE : ${USE_CCACHE}")
|
|
||||||
message("")
|
|
||||||
# So that the debug info only appears once
|
|
||||||
set(ENV{MINGW_DEBUG_INFO} SHOWN)
|
|
||||||
endif()
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2018 tech4me <guiwanglong@gmail.com>
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
|
|
||||||
set(CMAKE_SYSTEM_NAME Windows)
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
|
||||||
# Actually a hack, w/o this will cause some strange errors
|
|
||||||
set(CMAKE_HOST_WIN32 TRUE)
|
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
|
|
||||||
set(SDL2_PATH ${MINGW_PREFIX})
|
|
||||||
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
|
|
||||||
|
|
||||||
# Specify the cross compiler
|
|
||||||
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
|
|
||||||
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
|
|
||||||
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
|
|
||||||
|
|
||||||
# Mingw tools
|
|
||||||
set(STRIP ${MINGW_TOOL_PREFIX}strip)
|
|
||||||
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
|
|
||||||
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
|
|
||||||
|
|
||||||
# ccache wrapper
|
|
||||||
option(USE_CCACHE "Use ccache for compilation" OFF)
|
|
||||||
if(USE_CCACHE)
|
|
||||||
find_program(CCACHE ccache)
|
|
||||||
if(CCACHE)
|
|
||||||
message(STATUS "Using ccache found in PATH")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
|
|
||||||
else(CCACHE)
|
|
||||||
message(WARNING "USE_CCACHE enabled, but no ccache found")
|
|
||||||
endif(CCACHE)
|
|
||||||
endif(USE_CCACHE)
|
|
||||||
|
|
||||||
# Search for programs in the build host directories
|
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
|
||||||
|
|
||||||
|
|
||||||
# Echo modified cmake vars to screen for debugging purposes
|
|
||||||
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
|
|
||||||
message("")
|
|
||||||
message("Custom cmake vars: (blank = system default)")
|
|
||||||
message("-----------------------------------------")
|
|
||||||
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
|
|
||||||
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
|
|
||||||
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
|
|
||||||
message("* WINDRES : ${WINDRES}")
|
|
||||||
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
|
|
||||||
message("* STRIP : ${STRIP}")
|
|
||||||
message("* USE_CCACHE : ${USE_CCACHE}")
|
|
||||||
message("")
|
|
||||||
# So that the debug info only appears once
|
|
||||||
set(ENV{MINGW_DEBUG_INFO} SHOWN)
|
|
||||||
endif()
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
## When linking to a static Qt build on MinGW, certain additional libraries
|
||||||
|
## must be statically linked to as well.
|
||||||
|
|
||||||
|
function(static_qt_link target)
|
||||||
|
macro(extra_libs)
|
||||||
|
foreach(lib ${ARGN})
|
||||||
|
find_library(${lib}_LIBRARY ${lib} REQUIRED)
|
||||||
|
target_link_libraries(${target} PRIVATE ${${lib}_LIBRARY})
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# I am constantly impressed at how ridiculously stupid the linker is
|
||||||
|
# NB: yes, we have to put them here twice. I have no idea why
|
||||||
|
|
||||||
|
# libtiff.a
|
||||||
|
extra_libs(tiff jbig bz2 lzma deflate jpeg tiff)
|
||||||
|
|
||||||
|
# libfreetype.a
|
||||||
|
extra_libs(freetype bz2 Lerc brotlidec brotlicommon freetype)
|
||||||
|
|
||||||
|
# libharfbuzz.a
|
||||||
|
extra_libs(harfbuzz graphite2)
|
||||||
|
|
||||||
|
# sijfjkfnjkdfjsbjsbsdfhvbdf
|
||||||
|
if (ENABLE_OPENSSL)
|
||||||
|
target_link_libraries(${target} PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<!--
|
# Contributing
|
||||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
-->
|
|
||||||
|
|
||||||
**The Contributor's Guide has moved to [the yuzu wiki](https://github.com/yuzu-emu/yuzu/wiki/Contributing).**
|
You want to contribute? Please consult [the development guide](./docs/Development.md).
|
||||||
|
|
||||||
|
Don't forget to [get a git account](./docs/SIGNUP.md) - not a requirement per se but it's highly recommended.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/kXAmGCXBGD">
|
<a href="https://discord.gg/HstXbPch7X">
|
||||||
<img src="https://img.shields.io/discord/1367654015269339267?color=5865F2&label=Eden&logo=discord&logoColor=white"
|
<img src="https://img.shields.io/discord/1367654015269339267?color=5865F2&label=Eden&logo=discord&logoColor=white"
|
||||||
alt="Discord">
|
alt="Discord">
|
||||||
</a>
|
</a>
|
||||||
@@ -52,8 +52,8 @@ Check out our [website](https://eden-emu.dev) for the latest news on exciting fe
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/kXAmGCXBGD) or [Revolt](https://rvlt.gg/qKgFEAbH).
|
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Revolt](https://rvlt.gg/qKgFEAbH).
|
||||||
You can also follow us on [X (Twitter)](https://x.com/edenemuofficial) for updates and announcements.
|
You can also follow us on [X (Twitter)](https://nitter.poast.org/edenemuofficial) for updates and announcements.
|
||||||
|
|
||||||
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Revolt to learn more about the current state of the emulator.
|
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Revolt to learn more about the current state of the emulator.
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ Any donations received will go towards things such as:
|
|||||||
* Additional hardware (e.g. GPUs as needed to improve rendering support, other peripherals to add support for, etc.)
|
* Additional hardware (e.g. GPUs as needed to improve rendering support, other peripherals to add support for, etc.)
|
||||||
* CI Infrastructure
|
* CI Infrastructure
|
||||||
|
|
||||||
If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/edenemu) and talk to Camille or any of our other developers.
|
If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/HstXbPch7X) and talk to Camille or any of our other developers.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
"package": "OpenSSL",
|
"package": "OpenSSL",
|
||||||
"name": "openssl",
|
"name": "openssl",
|
||||||
"repo": "crueter-ci/OpenSSL",
|
"repo": "crueter-ci/OpenSSL",
|
||||||
"version": "3.6.0",
|
"version": "3.6.0-e3608d80df",
|
||||||
"min_version": "1.1.1",
|
"min_version": "1.1.1"
|
||||||
"disabled_platforms": [
|
|
||||||
"macos-universal",
|
|
||||||
"mingw-amd64",
|
|
||||||
"mingw-arm64"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"boost": {
|
"boost": {
|
||||||
"package": "Boost",
|
"package": "Boost",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 315 KiB After Width: | Height: | Size: 516 KiB |
@@ -0,0 +1,9 @@
|
|||||||
|
# Icon variations
|
||||||
|
|
||||||
|
These icons are licensed under GPLv3. Please see the [script for generating icons](../../tools/README.md) and appropriatedly redirect for seasonal icons.
|
||||||
|
|
||||||
|
- `base_named.svg` - Named variant.
|
||||||
|
- `base_small.svg`: Variant used for tiny icons (16x16, 64x64, etc).
|
||||||
|
- `base.svg`: Variant without branding/naming.
|
||||||
|
|
||||||
|
Try to keep the icons simple. And preferably automatically be able to be generated (to reduce maintanaince burden). Additionally keep the files small (use `svgo` and `optipng`) to not clutter the git.
|
||||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg7"
|
||||||
|
sodipodi:docname="base_small.svg"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs7">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient10"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#f977d9;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop10" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a655d5;stop-opacity:1;"
|
||||||
|
offset="0.54051435"
|
||||||
|
id="stop13" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#984fd5;stop-opacity:1;"
|
||||||
|
offset="0.5714342"
|
||||||
|
id="stop12" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8c4ad4;stop-opacity:1;"
|
||||||
|
offset="0.59666741"
|
||||||
|
id="stop14" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#3928d2;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop11" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient10"
|
||||||
|
id="linearGradient11"
|
||||||
|
x1="264.17508"
|
||||||
|
y1="28.385544"
|
||||||
|
x2="264.17508"
|
||||||
|
y2="488.65109"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.97815818,0,0,0.97880258,4.570042,5.8799159)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="0.88388348"
|
||||||
|
inkscape:cx="153.30075"
|
||||||
|
inkscape:cy="243.24473"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="849"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg7"
|
||||||
|
showguides="false" />
|
||||||
|
<path
|
||||||
|
id="path9"
|
||||||
|
style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:13.3314;stroke-opacity:1;paint-order:stroke fill markers"
|
||||||
|
d="M 262.97461 33.6875 A 218.44267 225.23091 0 0 0 138.83789 73.589844 L 141.13867 72.265625 L 161.2207 65.195312 L 181.01953 61.517578 L 204.35352 64.205078 L 228.96094 76.650391 L 265.80078 115 L 283 99.400391 L 304.59961 85.800781 L 331 76.400391 L 360.59961 69.599609 L 379.95508 69.208984 A 218.44267 225.23091 0 0 0 262.97461 33.6875 z M 380.07617 69.291016 L 350.19922 77.800781 L 329.19922 89.199219 L 307.40039 108 L 288.80078 129.80078 L 287.40039 135 L 302.40039 129.59961 L 319 127.80078 L 348.80078 131.80078 L 370.19922 141.40039 L 393 161.40039 L 399.59961 171.59961 L 374.80078 160.80078 L 338.40039 150.80078 L 309.19922 150 L 288.80078 154.40039 L 293.19922 155.19922 L 319.19922 168.80078 L 338 187.19922 L 350.80078 224 L 349.19922 260 L 326 222.80078 L 302.80078 194 L 277.59961 172.40039 L 269.19922 187.59961 L 256.80078 281.59961 L 258 364 L 278.40039 452.80078 L 297.19531 481.36914 A 218.44267 225.23091 0 0 0 481.41797 258.91797 A 218.44267 225.23091 0 0 0 380.07617 69.291016 z M 133.07422 77.839844 A 218.44267 225.23091 0 0 0 44.533203 258.91797 A 218.44267 225.23091 0 0 0 257.04102 484.06641 L 247.3457 458.62891 L 237.87109 418.18359 L 233.0625 380.42383 L 230.375 354.9668 L 229.95117 321.30859 L 232.35547 291.32812 L 237.44727 254.98242 L 254.55859 191.9082 L 261.62891 172.5332 L 255.54883 174.08984 L 240.98242 180.87695 L 229.59961 190.19922 L 210.59961 208.19922 L 197.40039 229.40039 L 186.40039 252.59961 L 173.40039 269 L 171.40039 253.19922 L 173.59961 229.40039 L 183 202.40039 L 199.40039 178 L 221.04102 153.44141 L 209.02148 155.70508 L 177.05859 162.77539 L 148.06836 171.40234 L 119.92578 183 L 120.63281 180.16992 L 129.82422 165.88672 L 151.17969 147.50195 L 172.95898 135.48242 L 190.07031 129.54102 L 209.02148 127.98633 L 227.6875 128.69336 L 247.76953 128.41016 L 246.49805 125.1582 L 226.69922 105.92383 L 219.62695 97.439453 L 221.4668 90.085938 L 206.75781 94.044922 L 195.86914 95.458984 L 179.46289 88.671875 L 156.12891 81.458984 L 133.07422 77.839844 z " />
|
||||||
|
<path
|
||||||
|
style="fill:#1b1b1b;fill-opacity:0.12492698;stroke:none;stroke-width:13.374;stroke-opacity:0.415999;paint-order:stroke fill markers"
|
||||||
|
d="m 259.36665,490.16617 39.03323,-6.96642 -20,-30.4 -20.4,-88.8 -1.2,-82.4 12.4,-94 8.4,-15.2 25.2,21.6 23.2,28.8 23.2,37.2 1.6,-36 -12.8,-36.8 -18.8,-18.4 -26,-13.6 -4.4,-0.8 20.4,-4.4 29.2,0.8 36.4,10 24.8,10.8 -6.6,-10.2 -22.8,-20 -21.4,-9.6 -29.8,-4 -16.6,1.8 -15,5.4 1.4,-5.2 18.6,-21.8 21.8,-18.800003 21,-11.4 30.2,-8.6 -19.8,0.4 -29.6,6.8 -26.4,9.4 -21.6,13.6 -17.2,15.600003 -36.83882,-38.349628 -24.60732,-12.445079 -23.33452,-2.687006 -19.79899,3.676955 -20.08184,7.071068 -9.33381,5.374012 24.32448,3.818376 23.33452,7.212489 16.40488,6.788226 10.88944,-1.414214 14.70782,-3.959798 -1.83847,7.353911 7.07106,8.485288 19.79899,19.2333 1.2728,3.25269 -20.08184,0.28284 -18.66762,-0.7071 -18.95046,1.55563 -17.11198,5.9397 -21.77889,12.02081 -21.35462,18.38478 -9.19239,14.28356 -0.70711,2.82843 28.14285,-11.59656 28.99138,-8.6267 31.96122,-7.07107 12.02082,-2.26274 -21.64158,24.55783 -16.4,24.4 -9.4,27 -2.2,23.8 2,15.8 13,-16.4 11,-23.2 13.2,-21.2 19,-18 11.38199,-9.32209 14.5664,-6.78822 6.08112,-1.55564 -7.07107,19.37473 -17.11198,63.07393 -5.09117,36.34528 -2.40416,29.98133 0.42426,33.65828 2.68701,25.45585 4.80832,37.7595 9.47523,40.44651 z"
|
||||||
|
id="path8-4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
@@ -26,7 +26,7 @@ Android has a completely different build process than other platforms. See its [
|
|||||||
|
|
||||||
If the configure phase fails, see the `Troubleshooting` section below. Usually, as long as you followed the dependencies guide, the defaults *should* successfully configure and build.
|
If the configure phase fails, see the `Troubleshooting` section below. Usually, as long as you followed the dependencies guide, the defaults *should* successfully configure and build.
|
||||||
|
|
||||||
### Qt Creator
|
### Option A: Qt Creator
|
||||||
|
|
||||||
This is the recommended GUI method for Linux, macOS, and Windows.
|
This is the recommended GUI method for Linux, macOS, and Windows.
|
||||||
|
|
||||||
@@ -46,39 +46,51 @@ Hit "Configure Project", then wait for CMake to finish configuring (may take a w
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Command Line
|
### Option B: Command Line
|
||||||
|
|
||||||
This is recommended for *BSD, Solaris, Linux, and MSYS2. MSVC is possible, but not recommended.
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click to Open</summary>
|
<summary>Click to Open</summary>
|
||||||
|
|
||||||
Note that CMake must be in your PATH, and you must be in the cloned Eden directory. On Windows, you must also set up a Visual C++ development environment. This can be done by running `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat` in the same terminal.
|
> [!WARNING]
|
||||||
|
>For all systems:
|
||||||
Recommended generators:
|
>- *CMake* **MUST** be in your PATH (and also *ninja*, if you are using it as `<GENERATOR>`)
|
||||||
|
>- You *MUST* be in the cloned *Eden* directory
|
||||||
|
>
|
||||||
|
>On Windows:
|
||||||
|
> - It's recommended to install **[Ninja](https://ninja-build.org/)**
|
||||||
|
> - You must load **Visual C++ development environment**, this can be done by running our convenience script:
|
||||||
|
> - `tools/windows/load-msvc-env.ps1` (for PowerShell 5+)
|
||||||
|
> - `tools/windows/load-msvc-env.sh` (for MSYS2, Git Bash, etc)
|
||||||
|
|
||||||
|
Available `<GENERATOR>`:
|
||||||
- MSYS2: `MSYS Makefiles`
|
- MSYS2: `MSYS Makefiles`
|
||||||
- MSVC: Install **[ninja](https://ninja-build.org/)** and use `Ninja`, OR use `Visual Studio 17 2022`
|
- MSVC: `Ninja` (preferred) or `Visual Studio 17 2022`
|
||||||
- macOS: `Ninja` (preferred) or `Xcode`
|
- macOS: `Ninja` (preferred) or `Xcode`
|
||||||
- Others: `Ninja` (preferred) or `UNIX Makefiles`
|
- Others: `Ninja` (preferred) or `UNIX Makefiles`
|
||||||
|
|
||||||
BUILD_TYPE should usually be `Release` or `RelWithDebInfo` (debug symbols--compiled executable will be large). If you are using a debugger and annoyed with stuff getting optimized out, try `Debug`.
|
Available `<BUILD_TYPE>`:
|
||||||
|
- `Release` (default)
|
||||||
|
- `RelWithDebInfo` (debug symbols--compiled executable will be large)
|
||||||
|
- `Debug` (if you are using a debugger and annoyed with stuff getting optimized out)
|
||||||
|
|
||||||
|
Caveat for Debug Builds:
|
||||||
|
- If you're building with CCache, you will need to add the environment variable `CL` with the `/FS` flag ([Reference](https://learn.microsoft.com/pt-br/cpp/build/reference/fs-force-synchronous-pdb-writes?view=msvc-170))
|
||||||
|
|
||||||
Also see the [Options](Options.md) page for additional CMake options.
|
Also see the [Options](Options.md) page for additional CMake options.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cmake -S . -B build -G "GENERATOR" -DCMAKE_BUILD_TYPE=<BUILD_TYPE> -DYUZU_TESTS=OFF
|
cmake -S . -B build -G "<GENERATOR>" -DCMAKE_BUILD_TYPE=<BUILD_TYPE> -DYUZU_TESTS=OFF
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are on Windows and prefer to use Clang:
|
If you are on Windows and prefer to use Clang:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cmake -S . -B build -G "GENERATOR" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
cmake -S . -B build -G "<GENERATOR>" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### [CLion](https://www.jetbrains.com/clion/)
|
### Option C: [CLion](https://www.jetbrains.com/clion/)
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click to Open</summary>
|
<summary>Click to Open</summary>
|
||||||
@@ -133,13 +145,13 @@ Many platforms have quirks, bugs, and other fun stuff that may cause issues when
|
|||||||
|
|
||||||
## Building & Running
|
## Building & Running
|
||||||
|
|
||||||
### Qt Creator
|
### On Qt Creator
|
||||||
|
|
||||||
Simply hit Ctrl+B, or the "hammer" icon in the bottom left. To run, hit the "play" icon, or Ctrl+R.
|
Simply hit Ctrl+B, or the "hammer" icon in the bottom left. To run, hit the "play" icon, or Ctrl+R.
|
||||||
|
|
||||||
### Command Line
|
### On Command Line
|
||||||
|
|
||||||
If you are not on Windows and are using the `UNIX Makefiles` generator, you must also add `-j$(nproc)` to this command.
|
If you are using the `UNIX Makefiles` or `Visual Studio 17 2022` as `<GENERATOR>`, you should also add `--parallel` for faster build times.
|
||||||
|
|
||||||
```
|
```
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
|||||||
@@ -3,10 +3,13 @@
|
|||||||
To build Eden, you MUST have a C++ compiler.
|
To build Eden, you MUST have a C++ compiler.
|
||||||
* On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+
|
* On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+
|
||||||
- GCC 12 also requires Clang 14+
|
- GCC 12 also requires Clang 14+
|
||||||
* On Windows, this is either:
|
* On Windows, we support:
|
||||||
- **[MSVC](https://visualstudio.microsoft.com/downloads/)** (you should select *Community* option),
|
- **[MSVC](https://visualstudio.microsoft.com/downloads/)** (default)
|
||||||
- clang-cl - can be downloaded from the MSVC installer,
|
- It's STRONGLY RECOMMENDED to use the **Community** option and **Visual Studio 2022**
|
||||||
- or **[MSYS2](https://www.msys2.org)**
|
- You need to install: **[Desktop development with C++](https://learn.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=msvc-170)**
|
||||||
|
- **[clang-cl](https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=msvc-180)**
|
||||||
|
- You need to install: **C++ Clang tools for Windows**
|
||||||
|
- **[MSYS2](https://www.msys2.org)** (experimental)
|
||||||
* On macOS, this is Apple Clang
|
* On macOS, this is Apple Clang
|
||||||
- This can be installed with `xcode-select --install`
|
- This can be installed with `xcode-select --install`
|
||||||
|
|
||||||
@@ -15,20 +18,23 @@ The following additional tools are also required:
|
|||||||
* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK
|
* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK
|
||||||
* **[Git](https://git-scm.com/)** for version control
|
* **[Git](https://git-scm.com/)** for version control
|
||||||
- **[Windows installer](https://gitforwindows.org)**
|
- **[Windows installer](https://gitforwindows.org)**
|
||||||
|
* **[Python3](https://www.python.org/downloads/)** 3.10+ - necessary to download external repositories
|
||||||
* On Windows, you must install the **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** as well
|
* On Windows, you must install the **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** as well
|
||||||
- *A convenience script to install the latest SDK is provided in `.ci/windows/install-vulkan-sdk.ps1`*
|
- *A convenience script to install the latest SDK is provided in:*
|
||||||
|
- `tools/windows/install-vulkan-sdk.ps1` (for PowerShell 5+)
|
||||||
|
- `tools/windows/install-vulkan-sdk.sh` (for MSYS2, Git Bash, etc)
|
||||||
|
|
||||||
If you are on desktop and plan to use the Qt frontend, you *must* install Qt 6, and optionally Qt Creator (the recommended IDE for building)
|
If you are on desktop and plan to use the Qt frontend, you *must* install Qt 6, and optionally Qt Creator (the **RECOMMENDED** IDE for building)
|
||||||
* On Linux, *BSD and macOS, this can be done by the package manager
|
* On Linux, *BSD and macOS, this can be done by the package manager
|
||||||
- If you wish to use Qt Creator, append `qtcreator` or `qt-creator` to the commands seen below.
|
- If you wish to use Qt Creator, append `qtcreator` or `qt-creator` to the commands seen below.
|
||||||
* MSVC/clang-cl users on Windows must install through the [official installer](https://www.qt.io/download-qt-installer-oss)
|
* MSVC/clang-cl users on Windows must install through the official [Qt](https://www.qt.io/download-qt-installer-oss) installer
|
||||||
* Linux and macOS users may choose to use the installer as well.
|
* Linux and macOS users may choose to use the installer as well.
|
||||||
* MSYS2 can also install Qt 6 via the package manager
|
* MSYS2 can also install Qt 6 via the package manager
|
||||||
|
|
||||||
If you are on Windows, a convenience script to install MSVC, MSYS2, Qt, all necessary packages for MSYS2, and set up a zsh environment with useful keybinds and aliases can be found [here](https://git.crueter.xyz/scripts/windev).
|
If you are on Windows, a convenience script to install MSVC, MSYS2, Qt, all necessary packages for MSYS2, and set up a zsh environment with useful keybinds and aliases can be found [here](https://git.crueter.xyz/scripts/windev).
|
||||||
- For help setting up Qt Creator, run `./install.sh -h qtcreator`
|
- For help setting up Qt Creator, run `./install.sh -h qtcreator`
|
||||||
|
|
||||||
If you are on Windows and NOT building with MSYS2, you may go [back home](Build.md) and continue.
|
If you are on **Windows** and building with **MSVC** or **clang-cl**, you may go [back home](Build.md) and continue.
|
||||||
|
|
||||||
## Externals
|
## Externals
|
||||||
The following are handled by Eden's externals:
|
The following are handled by Eden's externals:
|
||||||
|
|||||||
@@ -160,13 +160,6 @@ if (YUZU_USE_BUNDLED_SIRIT)
|
|||||||
AddJsonPackage(sirit-ci)
|
AddJsonPackage(sirit-ci)
|
||||||
else()
|
else()
|
||||||
AddJsonPackage(sirit)
|
AddJsonPackage(sirit)
|
||||||
# Change to old-but-more-cacheable debug info on Windows
|
|
||||||
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
|
||||||
get_target_property(sirit_opts sirit COMPILE_OPTIONS)
|
|
||||||
list(FILTER sirit_opts EXCLUDE REGEX "/Zi")
|
|
||||||
list(APPEND sirit_opts "/Z7")
|
|
||||||
set_target_properties(sirit PROPERTIES COMPILE_OPTIONS "${sirit_opts}")
|
|
||||||
endif()
|
|
||||||
if(MSVC AND CXX_CLANG)
|
if(MSVC AND CXX_CLANG)
|
||||||
target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument)
|
target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -167,11 +167,8 @@
|
|||||||
"package": "SDL2",
|
"package": "SDL2",
|
||||||
"name": "SDL2",
|
"name": "SDL2",
|
||||||
"repo": "crueter-ci/SDL2",
|
"repo": "crueter-ci/SDL2",
|
||||||
"version": "2.32.10",
|
"version": "2.32.10-38e0094637",
|
||||||
"min_version": "2.26.4",
|
"min_version": "2.26.4"
|
||||||
"disabled_platforms": [
|
|
||||||
"macos-universal"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"catch2": {
|
"catch2": {
|
||||||
"package": "Catch2",
|
"package": "Catch2",
|
||||||
|
|||||||
@@ -25,18 +25,26 @@ if (UNIX AND NOT ANDROID)
|
|||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
|
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
|
||||||
if(PLATFORM_SUN)
|
if(PLATFORM_SUN)
|
||||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
find_library(LIBDRM_LIB libdrm PATHS /usr/lib/64 /usr/lib/amd64 /usr/lib)
|
||||||
X11
|
if(LIBDRM_LIB)
|
||||||
"/usr/lib/xorg/amd64/libdrm.so")
|
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||||
|
X11
|
||||||
|
"${LIBDRM_LIB}")
|
||||||
|
message(STATUS "Found libdrm at: ${LIBDRM_LIB}")
|
||||||
|
else()
|
||||||
|
message(WARNING "libdrm not found, disabling libdrm support")
|
||||||
|
list(APPEND FFmpeg_HWACCEL_FLAGS
|
||||||
|
--disable-libdrm)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
pkg_check_modules(LIBDRM libdrm REQUIRED)
|
pkg_check_modules(LIBDRM libdrm REQUIRED)
|
||||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||||
${LIBDRM_LIBRARIES})
|
${LIBDRM_LIBRARIES})
|
||||||
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
|
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
|
||||||
${LIBDRM_INCLUDE_DIRS})
|
${LIBDRM_INCLUDE_DIRS})
|
||||||
|
list(APPEND FFmpeg_HWACCEL_FLAGS
|
||||||
|
--enable-libdrm)
|
||||||
endif()
|
endif()
|
||||||
list(APPEND FFmpeg_HWACCEL_FLAGS
|
|
||||||
--enable-libdrm)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(LIBVA_FOUND)
|
if(LIBVA_FOUND)
|
||||||
@@ -89,7 +97,7 @@ if (UNIX AND NOT ANDROID)
|
|||||||
endif(CUDA_FOUND)
|
endif(CUDA_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (VDPAU_FOUND)
|
if (VDPAU_FOUND AND NOT APPLE)
|
||||||
list(APPEND FFmpeg_HWACCEL_FLAGS
|
list(APPEND FFmpeg_HWACCEL_FLAGS
|
||||||
--enable-vdpau
|
--enable-vdpau
|
||||||
--enable-hwaccel=h264_vdpau
|
--enable-hwaccel=h264_vdpau
|
||||||
@@ -247,11 +255,19 @@ else()
|
|||||||
SYSTEM_THREADS)
|
SYSTEM_THREADS)
|
||||||
|
|
||||||
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
|
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
|
||||||
|
|
||||||
|
# BSD make or Solaris make don't support ffmpeg make-j8
|
||||||
|
if (PLATFORM_LINUX OR ANDROID OR APPLE OR WIN32 OR PLATFORM_FREEBSD)
|
||||||
|
set(FFmpeg_MAKE_ARGS -j${SYSTEM_THREADS})
|
||||||
|
else()
|
||||||
|
set(FFmpeg_MAKE_ARGS "")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${FFmpeg_BUILD_LIBRARIES}
|
${FFmpeg_BUILD_LIBRARIES}
|
||||||
COMMAND
|
COMMAND
|
||||||
make -j${SYSTEM_THREADS}
|
make ${FFmpeg_MAKE_ARGS}
|
||||||
WORKING_DIRECTORY
|
WORKING_DIRECTORY
|
||||||
${FFmpeg_BUILD_DIR}
|
${FFmpeg_BUILD_DIR}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,13 +10,7 @@
|
|||||||
"package": "FFmpeg",
|
"package": "FFmpeg",
|
||||||
"name": "ffmpeg",
|
"name": "ffmpeg",
|
||||||
"repo": "crueter-ci/FFmpeg",
|
"repo": "crueter-ci/FFmpeg",
|
||||||
"version": "8.0",
|
"version": "8.0-be99d2c0b2",
|
||||||
"min_version": "4.1",
|
"min_version": "4.1"
|
||||||
"disabled_platforms": [
|
|
||||||
"freebsd-amd64",
|
|
||||||
"solaris-amd64",
|
|
||||||
"openbsd-amd64",
|
|
||||||
"macos-universal"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"git_host": "git.crueter.xyz",
|
"git_host": "git.crueter.xyz",
|
||||||
"artifact": "%VERSION%.tar.gz",
|
"artifact": "%VERSION%.tar.gz",
|
||||||
"tag": "%VERSION%",
|
"tag": "%VERSION%",
|
||||||
"hash": "87abb2aeca716d5d77b05317086dbc2f8acfc2f3f76ce4778345ee3df19973e6cd8ecbf16cfab5ad94c9636a6c44fd3588f9aadd3cba89403cfd56c8bec645c5",
|
"hash": "dc37a189a44ce8b5c988ca550582431a6c7eadfd3c6e709bee6277116ee803e714333e85c9e6cbb5c69346a14d6f2cc7ed96e8aa09cc5fb8a89f945059651db6",
|
||||||
"version": "091025"
|
"version": "121125"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ if (MSVC AND NOT CXX_CLANG)
|
|||||||
|
|
||||||
# /W4 - Level 4 warnings
|
# /W4 - Level 4 warnings
|
||||||
# /MP - Multi-threaded compilation
|
# /MP - Multi-threaded compilation
|
||||||
# /Zi - Output debugging information
|
|
||||||
# /Zm - Specifies the precompiled header memory allocation limit
|
# /Zm - Specifies the precompiled header memory allocation limit
|
||||||
# /Zo - Enhanced debug info for optimized builds
|
# /Zo - Enhanced debug info for optimized builds
|
||||||
# /permissive- - Enables stricter C++ standards conformance checks
|
# /permissive- - Enables stricter C++ standards conformance checks
|
||||||
@@ -98,11 +97,6 @@ if (MSVC AND NOT CXX_CLANG)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
|
||||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
|
||||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86_64)
|
||||||
add_compile_options(/QIntel-jcc-erratum)
|
add_compile_options(/QIntel-jcc-erratum)
|
||||||
endif()
|
endif()
|
||||||
@@ -176,16 +170,28 @@ else()
|
|||||||
add_compile_definitions(_FILE_OFFSET_BITS=64)
|
add_compile_definitions(_FILE_OFFSET_BITS=64)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (YUZU_STATIC_BUILD)
|
||||||
|
add_compile_definitions(QT_STATICPLUGIN)
|
||||||
|
|
||||||
|
# macos doesn't even let you make static executables... wtf?
|
||||||
|
if (NOT APPLE)
|
||||||
|
add_compile_options(-static)
|
||||||
|
if (YUZU_STATIC_BUILD)
|
||||||
|
# yuzu-cmd requires us to explicitly link libpthread, libgcc, and libstdc++ as static
|
||||||
|
# At a guess, it's probably because Qt handles the Qt executable for us, whereas this does not
|
||||||
|
add_link_options(-static -lpthread)
|
||||||
|
add_link_options(-static-libgcc -static-libstdc++)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
add_compile_definitions(MINGW_HAS_SECURE_API)
|
add_compile_definitions(MINGW_HAS_SECURE_API)
|
||||||
|
|
||||||
# Only windows has this requirement, thanks windows
|
# Only windows has this requirement, thanks windows
|
||||||
if (WIN32)
|
if (WIN32 AND ARCHITECTURE_x86_64)
|
||||||
add_compile_options("-msse4.1")
|
add_compile_options("-msse4.1")
|
||||||
endif()
|
endif()
|
||||||
if (MINGW_STATIC_BUILD)
|
|
||||||
add_compile_definitions(QT_STATICPLUGIN)
|
|
||||||
add_compile_options("-static")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ android {
|
|||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionName = getGitVersion()
|
versionName = getGitVersion()
|
||||||
|
|
||||||
versionCode = autoVersion
|
versionCode = autoVersion
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
@@ -69,9 +68,6 @@ android {
|
|||||||
abiFilters += listOf("arm64-v8a")
|
abiFilters += listOf("arm64-v8a")
|
||||||
}
|
}
|
||||||
|
|
||||||
buildConfigField("String", "GIT_HASH", "\"${getGitHash()}\"")
|
|
||||||
buildConfigField("String", "BRANCH", "\"${getBranch()}\"")
|
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
val extraCMakeArgs =
|
val extraCMakeArgs =
|
||||||
@@ -92,14 +88,14 @@ android {
|
|||||||
"-DYUZU_TESTS=OFF",
|
"-DYUZU_TESTS=OFF",
|
||||||
"-DDYNARMIC_TESTS=OFF",
|
"-DDYNARMIC_TESTS=OFF",
|
||||||
*extraCMakeArgs.toTypedArray()
|
*extraCMakeArgs.toTypedArray()
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
abiFilters("arm64-v8a")
|
abiFilters("arm64-v8a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
if (keystoreFile != null) {
|
if (keystoreFile != null) {
|
||||||
@@ -162,7 +158,39 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is really annoying but idk any other ways to fix this behavior
|
flavorDimensions.add("version")
|
||||||
|
productFlavors {
|
||||||
|
create("mainline") {
|
||||||
|
dimension = "version"
|
||||||
|
resValue("string", "app_name_suffixed", "Eden")
|
||||||
|
}
|
||||||
|
|
||||||
|
create("genshinSpoof") {
|
||||||
|
dimension = "version"
|
||||||
|
resValue("string", "app_name_suffixed", "Eden Optimized")
|
||||||
|
applicationId = "com.miHoYo.Yuanshen"
|
||||||
|
}
|
||||||
|
|
||||||
|
create("legacy") {
|
||||||
|
dimension = "version"
|
||||||
|
resValue("string", "app_name_suffixed", "Eden Legacy")
|
||||||
|
applicationId = "dev.legacy.eden_emulator"
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
arguments.add("-DYUZU_LEGACY=ON")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
getByName("legacy") {
|
||||||
|
res.srcDirs("src/main/legacy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is really annoying but idk any other ways to fix this behavior
|
||||||
applicationVariants.all {
|
applicationVariants.all {
|
||||||
val variant = this
|
val variant = this
|
||||||
when {
|
when {
|
||||||
@@ -187,40 +215,6 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
|
||||||
flavorDimensions.add("version")
|
|
||||||
productFlavors {
|
|
||||||
create("mainline") {
|
|
||||||
dimension = "version"
|
|
||||||
resValue("string", "app_name_suffixed", "Eden")
|
|
||||||
}
|
|
||||||
|
|
||||||
create("genshinSpoof") {
|
|
||||||
dimension = "version"
|
|
||||||
resValue("string", "app_name_suffixed", "Eden Optimized")
|
|
||||||
applicationId = "com.miHoYo.Yuanshen"
|
|
||||||
}
|
|
||||||
|
|
||||||
create("legacy") {
|
|
||||||
dimension = "version"
|
|
||||||
resValue("string", "app_name_suffixed", "Eden Legacy")
|
|
||||||
applicationId = "dev.legacy.eden_emulator"
|
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
arguments.add("-DYUZU_LEGACY=ON")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
getByName("legacy") {
|
|
||||||
res.srcDirs("src/main/legacy")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
version = "3.22.1"
|
version = "3.22.1"
|
||||||
@@ -284,7 +278,6 @@ dependencies {
|
|||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2")
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2")
|
||||||
implementation("androidx.window:window:1.3.0")
|
implementation("androidx.window:window:1.3.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
|
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("org.commonmark:commonmark:0.22.0")
|
implementation("org.commonmark:commonmark:0.22.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.8.9")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.8.9")
|
||||||
@@ -302,7 +295,9 @@ fun runGitCommand(command: List<String>): String {
|
|||||||
.directory(project.rootDir)
|
.directory(project.rootDir)
|
||||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||||
.redirectError(ProcessBuilder.Redirect.PIPE)
|
.redirectError(ProcessBuilder.Redirect.PIPE)
|
||||||
.start().inputStream.bufferedReader().use { it.readText() }
|
.start()
|
||||||
|
.inputStream.bufferedReader()
|
||||||
|
.use { it.readText() }
|
||||||
.trim()
|
.trim()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger.error("Cannot find git")
|
logger.error("Cannot find git")
|
||||||
@@ -326,9 +321,3 @@ fun getGitVersion(): String {
|
|||||||
}
|
}
|
||||||
return versionName.ifEmpty { "0.0" }
|
return versionName.ifEmpty { "0.0" }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGitHash(): String =
|
|
||||||
runGitCommand(listOf("git", "rev-parse", "--short", "HEAD")).ifEmpty { "dummy-hash" }
|
|
||||||
|
|
||||||
fun getBranch(): String =
|
|
||||||
runGitCommand(listOf("git", "rev-parse", "--abbrev-ref", "HEAD")).ifEmpty { "dummy-hash" }
|
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
||||||
@@ -110,5 +109,15 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.provider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths" />
|
||||||
|
</provider>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -200,6 +200,18 @@ object NativeLibrary {
|
|||||||
|
|
||||||
external fun logSettings()
|
external fun logSettings()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Vulkan driver version / API version / GPU model
|
||||||
|
*/
|
||||||
|
external fun getVulkanDriverVersion(): String
|
||||||
|
external fun getVulkanApiVersion(): String
|
||||||
|
external fun getGpuModel(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a summary of detailed information about the CPU.
|
||||||
|
*/
|
||||||
|
external fun getCpuSummary(): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for available updates.
|
* Checks for available updates.
|
||||||
*/
|
*/
|
||||||
@@ -210,11 +222,21 @@ object NativeLibrary {
|
|||||||
*/
|
*/
|
||||||
external fun getUpdateUrl(version: String): String
|
external fun getUpdateUrl(version: String): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the URL to download the APK for the given version
|
||||||
|
*/
|
||||||
|
external fun getUpdateApkUrl(version: String, packageId: String): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the update checker is enabled through CMAKE options.
|
* Returns whether the update checker is enabled through CMAKE options.
|
||||||
*/
|
*/
|
||||||
external fun isUpdateCheckerEnabled(): Boolean
|
external fun isUpdateCheckerEnabled(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the build version generated by CMake (BUILD_VERSION).
|
||||||
|
*/
|
||||||
|
external fun getBuildVersion(): String
|
||||||
|
|
||||||
enum class CoreError {
|
enum class CoreError {
|
||||||
ErrorSystemFiles,
|
ErrorSystemFiles,
|
||||||
ErrorSavestate,
|
ErrorSavestate,
|
||||||
|
|||||||
@@ -16,11 +16,15 @@ import java.io.FileOutputStream
|
|||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import javax.net.ssl.TrustManagerFactory
|
import javax.net.ssl.TrustManagerFactory
|
||||||
import javax.net.ssl.X509TrustManager
|
import javax.net.ssl.X509TrustManager
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.os.LocaleList
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
import org.yuzu.yuzu_emu.utils.PowerStateUpdater
|
import org.yuzu.yuzu_emu.utils.PowerStateUpdater
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
||||||
|
|
||||||
@@ -73,5 +77,38 @@ class YuzuApplication : Application() {
|
|||||||
|
|
||||||
val appContext: Context
|
val appContext: Context
|
||||||
get() = application.applicationContext
|
get() = application.applicationContext
|
||||||
|
|
||||||
|
private val LANGUAGE_CODES = arrayOf(
|
||||||
|
"system", "en", "es", "fr", "de", "it", "pt", "pt-BR", "ru", "ja", "ko",
|
||||||
|
"zh-CN", "zh-TW", "pl", "cs", "nb", "hu", "uk", "vi", "id", "ar", "ckb", "fa", "he", "sr"
|
||||||
|
)
|
||||||
|
|
||||||
|
fun applyLanguage(context: Context): Context {
|
||||||
|
val languageIndex = IntSetting.APP_LANGUAGE.getInt()
|
||||||
|
val langCode = if (languageIndex in LANGUAGE_CODES.indices) {
|
||||||
|
LANGUAGE_CODES[languageIndex]
|
||||||
|
} else {
|
||||||
|
"system"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (langCode == "system") {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
val locale = when {
|
||||||
|
langCode.contains("-") -> {
|
||||||
|
val parts = langCode.split("-")
|
||||||
|
Locale.Builder().setLanguage(parts[0]).setRegion(parts[1]).build()
|
||||||
|
}
|
||||||
|
else -> Locale.Builder().setLanguage(langCode).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale.setDefault(locale)
|
||||||
|
|
||||||
|
val config = Configuration(context.resources.configuration)
|
||||||
|
config.setLocales(LocaleList(locale))
|
||||||
|
|
||||||
|
return context.createConfigurationContext(config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||||||
|
|
||||||
private var foregroundService: Intent? = null
|
private var foregroundService: Intent? = null
|
||||||
|
|
||||||
|
override fun attachBaseContext(base: Context) {
|
||||||
|
super.attachBaseContext(YuzuApplication.applyLanguage(base))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Log.gameLaunched = true
|
Log.gameLaunched = true
|
||||||
ThemeHelper.setTheme(this)
|
ThemeHelper.setTheme(this)
|
||||||
@@ -231,10 +235,13 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
|
||||||
|
event.device?.isVirtual == false
|
||||||
|
|
||||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
|
||||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
!isPhysicalKeyboard
|
||||||
) {
|
) {
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||||||
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
|
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
|
||||||
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
|
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
|
||||||
RENDERER_DEBUG("debug"),
|
RENDERER_DEBUG("debug"),
|
||||||
|
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||||
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
||||||
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
||||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||||
@@ -69,7 +70,9 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||||||
SHOW_SHADERS_BUILDING("show_shaders_building"),
|
SHOW_SHADERS_BUILDING("show_shaders_building"),
|
||||||
|
|
||||||
DEBUG_FLUSH_BY_LINE("flush_line"),
|
DEBUG_FLUSH_BY_LINE("flush_line"),
|
||||||
USE_LRU_CACHE("use_lru_cache");
|
USE_LRU_CACHE("use_lru_cache"),
|
||||||
|
|
||||||
|
DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning");
|
||||||
|
|
||||||
|
|
||||||
// external fun isFrameSkippingEnabled(): Boolean
|
// external fun isFrameSkippingEnabled(): Boolean
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
|||||||
MAX_ANISOTROPY("max_anisotropy"),
|
MAX_ANISOTROPY("max_anisotropy"),
|
||||||
THEME("theme"),
|
THEME("theme"),
|
||||||
THEME_MODE("theme_mode"),
|
THEME_MODE("theme_mode"),
|
||||||
|
APP_LANGUAGE("app_language"),
|
||||||
OVERLAY_SCALE("control_scale"),
|
OVERLAY_SCALE("control_scale"),
|
||||||
OVERLAY_OPACITY("control_opacity"),
|
OVERLAY_OPACITY("control_opacity"),
|
||||||
LOCK_DRAWER("lock_drawer"),
|
LOCK_DRAWER("lock_drawer"),
|
||||||
|
|||||||
@@ -146,6 +146,13 @@ abstract class SettingsItem(
|
|||||||
descriptionId = R.string.provoking_vertex_description
|
descriptionId = R.string.provoking_vertex_description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
put(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
|
||||||
|
titleId = R.string.vertex_input_dynamic_state,
|
||||||
|
descriptionId = R.string.vertex_input_dynamic_state_description
|
||||||
|
)
|
||||||
|
)
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
|
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
|
||||||
@@ -667,10 +674,11 @@ abstract class SettingsItem(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
SliderSetting(
|
SpinBoxSetting(
|
||||||
IntSetting.CPU_TICKS,
|
IntSetting.CPU_TICKS,
|
||||||
titleId = R.string.cpu_ticks,
|
titleId = R.string.cpu_ticks,
|
||||||
descriptionId = 0,
|
descriptionId = 0,
|
||||||
|
valueHint = R.string.cpu_ticks,
|
||||||
min = 77,
|
min = 77,
|
||||||
max = 65535
|
max = 65535
|
||||||
)
|
)
|
||||||
@@ -754,6 +762,16 @@ abstract class SettingsItem(
|
|||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
BooleanSetting.ENABLE_UPDATE_CHECKS,
|
BooleanSetting.ENABLE_UPDATE_CHECKS,
|
||||||
titleId = R.string.enable_update_checks,
|
titleId = R.string.enable_update_checks,
|
||||||
|
descriptionId = R.string.enable_update_checks_description,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
put(
|
||||||
|
SingleChoiceSetting(
|
||||||
|
IntSetting.APP_LANGUAGE,
|
||||||
|
titleId = R.string.app_language,
|
||||||
|
descriptionId = R.string.app_language_description,
|
||||||
|
choicesId = R.array.appLanguageNames,
|
||||||
|
valuesId = R.array.appLanguageValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.ui
|
package org.yuzu.yuzu_emu.features.settings.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup.MarginLayoutParams
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
@@ -24,6 +29,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
|
|||||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||||
import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
|
import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
|
||||||
import org.yuzu.yuzu_emu.utils.*
|
import org.yuzu.yuzu_emu.utils.*
|
||||||
|
import org.yuzu.yuzu_emu.utils.collect
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivitySettingsBinding
|
private lateinit var binding: ActivitySettingsBinding
|
||||||
@@ -32,6 +38,10 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun attachBaseContext(base: Context) {
|
||||||
|
super.attachBaseContext(YuzuApplication.applyLanguage(base))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeHelper.setTheme(this)
|
ThemeHelper.setTheme(this)
|
||||||
|
|
||||||
@@ -125,6 +135,16 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
NativeConfig.savePerGameConfig()
|
NativeConfig.savePerGameConfig()
|
||||||
NativeConfig.unloadPerGameConfig()
|
NativeConfig.unloadPerGameConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsViewModel.shouldRecreateForLanguageChange.value) {
|
||||||
|
settingsViewModel.setShouldRecreateForLanguageChange(false)
|
||||||
|
val relaunchIntent = packageManager?.getLaunchIntentForPackage(packageName)
|
||||||
|
if (relaunchIntent != null) {
|
||||||
|
relaunchIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK or android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
startActivity(relaunchIntent)
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -425,6 +425,14 @@ class SettingsAdapter(
|
|||||||
position
|
position
|
||||||
).show(fragment.childFragmentManager, SettingsDialogFragment.TAG)
|
).show(fragment.childFragmentManager, SettingsDialogFragment.TAG)
|
||||||
|
|
||||||
|
// reset language if detected
|
||||||
|
if (item.setting.key == "app_language") {
|
||||||
|
// recreate page apply language change instantly
|
||||||
|
fragment.requireActivity().recreate()
|
||||||
|
|
||||||
|
settingsViewModel.setShouldRecreateForLanguageChange(true)
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import android.text.TextWatcher
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
@@ -197,6 +200,54 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
|
|||||||
updateValidity(newValue)
|
updateValidity(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun attachRepeat(button: View, delta: Int) {
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
var runnable: Runnable? = null
|
||||||
|
val initialDelay = 400L
|
||||||
|
val minDelay = 40L
|
||||||
|
val accelerationFactor = 0.75f
|
||||||
|
|
||||||
|
button.setOnTouchListener { v, event ->
|
||||||
|
when (event.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
val current = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue
|
||||||
|
val newValue = (current + delta)
|
||||||
|
spinboxBinding.editValue.setText(newValue.toString())
|
||||||
|
updateValidity(newValue)
|
||||||
|
|
||||||
|
var delay = initialDelay
|
||||||
|
runnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
val curr = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue
|
||||||
|
val next = curr + delta
|
||||||
|
spinboxBinding.editValue.setText(next.toString())
|
||||||
|
updateValidity(next)
|
||||||
|
// accelerate
|
||||||
|
delay = (delay * accelerationFactor).toLong().coerceAtLeast(minDelay)
|
||||||
|
handler.postDelayed(this, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.postDelayed(runnable!!, initialDelay)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
if (runnable != null) {
|
||||||
|
handler.removeCallbacks(runnable!!)
|
||||||
|
runnable = null
|
||||||
|
}
|
||||||
|
v.performClick()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attachRepeat(spinboxBinding.buttonDecrement, -1)
|
||||||
|
attachRepeat(spinboxBinding.buttonIncrement, 1)
|
||||||
|
|
||||||
spinboxBinding.editValue.addTextChangedListener(object : TextWatcher {
|
spinboxBinding.editValue.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
@@ -336,6 +387,12 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
scSetting.setSelectedValue(value)
|
scSetting.setSelectedValue(value)
|
||||||
|
|
||||||
|
if (scSetting.setting.key == "app_language") {
|
||||||
|
settingsViewModel.setShouldRecreateForLanguageChange(true)
|
||||||
|
// recreate page apply language change instantly
|
||||||
|
requireActivity().recreate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is StringSingleChoiceSetting -> {
|
is StringSingleChoiceSetting -> {
|
||||||
|
|||||||
@@ -453,6 +453,7 @@ class SettingsFragmentPresenter(
|
|||||||
sl.apply {
|
sl.apply {
|
||||||
add(HeaderSetting(R.string.veil_extensions))
|
add(HeaderSetting(R.string.veil_extensions))
|
||||||
add(ByteSetting.RENDERER_DYNA_STATE.key)
|
add(ByteSetting.RENDERER_DYNA_STATE.key)
|
||||||
|
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
|
||||||
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
||||||
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
||||||
add(BooleanSetting.RENDERER_SAMPLE_SHADING.key)
|
add(BooleanSetting.RENDERER_SAMPLE_SHADING.key)
|
||||||
@@ -1030,8 +1031,10 @@ class SettingsFragmentPresenter(
|
|||||||
override fun reset() = IntSetting.THEME.setInt(defaultValue)
|
override fun reset() = IntSetting.THEME.setInt(defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(HeaderSetting(R.string.app_settings))
|
||||||
|
add(IntSetting.APP_LANGUAGE.key)
|
||||||
|
|
||||||
if (NativeLibrary.isUpdateCheckerEnabled()) {
|
if (NativeLibrary.isUpdateCheckerEnabled()) {
|
||||||
add(HeaderSetting(R.string.app_settings))
|
|
||||||
add(BooleanSetting.ENABLE_UPDATE_CHECKS.key)
|
add(BooleanSetting.ENABLE_UPDATE_CHECKS.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -54,6 +57,8 @@ class SettingsViewModel : ViewModel() {
|
|||||||
private val _shouldShowResetInputDialog = MutableStateFlow(false)
|
private val _shouldShowResetInputDialog = MutableStateFlow(false)
|
||||||
val shouldShowResetInputDialog = _shouldShowResetInputDialog.asStateFlow()
|
val shouldShowResetInputDialog = _shouldShowResetInputDialog.asStateFlow()
|
||||||
|
|
||||||
|
private val _shouldRecreateForLanguageChange = MutableStateFlow(false)
|
||||||
|
val shouldRecreateForLanguageChange = _shouldRecreateForLanguageChange.asStateFlow()
|
||||||
fun setShouldRecreate(value: Boolean) {
|
fun setShouldRecreate(value: Boolean) {
|
||||||
_shouldRecreate.value = value
|
_shouldRecreate.value = value
|
||||||
}
|
}
|
||||||
@@ -103,6 +108,10 @@ class SettingsViewModel : ViewModel() {
|
|||||||
_shouldShowResetInputDialog.value = value
|
_shouldShowResetInputDialog.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setShouldRecreateForLanguageChange(value: Boolean) {
|
||||||
|
_shouldRecreateForLanguageChange.value = value
|
||||||
|
}
|
||||||
|
|
||||||
fun getCurrentDeviceParams(defaultParams: ParamPackage): ParamPackage =
|
fun getCurrentDeviceParams(defaultParams: ParamPackage): ParamPackage =
|
||||||
try {
|
try {
|
||||||
InputHandler.registeredControllers[currentDevice]
|
InputHandler.registeredControllers[currentDevice]
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.yuzu.yuzu_emu.R
|
|||||||
import org.yuzu.yuzu_emu.databinding.FragmentAboutBinding
|
import org.yuzu.yuzu_emu.databinding.FragmentAboutBinding
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
|
|
||||||
class AboutFragment : Fragment() {
|
class AboutFragment : Fragment() {
|
||||||
private var _binding: FragmentAboutBinding? = null
|
private var _binding: FragmentAboutBinding? = null
|
||||||
@@ -78,11 +79,15 @@ class AboutFragment : Fragment() {
|
|||||||
binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment)
|
binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.textVersionName.text = BuildConfig.VERSION_NAME
|
val buildName = getString(R.string.app_name_suffixed)
|
||||||
|
val buildVersion = NativeLibrary.getBuildVersion()
|
||||||
|
val fullVersionText = "$buildName ($buildVersion)"
|
||||||
|
|
||||||
|
binding.textVersionName.text = fullVersionText
|
||||||
binding.buttonVersionName.setOnClickListener {
|
binding.buttonVersionName.setOnClickListener {
|
||||||
val clipBoard =
|
val clipBoard =
|
||||||
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
val clip = ClipData.newPlainText(getString(R.string.build), BuildConfig.GIT_HASH)
|
val clip = ClipData.newPlainText(getString(R.string.build), fullVersionText)
|
||||||
clipBoard.setPrimaryClip(clip)
|
clipBoard.setPrimaryClip(clip)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.fragments
|
package org.yuzu.yuzu_emu.fragments
|
||||||
@@ -91,6 +91,12 @@ class DriverManagerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
driverViewModel.shouldShowDriverShaderDialog.collect(viewLifecycleOwner) { shouldShow ->
|
||||||
|
if (shouldShow) {
|
||||||
|
showDriverShaderWipeDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!driverViewModel.isInteractionAllowed.value) {
|
if (!driverViewModel.isInteractionAllowed.value) {
|
||||||
DriversLoadingDialogFragment().show(
|
DriversLoadingDialogFragment().show(
|
||||||
childFragmentManager,
|
childFragmentManager,
|
||||||
@@ -236,4 +242,18 @@ class DriverManagerFragment : Fragment() {
|
|||||||
).show(requireActivity().supportFragmentManager, MessageDialogFragment.TAG)
|
).show(requireActivity().supportFragmentManager, MessageDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showDriverShaderWipeDialog() {
|
||||||
|
com.google.android.material.dialog.MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle(R.string.driver_shader_wipe_dialog_title)
|
||||||
|
.setMessage(R.string.driver_shader_wipe_dialog_message)
|
||||||
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
driverViewModel.onDriverShaderDialogDismissed(dontShowAgain = false)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.dont_show_again) { _, _ ->
|
||||||
|
driverViewModel.onDriverShaderDialogDismissed(dontShowAgain = true)
|
||||||
|
}
|
||||||
|
.setCancelable(false)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,13 +145,12 @@ class GamePropertiesFragment : Fragment() {
|
|||||||
val seconds = playTimeSeconds % 60
|
val seconds = playTimeSeconds % 60
|
||||||
|
|
||||||
val readablePlayTime = when {
|
val readablePlayTime = when {
|
||||||
hours > 0 -> "${hours}h ${minutes}m ${seconds}s"
|
hours > 0 -> "$hours${getString(R.string.hours_abbr)} $minutes${getString(R.string.minutes_abbr)} $seconds${getString(R.string.seconds_abbr)}"
|
||||||
minutes > 0 -> "${minutes}m ${seconds}s"
|
minutes > 0 -> "$minutes${getString(R.string.minutes_abbr)} $seconds${getString(R.string.seconds_abbr)}"
|
||||||
else -> "${seconds}s"
|
else -> "$seconds${getString(R.string.seconds_abbr)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
append(getString(R.string.playtime))
|
append(getString(R.string.playtime) + " " + readablePlayTime)
|
||||||
append(readablePlayTime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playtime.setOnClickListener {
|
binding.playtime.setOnClickListener {
|
||||||
|
|||||||
@@ -230,6 +230,17 @@ class HomeSettingsFragment : Fragment() {
|
|||||||
{ openFileManager() }
|
{ openFileManager() }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
HomeSetting(
|
||||||
|
R.string.system_information,
|
||||||
|
R.string.system_information_description,
|
||||||
|
R.drawable.ic_system,
|
||||||
|
{
|
||||||
|
SystemInfoDialogFragment.newInstance()
|
||||||
|
.show(parentFragmentManager, SystemInfoDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
HomeSetting(
|
HomeSetting(
|
||||||
R.string.about,
|
R.string.about,
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.fragments
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.databinding.DialogSystemInfoBinding
|
||||||
|
|
||||||
|
class SystemInfoDialogFragment : DialogFragment() {
|
||||||
|
private var _binding: DialogSystemInfoBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
_binding = DialogSystemInfoBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
populateSystemInfo()
|
||||||
|
|
||||||
|
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle(R.string.system_information)
|
||||||
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
dialog.setView(binding.root)
|
||||||
|
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateSystemInfo() {
|
||||||
|
val systemInfo = buildString {
|
||||||
|
// General Device Info
|
||||||
|
appendLine("=== ${getString(R.string.general_information)} ===")
|
||||||
|
appendLine("${getString(R.string.device_manufacturer)}: ${Build.MANUFACTURER}")
|
||||||
|
appendLine("${getString(R.string.device_model)}: ${Build.MODEL}")
|
||||||
|
appendLine("${getString(R.string.device_name)}: ${Build.DEVICE}")
|
||||||
|
appendLine("${getString(R.string.product)}: ${Build.PRODUCT}")
|
||||||
|
appendLine("${getString(R.string.hardware)}: ${Build.HARDWARE}")
|
||||||
|
appendLine("${getString(R.string.supported_abis)}: ${Build.SUPPORTED_ABIS.joinToString(", ")}")
|
||||||
|
appendLine("${getString(R.string.android_version)}: ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})")
|
||||||
|
appendLine("${getString(R.string.android_security_patch)}: ${Build.VERSION.SECURITY_PATCH}")
|
||||||
|
appendLine("${getString(R.string.build_id)}: ${Build.ID}")
|
||||||
|
|
||||||
|
appendLine()
|
||||||
|
appendLine("=== ${getString(R.string.cpu_info)} ===")
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && Build.SOC_MODEL.isNotBlank()) {
|
||||||
|
appendLine("${getString(R.string.soc)} ${Build.SOC_MODEL}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val cpuSummary = NativeLibrary.getCpuSummary()
|
||||||
|
if (cpuSummary.isNotEmpty() && cpuSummary != "Unknown") {
|
||||||
|
appendLine(cpuSummary)
|
||||||
|
}
|
||||||
|
|
||||||
|
appendLine()
|
||||||
|
|
||||||
|
// GPU Info
|
||||||
|
appendLine("=== ${getString(R.string.gpu_information)} ===")
|
||||||
|
try {
|
||||||
|
val gpuModel = NativeLibrary.getGpuModel()
|
||||||
|
appendLine("${getString(R.string.gpu_model)}: $gpuModel")
|
||||||
|
|
||||||
|
val vulkanApi = NativeLibrary.getVulkanApiVersion()
|
||||||
|
appendLine("Vulkan API: $vulkanApi")
|
||||||
|
|
||||||
|
val vulkanDriver = NativeLibrary.getVulkanDriverVersion()
|
||||||
|
appendLine("${getString(R.string.vulkan_driver_version)}: $vulkanDriver")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
appendLine("${getString(R.string.error_getting_emulator_info)}: ${e.message}")
|
||||||
|
}
|
||||||
|
appendLine()
|
||||||
|
|
||||||
|
// Memory Info
|
||||||
|
appendLine("=== ${getString(R.string.memory_info)} ===")
|
||||||
|
|
||||||
|
val activityManager =
|
||||||
|
requireContext().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
|
val memInfo = ActivityManager.MemoryInfo()
|
||||||
|
activityManager.getMemoryInfo(memInfo)
|
||||||
|
val totalDeviceRam = memInfo.totalMem / (1024 * 1024)
|
||||||
|
|
||||||
|
appendLine("${getString(R.string.total_memory)}: $totalDeviceRam MB")
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.textSystemInfo.text = systemInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "SystemInfoDialogFragment"
|
||||||
|
|
||||||
|
fun newInstance(): SystemInfoDialogFragment {
|
||||||
|
return SystemInfoDialogFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -16,6 +19,7 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||||
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
||||||
@@ -52,9 +56,15 @@ class DriverViewModel : ViewModel() {
|
|||||||
|
|
||||||
private val driversToDelete = mutableListOf<String>()
|
private val driversToDelete = mutableListOf<String>()
|
||||||
|
|
||||||
|
private var previousDriverPath: String = ""
|
||||||
|
|
||||||
|
private val _shouldShowDriverShaderDialog = MutableStateFlow(false)
|
||||||
|
val shouldShowDriverShaderDialog: StateFlow<Boolean> get() = _shouldShowDriverShaderDialog
|
||||||
|
|
||||||
init {
|
init {
|
||||||
updateDriverList()
|
updateDriverList()
|
||||||
updateDriverNameForGame(null)
|
updateDriverNameForGame(null)
|
||||||
|
previousDriverPath = StringSetting.DRIVER_PATH.getString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadDriverData() {
|
fun reloadDriverData() {
|
||||||
@@ -79,6 +89,7 @@ class DriverViewModel : ViewModel() {
|
|||||||
newDriverList.add(it.second.toDriver(it.second == selectedDriver))
|
newDriverList.add(it.second.toDriver(it.second == selectedDriver))
|
||||||
}
|
}
|
||||||
_driverList.value = newDriverList
|
_driverList.value = newDriverList
|
||||||
|
previousDriverPath = StringSetting.DRIVER_PATH.getString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onOpenDriverManager(game: Game?) {
|
fun onOpenDriverManager(game: Game?) {
|
||||||
@@ -92,12 +103,49 @@ class DriverViewModel : ViewModel() {
|
|||||||
_showClearButton.value = value
|
_showClearButton.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDriverSelected(position: Int) {
|
fun onDriverSelected(position: Int, skipShaderWipe: Boolean = false) {
|
||||||
|
val newDriverPath = if (position == 0) {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
driverData[position - 1].first
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipShaderWipe && newDriverPath != previousDriverPath) {
|
||||||
|
wipeAllShaders()
|
||||||
|
|
||||||
|
if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) {
|
||||||
|
_shouldShowDriverShaderDialog.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
StringSetting.DRIVER_PATH.setString("")
|
StringSetting.DRIVER_PATH.setString("")
|
||||||
} else {
|
} else {
|
||||||
StringSetting.DRIVER_PATH.setString(driverData[position - 1].first)
|
StringSetting.DRIVER_PATH.setString(driverData[position - 1].first)
|
||||||
}
|
}
|
||||||
|
previousDriverPath = newDriverPath
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDriverShaderDialogDismissed(dontShowAgain: Boolean) {
|
||||||
|
if (dontShowAgain) {
|
||||||
|
BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.setBoolean(true)
|
||||||
|
NativeConfig.saveGlobalConfig()
|
||||||
|
}
|
||||||
|
_shouldShowDriverShaderDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wipeAllShaders() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val shaderDir = File(
|
||||||
|
YuzuApplication.appContext.getExternalFilesDir(null)?.canonicalPath +
|
||||||
|
"/shader/"
|
||||||
|
)
|
||||||
|
if (shaderDir.exists()) {
|
||||||
|
shaderDir.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) {
|
fun onDriverRemoved(removedPosition: Int, selectedPosition: Int) {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class GamesFragment : Fragment() {
|
|||||||
private var originalHeaderLeftMargin: Int? = null
|
private var originalHeaderLeftMargin: Int? = null
|
||||||
|
|
||||||
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
|
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
|
||||||
|
private var fallbackBottomInset: Int = 0
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SEARCH_TEXT = "SearchText"
|
private const val SEARCH_TEXT = "SearchText"
|
||||||
@@ -208,12 +209,12 @@ class GamesFragment : Fragment() {
|
|||||||
else -> throw IllegalArgumentException("Invalid view type: $savedViewType")
|
else -> throw IllegalArgumentException("Invalid view type: $savedViewType")
|
||||||
}
|
}
|
||||||
if (savedViewType == GameAdapter.VIEW_TYPE_CAROUSEL) {
|
if (savedViewType == GameAdapter.VIEW_TYPE_CAROUSEL) {
|
||||||
doOnNextLayout {
|
(binding.gridGames as? View)?.let { it -> ViewCompat.requestApplyInsets(it)}
|
||||||
(this as? CarouselRecyclerView)?.setCarouselMode(true, gameAdapter)
|
doOnNextLayout { //Carousel: important to avoid overlap issues
|
||||||
adapter = gameAdapter
|
(this as? CarouselRecyclerView)?.notifyLaidOut(fallbackBottomInset)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(this as? CarouselRecyclerView)?.setCarouselMode(false)
|
(this as? CarouselRecyclerView)?.setupCarousel(false)
|
||||||
}
|
}
|
||||||
adapter = gameAdapter
|
adapter = gameAdapter
|
||||||
lastViewType = savedViewType
|
lastViewType = savedViewType
|
||||||
@@ -237,9 +238,8 @@ class GamesFragment : Fragment() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (getCurrentViewType() == GameAdapter.VIEW_TYPE_CAROUSEL) {
|
if (getCurrentViewType() == GameAdapter.VIEW_TYPE_CAROUSEL) {
|
||||||
(binding.gridGames as? CarouselRecyclerView)?.restoreScrollState(
|
(binding.gridGames as? CarouselRecyclerView)?.setupCarousel(true)
|
||||||
gamesViewModel.lastScrollPosition
|
(binding.gridGames as? CarouselRecyclerView)?.restoreScrollState(gamesViewModel.lastScrollPosition)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,6 +494,11 @@ class GamesFragment : Fragment() {
|
|||||||
mlpFab.rightMargin = rightInset + fabPadding
|
mlpFab.rightMargin = rightInset + fabPadding
|
||||||
binding.addDirectory.layoutParams = mlpFab
|
binding.addDirectory.layoutParams = mlpFab
|
||||||
|
|
||||||
|
val navInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
||||||
|
val gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
|
||||||
|
val bottomInset = maxOf(navInsets.bottom, gestureInsets.bottom, cutoutInsets.bottom)
|
||||||
|
fallbackBottomInset = bottomInset
|
||||||
|
(binding.gridGames as? CarouselRecyclerView)?.notifyInsetsReady(bottomInset)
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package org.yuzu.yuzu_emu.ui.main
|
package org.yuzu.yuzu_emu.ui.main
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -52,7 +53,16 @@ import androidx.core.content.edit
|
|||||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||||
import kotlin.text.compareTo
|
import kotlin.text.compareTo
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
import com.google.android.material.textview.MaterialTextView
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||||
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
|
import org.yuzu.yuzu_emu.updater.APKDownloader
|
||||||
|
import org.yuzu.yuzu_emu.updater.APKInstaller
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), ThemeProvider {
|
class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
@@ -68,6 +78,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
private val CHECKED_DECRYPTION = "CheckedDecryption"
|
private val CHECKED_DECRYPTION = "CheckedDecryption"
|
||||||
private var checkedDecryption = false
|
private var checkedDecryption = false
|
||||||
|
|
||||||
|
override fun attachBaseContext(base: Context) {
|
||||||
|
super.attachBaseContext(YuzuApplication.applyLanguage(base))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
val splashScreen = installSplashScreen()
|
val splashScreen = installSplashScreen()
|
||||||
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
||||||
@@ -180,9 +194,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
.setTitle(R.string.update_available)
|
.setTitle(R.string.update_available)
|
||||||
.setMessage(getString(R.string.update_available_description, version))
|
.setMessage(getString(R.string.update_available_description, version))
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
val url = NativeLibrary.getUpdateUrl(version)
|
downloadAndInstallUpdate(version)
|
||||||
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
|
|
||||||
startActivity(intent)
|
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
@@ -195,6 +207,87 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun downloadAndInstallUpdate(version: String) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val packageId = applicationContext.packageName
|
||||||
|
val apkUrl = NativeLibrary.getUpdateApkUrl(version, packageId)
|
||||||
|
val apkFile = File(cacheDir, "update-$version.apk")
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
showDownloadProgressDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
val downloader = APKDownloader(apkUrl, apkFile)
|
||||||
|
downloader.download(
|
||||||
|
onProgress = { progress ->
|
||||||
|
runOnUiThread {
|
||||||
|
updateDownloadProgress(progress)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onComplete = { success ->
|
||||||
|
runOnUiThread {
|
||||||
|
dismissDownloadProgressDialog()
|
||||||
|
if (success) {
|
||||||
|
val installer = APKInstaller(this@MainActivity)
|
||||||
|
installer.install(
|
||||||
|
apkFile,
|
||||||
|
onComplete = {
|
||||||
|
Toast.makeText(
|
||||||
|
this@MainActivity,
|
||||||
|
R.string.update_installed_successfully,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
},
|
||||||
|
onFailure = { exception ->
|
||||||
|
Toast.makeText(
|
||||||
|
this@MainActivity,
|
||||||
|
getString(R.string.update_install_failed, exception.message),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(
|
||||||
|
this@MainActivity,
|
||||||
|
getString(R.string.update_download_failed) + "\n\nURL: $apkUrl",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var progressDialog: androidx.appcompat.app.AlertDialog? = null
|
||||||
|
private var progressBar: LinearProgressIndicator? = null
|
||||||
|
private var progressMessage: MaterialTextView? = null
|
||||||
|
|
||||||
|
private fun showDownloadProgressDialog() {
|
||||||
|
val progressView = layoutInflater.inflate(R.layout.dialog_download_progress, null)
|
||||||
|
progressBar = progressView.findViewById(R.id.download_progress_bar)
|
||||||
|
progressMessage = progressView.findViewById(R.id.download_progress_message)
|
||||||
|
|
||||||
|
progressDialog = MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle(R.string.downloading_update)
|
||||||
|
.setView(progressView)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
progressDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateDownloadProgress(progress: Int) {
|
||||||
|
progressBar?.progress = progress
|
||||||
|
progressMessage?.text = "$progress%"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dismissDownloadProgressDialog() {
|
||||||
|
progressDialog?.dismiss()
|
||||||
|
progressDialog = null
|
||||||
|
progressBar = null
|
||||||
|
progressMessage = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun displayMultiplayerDialog() {
|
fun displayMultiplayerDialog() {
|
||||||
val dialog = NetPlayDialog(this)
|
val dialog = NetPlayDialog(this)
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.updater
|
||||||
|
|
||||||
|
import okhttp3.Call
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class APKDownloader(private val url: String, private val outputFile: File) {
|
||||||
|
|
||||||
|
fun download(onProgress: (Int) -> Unit, onComplete: (Boolean) -> Unit) {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
val request = Request.Builder().url(url).build()
|
||||||
|
|
||||||
|
client.newCall(request).enqueue(object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
onComplete(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body?.let { body ->
|
||||||
|
val contentLength = body.contentLength()
|
||||||
|
try {
|
||||||
|
val inputStream = body.byteStream()
|
||||||
|
val outputStream = FileOutputStream(outputFile)
|
||||||
|
val buffer = ByteArray(4096)
|
||||||
|
var bytesRead: Int
|
||||||
|
var totalBytesRead: Long = 0
|
||||||
|
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead)
|
||||||
|
totalBytesRead += bytesRead
|
||||||
|
val progress = (totalBytesRead * 100 / contentLength).toInt()
|
||||||
|
onProgress(progress)
|
||||||
|
}
|
||||||
|
outputStream.flush()
|
||||||
|
outputStream.close()
|
||||||
|
inputStream.close()
|
||||||
|
onComplete(true)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
onComplete(false)
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
onComplete(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onComplete(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.updater
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class APKInstaller(private val context: Context) {
|
||||||
|
|
||||||
|
fun install(apkFile: File, onComplete: () -> Unit, onFailure: (Exception) -> Unit) {
|
||||||
|
try {
|
||||||
|
val apkUri: Uri = FileProvider.getUriForFile(
|
||||||
|
context,
|
||||||
|
context.applicationContext.packageName + ".provider",
|
||||||
|
apkFile
|
||||||
|
)
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
|
||||||
|
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
context.startActivity(intent)
|
||||||
|
|
||||||
|
GlobalScope.launch {
|
||||||
|
val receiver = AppInstallReceiver(onComplete, onFailure)
|
||||||
|
context.registerReceiver(receiver, IntentFilter().apply {
|
||||||
|
addAction(Intent.ACTION_PACKAGE_ADDED)
|
||||||
|
addAction(Intent.ACTION_PACKAGE_REPLACED)
|
||||||
|
addDataScheme("package")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
onFailure(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.updater
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
class AppInstallReceiver(
|
||||||
|
private val onComplete: () -> Unit,
|
||||||
|
private val onFailure: (Exception) -> Unit
|
||||||
|
) : BroadcastReceiver() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
val packageName = intent.data?.schemeSpecificPart
|
||||||
|
when (intent.action) {
|
||||||
|
Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REPLACED -> {
|
||||||
|
Log.i("AppInstallReceiver", "Package installed or updated: $packageName")
|
||||||
|
onComplete()
|
||||||
|
context.unregisterReceiver(this)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
onFailure(Exception("Installation failed for package: $packageName"))
|
||||||
|
context.unregisterReceiver(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.utils
|
package org.yuzu.yuzu_emu.utils
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
|
||||||
@@ -25,6 +29,15 @@ object Log {
|
|||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
|
||||||
info("SoC Manufacturer - ${Build.SOC_MANUFACTURER}")
|
info("SoC Manufacturer - ${Build.SOC_MANUFACTURER}")
|
||||||
info("SoC Model - ${Build.SOC_MODEL}")
|
info("SoC Model - ${Build.SOC_MODEL}")
|
||||||
|
NativeLibrary.getCpuSummary().split('\n').forEach {
|
||||||
|
info("CPU Info - $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NativeLibrary.getVulkanDriverVersion().split('\n').forEach {
|
||||||
|
info("Vulkan Driver: - $it")
|
||||||
|
}
|
||||||
|
NativeLibrary.getVulkanApiVersion().split('\n').forEach {
|
||||||
|
info("Vulkan API Version: - $it")
|
||||||
}
|
}
|
||||||
info("Total System Memory - ${MemoryUtil.getDeviceRAM()}")
|
info("Total System Memory - ${MemoryUtil.getDeviceRAM()}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,8 @@ import androidx.core.view.doOnNextLayout
|
|||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CarouselRecyclerView encapsulates all carousel logic for the games UI.
|
* CarouselRecyclerView encapsulates all carousel content for the games UI.
|
||||||
* It manages overlapping cards, center snapping, custom drawing order,
|
* It manages overlapping cards, center snapping, custom drawing order,
|
||||||
* joypad & fling navigation and mid-screen swipe-to-refresh.
|
* joypad & fling navigation and mid-screen swipe-to-refresh.
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +33,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
|
|
||||||
private var overlapFactor: Float = 0f
|
private var overlapFactor: Float = 0f
|
||||||
private var overlapPx: Int = 0
|
private var overlapPx: Int = 0
|
||||||
|
private var bottomInset: Int = -1
|
||||||
private var overlapDecoration: OverlappingDecoration? = null
|
private var overlapDecoration: OverlappingDecoration? = null
|
||||||
private var pagerSnapHelper: PagerSnapHelper? = null
|
private var pagerSnapHelper: PagerSnapHelper? = null
|
||||||
private var scalingScrollListener: OnScrollListener? = null
|
private var scalingScrollListener: OnScrollListener? = null
|
||||||
@@ -202,46 +202,61 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setCarouselMode(enabled: Boolean, gameAdapter: GameAdapter? = null) {
|
fun refreshView() {
|
||||||
|
updateChildScalesAndAlpha()
|
||||||
|
focusCenteredCard()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notifyInsetsReady(newBottomInset: Int) {
|
||||||
|
if (bottomInset != newBottomInset) {
|
||||||
|
bottomInset = newBottomInset
|
||||||
|
}
|
||||||
|
setupCarousel(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notifyLaidOut(fallBackBottomInset: Int) {
|
||||||
|
if (bottomInset < 0) bottomInset = fallBackBottomInset
|
||||||
|
var gameAdapter = adapter as? GameAdapter ?: return
|
||||||
|
var newCardSize = cardSize(bottomInset)
|
||||||
|
if (gameAdapter.cardSize != newCardSize) {
|
||||||
|
gameAdapter.setCardSize(newCardSize)
|
||||||
|
}
|
||||||
|
setupCarousel(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cardSize(bottomInset: Int): Int {
|
||||||
|
val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1)
|
||||||
|
val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn(
|
||||||
|
0f,
|
||||||
|
1f
|
||||||
|
)
|
||||||
|
return (userFactor * (height - bottomInset)).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setupCarousel(enabled: Boolean) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
val gameAdapter = adapter as? GameAdapter ?: return
|
||||||
|
if (gameAdapter.cardSize == 0) return
|
||||||
|
if (bottomInset < 0) return
|
||||||
|
|
||||||
useCustomDrawingOrder = true
|
useCustomDrawingOrder = true
|
||||||
|
val cardSize = gameAdapter.cardSize
|
||||||
|
|
||||||
val insets = rootWindowInsets?.let { WindowInsetsCompat.toWindowInsetsCompat(it, this) }
|
val internalOverlapFactor = resources.getFraction(R.fraction.carousel_overlap_factor,1,1)
|
||||||
val bottomInset = insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: 0
|
overlapFactor = preferences.getFloat(CAROUSEL_OVERLAP_FACTOR, internalOverlapFactor).coerceIn(0f,1f)
|
||||||
val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1)
|
|
||||||
val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn(
|
|
||||||
0f,
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
val cardSize = (userFactor * (height - bottomInset)).toInt()
|
|
||||||
gameAdapter?.setCardSize(cardSize)
|
|
||||||
|
|
||||||
val internalOverlapFactor = resources.getFraction(
|
|
||||||
R.fraction.carousel_overlap_factor,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
)
|
|
||||||
overlapFactor = preferences.getFloat(CAROUSEL_OVERLAP_FACTOR, internalOverlapFactor).coerceIn(
|
|
||||||
0f,
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
overlapPx = (cardSize * overlapFactor).toInt()
|
overlapPx = (cardSize * overlapFactor).toInt()
|
||||||
|
|
||||||
val internalFlingMultiplier = resources.getFraction(
|
val internalFlingMultiplier = resources.getFraction(R.fraction.carousel_fling_multiplier,1,1)
|
||||||
R.fraction.carousel_fling_multiplier,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
)
|
|
||||||
flingMultiplier = preferences.getFloat(
|
flingMultiplier = preferences.getFloat(
|
||||||
CAROUSEL_FLING_MULTIPLIER,
|
CAROUSEL_FLING_MULTIPLIER,
|
||||||
internalFlingMultiplier
|
internalFlingMultiplier
|
||||||
).coerceIn(1f, 5f)
|
).coerceIn(1f, 5f)
|
||||||
|
|
||||||
gameAdapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
gameAdapter .registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||||
override fun onChanged() {
|
override fun onChanged() {
|
||||||
if (pendingScrollAfterReload) {
|
if (pendingScrollAfterReload) {
|
||||||
post {
|
doOnNextLayout {
|
||||||
jigglyScroll()
|
refreshView()
|
||||||
pendingScrollAfterReload = false
|
pendingScrollAfterReload = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +272,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
addItemDecoration(overlapDecoration!!)
|
addItemDecoration(overlapDecoration!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gradual scalingAdd commentMore actions
|
// Gradual scaling on scroll
|
||||||
if (scalingScrollListener == null) {
|
if (scalingScrollListener == null) {
|
||||||
scalingScrollListener = object : OnScrollListener() {
|
scalingScrollListener = object : OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
@@ -315,8 +330,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
super.scrollToPosition(position)
|
super.scrollToPosition(position)
|
||||||
(layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(position, overlapPx)
|
(layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(position, overlapPx)
|
||||||
doOnNextLayout {
|
doOnNextLayout {
|
||||||
updateChildScalesAndAlpha()
|
refreshView()
|
||||||
focusCenteredCard()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,12 +396,6 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
return sorted[i].first
|
return sorted[i].first
|
||||||
}
|
}
|
||||||
|
|
||||||
fun jigglyScroll() {
|
|
||||||
scrollBy(-1, 0)
|
|
||||||
scrollBy(1, 0)
|
|
||||||
focusCenteredCard()
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class OverlappingDecoration(private val overlap: Int) : ItemDecoration() {
|
inner class OverlappingDecoration(private val overlap: Int) : ItemDecoration() {
|
||||||
override fun getItemOffsets(
|
override fun getItemOffsets(
|
||||||
outRect: Rect,
|
outRect: Rect,
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ namespace AndroidSettings {
|
|||||||
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
|
||||||
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
|
||||||
Settings::Category::Android};
|
Settings::Category::Android};
|
||||||
|
Settings::Setting<s32> app_language{linkage, 0, "app_language", Settings::Category::Android};
|
||||||
Settings::Setting<bool> enable_update_checks{linkage, true, "enable_update_checks",
|
Settings::Setting<bool> enable_update_checks{linkage, true, "enable_update_checks",
|
||||||
Settings::Category::Android};
|
Settings::Category::Android};
|
||||||
|
|
||||||
@@ -181,9 +182,9 @@ namespace AndroidSettings {
|
|||||||
Settings::Specialization::Default, true, true,
|
Settings::Specialization::Default, true, true,
|
||||||
&show_soc_overlay};
|
&show_soc_overlay};
|
||||||
|
|
||||||
Settings::Setting<bool> dont_show_eden_veil_warning{linkage, false,
|
Settings::Setting<bool> dont_show_driver_shader_warning{linkage, false,
|
||||||
"dont_show_eden_veil_warning",
|
"dont_show_driver_shader_warning",
|
||||||
Settings::Category::Miscellaneous};
|
Settings::Category::Android, Settings::Specialization::Default, true, true};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Values values;
|
extern Values values;
|
||||||
|
|||||||
@@ -4,15 +4,25 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
#include "video_core/vulkan_common/vma.h"
|
||||||
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
#include <adrenotools/driver.h>
|
#include <adrenotools/driver.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -463,6 +473,205 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
|||||||
return Core::SystemResultStatus::Success;
|
return Core::SystemResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct CpuPartInfo {
|
||||||
|
u32 vendor;
|
||||||
|
u32 part;
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr CpuPartInfo s_cpu_list[] = {
|
||||||
|
// ARM - 0x41
|
||||||
|
{0x41, 0xd01, "Cortex-A32"},
|
||||||
|
{0x41, 0xd02, "Cortex-A34"},
|
||||||
|
{0x41, 0xd04, "Cortex-A35"},
|
||||||
|
{0x41, 0xd03, "Cortex-A53"},
|
||||||
|
{0x41, 0xd05, "Cortex-A55"},
|
||||||
|
{0x41, 0xd46, "Cortex-A510"},
|
||||||
|
{0x41, 0xd80, "Cortex-A520"},
|
||||||
|
{0x41, 0xd88, "Cortex-A520AE"},
|
||||||
|
{0x41, 0xd07, "Cortex-A57"},
|
||||||
|
{0x41, 0xd06, "Cortex-A65"},
|
||||||
|
{0x41, 0xd43, "Cortex-A65AE"},
|
||||||
|
{0x41, 0xd08, "Cortex-A72"},
|
||||||
|
{0x41, 0xd09, "Cortex-A73"},
|
||||||
|
{0x41, 0xd0a, "Cortex-A75"},
|
||||||
|
{0x41, 0xd0b, "Cortex-A76"},
|
||||||
|
{0x41, 0xd0e, "Cortex-A76AE"},
|
||||||
|
{0x41, 0xd0d, "Cortex-A77"},
|
||||||
|
{0x41, 0xd41, "Cortex-A78"},
|
||||||
|
{0x41, 0xd42, "Cortex-A78AE"},
|
||||||
|
{0x41, 0xd4b, "Cortex-A78C"},
|
||||||
|
{0x41, 0xd47, "Cortex-A710"},
|
||||||
|
{0x41, 0xd4d, "Cortex-A715"},
|
||||||
|
{0x41, 0xd81, "Cortex-A720"},
|
||||||
|
{0x41, 0xd89, "Cortex-A720AE"},
|
||||||
|
{0x41, 0xd87, "Cortex-A725"},
|
||||||
|
{0x41, 0xd44, "Cortex-X1"},
|
||||||
|
{0x41, 0xd4c, "Cortex-X1C"},
|
||||||
|
{0x41, 0xd48, "Cortex-X2"},
|
||||||
|
{0x41, 0xd4e, "Cortex-X3"},
|
||||||
|
{0x41, 0xd82, "Cortex-X4"},
|
||||||
|
{0x41, 0xd85, "Cortex-X925"},
|
||||||
|
{0x41, 0xd4a, "Neoverse E1"},
|
||||||
|
{0x41, 0xd0c, "Neoverse N1"},
|
||||||
|
{0x41, 0xd49, "Neoverse N2"},
|
||||||
|
{0x41, 0xd8e, "Neoverse N3"},
|
||||||
|
{0x41, 0xd40, "Neoverse V1"},
|
||||||
|
{0x41, 0xd4f, "Neoverse V2"},
|
||||||
|
{0x41, 0xd84, "Neoverse V3"},
|
||||||
|
{0x41, 0xd83, "Neoverse V3AE"},
|
||||||
|
// Qualcomm - 0x51
|
||||||
|
{0x51, 0x201, "Kryo"},
|
||||||
|
{0x51, 0x205, "Kryo"},
|
||||||
|
{0x51, 0x211, "Kryo"},
|
||||||
|
{0x51, 0x800, "Kryo 385 Gold"},
|
||||||
|
{0x51, 0x801, "Kryo 385 Silver"},
|
||||||
|
{0x51, 0x802, "Kryo 485 Gold"},
|
||||||
|
{0x51, 0x803, "Kryo 485 Silver"},
|
||||||
|
{0x51, 0x804, "Kryo 680 Prime"},
|
||||||
|
{0x51, 0x805, "Kryo 680 Gold"},
|
||||||
|
{0x51, 0x06f, "Krait"},
|
||||||
|
{0x51, 0xc00, "Falkor"},
|
||||||
|
{0x51, 0xc01, "Saphira"},
|
||||||
|
{0x51, 0x001, "Oryon"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* find_cpu_name(u32 vendor, u32 part) {
|
||||||
|
for (const auto& cpu : s_cpu_list) {
|
||||||
|
if (cpu.vendor == vendor && cpu.part == part) {
|
||||||
|
return cpu.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 read_midr_sysfs(u32 cpu_id) {
|
||||||
|
char path[128];
|
||||||
|
std::snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/regs/identification/midr_el1", cpu_id);
|
||||||
|
|
||||||
|
FILE* f = std::fopen(path, "r");
|
||||||
|
if (!f) return 0;
|
||||||
|
|
||||||
|
char value[32];
|
||||||
|
if (!std::fgets(value, sizeof(value), f)) {
|
||||||
|
std::fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::fclose(f);
|
||||||
|
|
||||||
|
return std::strtoull(value, nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, std::string> get_pretty_cpus() {
|
||||||
|
std::map<u64, int> core_layout;
|
||||||
|
u32 valid_cpus = 0;
|
||||||
|
for (u32 i = 0; i < std::thread::hardware_concurrency(); ++i) {
|
||||||
|
const auto midr = read_midr_sysfs(i);
|
||||||
|
if (midr == 0) break;
|
||||||
|
|
||||||
|
valid_cpus++;
|
||||||
|
core_layout[midr]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cpus;
|
||||||
|
|
||||||
|
if (!core_layout.empty()) {
|
||||||
|
const CpuPartInfo* lowest_part = nullptr;
|
||||||
|
u32 lowest_part_id = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
for (const auto& [midr, count] : core_layout) {
|
||||||
|
const auto vendor = (midr >> 24) & 0xff;
|
||||||
|
const auto part = (midr >> 4) & 0xfff;
|
||||||
|
|
||||||
|
if (!cpus.empty()) cpus += " + ";
|
||||||
|
cpus += fmt::format("{}x {}", count, find_cpu_name(vendor, part));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {valid_cpus, cpus};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_arm_cpu_name() {
|
||||||
|
std::map<u64, int> core_layout;
|
||||||
|
for (u32 i = 0; i < std::thread::hardware_concurrency(); ++i) {
|
||||||
|
const auto midr = read_midr_sysfs(i);
|
||||||
|
if (midr == 0) break;
|
||||||
|
|
||||||
|
core_layout[midr]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!core_layout.empty()) {
|
||||||
|
const CpuPartInfo* lowest_part = nullptr;
|
||||||
|
u32 lowest_part_id = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
for (const auto& [midr, count] : core_layout) {
|
||||||
|
const auto vendor = (midr >> 24) & 0xff;
|
||||||
|
const auto part = (midr >> 4) & 0xfff;
|
||||||
|
|
||||||
|
for (const auto& cpu : s_cpu_list) {
|
||||||
|
if (cpu.vendor == vendor && cpu.part == part) {
|
||||||
|
if (cpu.part < lowest_part_id) {
|
||||||
|
lowest_part_id = cpu.part;
|
||||||
|
lowest_part = &cpu;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowest_part) {
|
||||||
|
return lowest_part->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* f = std::fopen("/proc/cpuinfo", "r");
|
||||||
|
if (!f) return "";
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
auto trim = [](std::string& s) {
|
||||||
|
const auto start = s.find_first_not_of(" \t\r\n");
|
||||||
|
const auto end = s.find_last_not_of(" \t\r\n");
|
||||||
|
s = (start == std::string::npos) ? "" : s.substr(start, end - start + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (std::fgets(buf, sizeof(buf), f)) {
|
||||||
|
std::string line(buf);
|
||||||
|
if (line.find("Hardware") == 0) {
|
||||||
|
auto pos = line.find(':');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
result = line.substr(pos + 1);
|
||||||
|
trim(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::fclose(f);
|
||||||
|
|
||||||
|
if (!result.empty()) {
|
||||||
|
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* fallback_cpu_detection() {
|
||||||
|
static std::string s_result = []() -> std::string {
|
||||||
|
std::string result = get_arm_cpu_name();
|
||||||
|
if (result.empty()) {
|
||||||
|
return "Cortex-A34";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
|
||||||
|
return s_result.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance,
|
||||||
@@ -555,6 +764,7 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
|
|||||||
|
|
||||||
jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
||||||
JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
||||||
|
#ifdef ARCHITECTURE_arm64
|
||||||
const char* file_redirect_dir_{};
|
const char* file_redirect_dir_{};
|
||||||
int featureFlags{};
|
int featureFlags{};
|
||||||
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
||||||
@@ -577,15 +787,19 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
|||||||
auto version_string =
|
auto version_string =
|
||||||
fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
|
fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
|
||||||
VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
|
VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
|
||||||
|
auto driver_name = device.GetDriverName();
|
||||||
jobjectArray j_driver_info = env->NewObjectArray(
|
#else
|
||||||
2, Common::Android::GetStringClass(), Common::Android::ToJString(env, version_string));
|
auto driver_version = "1.0.0";
|
||||||
env->SetObjectArrayElement(j_driver_info, 1,
|
auto version_string = "1.1.0"; //Assume lowest Vulkan level
|
||||||
Common::Android::ToJString(env, device.GetDriverName()));
|
auto driver_name = "generic";
|
||||||
|
#endif
|
||||||
|
jobjectArray j_driver_info = env->NewObjectArray(2, Common::Android::GetStringClass(), Common::Android::ToJString(env, version_string));
|
||||||
|
env->SetObjectArrayElement(j_driver_info, 1, Common::Android::ToJString(env, driver_name));
|
||||||
return j_driver_info;
|
return j_driver_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
||||||
|
#ifdef ARCHITECTURE_arm64
|
||||||
const char* file_redirect_dir_{};
|
const char* file_redirect_dir_{};
|
||||||
int featureFlags{};
|
int featureFlags{};
|
||||||
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
||||||
@@ -609,6 +823,9 @@ jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, j
|
|||||||
window.release();
|
window.release();
|
||||||
|
|
||||||
return Common::Android::ToJString(env, model_name);
|
return Common::Android::ToJString(env, model_name);
|
||||||
|
#else
|
||||||
|
return Common::Android::ToJString(env, "no-info");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
||||||
@@ -684,6 +901,209 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuDriver(JNIEnv* env, jobject
|
|||||||
env, EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor());
|
env, EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject /*jobj*/) {
|
||||||
|
get_arm_cpu_name();
|
||||||
|
constexpr const char* CPUINFO_PATH = "/proc/cpuinfo";
|
||||||
|
|
||||||
|
auto trim = [](std::string& s) {
|
||||||
|
const auto start = s.find_first_not_of(" \t\r\n");
|
||||||
|
const auto end = s.find_last_not_of(" \t\r\n");
|
||||||
|
s = (start == std::string::npos) ? "" : s.substr(start, end - start + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto to_lower = [](std::string s) {
|
||||||
|
for (auto& c : s) c = std::tolower(c);
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string result;
|
||||||
|
std::pair<u32, std::string> pretty_cpus = get_pretty_cpus();
|
||||||
|
u32 threads = pretty_cpus.first;
|
||||||
|
std::string cpus = pretty_cpus.second;
|
||||||
|
|
||||||
|
fmt::format_to(std::back_inserter(result), "CPUs: {}\n{} Threads",
|
||||||
|
cpus, threads);
|
||||||
|
|
||||||
|
FILE* f = std::fopen(CPUINFO_PATH, "r");
|
||||||
|
if (!f) return Common::Android::ToJString(env, result);
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
if (f) {
|
||||||
|
std::set<std::string> feature_set;
|
||||||
|
while (std::fgets(buf, sizeof(buf), f)) {
|
||||||
|
std::string line(buf);
|
||||||
|
if (line.find("Features") == 0 || line.find("features") == 0) {
|
||||||
|
auto pos = line.find(':');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
std::string feat_line = line.substr(pos + 1);
|
||||||
|
trim(feat_line);
|
||||||
|
|
||||||
|
std::istringstream iss(feat_line);
|
||||||
|
std::string feature;
|
||||||
|
while (iss >> feature) {
|
||||||
|
feature_set.insert(to_lower(feature));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::fclose(f);
|
||||||
|
|
||||||
|
bool has_neon = feature_set.count("neon") || feature_set.count("asimd");
|
||||||
|
bool has_fp = feature_set.count("fp") || feature_set.count("vfp");
|
||||||
|
bool has_sve = feature_set.count("sve");
|
||||||
|
bool has_sve2 = feature_set.count("sve2");
|
||||||
|
bool has_crypto = feature_set.count("aes") || feature_set.count("sha1") ||
|
||||||
|
feature_set.count("sha2") || feature_set.count("pmull");
|
||||||
|
bool has_dotprod = feature_set.count("asimddp") || feature_set.count("dotprod");
|
||||||
|
bool has_i8mm = feature_set.count("i8mm");
|
||||||
|
bool has_bf16 = feature_set.count("bf16");
|
||||||
|
bool has_atomics = feature_set.count("atomics") || feature_set.count("lse");
|
||||||
|
|
||||||
|
std::string features;
|
||||||
|
if (has_neon || has_fp) {
|
||||||
|
features += "NEON";
|
||||||
|
if (has_dotprod) features += "+DP";
|
||||||
|
if (has_i8mm) features += "+I8MM";
|
||||||
|
if (has_bf16) features += "+BF16";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_sve) {
|
||||||
|
if (!features.empty()) features += " | ";
|
||||||
|
features += "SVE";
|
||||||
|
if (has_sve2) features += "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_crypto) {
|
||||||
|
if (!features.empty()) features += " | ";
|
||||||
|
features += "Crypto";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_atomics) {
|
||||||
|
if (!features.empty()) features += " | ";
|
||||||
|
features += "LSE";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!features.empty()) {
|
||||||
|
result += "\nFeatures: " + features;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::format_to(std::back_inserter(result), "\nLLVM CPU: {}", fallback_cpu_detection());
|
||||||
|
|
||||||
|
return Common::Android::ToJString(env, result);
|
||||||
|
} catch (...) {
|
||||||
|
return Common::Android::ToJString(env, "Unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr u32 VENDOR_QUALCOMM = 0x5143;
|
||||||
|
constexpr u32 VENDOR_ARM = 0x13B5;
|
||||||
|
|
||||||
|
VkPhysicalDeviceProperties GetVulkanDeviceProperties() {
|
||||||
|
Common::DynamicLibrary library;
|
||||||
|
if (!library.Open("libvulkan.so")) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Vulkan::vk::InstanceDispatch dld;
|
||||||
|
// TODO: warn the user that Vulkan is unavailable rather than hard crash
|
||||||
|
const auto instance = Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1);
|
||||||
|
const auto physical_devices = instance.EnumeratePhysicalDevices();
|
||||||
|
if (physical_devices.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
|
||||||
|
return physical_device.GetProperties();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanDriverVersion(JNIEnv* env, jobject jobj) {
|
||||||
|
try {
|
||||||
|
const auto props = GetVulkanDeviceProperties();
|
||||||
|
if (props.deviceID == 0) {
|
||||||
|
return Common::Android::ToJString(env, "N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 driver_version = props.driverVersion;
|
||||||
|
const u32 vendor_id = props.vendorID;
|
||||||
|
|
||||||
|
if (driver_version == 0) {
|
||||||
|
return Common::Android::ToJString(env, "N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string version_str;
|
||||||
|
|
||||||
|
if (vendor_id == VENDOR_QUALCOMM) {
|
||||||
|
const u32 major = (driver_version >> 24) << 2;
|
||||||
|
const u32 minor = (driver_version >> 12) & 0xFFF;
|
||||||
|
const u32 patch = driver_version & 0xFFF;
|
||||||
|
version_str = fmt::format("{}.{}.{}", major, minor, patch);
|
||||||
|
}
|
||||||
|
else if (vendor_id == VENDOR_ARM) {
|
||||||
|
u32 major = VK_API_VERSION_MAJOR(driver_version);
|
||||||
|
u32 minor = VK_API_VERSION_MINOR(driver_version);
|
||||||
|
u32 patch = VK_API_VERSION_PATCH(driver_version);
|
||||||
|
|
||||||
|
// ARM custom encoding for newer drivers
|
||||||
|
if (major > 10) {
|
||||||
|
major = (driver_version >> 22) & 0x3FF;
|
||||||
|
minor = (driver_version >> 12) & 0x3FF;
|
||||||
|
patch = driver_version & 0xFFF;
|
||||||
|
}
|
||||||
|
version_str = fmt::format("{}.{}.{}", major, minor, patch);
|
||||||
|
}
|
||||||
|
// Standard Vulkan version encoding for other vendors
|
||||||
|
else {
|
||||||
|
const u32 major = VK_API_VERSION_MAJOR(driver_version);
|
||||||
|
const u32 minor = VK_API_VERSION_MINOR(driver_version);
|
||||||
|
const u32 patch = VK_API_VERSION_PATCH(driver_version);
|
||||||
|
version_str = fmt::format("{}.{}.{}", major, minor, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Common::Android::ToJString(env, version_str);
|
||||||
|
} catch (...) {
|
||||||
|
return Common::Android::ToJString(env, "N/A");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanApiVersion(JNIEnv* env, jobject jobj) {
|
||||||
|
try {
|
||||||
|
const auto props = GetVulkanDeviceProperties();
|
||||||
|
if (props.deviceID == 0) {
|
||||||
|
return Common::Android::ToJString(env, "N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 api_version = props.apiVersion;
|
||||||
|
const u32 major = VK_API_VERSION_MAJOR(api_version);
|
||||||
|
const u32 minor = VK_API_VERSION_MINOR(api_version);
|
||||||
|
const u32 patch = VK_API_VERSION_PATCH(api_version);
|
||||||
|
const u32 variant = VK_API_VERSION_VARIANT(api_version);
|
||||||
|
|
||||||
|
// Include variant if non-zero (rare on Android)
|
||||||
|
const std::string version_str = variant > 0
|
||||||
|
? fmt::format("{}.{}.{}.{}", variant, major, minor, patch)
|
||||||
|
: fmt::format("{}.{}.{}", major, minor, patch);
|
||||||
|
|
||||||
|
return Common::Android::ToJString(env, version_str);
|
||||||
|
} catch (...) {
|
||||||
|
return Common::Android::ToJString(env, "N/A");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuModel(JNIEnv* env, jobject jobj) {
|
||||||
|
const auto props = GetVulkanDeviceProperties();
|
||||||
|
if (props.deviceID == 0) {
|
||||||
|
return Common::Android::ToJString(env, "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Common::Android::ToJString(env, props.deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) {
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) {
|
||||||
EmulationSession::GetInstance().System().ApplySettings();
|
EmulationSession::GetInstance().System().ApplySettings();
|
||||||
EmulationSession::GetInstance().System().HIDCore().ReloadInputDevices();
|
EmulationSession::GetInstance().System().HIDCore().ReloadInputDevices();
|
||||||
@@ -1193,6 +1613,43 @@ JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateUrl(
|
|||||||
env->ReleaseStringUTFChars(version, version_str);
|
env->ReleaseStringUTFChars(version, version_str);
|
||||||
return env->NewStringUTF(url.c_str());
|
return env->NewStringUTF(url.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateApkUrl(
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject obj,
|
||||||
|
jstring version,
|
||||||
|
jstring packageId) {
|
||||||
|
const char* version_str = env->GetStringUTFChars(version, nullptr);
|
||||||
|
const char* package_id_str = env->GetStringUTFChars(packageId, nullptr);
|
||||||
|
|
||||||
|
std::string variant;
|
||||||
|
std::string package_id(package_id_str);
|
||||||
|
|
||||||
|
if (package_id.find("dev.legacy.eden_emulator") != std::string::npos) {
|
||||||
|
variant = "legacy";
|
||||||
|
} else if (package_id.find("com.miHoYo.Yuanshen") != std::string::npos) {
|
||||||
|
variant = "optimized";
|
||||||
|
} else {
|
||||||
|
variant = "standard";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string apk_filename = fmt::format("Eden-Android-{}-{}.apk", version_str, variant);
|
||||||
|
const std::string url = fmt::format("{}/{}/releases/download/{}/{}",
|
||||||
|
std::string{Common::g_build_auto_update_website},
|
||||||
|
std::string{Common::g_build_auto_update_repo},
|
||||||
|
version_str,
|
||||||
|
apk_filename);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(version, version_str);
|
||||||
|
env->ReleaseStringUTFChars(packageId, package_id_str);
|
||||||
|
return env->NewStringUTF(url.c_str());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getBuildVersion(
|
||||||
|
JNIEnv* env,
|
||||||
|
[[maybe_unused]] jobject obj) {
|
||||||
|
return env->NewStringUTF(Common::g_build_version);
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 104 KiB |
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/download_progress_message"
|
||||||
|
style="@style/TextAppearance.Material3.BodyMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:text="0%"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
android:id="@+id/download_progress_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:max="100"
|
||||||
|
android:progress="0"
|
||||||
|
app:indicatorColor="?attr/colorPrimary"
|
||||||
|
app:trackColor="?attr/colorSurfaceVariant"
|
||||||
|
app:trackCornerRadius="4dp"
|
||||||
|
app:trackThickness="8dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
app:cardBackgroundColor="?attr/colorSurfaceVariant">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxHeight="400dp"
|
||||||
|
android:padding="12dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_system_info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||||
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
|
android:textIsSelectable="true" />
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||||
|
|
||||||
<string name="app_disclaimer">سيشغل هذا البرنامج ألعابًا لأجهزة الألعاب نينتندو سويتش. لا يتضمن البرنامج أي ألعاب أو مفاتيح.<br /><br />قبل أن تبدأ، يرجى تحديد موقع <![CDATA[<b> prod.keys </b>]]> ملف على وحدة تخزين جهازك.<br /><br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">اعرف المزيد</a>]]></string>
|
<string name="app_disclaimer">سيشغل هذا البرنامج ألعابًا لأجهزة الألعاب Nintendo Switch. لا يتضمن البرنامج أي ألعاب أو مفاتيح.<br /><br />قبل أن تبدأ، يرجى تحديد موقع <![CDATA[<b> prod.keys </b>]]> ملف على وحدة تخزين جهازك.<br /><br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">اعرف المزيد</a>]]></string>
|
||||||
<string name="notice_notification_channel_name">الإشعارات والأخطاء</string>
|
<string name="notice_notification_channel_name">الإشعارات والأخطاء</string>
|
||||||
<string name="notice_notification_channel_description">عرض الإشعارات عند حدوث خطأ ما.</string>
|
<string name="notice_notification_channel_description">عرض الإشعارات عند حدوث خطأ ما.</string>
|
||||||
<string name="notification_permission_not_granted">لم يتم منح إذن الإشعار!</string>
|
<string name="notification_permission_not_granted">لم يتم منح إذن الإشعار!</string>
|
||||||
<string name="app_notification_channel_description">إشعارات محاكي السويتش Eden</string>
|
<string name="app_notification_channel_description">إشعارات محاكي Eden Switch</string>
|
||||||
<string name="app_notification_running">Eden قيد التشغيل</string>
|
<string name="app_notification_running">Eden قيد التشغيل</string>
|
||||||
<string name="seconds">ثواني</string>
|
<string name="seconds">ثواني</string>
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<string name="enhanced_fps_suffix">(Enhanced)</string>
|
<string name="enhanced_fps_suffix">(Enhanced)</string>
|
||||||
<string name="process_ram">Process RAM: %1$d MB</string>
|
<string name="process_ram">Process RAM: %1$d MB</string>
|
||||||
<string name="shaders_prefix">بناء</string>
|
<string name="shaders_prefix">بناء</string>
|
||||||
<string name="shaders_suffix">مظلل (مظللات)</string>
|
<string name="shaders_suffix">تظليل(ات)</string>
|
||||||
<string name="charging">(يشحن)</string>
|
<string name="charging">(يشحن)</string>
|
||||||
|
|
||||||
<string name="system_info_label">النظام:</string>
|
<string name="system_info_label">النظام:</string>
|
||||||
@@ -53,10 +53,10 @@
|
|||||||
<string name="bat_temperature_unit">وحدات قياس درجة حرارة البطارية</string>
|
<string name="bat_temperature_unit">وحدات قياس درجة حرارة البطارية</string>
|
||||||
<string name="show_power_info">عرض معلومات البطارية</string>
|
<string name="show_power_info">عرض معلومات البطارية</string>
|
||||||
<string name="show_power_info_description">عرض استهلاك الطاقة الحالي والسعة المتبقية في البطارية</string>
|
<string name="show_power_info_description">عرض استهلاك الطاقة الحالي والسعة المتبقية في البطارية</string>
|
||||||
<string name="show_shaders_building">عرض بناء الظلال</string>
|
<string name="show_shaders_building">عرض بناء التظليل</string>
|
||||||
<string name="show_shaders_building_description">عرض عدد الظلال التي يتم بناؤها</string>
|
<string name="show_shaders_building_description">عرض عدد التظليل التي يتم بناؤها</string>
|
||||||
<string name="overlay_position">موضع التراكب</string>
|
<string name="overlay_position">موضع التراكب</string>
|
||||||
<string name="overlay_position_description">اختر مكان عرض التراكب على الشاشة</string>
|
<string name="overlay_position_description">حدد مكان عرض التراكب على الشاشة</string>
|
||||||
<string name="overlay_position_top_left">أعلى اليمين</string>
|
<string name="overlay_position_top_left">أعلى اليمين</string>
|
||||||
<string name="overlay_position_top_right">أعلى اليسار</string>
|
<string name="overlay_position_top_right">أعلى اليسار</string>
|
||||||
<string name="overlay_position_bottom_left">أسفل اليمين</string>
|
<string name="overlay_position_bottom_left">أسفل اليمين</string>
|
||||||
@@ -79,23 +79,23 @@
|
|||||||
<string name="show_soc_model">عرض طراز الرقائق</string>
|
<string name="show_soc_model">عرض طراز الرقائق</string>
|
||||||
<string name="show_soc_model_description">عرض طراز رقائق المضيف</string>
|
<string name="show_soc_model_description">عرض طراز رقائق المضيف</string>
|
||||||
<string name="show_fw_version">عرض إصدار الفيرموير</string>
|
<string name="show_fw_version">عرض إصدار الفيرموير</string>
|
||||||
<string name="show_fw_version_description">عرض إصدار الفيرموير</string>
|
<string name="show_fw_version_description">عرض إصدار الفيرموير المثبت</string>
|
||||||
|
|
||||||
<!-- Eden\'s Veil -->
|
<!-- Eden\'s Veil -->
|
||||||
<string name="eden_veil">حجاب Eden</string>
|
<string name="eden_veil">ميزات Eden</string>
|
||||||
<string name="eden_veil_description">إعدادات تجريبية لتحسين الأداء والقدرة. قد تسبب هذه الإعدادات شاشات سوداء أو مشاكل أخرى في اللعبة.</string>
|
<string name="eden_veil_description">إعدادات تجريبية لتحسين الأداء والقدرة. قد تتسبب هذه الإعدادات في ظهور شاشات سوداء أو مشكلات أخرى في اللعبة.</string>
|
||||||
|
|
||||||
<string name="veil_extensions">امتدادات وحدة معالجة الرسوميات</string>
|
<string name="veil_extensions">ملحقات وحدة معالجة الرسومات</string>
|
||||||
<string name="dyna_state">الحالة الديناميكية الموسعة</string>
|
<string name="dyna_state">الحالة الديناميكية الموسعة</string>
|
||||||
<string name="dyna_state_description">يتحكم في عدد المميزات التي يمكن استخدامها في الحالة الديناميكية الموسعة. الأرقام الأعلى تسمح بميزات أكثر ويمكن أن تعزز الأداء، ولكن قد تسبب مشكلات مع بعض السائقين والبائعين. قد تختلف القيمة الافتراضية بحسب نظامك وقدرات الأجهزة. يمكن تغيير هذه القيمة حتى يتم تحقيق الاستقرار وجودة الصورة الأفضل.</string>
|
<string name="dyna_state_description">يتحكم في عدد المميزات التي يمكن استخدامها في الحالة الديناميكية الموسعة. الأرقام الأعلى تسمح بميزات أكثر ويمكن أن تعزز الأداء، ولكن قد تسبب مشكلات مع بعض السائقين والبائعين. قد تختلف القيمة الافتراضية بحسب نظامك وقدرات الأجهزة. يمكن تغيير هذه القيمة حتى يتم تحقيق الاستقرار وجودة الصورة الأفضل.</string>
|
||||||
<string name="disabled">معطل</string>
|
<string name="disabled">معطل</string>
|
||||||
<string name="provoking_vertex">الرأس المثير</string>
|
<string name="provoking_vertex">الرأس المثير</string>
|
||||||
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات التي تدعم فولكان 1.0+</string>
|
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات Vulkan 1.0+.</string>
|
||||||
<string name="descriptor_indexing">فهرسة الوصف</string>
|
<string name="descriptor_indexing">فهرسة الوصف</string>
|
||||||
<string name="descriptor_indexing_description">يحسن معالجة النسيج والمخزن المؤقت، بالإضافة إلى طبقة الترجمة Maxwell. مدعوم من بعض وحدات معالجة الرسومات Vulkan 1.1 وجميع وحدات معالجة الرسومات Vulkan 1.2+.</string>
|
<string name="descriptor_indexing_description">يحسن معالجة النسيج والمخزن المؤقت، بالإضافة إلى طبقة الترجمة Maxwell. مدعوم من بعض وحدات معالجة الرسومات Vulkan 1.1 وجميع وحدات معالجة الرسومات Vulkan 1.2+.</string>
|
||||||
<string name="sample_shading">تظليل العينة</string>
|
<string name="sample_shading">تظليل العينة</string>
|
||||||
<string name="sample_shading_description">يسمح لمظلل الأجزاء بتنفيذ كل عينة في جزء متعدد العينات بدلاً من مرة واحدة لكل جزء. يحسن جودة الرسومات على حساب بعض الأداء. لا تدعم هذه الإضافة سوى أجهزة Vulkan 1.1+ فقط.</string>
|
<string name="sample_shading_description">يُتيح لمُكَوِّن التظليل الجزئي تنفيذ العملية لكل عينة في القسم متعدد العينات بدلاً من تنفيذها مرة واحدة لكل قسم. يُحسّن جودة الرسومات على حساب بعض الأداء. تدعم هذه الإضافة الأجهزة التي تعمل بنظام Vulkan 1.1 وما فوق فقط.</string>
|
||||||
<string name="sample_shading_fraction">كسر التظليل العيني</string>
|
<string name="sample_shading_fraction">نسبة التظليل النموذجية</string>
|
||||||
<string name="sample_shading_fraction_description">كثافة تمرير تظليل العينة. تؤدي القيم الأعلى إلى تحسين الجودة بشكل أكبر، ولكنها تقلل أيضًا من الأداء إلى حد كبير.</string>
|
<string name="sample_shading_fraction_description">كثافة تمرير تظليل العينة. تؤدي القيم الأعلى إلى تحسين الجودة بشكل أكبر، ولكنها تقلل أيضًا من الأداء إلى حد كبير.</string>
|
||||||
|
|
||||||
<string name="veil_renderer">العارض</string>
|
<string name="veil_renderer">العارض</string>
|
||||||
@@ -111,27 +111,27 @@
|
|||||||
<string name="veil_misc">وحدة المعالجة المركزية والذاكرة</string>
|
<string name="veil_misc">وحدة المعالجة المركزية والذاكرة</string>
|
||||||
<string name="use_sync_core">مزامنة سرعة النواة</string>
|
<string name="use_sync_core">مزامنة سرعة النواة</string>
|
||||||
<string name="use_sync_core_description">مزامنة سرعة النواة مع النسبة القصوى للسرعة لتحسين الأداء دون تغيير السرعة الفعلية للعبة.</string>
|
<string name="use_sync_core_description">مزامنة سرعة النواة مع النسبة القصوى للسرعة لتحسين الأداء دون تغيير السرعة الفعلية للعبة.</string>
|
||||||
<string name="use_lru_cache">تمكين ذاكرة التخزين المؤقت LRU</string>
|
<string name="use_lru_cache">تمكين ذاكرة التخزين المؤقتة LRU</string>
|
||||||
<string name="use_lru_cache_description">تمكين أو تعطيل ذاكرة التخزين المؤقت الأقل استخداماً مؤخراً (LRU) لتحسين الأداء عن طريق تقليل استخدام وحدة المعالجة المركزية. بعض الألعاب قد تواجه مشاكل معه، خاصةً TotK 1.2.1، لذا قم بتعطيله إذا لم تعمل اللعبة أو انهارت عشوائياً.</string>
|
<string name="use_lru_cache_description">قم بتمكين أو تعطيل ذاكرة التخزين المؤقتة الأقل استخدامًا (LRU)، مما يزيد من الأداء عن طريق توفير استخدام معالج وحدة المعالجة المركزية. قد تواجه بعض الألعاب مشكلات مع هذا الإعداد، لذا قم بتعطيله إذا لم يتم تشغيل اللعبة أو تعطلت بشكل عشوائي.</string>
|
||||||
<string name="use_fast_cpu_time">وقت وحدة المعالجة المركزية السريع</string>
|
<string name="use_fast_cpu_time">وقت وحدة المعالجة المركزية السريع</string>
|
||||||
<string name="use_fast_cpu_time_description">يجبر وحدة المعالجة المركزية المحاكاة على العمل بسرعة أعلى، مما يقلل من بعض محددات معدل الإطارات. هذا الخيار غير مستقر وقد يسبب مشاكل، وقد يرى المستخدمون بأجهزة أضعف انخفاضًا في الأداء.</string>
|
<string name="use_fast_cpu_time_description">يجبر وحدة المعالجة المركزية المحاكاة على العمل بسرعة أعلى، مما يقلل من بعض محددات معدل الإطارات. هذا الخيار غير مستقر وقد يسبب مشاكل، وقد يرى المستخدمون بأجهزة أضعف انخفاضًا في الأداء.</string>
|
||||||
<string name="custom_cpu_ticks">تخصيص دورات المعالج</string>
|
<string name="custom_cpu_ticks">تخصيص دورات المعالج</string>
|
||||||
<string name="custom_cpu_ticks_description">قم بتعيين قيمة مخصصة لدورات المعالج. القيم الأعلى يمكن أن تزيد من الأداء، ولكنها قد تتسبب أيضًا في تجميد اللعبة. يوصى باستخدام نطاق 77-21000.</string>
|
<string name="custom_cpu_ticks_description">قم بتعيين قيمة مخصصة لدورات المعالج. القيم الأعلى يمكن أن تزيد من الأداء، ولكنها قد تتسبب أيضًا في تجميد اللعبة. يوصى باستخدام نطاق 77-21000.</string>
|
||||||
<string name="cpu_ticks">دورات</string>
|
<string name="cpu_ticks">دورات</string>
|
||||||
<string name="skip_cpu_inner_invalidation">تخطي إبطال ذاكرة التخزين المؤقت الداخلية للوحدة المركزية</string>
|
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقت أثناء تحديثات الذاكرة، مما يقلل استخدام المعالج ويحسن أدائه. قد يسبب هذا أعطالاً أو تعطلًا في بعض الألعاب.</string>
|
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu">تمكين محاكاة MMU المضيف</string>
|
<string name="cpuopt_unsafe_host_mmu">تمكين محاكاة MMU المضيف</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu_description">يعمل هذا التحسين على تسريع وصول الذاكرة بواسطة البرنامج الضيف. يؤدي تمكينه إلى إجراء عمليات قراءة/كتابة ذاكرة الضيف مباشرة في الذاكرة والاستفادة من MMU المضيف. يؤدي تعطيل هذا إلى إجبار جميع عمليات الوصول إلى الذاكرة على استخدام محاكاة MMU البرمجية.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">يعمل هذا التحسين على تسريع وصول الذاكرة بواسطة البرنامج الضيف. يؤدي تمكينه إلى إجراء عمليات قراءة/كتابة ذاكرة الضيف مباشرة في الذاكرة والاستفادة من MMU المضيف. يؤدي تعطيل هذا إلى إجبار جميع عمليات الوصول إلى الذاكرة على استخدام محاكاة MMU البرمجية.</string>
|
||||||
<string name="fast_cpu_time">CPU Clock</string>
|
<string name="fast_cpu_time">CPU Clock</string>
|
||||||
<string name="fast_cpu_time_description">استخدم Boost (1700MHz) للتشغيل بأعلى سرعة أصلية لـ Switch، أو Fast (2000MHz) للتشغيل بضعف السرعة.</string>
|
<string name="fast_cpu_time_description">استخدم تعزيز (1700MHz) للتشغيل بأعلى سرعة أصلية لـ Switch، أو سريع (2000MHz) للتشغيل بضعف السرعة.</string>
|
||||||
<string name="memory_layout">تخطيط الذاكرة</string>
|
<string name="memory_layout">تخطيط الذاكرة</string>
|
||||||
<string name="memory_layout_description">(تجريبي) تغيير تخطيط الذاكرة المحاكي. هذا الإعداد لن يزيد من الأداء، ولكن قد يساعد في الألعاب باستخدام قرارات عالية عبر التعديلات. لا تستخدم على الهواتف التي تحتوي على 8GB من ذاكرة الوصول العشوائي أو أقل. يعمل فقط على الواجهة الخلفية الديناميكية (JIT).</string>
|
<string name="memory_layout_description">(تجريبي) تغيير تخطيط الذاكرة المحاكي. هذا الإعداد لن يزيد من الأداء، ولكن قد يساعد في الألعاب باستخدام قرارات عالية عبر التعديلات. لا تستخدم على الهواتف التي تحتوي على 8GB من ذاكرة الوصول العشوائي أو أقل. يعمل فقط على الواجهة الخلفية الديناميكية (JIT).</string>
|
||||||
<string name="dma_accuracy">دقة DMA</string>
|
<string name="dma_accuracy">دقة DMA</string>
|
||||||
<string name="dma_accuracy_description">يتحكم في دقة تحديد DMA. يمكن أن تصلح الدقة الآمنة المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اترك هذا على الوضع الافتراضي.</string>
|
<string name="dma_accuracy_description">يتحكم في دقة تحديد DMA. يمكن أن تصلح الدقة الآمنة المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اترك هذا على الوضع الافتراضي.</string>
|
||||||
|
|
||||||
<!-- Shader Backend -->
|
<!-- Shader Backend -->
|
||||||
<string name="shader_backend">واجهة برمجة الظلال</string>
|
<string name="shader_backend">واجهة برمجة التظليل</string>
|
||||||
<string name="shader_backend_description">Choose how shaders are compiled and translated for your GPU.</string>
|
<string name="shader_backend_description">حدد كيفية تجميع وترجمة برامج التظليل لوحدة معالجة الرسومات الخاصة بك.</string>
|
||||||
<string name="shader_backend_glsl">GLSL</string>
|
<string name="shader_backend_glsl">GLSL</string>
|
||||||
<string name="shader_backend_glasm">GLASM</string>
|
<string name="shader_backend_glasm">GLASM</string>
|
||||||
<string name="shader_backend_spirv">Spir-V</string>
|
<string name="shader_backend_spirv">Spir-V</string>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<string name="multiplayer_join_room_success">تم الانضمام إلى الغرفة بنجاح</string>
|
<string name="multiplayer_join_room_success">تم الانضمام إلى الغرفة بنجاح</string>
|
||||||
<string name="multiplayer_exit_room">مغادرة الغرفة</string>
|
<string name="multiplayer_exit_room">مغادرة الغرفة</string>
|
||||||
<string name="multiplayer_network_error">خطأ في الشبكة</string>
|
<string name="multiplayer_network_error">خطأ في الشبكة</string>
|
||||||
<string name="multiplayer_lost_connection">فقدان الاتصال</string>
|
<string name="multiplayer_lost_connection">انقطع الاتصال</string>
|
||||||
<string name="multiplayer_name_collision">اسم المستخدم محجوز مسبقاً</string>
|
<string name="multiplayer_name_collision">اسم المستخدم محجوز مسبقاً</string>
|
||||||
<string name="multiplayer_mac_collision">تعارض عناوين MAC</string>
|
<string name="multiplayer_mac_collision">تعارض عناوين MAC</string>
|
||||||
<string name="multiplayer_console_id_collision">تعارض معرف وحدة التحكم</string>
|
<string name="multiplayer_console_id_collision">تعارض معرف وحدة التحكم</string>
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
<string name="multiplayer_room_is_full">الغرفة ممتلئة</string>
|
<string name="multiplayer_room_is_full">الغرفة ممتلئة</string>
|
||||||
<string name="multiplayer_host_banned">أنت محظور من هذه الغرفة</string>
|
<string name="multiplayer_host_banned">أنت محظور من هذه الغرفة</string>
|
||||||
<string name="multiplayer_permission_denied">تم رفض الإذن</string>
|
<string name="multiplayer_permission_denied">تم رفض الإذن</string>
|
||||||
<string name="multiplayer_no_such_user">لا يوجد مثل هذا المستخدم</string>
|
<string name="multiplayer_no_such_user">لا يوجد مستخدم بهذا الاسم</string>
|
||||||
<string name="multiplayer_already_in_room">موجود بالفعل في الغرفة</string>
|
<string name="multiplayer_already_in_room">موجود بالفعل في الغرفة</string>
|
||||||
<string name="multiplayer_create_room_error">خطأ في إنشاء الغرفة</string>
|
<string name="multiplayer_create_room_error">خطأ في إنشاء الغرفة</string>
|
||||||
<string name="multiplayer_host_kicked">تم طرد المضيف</string>
|
<string name="multiplayer_host_kicked">تم طرد المضيف</string>
|
||||||
@@ -195,6 +195,7 @@
|
|||||||
<string name="multiplayer_chat">الدردشة</string>
|
<string name="multiplayer_chat">الدردشة</string>
|
||||||
<string name="multiplayer_more_options">المزيد من الخيارات</string>
|
<string name="multiplayer_more_options">المزيد من الخيارات</string>
|
||||||
<string name="chat">الدردشة</string>
|
<string name="chat">الدردشة</string>
|
||||||
|
<string name="clear">مسح</string>
|
||||||
<string name="type_message">اكتب رسالة…</string>
|
<string name="type_message">اكتب رسالة…</string>
|
||||||
<string name="send_message">إرسال رسالة</string>
|
<string name="send_message">إرسال رسالة</string>
|
||||||
<string name="multiplayer_moderation">الإشراف</string>
|
<string name="multiplayer_moderation">الإشراف</string>
|
||||||
@@ -214,7 +215,7 @@
|
|||||||
<string name="multiplayer_hide_full_rooms">إخفاء الغرف الممتلئة</string>
|
<string name="multiplayer_hide_full_rooms">إخفاء الغرف الممتلئة</string>
|
||||||
<string name="multiplayer_hide_empty_rooms">إخفاء الغرف الفارغة</string>
|
<string name="multiplayer_hide_empty_rooms">إخفاء الغرف الفارغة</string>
|
||||||
<string name="multiplayer_tap_refresh_to_check_again">اضغط على تحديث للتحقق مرة أخرى</string>
|
<string name="multiplayer_tap_refresh_to_check_again">اضغط على تحديث للتحقق مرة أخرى</string>
|
||||||
<string name="multiplayer_search_public_lobbies">البحث في الغرف…</string>
|
<string name="multiplayer_search_public_lobbies">البحث في القائمة…</string>
|
||||||
<string name="multiplayer_preferred_game_name">اللعبة المفضلة</string>
|
<string name="multiplayer_preferred_game_name">اللعبة المفضلة</string>
|
||||||
<string name="multiplayer_lobby_type">نوع الغرفة</string>
|
<string name="multiplayer_lobby_type">نوع الغرفة</string>
|
||||||
<string name="multiplayer_room_name_error">يجب أن يتكون من 3 إلى 20 حرفًا</string>
|
<string name="multiplayer_room_name_error">يجب أن يتكون من 3 إلى 20 حرفًا</string>
|
||||||
@@ -222,7 +223,7 @@
|
|||||||
<string name="multiplayer_token_required">مطلوب رمز ويب، انتقل إلى الإعدادات المتقدمة -> النظام -> الشبكة</string>
|
<string name="multiplayer_token_required">مطلوب رمز ويب، انتقل إلى الإعدادات المتقدمة -> النظام -> الشبكة</string>
|
||||||
<string name="multiplayer_ip_error">تنسيق IP غير صالح</string>
|
<string name="multiplayer_ip_error">تنسيق IP غير صالح</string>
|
||||||
<string name="multiplayer_username_error">يجب أن يتكون من 4 إلى 20 حرفًا، وأن يحتوي على أحرف أبجدية رقمية ونقاط وشرطات وشرطات سفلية ومسافات فقط</string>
|
<string name="multiplayer_username_error">يجب أن يتكون من 4 إلى 20 حرفًا، وأن يحتوي على أحرف أبجدية رقمية ونقاط وشرطات وشرطات سفلية ومسافات فقط</string>
|
||||||
<string name="multiplayer_nickname_invalid">اسم مستخدم غير صالح، تأكد من إعداده بشكل صحيح في النظام → الشبكة</string>
|
<string name="multiplayer_nickname_invalid">اسم مستخدم غير صالح، تأكد من إعداده بشكل صحيح في النظام -> الشبكة </string>
|
||||||
<string name="multiplayer_token_error">يجب أن يتكون من 48 حرفًا، وأحرف صغيرة من a-z فقط</string>
|
<string name="multiplayer_token_error">يجب أن يتكون من 48 حرفًا، وأحرف صغيرة من a-z فقط</string>
|
||||||
<string name="multiplayer_port_error">يجب أن يكون بين 1 و65535</string>
|
<string name="multiplayer_port_error">يجب أن يكون بين 1 و65535</string>
|
||||||
<string name="cancel">إلغاء</string>
|
<string name="cancel">إلغاء</string>
|
||||||
@@ -237,16 +238,16 @@
|
|||||||
<string name="welcome_description">تعلم كيفية إعداد <b>Eden</b> والبدء في المحاكاة.</string>
|
<string name="welcome_description">تعلم كيفية إعداد <b>Eden</b> والبدء في المحاكاة.</string>
|
||||||
<string name="get_started">ابدأ الآن</string>
|
<string name="get_started">ابدأ الآن</string>
|
||||||
<string name="keys">المفاتيح</string>
|
<string name="keys">المفاتيح</string>
|
||||||
<string name="keys_description">اختر ملف <b>prod.keys</b> الخاص بك باستخدام الزر أدناه.</string>
|
<string name="keys_description">حدد ملف <b>prod.keys</b> الخاص بك باستخدام الزر أدناه.</string>
|
||||||
<string name="select_keys">اختر المفاتيح</string>
|
<string name="select_keys">حدد المفاتيح</string>
|
||||||
<string name="firmware">الفيرموير</string>
|
<string name="firmware">الفيرموير</string>
|
||||||
<string name="firmware_description">قم بتحديد ملف <b>firmware.zip</b> الخاص بك باستخدام الزر الموجود أدناه.</string>
|
<string name="firmware_description">حدد ملف <b>firmware.zip</b> الخاص بك باستخدام الزر أدناه.</string>
|
||||||
<string name="select_firmware">حدد الفيرموير</string>
|
<string name="select_firmware">حدد الفيرموير</string>
|
||||||
<string name="games">الألعاب</string>
|
<string name="games">الألعاب</string>
|
||||||
<string name="games_description">حدد مجلد <b>الألعاب</b> الخاص بك باستخدام الزر أدناه.</string>
|
<string name="games_description">حدد مجلد <b>الألعاب</b> الخاص بك باستخدام الزر أدناه.</string>
|
||||||
<string name="done">إنهاء</string>
|
<string name="done">إنهاء</string>
|
||||||
<string name="done_description">أنت جاهز تمامًا.\nاستمتع بألعابك!</string>
|
<string name="done_description">أنت جاهز تمامًا.\nاستمتع بألعابك!</string>
|
||||||
<string name="text_continue">استمر</string>
|
<string name="text_continue">متابعة</string>
|
||||||
<string name="next">التالي</string>
|
<string name="next">التالي</string>
|
||||||
<string name="back">عودة</string>
|
<string name="back">عودة</string>
|
||||||
<string name="add_games">إضافة الألعاب</string>
|
<string name="add_games">إضافة الألعاب</string>
|
||||||
@@ -264,17 +265,17 @@
|
|||||||
<string name="dont_show_again">لا تعرض مرة أخرى</string>
|
<string name="dont_show_again">لا تعرض مرة أخرى</string>
|
||||||
<string name="add_directory_success">تمت إضافة مجلد اللعبة الجديد بنجاح</string>
|
<string name="add_directory_success">تمت إضافة مجلد اللعبة الجديد بنجاح</string>
|
||||||
<string name="enable_update_checks">تحقق من وجود تحديثات عند بدء تشغيل التطبيق.</string>
|
<string name="enable_update_checks">تحقق من وجود تحديثات عند بدء تشغيل التطبيق.</string>
|
||||||
<string name="update_available">تحديث متاح</string>
|
<string name="update_available">تحديث متوفر</string>
|
||||||
<string name="update_available_description">نسخة جديدة متاحة: %1$s\n\nهل ترغب في تنزيلها؟</string>
|
<string name="update_available_description">يتوفر إصدار جديد: %1$s\n\nهل ترغب في تنزيله؟</string>
|
||||||
<string name="home_search">البحث</string>
|
<string name="home_search">البحث</string>
|
||||||
<string name="home_settings">الإعدادات</string>
|
<string name="home_settings">الإعدادات</string>
|
||||||
<string name="empty_gamelist">لم يتم العثور على ملفات أو لم يتم تحديد مجلد الألعاب حتى الآن.</string>
|
<string name="empty_gamelist">لم يتم العثور على أي ملفات أو لم يتم تحديد أي مجلد ألعاب بعد.</string>
|
||||||
<string name="manage_game_folders">إدارة مجلدات اللعبة</string>
|
<string name="manage_game_folders">إدارة مجلدات اللعبة</string>
|
||||||
<string name="select_games_folder_description">يسمح لـ Eden بملء قائمة الألعاب</string>
|
<string name="select_games_folder_description">يسمح لـ Eden بملء قائمة الألعاب</string>
|
||||||
<string name="add_games_warning">تخطي تحديد مجلد الألعاب؟</string>
|
<string name="add_games_warning">تخطي تحديد مجلد الألعاب؟</string>
|
||||||
<string name="add_games_warning_description">لن يتم عرض الألعاب في قائمة الألعاب إذا لم يتم تحديد مجلد.</string>
|
<string name="add_games_warning_description">لن يتم عرض الألعاب في قائمة الألعاب إذا لم يتم تحديد مجلد.</string>
|
||||||
<string name="add_games_warning_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-games</string>
|
<string name="add_games_warning_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-games</string>
|
||||||
<string name="home_search_games">البحث عن الألعاب</string>
|
<string name="home_search_games">البحث عن ألعاب</string>
|
||||||
<string name="search_settings">إعدادات البحث</string>
|
<string name="search_settings">إعدادات البحث</string>
|
||||||
<string name="install_prod_keys">تثبيت prod.keys</string>
|
<string name="install_prod_keys">تثبيت prod.keys</string>
|
||||||
<string name="install_prod_keys_description">مطلوب لفك تشفير ألعاب البيع بالتجزئة</string>
|
<string name="install_prod_keys_description">مطلوب لفك تشفير ألعاب البيع بالتجزئة</string>
|
||||||
@@ -292,7 +293,26 @@
|
|||||||
<string name="permission_denied">تم رفض الإذن</string>
|
<string name="permission_denied">تم رفض الإذن</string>
|
||||||
<string name="permission_denied_description">لقد رفضت هذا الإذن عدة مرات ويتعين عليك الآن منحه يدويًا في إعدادات النظام</string>
|
<string name="permission_denied_description">لقد رفضت هذا الإذن عدة مرات ويتعين عليك الآن منحه يدويًا في إعدادات النظام</string>
|
||||||
<string name="about">حول</string>
|
<string name="about">حول</string>
|
||||||
<string name="about_description">بناء الإصدار، والاعتمادات، وأكثر من ذلك</string>
|
<string name="about_description">إصدار البرنامج، الاعتمادات، والمزيد</string>
|
||||||
|
<string name="system_information">معلومات النظام</string>
|
||||||
|
<string name="system_information_description">عرض معلومات تفصيلية عن الجهاز</string>
|
||||||
|
<string name="device_manufacturer">الشركة المصنعة</string>
|
||||||
|
<string name="device_model">طراز</string>
|
||||||
|
<string name="product">المنتج</string>
|
||||||
|
<string name="android_version">إصدار Android</string>
|
||||||
|
<string name="android_security_patch">تصحيح الأمان</string>
|
||||||
|
<string name="build_id">معرف البناء</string>
|
||||||
|
<string name="general_information">معلومات عامة</string>
|
||||||
|
<string name="hardware">الأجهزة</string>
|
||||||
|
<string name="supported_abis">واجهات برمجة التطبيقات المدعومة</string>
|
||||||
|
<string name="cpu_info">معلومات وحدة المعالجة المركزية</string>
|
||||||
|
<string name="gpu_information">معلومات وحدة معالجة الرسومات</string>
|
||||||
|
<string name="vulkan_driver_version">إصدار برنامج تشغيل Vulkan</string>
|
||||||
|
<string name="error_getting_emulator_info">خطأ في الحصول على معلومات المحاكي</string>
|
||||||
|
<string name="memory_info">معلومات الذاكرة</string>
|
||||||
|
<string name="total_memory">إجمالي الذاكرة</string>
|
||||||
|
<string name="soc">نظام الرقاقة:</string>
|
||||||
|
|
||||||
<string name="warning_help">مساعدة</string>
|
<string name="warning_help">مساعدة</string>
|
||||||
<string name="warning">تحذير</string>
|
<string name="warning">تحذير</string>
|
||||||
<string name="warning_skip">تخطي</string>
|
<string name="warning_skip">تخطي</string>
|
||||||
@@ -310,12 +330,12 @@
|
|||||||
<string name="open_user_folder_description">إدارة الملفات الداخلية لـ Eden</string>
|
<string name="open_user_folder_description">إدارة الملفات الداخلية لـ Eden</string>
|
||||||
<string name="app_settings_description">تعديل سلوك ومظهر التطبيق</string>
|
<string name="app_settings_description">تعديل سلوك ومظهر التطبيق</string>
|
||||||
<string name="no_file_manager">لم يتم العثور على مدير الملفات</string>
|
<string name="no_file_manager">لم يتم العثور على مدير الملفات</string>
|
||||||
<string name="notification_no_directory_link">لا يمكن فتح مجلد Eden</string>
|
<string name="notification_no_directory_link">تعذر فتح مجلد Eden</string>
|
||||||
<string name="notification_no_directory_link_description">يرجى تحديد موقع مجلد المستخدم يدويًا باستخدام اللوحة الجانبية لمدير الملفات.</string>
|
<string name="notification_no_directory_link_description">يرجى تحديد موقع مجلد المستخدم يدويًا باستخدام اللوحة الجانبية لمدير الملفات.</string>
|
||||||
<string name="manage_save_data">إدارة حفظ البيانات</string>
|
<string name="manage_save_data">إدارة بيانات الحفظ</string>
|
||||||
<string name="manage_save_data_description">حفظ البيانات التي تم العثور عليها. يرجى اختيار أحد الخيارات التالية</string>
|
<string name="manage_save_data_description">تم العثور على بيانات محفوظة. يرجى تحديد أحد الخيارات أدناه.</string>
|
||||||
<string name="import_save_warning">استيراد حفظ البيانات</string>
|
<string name="import_save_warning">استيراد بيانات الحفظ</string>
|
||||||
<string name="import_save_warning_description">سيؤدي هذا إلى استبدال جميع بيانات الحفظ الموجودة بالملف المقدم. هل أنت متأكد أنك تريد الاستمرار؟</string>
|
<string name="import_save_warning_description">سيؤدي هذا إلى استبدال جميع البيانات المحفوظة الموجودة بالملف المقدم. هل أنت متأكد من أنك تريد المتابعة؟</string>
|
||||||
<string name="save_files_importing">جارٍ استيراد ملفات الحفظ…</string>
|
<string name="save_files_importing">جارٍ استيراد ملفات الحفظ…</string>
|
||||||
<string name="save_files_exporting">جارٍ تصدير ملفات الحفظ...</string>
|
<string name="save_files_exporting">جارٍ تصدير ملفات الحفظ...</string>
|
||||||
<string name="save_file_imported_success">تم الاستيراد بنجاح</string>
|
<string name="save_file_imported_success">تم الاستيراد بنجاح</string>
|
||||||
@@ -336,13 +356,13 @@
|
|||||||
<string name="install_game_content_failure">خطأ في تثبيت الملف(ات) على الذاكرة الداخلية</string>
|
<string name="install_game_content_failure">خطأ في تثبيت الملف(ات) على الذاكرة الداخلية</string>
|
||||||
<string name="install_game_content_failure_description">يرجى التأكد من صحة المحتوى (المحتويات) وتثبيت ملف prod.keys.</string>
|
<string name="install_game_content_failure_description">يرجى التأكد من صحة المحتوى (المحتويات) وتثبيت ملف prod.keys.</string>
|
||||||
<string name="install_game_content_failure_base">لا يُسمح بتثبيت الألعاب الأساسية لتجنب التعارضات المحتملة.</string>
|
<string name="install_game_content_failure_base">لا يُسمح بتثبيت الألعاب الأساسية لتجنب التعارضات المحتملة.</string>
|
||||||
<string name="install_game_content_failed_count">%1$d حدث خطأ (أخطاء) في التثبيت </string>
|
<string name="install_game_content_failed_count">%1$d خطأ (أخطاء) في التثبيت</string>
|
||||||
<string name="install_game_content_success">تم تثبيت محتوى (محتويات) اللعبة بنجاح</string>
|
<string name="install_game_content_success">تم تثبيت محتوى (محتويات) اللعبة بنجاح</string>
|
||||||
<string name="install_game_content_success_install">%1$d تم التثبيت بنجاح</string>
|
<string name="install_game_content_success_install">%1$d تم التثبيت بنجاح</string>
|
||||||
<string name="install_game_content_success_overwrite">%1$d تمت الكتابة فوقه بنجاح</string>
|
<string name="install_game_content_success_overwrite">%1$d تمت الكتابة فوقه بنجاح</string>
|
||||||
<string name="install_game_content_help_link">https://yuzu-mirror.github.io/help/quickstart/#dumping-installed-updates</string>
|
<string name="install_game_content_help_link">https://yuzu-mirror.github.io/help/quickstart/#dumping-installed-updates</string>
|
||||||
<string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string>
|
<string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string>
|
||||||
<string name="custom_driver_not_supported_description">تحميل برنامج التشغيل المخصص غير مدعوم حاليًا لهذا الجهاز. يُرجى إعادة تفعيل هذا الخيار لاحقًا للتحقق من إضافة الدعم.</string>
|
<string name="custom_driver_not_supported_description">لا يتم دعم تحميل برنامج التشغيل المخصص حاليًا لهذا الجهاز.\nتحقق من هذا الخيار مرة أخرى في المستقبل لمعرفة ما إذا تمت إضافة الدعم!</string>
|
||||||
<string name="manage_yuzu_data">إدارة بيانات Eden</string>
|
<string name="manage_yuzu_data">إدارة بيانات Eden</string>
|
||||||
<string name="manage_yuzu_data_description">استيراد/تصدير فيرموير والمفاتيح وبيانات المستخدم والمزيد</string>
|
<string name="manage_yuzu_data_description">استيراد/تصدير فيرموير والمفاتيح وبيانات المستخدم والمزيد</string>
|
||||||
<string name="game_folders">مجلدات اللعبة</string>
|
<string name="game_folders">مجلدات اللعبة</string>
|
||||||
@@ -387,19 +407,19 @@
|
|||||||
<string name="error_keys_failed_init">فشل تهيئة المفاتيح. تحقق من أن أدوات النسخ محدثة وأعد نسخ المفاتيح.</string>
|
<string name="error_keys_failed_init">فشل تهيئة المفاتيح. تحقق من أن أدوات النسخ محدثة وأعد نسخ المفاتيح.</string>
|
||||||
|
|
||||||
<!-- Applet launcher strings -->
|
<!-- Applet launcher strings -->
|
||||||
<string name="qlaunch_applet">الشاشة الرئيسية</string>
|
<string name="qlaunch_applet">القائمة الرئيسية</string>
|
||||||
<string name="qlaunch_description">تشغيل التطبيقات من الشاشة الرئيسية للنظام</string>
|
<string name="qlaunch_description">تشغيل التطبيقات من شاشة النظام الرئيسية</string>
|
||||||
<string name="applets">قائمة التطبيقات المصغرة</string>
|
<string name="applets">مشغل التطبيقات الصغيرة</string>
|
||||||
<string name="applets_description">تطبيقات نظام التشغيل باستخدام الفيرموير المثبتة</string>
|
<string name="applets_description">تشغيل تطبيقات الصغيرة للنظام باستخدام الفيرموير المثبت</string>
|
||||||
<string name="applets_error_firmware">الفيرموير غير مثبت أو إصدار غير صالح</string>
|
<string name="applets_error_firmware">الفيرموير غير مثبت أو إصدار غير صالح</string>
|
||||||
<string name="applets_error_applet">التطبيق المصغر غير متوفر</string>
|
<string name="applets_error_applet">التطبيق الصغير غير متوفر</string>
|
||||||
<string name="applets_error_description"><![CDATA[يرجى التأكد من أن ملف <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> الخاص بك و <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">الفيرموير</a> مثبتة وحاول مرة أخرى.<br>بالإضافة إلى ذلك، تأكد من أن الفيرموير الخاص بك هو من الإصدار 19.0.1 أو أقدم.]]></string>
|
<string name="applets_error_description"><![CDATA[يرجى التأكد من أن ملف <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> الخاص بك و <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">الفيرموير</a> مثبتة وحاول مرة أخرى.<br>بالإضافة إلى ذلك، تأكد من أن الفيرموير الخاص بك هو من الإصدار 19.0.1 أو أقدم.]]></string>
|
||||||
<string name="album_applet">الألبوم</string>
|
<string name="album_applet">الألبوم</string>
|
||||||
<string name="album_applet_description">عرض الصور المخزنة في مجلد لقطات شاشة المستخدم باستخدام عارض صور النظام</string>
|
<string name="album_applet_description">عرض الصور المخزنة في مجلد لقطات شاشة المستخدم باستخدام عارض صور النظام</string>
|
||||||
<string name="mii_edit_applet">تعديل Mii</string>
|
<string name="mii_edit_applet">تحرير Mii</string>
|
||||||
<string name="mii_edit_applet_description">عرض وتحرير Miis باستخدام محرر النظام</string>
|
<string name="mii_edit_applet_description">عرض وتحرير Miis باستخدام محرر النظام</string>
|
||||||
<string name="cabinet_applet">الخزانة</string>
|
<string name="cabinet_applet">الخزانة</string>
|
||||||
<string name="cabinet_applet_description">تعديل وحذف البيانات المخزنة على أميبو</string>
|
<string name="cabinet_applet_description">تحرير وحذف البيانات المخزنة على أميبو</string>
|
||||||
<string name="cabinet_launcher">مشغل الخزانة</string>
|
<string name="cabinet_launcher">مشغل الخزانة</string>
|
||||||
<string name="cabinet_nickname_and_owner">إعدادات الاسم المستعار والمالك</string>
|
<string name="cabinet_nickname_and_owner">إعدادات الاسم المستعار والمالك</string>
|
||||||
<string name="cabinet_game_data_eraser">ممحاة بيانات اللعبة</string>
|
<string name="cabinet_game_data_eraser">ممحاة بيانات اللعبة</string>
|
||||||
@@ -445,7 +465,7 @@
|
|||||||
<string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة في الوقت الفعلي منفصلة عن وقت النظام الحالي لديك</string>
|
<string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة في الوقت الفعلي منفصلة عن وقت النظام الحالي لديك</string>
|
||||||
<string name="set_custom_rtc">تعيين ساعة مخصصة في الوقت الحقيقي</string>
|
<string name="set_custom_rtc">تعيين ساعة مخصصة في الوقت الحقيقي</string>
|
||||||
|
|
||||||
<string name="generate">توليد</string>
|
<string name="generate">إنشاء</string>
|
||||||
|
|
||||||
<!-- Network settings strings -->
|
<!-- Network settings strings -->
|
||||||
<string name="web_token">رمز الويب</string>
|
<string name="web_token">رمز الويب</string>
|
||||||
@@ -457,19 +477,19 @@
|
|||||||
<!-- Graphics settings strings -->
|
<!-- Graphics settings strings -->
|
||||||
<string name="backend">الخلفية</string>
|
<string name="backend">الخلفية</string>
|
||||||
<string name="display">الشاشة</string>
|
<string name="display">الشاشة</string>
|
||||||
<string name="processing">المعالجة اللاحقة</string>
|
<string name="processing">تأثيرات بعد المعالجة</string>
|
||||||
|
|
||||||
<string name="frame_skipping">قيد التطوير: تخطي الإطارات</string>
|
<string name="frame_skipping">قيد التطوير: تخطي الإطارات</string>
|
||||||
<string name="frame_skipping_description">تبديل تخطي الإطارات لتحسين الأداء عن طريق تقليل عدد الإطارات المعروضة. هذه الميزة قيد التطوير وسيتم تمكينها في الإصدارات المستقبلية.</string>
|
<string name="frame_skipping_description">تبديل تخطي الإطارات لتحسين الأداء عن طريق تقليل عدد الإطارات المعروضة. هذه الميزة قيد التطوير وسيتم تمكينها في الإصدارات المستقبلية.</string>
|
||||||
<string name="renderer_accuracy">مستوى الدقة</string>
|
<string name="renderer_accuracy">مستوى الدقة</string>
|
||||||
<string name="renderer_resolution">الدقة (محمول/الإرساء)</string>
|
<string name="renderer_resolution">الدقة (الإرساء/محمول)</string>
|
||||||
<string name="renderer_vsync">VSync وضع</string>
|
<string name="renderer_vsync">VSync وضع</string>
|
||||||
<string name="renderer_screen_layout">اتجاه العرض</string>
|
<string name="renderer_screen_layout">اتجاه العرض</string>
|
||||||
<string name="renderer_aspect_ratio">تناسب الابعاد</string>
|
<string name="renderer_aspect_ratio">نسبة العرض إلى الارتفاع</string>
|
||||||
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
|
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
|
||||||
<string name="fsr_sharpness">حدة FSR</string>
|
<string name="fsr_sharpness">حدة FSR</string>
|
||||||
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
|
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
|
||||||
<string name="renderer_anti_aliasing">طريقة مكافحة التعرج</string>
|
<string name="renderer_anti_aliasing">طريقة مضاد التعرج</string>
|
||||||
<string name="renderer_force_max_clock">إجبار السرعة القصوى (لأجهزة Adreno فقط)</string>
|
<string name="renderer_force_max_clock">إجبار السرعة القصوى (لأجهزة Adreno فقط)</string>
|
||||||
<string name="renderer_force_max_clock_description">يجبر وحدة معالجة الرسومات على العمل بأقصى سرعة ممكنة (سيظل يتم تطبيق القيود الحرارية).</string>
|
<string name="renderer_force_max_clock_description">يجبر وحدة معالجة الرسومات على العمل بأقصى سرعة ممكنة (سيظل يتم تطبيق القيود الحرارية).</string>
|
||||||
<string name="renderer_optimize_spirv_output">تحسين إخراج Spir-V</string>
|
<string name="renderer_optimize_spirv_output">تحسين إخراج Spir-V</string>
|
||||||
@@ -478,11 +498,11 @@
|
|||||||
<string name="renderer_asynchronous_shaders_description">يقوم بتجميع التظليل بشكل غير متزامن. قد يقلل ذلك من التقطعات ولكنه قد يؤدي أيضًا إلى حدوث أخطاء.</string>
|
<string name="renderer_asynchronous_shaders_description">يقوم بتجميع التظليل بشكل غير متزامن. قد يقلل ذلك من التقطعات ولكنه قد يؤدي أيضًا إلى حدوث أخطاء.</string>
|
||||||
<string name="use_fast_gpu_time">استخدم وقت المعالج الرسومي السريع</string>
|
<string name="use_fast_gpu_time">استخدم وقت المعالج الرسومي السريع</string>
|
||||||
<string name="use_fast_gpu_time_description">يجبر معظم الألعاب على التشغيل بأعلى دقة أصلية لها. هذا الخيار غير آمن وقد يتسبب في مشاكل.</string>
|
<string name="use_fast_gpu_time_description">يجبر معظم الألعاب على التشغيل بأعلى دقة أصلية لها. هذا الخيار غير آمن وقد يتسبب في مشاكل.</string>
|
||||||
<string name="fast_gpu_time">عامل زيادة تردد وحدة معالجة الرسوميات</string>
|
<string name="fast_gpu_time">عامل زيادة تردد وحدة معالجة الرسومات</string>
|
||||||
<string name="fast_gpu_time_description">استخدم 128 لأقصى أداء و512 لأقصى دقة رسومية.</string>
|
<string name="fast_gpu_time_description">استخدم 128 لأقصى أداء و512 لأقصى دقة رسومية.</string>
|
||||||
<string name="renderer_reactive_flushing">استخدم التنظيف التفاعلي</string>
|
<string name="renderer_reactive_flushing">استخدم التنظيف التفاعلي</string>
|
||||||
<string name="renderer_reactive_flushing_description">يحسن دقة العرض في بعض الألعاب على حساب الأداء.</string>
|
<string name="renderer_reactive_flushing_description">يحسن دقة العرض في بعض الألعاب على حساب الأداء.</string>
|
||||||
<string name="use_disk_shader_cache">ذاكرة التخزين المؤقت للتظليل</string>
|
<string name="use_disk_shader_cache">ذاكرة التخزين المؤقتة لتظلل القرص</string>
|
||||||
<string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string>
|
<string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string>
|
||||||
<string name="anisotropic_filtering">تصفية متباينة الخواص</string>
|
<string name="anisotropic_filtering">تصفية متباينة الخواص</string>
|
||||||
<string name="anisotropic_filtering_description">يحسن جودة الأنسجة عند عرضها بزوايا مائلة</string>
|
<string name="anisotropic_filtering_description">يحسن جودة الأنسجة عند عرضها بزوايا مائلة</string>
|
||||||
@@ -500,7 +520,7 @@
|
|||||||
<string name="renderer_debug_description">يضبط واجهة برمجة التطبيقات الرسومية على وضع تصحيح الأخطاء البطيء.</string>
|
<string name="renderer_debug_description">يضبط واجهة برمجة التطبيقات الرسومية على وضع تصحيح الأخطاء البطيء.</string>
|
||||||
<string name="fastmem">Fastmem</string>
|
<string name="fastmem">Fastmem</string>
|
||||||
|
|
||||||
<string name="log">تسجيل الدخول</string>
|
<string name="log">السجلات</string>
|
||||||
<string name="flush_by_line">تفريغ سجلات التصحيح حسب السطر</string>
|
<string name="flush_by_line">تفريغ سجلات التصحيح حسب السطر</string>
|
||||||
<string name="flush_by_line_description">يفرغ سجلات التصحيح عند كتابة كل سطر، مما يجعل التصحيح أسهل في حالات التوقف أو التجميد.</string>
|
<string name="flush_by_line_description">يفرغ سجلات التصحيح عند كتابة كل سطر، مما يجعل التصحيح أسهل في حالات التوقف أو التجميد.</string>
|
||||||
|
|
||||||
@@ -532,46 +552,46 @@
|
|||||||
<string name="pressed">مضغوط</string>
|
<string name="pressed">مضغوط</string>
|
||||||
<string name="range">النطاق</string>
|
<string name="range">النطاق</string>
|
||||||
<string name="deadzone">المنطقة الميتة</string>
|
<string name="deadzone">المنطقة الميتة</string>
|
||||||
<string name="modifier">المعدل</string>
|
<string name="modifier">تعديل</string>
|
||||||
<string name="modifier_range">نطاق المعدل</string>
|
<string name="modifier_range">تعديل النطاق</string>
|
||||||
<string name="triggers">المحفزات</string>
|
<string name="triggers">المحفزات</string>
|
||||||
<string name="button_l">L</string>
|
<string name="button_l">L</string>
|
||||||
<string name="button_r">R</string>
|
<string name="button_r">R</string>
|
||||||
<string name="button_zl">ZL</string>
|
<string name="button_zl">ZL</string>
|
||||||
<string name="button_zr">ZR</string>
|
<string name="button_zr">ZR</string>
|
||||||
<string name="button_sl_left">Left SL</string>
|
<string name="button_sl_left">SL الأيسر</string>
|
||||||
<string name="button_sr_left">Left SR</string>
|
<string name="button_sr_left">SR الأيسر</string>
|
||||||
<string name="button_sl_right">Right SL</string>
|
<string name="button_sl_right">SL الأيمن</string>
|
||||||
<string name="button_sr_right">Right SR</string>
|
<string name="button_sr_right">SR الأيمن</string>
|
||||||
<string name="button_z">Z</string>
|
<string name="button_z">Z</string>
|
||||||
<string name="invalid">غير صالح</string>
|
<string name="invalid">غير صالح</string>
|
||||||
<string name="not_set">غير محدد</string>
|
<string name="not_set">غير محدد</string>
|
||||||
<string name="unknown">غير معروف</string>
|
<string name="unknown">غير معروف</string>
|
||||||
<string name="qualified_hat">%1$s%2$s%3$sHat %4$s</string>
|
<string name="qualified_hat">%1$s%2$s%3$sHat %4$s</string>
|
||||||
<string name="qualified_button_stick_axis">%1$s%2$s%3$sAxis %4$s</string>
|
<string name="qualified_button_stick_axis">%1$s%2$s%3$sالمحور %4$s</string>
|
||||||
<string name="qualified_button">%1$s%2$s%3$sزر %4$s</string>
|
<string name="qualified_button">%1$s%2$s%3$sزر %4$s</string>
|
||||||
<string name="qualified_axis">Axis %1$s%2$s</string>
|
<string name="qualified_axis">المحور %1$s%2$s</string>
|
||||||
<string name="unused">غير مستخدم</string>
|
<string name="unused">غير مستخدم</string>
|
||||||
<string name="input_mapping_filter">مرشح تعيين الإدخال</string>
|
<string name="input_mapping_filter">مرشح تعيين الإدخال</string>
|
||||||
<string name="input_mapping_filter_description">حدد جهازًا لتصفية مدخلات التعيين</string>
|
<string name="input_mapping_filter_description">حدد جهازًا لتصفية مدخلات التعيين</string>
|
||||||
<string name="auto_map">تعيين ذراع التحكم تلقائيًا</string>
|
<string name="auto_map">تعيين ذراع التحكم تلقائيًا</string>
|
||||||
<string name="auto_map_description">حدد جهازًا لمحاولة التعيين التلقائي</string>
|
<string name="auto_map_description">حدد جهازًا لمحاولة التعيين التلقائي</string>
|
||||||
<string name="attempted_auto_map">تم محاولة التعيين التلقائي باستخدام %1$s</string>
|
<string name="attempted_auto_map">محاولة التعيين التلقائي مع %1$s</string>
|
||||||
<string name="controller_type">نوع ذراع التحكم</string>
|
<string name="controller_type">نوع ذراع التحكم</string>
|
||||||
<string name="pro_controller">Pro Controller</string>
|
<string name="pro_controller">Pro Controller</string>
|
||||||
<string name="handheld">محمول</string>
|
<string name="handheld">محمول</string>
|
||||||
<string name="dual_joycons">جوي كون ثنائي</string>
|
<string name="dual_joycons">جوي كون ثنائي</string>
|
||||||
<string name="left_joycon">جوي كون اليسرى</string>
|
<string name="left_joycon">جوي كون اليسرى</string>
|
||||||
<string name="right_joycon">جوي كون اليمنى</string>
|
<string name="right_joycon">جوي كون اليمنى</string>
|
||||||
<string name="gamecube_controller">GameCube ذراع تحكم</string>
|
<string name="gamecube_controller">ذراع تحكم GameCube</string>
|
||||||
<string name="invert_axis">عكس المحور</string>
|
<string name="invert_axis">عكس المحور</string>
|
||||||
<string name="invert_button">Invert button</string>
|
<string name="invert_button">عكس الزر</string>
|
||||||
<string name="toggle_button">Toggle button</string>
|
<string name="toggle_button">زر التبديل</string>
|
||||||
<string name="turbo_button">Turbo button</string>
|
<string name="turbo_button">زر التوربو</string>
|
||||||
<string name="set_threshold">Set threshold</string>
|
<string name="set_threshold">تعيين الحد الفاصل</string>
|
||||||
<string name="toggle_axis">Toggle axis</string>
|
<string name="toggle_axis">تبديل المحور</string>
|
||||||
<string name="connected">متصل</string>
|
<string name="connected">متصل</string>
|
||||||
<string name="use_system_vibrator">استخدام هزاز النظام</string>
|
<string name="use_system_vibrator">استخدم هزاز النظام</string>
|
||||||
<string name="input_overlay">تراكب الإدخال</string>
|
<string name="input_overlay">تراكب الإدخال</string>
|
||||||
<string name="vibration">الاهتزاز</string>
|
<string name="vibration">الاهتزاز</string>
|
||||||
<string name="vibration_strength">قوة الاهتزاز</string>
|
<string name="vibration_strength">قوة الاهتزاز</string>
|
||||||
@@ -587,7 +607,7 @@
|
|||||||
<string name="stick_map_description">حرك العصا إلى اليسار ثم للأعلى أو اضغط على زر</string>
|
<string name="stick_map_description">حرك العصا إلى اليسار ثم للأعلى أو اضغط على زر</string>
|
||||||
<string name="button_map_description">اضغط على زر أو حرك الزناد/العصا</string>
|
<string name="button_map_description">اضغط على زر أو حرك الزناد/العصا</string>
|
||||||
<string name="map_dpad_direction">تعيين الأسهم %1$s</string>
|
<string name="map_dpad_direction">تعيين الأسهم %1$s</string>
|
||||||
<string name="map_control">تعيين %1$s</string>
|
<string name="map_control">تعيين إلى %1$s</string>
|
||||||
<string name="failed_to_load_profile">فشل تحميل ملف التعريف</string>
|
<string name="failed_to_load_profile">فشل تحميل ملف التعريف</string>
|
||||||
<string name="failed_to_save_profile">فشل في حفظ ملف التعريف</string>
|
<string name="failed_to_save_profile">فشل في حفظ ملف التعريف</string>
|
||||||
<string name="reset_mapping">إعادة تعيين التعيينات</string>
|
<string name="reset_mapping">إعادة تعيين التعيينات</string>
|
||||||
@@ -616,7 +636,7 @@
|
|||||||
<string name="install">تثبيت</string>
|
<string name="install">تثبيت</string>
|
||||||
<string name="fetch">جلب</string>
|
<string name="fetch">جلب</string>
|
||||||
<string name="delete">حذف</string>
|
<string name="delete">حذف</string>
|
||||||
<string name="edit">تعديل</string>
|
<string name="edit">تحرير</string>
|
||||||
<string name="import_success">تم الاستيراد بنجاح</string>
|
<string name="import_success">تم الاستيراد بنجاح</string>
|
||||||
<string name="export_success">تم التصدير بنجاح</string>
|
<string name="export_success">تم التصدير بنجاح</string>
|
||||||
<string name="start">بدء</string>
|
<string name="start">بدء</string>
|
||||||
@@ -642,7 +662,7 @@
|
|||||||
<string name="error_during_fetch">خطأ أثناء الجلب</string>
|
<string name="error_during_fetch">خطأ أثناء الجلب</string>
|
||||||
<string name="show_downloads">عرض التنزيلات</string>
|
<string name="show_downloads">عرض التنزيلات</string>
|
||||||
<string name="hide_downloads">إخفاء التنزيلات</string>
|
<string name="hide_downloads">إخفاء التنزيلات</string>
|
||||||
<string name="failed_cache_dir">دليل الذاكرة المؤقتة غير متاح</string>
|
<string name="failed_cache_dir">مجلد ذاكرة التخزين المؤقتة غير متوفر</string>
|
||||||
<string name="empty_response_body">نص الاستجابة فارغ</string>
|
<string name="empty_response_body">نص الاستجابة فارغ</string>
|
||||||
<string name="successfully_installed">تم تثبيت %1$s بنجاح</string>
|
<string name="successfully_installed">تم تثبيت %1$s بنجاح</string>
|
||||||
<string name="driver_failed_title">فشل تثبيت برنامج التشغيل</string>
|
<string name="driver_failed_title">فشل تثبيت برنامج التشغيل</string>
|
||||||
@@ -652,18 +672,18 @@
|
|||||||
<string name="installing">جارٍ التثبيت...</string>
|
<string name="installing">جارٍ التثبيت...</string>
|
||||||
<string name="latest">الأحدث</string>
|
<string name="latest">الأحدث</string>
|
||||||
<string name="recommended_driver">برنامج التشغيل الموصى به:</string>
|
<string name="recommended_driver">برنامج التشغيل الموصى به:</string>
|
||||||
<string name="gpu_model">طراز وحدة معالجة الرسومات:</string>
|
<string name="gpu_model">طراز وحدة معالجة الرسومات</string>
|
||||||
<string name="unsupported_gpu">بطاقة رسومات غير مدعومة</string>
|
<string name="unsupported_gpu">وحدة معالجة الرسومات غير مدعومة</string>
|
||||||
<string name="unsupported_gpu_warning">لا تدعم وحدة معالجة الرسومات الخاصة بك إدخال برامج التشغيل. لا يُنصح بمحاولة تعيين برامج تشغيل مخصصة.</string>
|
<string name="unsupported_gpu_warning">لا تدعم وحدة معالجة الرسومات الخاصة بك إدخال برامج التشغيل. لا يُنصح بمحاولة تعيين برامج تشغيل مخصصة.</string>
|
||||||
|
|
||||||
<!-- Preferences Screen -->
|
<!-- Preferences Screen -->
|
||||||
<string name="preferences_settings">الإعدادات</string>
|
<string name="preferences_settings">الإعدادات</string>
|
||||||
<string name="preferences_system">النظام</string>
|
<string name="preferences_system">النظام</string>
|
||||||
<string name="preferences_system_description">وضع الإرساء ،المنطقة ،اللغة</string>
|
<string name="preferences_system_description">وضع الإرساء، المنطقة، اللغة</string>
|
||||||
<string name="preferences_graphics">الرسومات</string>
|
<string name="preferences_graphics">الرسومات</string>
|
||||||
<string name="preferences_graphics_description">مستوى الدقة ،الدقة ،ذاكرة التخزين المؤقت للتظليل</string>
|
<string name="preferences_graphics_description">مستوى الدقة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string>
|
||||||
<string name="preferences_audio">الصوت</string>
|
<string name="preferences_audio">الصوت</string>
|
||||||
<string name="preferences_audio_description">محرك الإخراج ، حجم الصوت</string>
|
<string name="preferences_audio_description">محرك الإخراج، حجم الصوت</string>
|
||||||
<string name="preferences_controls">عناصر التحكم</string>
|
<string name="preferences_controls">عناصر التحكم</string>
|
||||||
<string name="preferences_controls_description">مدخلات ذراع تحكم في الخريطة</string>
|
<string name="preferences_controls_description">مدخلات ذراع تحكم في الخريطة</string>
|
||||||
<string name="preferences_player">اللاعب %d</string>
|
<string name="preferences_player">اللاعب %d</string>
|
||||||
@@ -672,9 +692,9 @@
|
|||||||
|
|
||||||
<!-- Game properties -->
|
<!-- Game properties -->
|
||||||
<string name="info">معلومات</string>
|
<string name="info">معلومات</string>
|
||||||
<string name="info_description">معرف البرنامج، المطور، الإصدار</string>
|
<string name="info_description">معرف العنوان، المطور، الإصدار</string>
|
||||||
<string name="per_game_settings">إعدادات خاصة للعبة</string>
|
<string name="per_game_settings">إعدادات خاصة للعبة</string>
|
||||||
<string name="per_game_settings_description">تعديل الإعدادات الخاصة بهذه اللعبة</string>
|
<string name="per_game_settings_description">تحرير الإعدادات الخاصة بهذه اللعبة</string>
|
||||||
<string name="launch_options">تشغيل التكوين</string>
|
<string name="launch_options">تشغيل التكوين</string>
|
||||||
<string name="path">المسار</string>
|
<string name="path">المسار</string>
|
||||||
<string name="program_id">معرف العنوان</string>
|
<string name="program_id">معرف العنوان</string>
|
||||||
@@ -682,28 +702,31 @@
|
|||||||
<string name="version">الإصدار</string>
|
<string name="version">الإصدار</string>
|
||||||
<string name="copy_details">نسخ التفاصيل</string>
|
<string name="copy_details">نسخ التفاصيل</string>
|
||||||
<string name="add_ons">الإضافات</string>
|
<string name="add_ons">الإضافات</string>
|
||||||
<string name="add_ons_description">التعديلات والتحديثات والمحتوى القابل للتنزيل</string>
|
<string name="add_ons_description">التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
|
||||||
|
<string name="playtime">زمن اللعب: </string>
|
||||||
<string name="reset_playtime">مسح زمن اللعب</string>
|
<string name="reset_playtime">مسح زمن اللعب</string>
|
||||||
<string name="reset_playtime_description">إعادة ضبط زمن اللعب الحالي للعبة إلى 0 ثانية</string>
|
<string name="reset_playtime_description">إعادة ضبط زمن اللعب الحالي للعبة إلى 0 ثانية</string>
|
||||||
<string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات زمن اللعب الحالية للعبة. هل أنت متأكد؟</string>
|
<string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات زمن اللعب الحالية للعبة. هل أنت متأكد؟</string>
|
||||||
<string name="playtime_reset_successfully">تمت إعادة ضبط زمن اللعب</string>
|
<string name="playtime_reset_successfully">تمت إعادة ضبط زمن اللعب</string>
|
||||||
<string name="edit_playtime">تعديل زمن التشغيل</string>
|
<string name="edit_playtime">تحرير زمن التشغيل</string>
|
||||||
<string name="hours">ساعات</string>
|
<string name="hours">ساعات</string>
|
||||||
<string name="minutes">دقائق</string>
|
<string name="minutes">دقائق</string>
|
||||||
<string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string>
|
<string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string>
|
||||||
<string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string>
|
<string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string>
|
||||||
<string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string>
|
<string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string>
|
||||||
<string name="playtime_updated_successfully">تم تحديث زمن اللعب بنجاح</string>
|
<string name="playtime_updated_successfully">تم تحديث زمن اللعب بنجاح</string>
|
||||||
<string name="clear_shader_cache">مسح ذاكرة التخزين المؤقت للتظليل</string>
|
<string name="clear_shader_cache">مسح ذاكرة التخزين المؤقتة للتظليل</string>
|
||||||
<string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
|
<string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
|
||||||
<string name="clear_shader_cache_warning_description">سوف تواجه المزيد من التأتأة مع تجديد ذاكرة التخزين المؤقت للتظليل</string>
|
<string name="clear_shader_cache_warning_description">ستواجه المزيد من التقطع مع إعادة إنشاء ذاكرة التخزين المؤقتة للتظلل</string>
|
||||||
<string name="cleared_shaders_successfully">تم مسح التظليل بنجاح</string>
|
<string name="cleared_shaders_successfully">تم مسح التظليل بنجاح</string>
|
||||||
|
<string name="driver_shader_wipe_dialog_title">تم مسح الشادر</string>
|
||||||
|
<string name="driver_shader_wipe_dialog_message">قام Eden تلقائيًا بمسح جميع ذاكرات التخزين المؤقت للتظليل للحفاظ على صحة خط أنابيب Vulkan. هذا ضروري عند تبديل برامج تشغيل وحدة معالجة الرسومات لمنع الأعطال وتلف الرسومات. قد تواجه بعض التلعثم أثناء إعادة بناء وحدات التظليل.</string>
|
||||||
<string name="addons_game">إضافات: %1$s</string>
|
<string name="addons_game">إضافات: %1$s</string>
|
||||||
<string name="save_data">حفظ البيانات</string>
|
<string name="save_data">البيانات المحفوظة</string>
|
||||||
<string name="save_data_description">إدارة حفظ البيانات الخاصة بهذه اللعبة</string>
|
<string name="save_data_description">إدارة البيانات المحفوظة الخاصة بهذه اللعبة</string>
|
||||||
<string name="delete_save_data">حذف حفظ البيانات</string>
|
<string name="delete_save_data">حذف البيانات المحفوظة</string>
|
||||||
<string name="delete_save_data_description">يزيل كافة البيانات المحفوظة الخاصة بهذه اللعبة</string>
|
<string name="delete_save_data_description">يزيل كافة البيانات المحفوظة الخاصة بهذه اللعبة</string>
|
||||||
<string name="delete_save_data_warning_description">يؤدي هذا إلى إزالة كافة البيانات المحفوظة لهذه اللعبة بشكل لا يمكن استرداده. هل أنت متأكد أنك تريد الاستمرار؟</string>
|
<string name="delete_save_data_warning_description">سيؤدي هذا إلى حذف جميع بيانات حفظ اللعبة بشكل نهائي. هل أنت متأكد من أنك تريد المتابعة؟</string>
|
||||||
<string name="save_data_deleted_successfully">تم حذف البيانات المحفوظة بنجاح</string>
|
<string name="save_data_deleted_successfully">تم حذف البيانات المحفوظة بنجاح</string>
|
||||||
<string name="select_content_type">نوع المحتوى</string>
|
<string name="select_content_type">نوع المحتوى</string>
|
||||||
<string name="updates_and_dlc">التحديثات والمحتوى القابل للتنزيل</string>
|
<string name="updates_and_dlc">التحديثات والمحتوى القابل للتنزيل</string>
|
||||||
@@ -722,16 +745,16 @@
|
|||||||
<string name="confirm_uninstall_description">هل أنت متأكد من أنك تريد إلغاء تثبيت هذا الإضافة؟</string>
|
<string name="confirm_uninstall_description">هل أنت متأكد من أنك تريد إلغاء تثبيت هذا الإضافة؟</string>
|
||||||
<string name="verify_integrity">التحقق من السلامة</string>
|
<string name="verify_integrity">التحقق من السلامة</string>
|
||||||
<string name="verifying">جارٍ التحقق...</string>
|
<string name="verifying">جارٍ التحقق...</string>
|
||||||
<string name="verify_success">نجح التحقق من السلامة!</string>
|
<string name="verify_success">تم التحقق من السلامة بنجاح!</string>
|
||||||
<string name="verify_failure">فشل التحقق من السلامة!</string>
|
<string name="verify_failure">فشل التحقق من السلامة!</string>
|
||||||
<string name="verify_failure_description">قد تكون محتويات الملف تالفة</string>
|
<string name="verify_failure_description">قد تكون محتويات الملف تالفة</string>
|
||||||
<string name="verify_no_result">تعذر التحقق من السلامة</string>
|
<string name="verify_no_result">تعذر إجراء التحقق من السلامة</string>
|
||||||
<string name="verify_no_result_description">لم يتم التحقق من صحة محتويات الملف</string>
|
<string name="verify_no_result_description">لم يتم التحقق من صحة محتويات الملف</string>
|
||||||
<string name="verification_failed_for">فشل التحقق من الملفات التالية:\n%1$s</string>
|
<string name="verification_failed_for">فشل التحقق من الملفات التالية:\n%1$s</string>
|
||||||
<string name="share_game_settings">مشاركة الإعدادات</string>
|
<string name="share_game_settings">مشاركة التكوين</string>
|
||||||
<string name="import_config">استيراد الإعدادات</string>
|
<string name="import_config">استيراد التكوين</string>
|
||||||
<string name="export_config">تصدير الإعدادات</string>
|
<string name="export_config">تصدير التكوين</string>
|
||||||
<string name="share_config_failed">فشل مشاركة ملف الإعدادات</string>
|
<string name="share_config_failed">فشل مشاركة ملف التكوين</string>
|
||||||
|
|
||||||
<!-- ROM loading errors -->
|
<!-- ROM loading errors -->
|
||||||
<string name="loader_error_encrypted">ROM الخاص بك مشفر</string>
|
<string name="loader_error_encrypted">ROM الخاص بك مشفر</string>
|
||||||
@@ -751,7 +774,7 @@
|
|||||||
<string name="custom_settings_failed_message">فشل تطبيق الإعدادات المخصصة لـ %1$s: %2$s</string>
|
<string name="custom_settings_failed_message">فشل تطبيق الإعدادات المخصصة لـ %1$s: %2$s</string>
|
||||||
<string name="launch_with_default_settings">التشغيل بالإعدادات الافتراضية</string>
|
<string name="launch_with_default_settings">التشغيل بالإعدادات الافتراضية</string>
|
||||||
<string name="launch_cancelled">تم إلغاء التشغيل</string>
|
<string name="launch_cancelled">تم إلغاء التشغيل</string>
|
||||||
<string name="custom_settings_failure_reasons">غير قادر على تطبيق الإعدادات المطلوبة. قد يكون ذلك بسبب نقص برامج تشغيل وحدة معالجة الرسوميات أو مشكلات في التكوين.</string>
|
<string name="custom_settings_failure_reasons">غير قادر على تطبيق الإعدادات المطلوبة. قد يكون ذلك بسبب نقص برامج تشغيل وحدة معالجة الرسومات أو مشكلات في التكوين.</string>
|
||||||
<string name="custom_settings_applied">تم تطبيق الإعدادات المخصصة</string>
|
<string name="custom_settings_applied">تم تطبيق الإعدادات المخصصة</string>
|
||||||
<string name="launching_game">جارٍ التشغيل %1$s...</string>
|
<string name="launching_game">جارٍ التشغيل %1$s...</string>
|
||||||
<string name="failed_to_initialize_game">فشل في تهيئة اللعبة</string>
|
<string name="failed_to_initialize_game">فشل في تهيئة اللعبة</string>
|
||||||
@@ -792,21 +815,32 @@
|
|||||||
<string name="emulation_control_scale">الحجم</string>
|
<string name="emulation_control_scale">الحجم</string>
|
||||||
<string name="emulation_control_opacity">الشفافية</string>
|
<string name="emulation_control_opacity">الشفافية</string>
|
||||||
<string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string>
|
<string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string>
|
||||||
<string name="emulation_touch_overlay_edit">تعديل التراكب</string>
|
<string name="emulation_touch_overlay_edit">تحرير التراكب</string>
|
||||||
<string name="emulation_pause">إيقاف المحاكاة مؤقتًا</string>
|
<string name="emulation_pause">إيقاف المحاكاة مؤقتًا</string>
|
||||||
<string name="emulation_unpause">إلغاء الإيقاف المؤقت للمحاكاة</string>
|
<string name="emulation_unpause">إلغاء الإيقاف المؤقت للمحاكاة</string>
|
||||||
<string name="emulation_input_overlay">خيارات التراكب</string>
|
<string name="emulation_input_overlay">خيارات التراكب</string>
|
||||||
|
<string name="load_amiibo">تحميل أميبو</string>
|
||||||
<string name="touchscreen">شاشة اللمس</string>
|
<string name="touchscreen">شاشة اللمس</string>
|
||||||
<string name="lock_drawer">قفل الدرج</string>
|
<string name="lock_drawer">قفل الدرج</string>
|
||||||
<string name="unlock_drawer">فتح الدرج</string>
|
<string name="unlock_drawer">فتح الدرج</string>
|
||||||
<string name="reset">إعادة الضبط</string>
|
<string name="reset">إعادة الضبط</string>
|
||||||
|
|
||||||
|
<!-- Amiibo -->
|
||||||
|
<string name="amiibo_title">أميبو</string>
|
||||||
|
<string name="amiibo_removed_message">تمت إزالة أميبو الحالي.</string>
|
||||||
|
<string name="amiibo_wrong_state">اللعبة الحالية لا تبحث عن أميبو</string>
|
||||||
|
<string name="amiibo_not_valid">الملف المحدد ليس أميبو صالح</string>
|
||||||
|
<string name="amiibo_in_use">الملف المحدد قيد الاستخدام بالفعل</string>
|
||||||
|
<string name="amiibo_unknown_error">حدث خطأ غير معروف</string>
|
||||||
|
<string name="amiibo_load_success">أميبو محملة</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Software keyboard -->
|
<!-- Software keyboard -->
|
||||||
<string name="software_keyboard">لوحة المفاتيح البرمجية</string>
|
<string name="software_keyboard">لوحة المفاتيح البرمجية</string>
|
||||||
|
|
||||||
<!-- Errors and warnings -->
|
<!-- Errors and warnings -->
|
||||||
<string name="abort_button">إلغاء</string>
|
<string name="abort_button">إلغاء</string>
|
||||||
<string name="continue_button">استمر</string>
|
<string name="continue_button">متابعة</string>
|
||||||
<string name="system_archive_not_found">لم يتم العثور على أرشيف النظام</string>
|
<string name="system_archive_not_found">لم يتم العثور على أرشيف النظام</string>
|
||||||
<string name="system_archive_not_found_message">%sمفقود. يرجى تفريغ أرشيفات النظام.\nقد يؤدي استمرار المحاكاة إلى حدوث أعطال.</string>
|
<string name="system_archive_not_found_message">%sمفقود. يرجى تفريغ أرشيفات النظام.\nقد يؤدي استمرار المحاكاة إلى حدوث أعطال.</string>
|
||||||
<string name="system_archive_general">أرشيف النظام</string>
|
<string name="system_archive_general">أرشيف النظام</string>
|
||||||
@@ -815,7 +849,7 @@
|
|||||||
<string name="fatal_error_message">حدث خطأ فادح. تحقق من السجل للحصول على التفاصيل.\nقد يؤدي استمرار المحاكاة إلى حدوث أعطال.</string>
|
<string name="fatal_error_message">حدث خطأ فادح. تحقق من السجل للحصول على التفاصيل.\nقد يؤدي استمرار المحاكاة إلى حدوث أعطال.</string>
|
||||||
<string name="device_memory_inadequate">ذاكرة الوصول العشوائي للجهاز: %1$s\nموصى به: %2$s</string>
|
<string name="device_memory_inadequate">ذاكرة الوصول العشوائي للجهاز: %1$s\nموصى به: %2$s</string>
|
||||||
<string name="memory_formatted">%1$s %2$s</string>
|
<string name="memory_formatted">%1$s %2$s</string>
|
||||||
<string name="no_game_present">لا توجد لعبة قابلة للتمهيد</string>
|
<string name="no_game_present">لا توجد لعبة قابلة للتشغيل!</string>
|
||||||
|
|
||||||
<!-- Region Names -->
|
<!-- Region Names -->
|
||||||
<string name="region_japan">اليابان</string>
|
<string name="region_japan">اليابان</string>
|
||||||
@@ -860,7 +894,7 @@
|
|||||||
<!-- Renderer Accuracy -->
|
<!-- Renderer Accuracy -->
|
||||||
<string name="renderer_accuracy_normal">عادي</string>
|
<string name="renderer_accuracy_normal">عادي</string>
|
||||||
<string name="renderer_accuracy_high">عالي</string>
|
<string name="renderer_accuracy_high">عالي</string>
|
||||||
<string name="renderer_accuracy_extreme">أقصى حد</string>
|
<string name="renderer_accuracy_extreme">أقصى</string>
|
||||||
|
|
||||||
<!-- DMA Accuracy -->
|
<!-- DMA Accuracy -->
|
||||||
<string name="dma_accuracy_default">افتراضي</string>
|
<string name="dma_accuracy_default">افتراضي</string>
|
||||||
@@ -869,16 +903,16 @@
|
|||||||
|
|
||||||
<!-- ASTC Decoding Method -->
|
<!-- ASTC Decoding Method -->
|
||||||
<string name="accelerate_astc">طريقة فك ضغط ASTC</string>
|
<string name="accelerate_astc">طريقة فك ضغط ASTC</string>
|
||||||
<string name="accelerate_astc_description">اختر كيفية فك ضغط نسيج ASTC للعرض: CPU (بطيء، آمن)، GPU (سريع، موصى به)، أو CPU Async (بدون توقف، قد يسبب مشاكل)</string>
|
<string name="accelerate_astc_description">حدد كيفية فك ضغط نسيج ASTC للعرض: CPU (بطيء، آمن)، GPU (سريع، موصى به)، أو CPU Async (بدون توقف، قد يسبب مشاكل)</string>
|
||||||
|
|
||||||
<!-- ASTC Decoding Method Choices -->
|
<!-- ASTC Decoding Method Choices -->
|
||||||
<string name="accelerate_astc_cpu">وحدة المعالجة المركزية</string>
|
<string name="accelerate_astc_cpu">وحدة المعالجة المركزية</string>
|
||||||
<string name="accelerate_astc_gpu">وحدة المعالجة الرسومية</string>
|
<string name="accelerate_astc_gpu">وحدة معالجة الرسومات</string>
|
||||||
<string name="accelerate_astc_async">وحدة المعالجة المركزية غير المتزامنة</string>
|
<string name="accelerate_astc_async">وحدة المعالجة المركزية غير المتزامنة</string>
|
||||||
|
|
||||||
<!-- ASTC Recompression Method -->
|
<!-- ASTC Recompression Method -->
|
||||||
<string name="astc_recompression">طريقة إعادة ضغط ASTC</string>
|
<string name="astc_recompression">طريقة إعادة ضغط ASTC</string>
|
||||||
<string name="astc_recompression_description">اختر كيفية إعادة ضغط نسيج ASTC لتحسين التوافق والأداء. تمكين هذا الخيار يوفر VRAM ولكن قد يقلل من جودة النسيج.</string>
|
<string name="astc_recompression_description">حدد كيفية إعادة ضغط نسيج ASTC لتحسين التوافق والأداء. تمكين هذا الخيار يوفر VRAM ولكن قد يقلل من جودة النسيج.</string>
|
||||||
|
|
||||||
<!-- ASTC Recompression Method Choices -->
|
<!-- ASTC Recompression Method Choices -->
|
||||||
<string name="astc_recompression_uncompressed">غير مضغوط</string>
|
<string name="astc_recompression_uncompressed">غير مضغوط</string>
|
||||||
@@ -887,7 +921,7 @@
|
|||||||
|
|
||||||
<!-- ASTC Recompression Method Choices -->
|
<!-- ASTC Recompression Method Choices -->
|
||||||
<string name="vram_usage_mode">وضع استخدام ذاكرة VRAM</string>
|
<string name="vram_usage_mode">وضع استخدام ذاكرة VRAM</string>
|
||||||
<string name="vram_usage_mode_description">تحكم في مدى قوة تخصيص المحاكي لذاكرة وحدة معالجة الرسوميات وتحريرها.</string>
|
<string name="vram_usage_mode_description">تحكم في مدى قوة تخصيص المحاكي لذاكرة وحدة معالجة الرسومات وتحريرها.</string>
|
||||||
<string name="vram_usage_conservative">محافظ</string>
|
<string name="vram_usage_conservative">محافظ</string>
|
||||||
<string name="vram_usage_aggressive">عدواني</string>
|
<string name="vram_usage_aggressive">عدواني</string>
|
||||||
|
|
||||||
@@ -903,9 +937,9 @@
|
|||||||
<string name="resolution_four">4X (2880p/4320p) (بطيء)</string>
|
<string name="resolution_four">4X (2880p/4320p) (بطيء)</string>
|
||||||
|
|
||||||
<!-- Renderer VSync -->
|
<!-- Renderer VSync -->
|
||||||
<string name="renderer_vsync_immediate">Immediate (إيقاف)</string>
|
<string name="renderer_vsync_immediate">Immediate (Off)</string>
|
||||||
<string name="renderer_vsync_mailbox">Mailbox</string>
|
<string name="renderer_vsync_mailbox">Mailbox</string>
|
||||||
<string name="renderer_vsync_fifo">FIFO (تشغيل)</string>
|
<string name="renderer_vsync_fifo">FIFO (On)</string>
|
||||||
<string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
|
<string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
|
||||||
|
|
||||||
<!-- Scaling Filters -->
|
<!-- Scaling Filters -->
|
||||||
@@ -942,7 +976,7 @@
|
|||||||
<string name="ratio_force_four_three">4:3 فرض</string>
|
<string name="ratio_force_four_three">4:3 فرض</string>
|
||||||
<string name="ratio_force_twenty_one_nine">21:9 فرض</string>
|
<string name="ratio_force_twenty_one_nine">21:9 فرض</string>
|
||||||
<string name="ratio_force_sixteen_ten">16:10 فرض</string>
|
<string name="ratio_force_sixteen_ten">16:10 فرض</string>
|
||||||
<string name="ratio_stretch">تمتد إلى النافذة</string>
|
<string name="ratio_stretch">تمديد إلى النافذة</string>
|
||||||
|
|
||||||
<!-- CPU Backend -->
|
<!-- CPU Backend -->
|
||||||
<string name="cpu_backend_dynarmic">Dynarmic (JIT)</string>
|
<string name="cpu_backend_dynarmic">Dynarmic (JIT)</string>
|
||||||
@@ -959,7 +993,7 @@
|
|||||||
<string name="gamepad_left_stick">العصا اليسرى</string>
|
<string name="gamepad_left_stick">العصا اليسرى</string>
|
||||||
<string name="gamepad_right_stick">العصا اليمنى</string>
|
<string name="gamepad_right_stick">العصا اليمنى</string>
|
||||||
<string name="gamepad_home">Home</string>
|
<string name="gamepad_home">Home</string>
|
||||||
<string name="gamepad_screenshot">لقطة شاشة</string>
|
<string name="gamepad_screenshot">Screenshot</string>
|
||||||
|
|
||||||
<!-- Disk shader cache -->
|
<!-- Disk shader cache -->
|
||||||
<string name="building_shaders">بناء التظليل</string>
|
<string name="building_shaders">بناء التظليل</string>
|
||||||
@@ -991,6 +1025,35 @@
|
|||||||
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
||||||
<string name="use_black_backgrounds_description">عند استخدام السمة الداكنة، قم بتطبيق خلفيات سوداء.</string>
|
<string name="use_black_backgrounds_description">عند استخدام السمة الداكنة، قم بتطبيق خلفيات سوداء.</string>
|
||||||
|
|
||||||
|
<!-- App Language -->
|
||||||
|
<string name="app_language">لغة التطبيق</string>
|
||||||
|
<string name="app_language_description">تغيير لغة واجهة التطبيق</string>
|
||||||
|
<string name="app_language_system">اتبع النظام</string>
|
||||||
|
<string name="app_language_english">الإنجليزية</string>
|
||||||
|
<string name="app_language_spanish">الإسبانية</string>
|
||||||
|
<string name="app_language_french">الفرنسية</string>
|
||||||
|
<string name="app_language_german">الألمانية</string>
|
||||||
|
<string name="app_language_italian">الإيطالية</string>
|
||||||
|
<string name="app_language_portuguese">البرتغالية</string>
|
||||||
|
<string name="app_language_brazilian_portuguese">البرتغالية البرازيلية</string>
|
||||||
|
<string name="app_language_russian">الروسية</string>
|
||||||
|
<string name="app_language_japanese">اليابانية</string>
|
||||||
|
<string name="app_language_korean">الكورية</string>
|
||||||
|
<string name="app_language_simplified_chinese">الصينية المبسطة</string>
|
||||||
|
<string name="app_language_traditional_chinese">الصينية التقليدية</string>
|
||||||
|
<string name="app_language_polish">البولندية</string>
|
||||||
|
<string name="app_language_czech">التشيكية</string>
|
||||||
|
<string name="app_language_norwegian">النرويجية البوكمال</string>
|
||||||
|
<string name="app_language_hungarian">المجرية</string>
|
||||||
|
<string name="app_language_ukrainian">الأوكرانية</string>
|
||||||
|
<string name="app_language_vietnamese">الفيتنامية</string>
|
||||||
|
<string name="app_language_indonesian">الإندونيسية</string>
|
||||||
|
<string name="app_language_arabic">العربية</string>
|
||||||
|
<string name="app_language_central_kurdish">الكردية الوسطى</string>
|
||||||
|
<string name="app_language_persian">فارسی</string>
|
||||||
|
<string name="app_language_hebrew">العبرية</string>
|
||||||
|
<string name="app_language_serbian">الصربية</string>
|
||||||
|
|
||||||
<!-- Static Themes -->
|
<!-- Static Themes -->
|
||||||
<string name="static_theme_color">لون السمة</string>
|
<string name="static_theme_color">لون السمة</string>
|
||||||
<string name="eden_theme">Eden (افتراضي)</string>
|
<string name="eden_theme">Eden (افتراضي)</string>
|
||||||
@@ -1007,7 +1070,7 @@
|
|||||||
<!-- Picture-In-Picture -->
|
<!-- Picture-In-Picture -->
|
||||||
<string name="picture_in_picture">صورة داخل صورة</string>
|
<string name="picture_in_picture">صورة داخل صورة</string>
|
||||||
<string name="picture_in_picture_description">تصغير النافذة عند وضعها في الخلفية</string>
|
<string name="picture_in_picture_description">تصغير النافذة عند وضعها في الخلفية</string>
|
||||||
<string name="pause">توقف</string>
|
<string name="pause">إيقاف مؤقت</string>
|
||||||
<string name="play">تشغيل</string>
|
<string name="play">تشغيل</string>
|
||||||
<string name="mute">كتم الصوت</string>
|
<string name="mute">كتم الصوت</string>
|
||||||
<string name="unmute">إلغاء كتم الصوت</string>
|
<string name="unmute">إلغاء كتم الصوت</string>
|
||||||
@@ -1020,15 +1083,15 @@
|
|||||||
|
|
||||||
<!-- Applet Modes -->
|
<!-- Applet Modes -->
|
||||||
<string name="applets_menu">التطبيقات الصغيرة</string>
|
<string name="applets_menu">التطبيقات الصغيرة</string>
|
||||||
<string name="applets_menu_description">(قيد العمل) تغيير واجهات التطبيقات الصغيرة والإعدادات</string>
|
<string name="applets_menu_description">(قيد التطوير) تغيير واجهات التطبيقات الصغيرة والإعدادات</string>
|
||||||
|
|
||||||
<string name="applet_hle">واجهة مخصصة</string>
|
<string name="applet_hle">واجهة مخصصة</string>
|
||||||
<string name="applet_lle">تطبيق حقيقي</string>
|
<string name="applet_lle">تطبيق صغير حقيقي</string>
|
||||||
|
|
||||||
<string name="swkbd_applet">لوحة المفاتيح البرمجية</string>
|
<string name="swkbd_applet">لوحة المفاتيح البرمجية</string>
|
||||||
|
|
||||||
<string name="airplane_mode">وضع الطيران</string>
|
<string name="airplane_mode">وضع الطيران</string>
|
||||||
<string name="airplane_mode_description">تشغيل وضع الطيران في نظام التشغيل سويتش</string>
|
<string name="airplane_mode_description">ينقل وضع الطيران إلى نظام التشغيل Switch</string>
|
||||||
|
|
||||||
<!-- Licenses screen strings -->
|
<!-- Licenses screen strings -->
|
||||||
<string name="licenses">التراخيص</string>
|
<string name="licenses">التراخيص</string>
|
||||||
|
|||||||
@@ -519,7 +519,6 @@
|
|||||||
<string name="installing">لە دامەزراندن...</string>
|
<string name="installing">لە دامەزراندن...</string>
|
||||||
<string name="latest">نوێترین</string>
|
<string name="latest">نوێترین</string>
|
||||||
<string name="recommended_driver">درایڤەری پێشنیارکراو:</string>
|
<string name="recommended_driver">درایڤەری پێشنیارکراو:</string>
|
||||||
<string name="gpu_model">مۆدێلی GPU:</string>
|
|
||||||
<string name="unsupported_gpu">GPU پشتگیری نەکراوە</string>
|
<string name="unsupported_gpu">GPU پشتگیری نەکراوە</string>
|
||||||
<string name="unsupported_gpu_warning">GPUی تۆ پشتگیری لە درایڤەری تایبەت ناکات. پێشنیار ناکرێت درایڤەری تایبەت دابنێیت.</string>
|
<string name="unsupported_gpu_warning">GPUی تۆ پشتگیری لە درایڤەری تایبەت ناکات. پێشنیار ناکرێت درایڤەری تایبەت دابنێیت.</string>
|
||||||
|
|
||||||
|
|||||||
@@ -469,7 +469,6 @@
|
|||||||
<string name="installing">Instalace…</string>
|
<string name="installing">Instalace…</string>
|
||||||
<string name="latest">Nejnovější</string>
|
<string name="latest">Nejnovější</string>
|
||||||
<string name="recommended_driver">Doporučený ovladač:</string>
|
<string name="recommended_driver">Doporučený ovladač:</string>
|
||||||
<string name="gpu_model">Model GPU:</string>
|
|
||||||
<string name="unsupported_gpu">Nepodporovaná GPU</string>
|
<string name="unsupported_gpu">Nepodporovaná GPU</string>
|
||||||
<string name="unsupported_gpu_warning">Vaše GPU nepodporuje vkládání ovladačů. Nastavení vlastních ovladačů se nedoporučuje.</string>
|
<string name="unsupported_gpu_warning">Vaše GPU nepodporuje vkládání ovladačů. Nastavení vlastních ovladačů se nedoporučuje.</string>
|
||||||
|
|
||||||
|
|||||||