mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-14 04:24:31 +00:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a8a30ba43 | |||
| 59384de777 | |||
| 9b20c6c609 | |||
| 1428abe1d1 | |||
| f069ff50a6 | |||
| ae395352a7 | |||
| 4ed084153f | |||
| 81f396e70b | |||
| 3725b4d46d | |||
| 42b8ca5f9d | |||
| 52ffc8a7ce | |||
| e26bf22d36 | |||
| 42c5a12577 | |||
| a18d2b5c05 | |||
| 30be8a5e18 | |||
| 44e3211d1c | |||
| 52e0b2a005 | |||
| 9a1258c59d | |||
| 232656df4e | |||
| 367e5084da | |||
| 7467506cfa | |||
| 61f3a1d135 | |||
| 4f4f4a3586 | |||
| 8470ad4b2a | |||
| 4b33a2746c | |||
| e7a931d06b | |||
| 8648c27cbb | |||
| def76946f0 | |||
| 13d39f39aa | |||
| 7731b5bc86 | |||
| c4ab2f6b9e | |||
| dd12266c26 | |||
| a3d32a18b8 | |||
| c0ffc900cd | |||
| 3f52bf4b4b | |||
| 5ec94b1971 | |||
| 627770cd3a | |||
| a43664c0fd | |||
| a0f1cd1baf | |||
| 49a0ca6d5d | |||
| 5e1d5e82dc | |||
| ba9130fbf9 | |||
| 7d5f390ffb | |||
| 8fe1e6efa2 | |||
| ee197e6222 | |||
| 612409c7ba | |||
| 54046ac60e | |||
| 39763e7321 | |||
| e69415c07b | |||
| dc1486485b | |||
| f561a10bd8 | |||
| 6272f8ab24 | |||
| eebb4bd91e | |||
| 58dee53305 | |||
| 7b13113fbe | |||
| b9a88297cb | |||
| 0133caf702 | |||
| 9d60030af5 | |||
| f5d1a78846 | |||
| 5d3ad94e18 | |||
| 479df9809a | |||
| 5b4c29b123 | |||
| 5b4dc32c1a | |||
| a90ba7f6ac | |||
| 9b2a36791d | |||
| b85f289048 | |||
| 89004124a5 | |||
| eb9280dedf | |||
| 8b8034a2a0 | |||
| 9a0e6b3c28 | |||
| defb8bf2e2 | |||
| 6295d23581 | |||
| 7f85c6e282 | |||
| 39b2c79985 | |||
| a27d35463e | |||
| 5606edd1a6 | |||
| cd003e5ec9 |
@@ -1,9 +1,9 @@
|
||||
name: tx-pull
|
||||
|
||||
on:
|
||||
# tuesday, saturday at 2pm
|
||||
# monday at 4pm
|
||||
schedule:
|
||||
- cron: '0 14 * * 2,6'
|
||||
- cron: '0 16 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -3,7 +3,7 @@ description: File a bug report
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with yuzu.
|
||||
value: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with Eden.
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
@@ -43,7 +43,7 @@ body:
|
||||
id: log
|
||||
attributes:
|
||||
label: Log File
|
||||
description: A log file will help our developers to better diagnose and fix the issue. Instructions can be found [here](https://yuzu-emu.org/help/reference/log-files).
|
||||
description: A log file will help our developers to better diagnose and fix the issue. Instructions can be found [here](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/user/HowToAccessLogs.md).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
+2
-2
@@ -4,7 +4,7 @@ labels: "request"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Tech support does not belong here. You should only file an issue here if you are requesting a feature you believe would make yuzu better.
|
||||
value: Tech support does not belong here. You should only file an issue here if you are requesting a feature you believe would make Eden better.
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
@@ -23,6 +23,6 @@ body:
|
||||
id: why-feature
|
||||
attributes:
|
||||
label: Why would this feature be useful?
|
||||
description: A brief description of why this feature would make yuzu better.
|
||||
description: A brief description of why this feature would make Eden better.
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,5 @@
|
||||
- [ ] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
|
||||
- [ ] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
|
||||
- [ ] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
|
||||
|
||||
-------------------
|
||||
@@ -112,11 +112,6 @@ Files: src/yuzu/*.ui
|
||||
Copyright: 2018-2022 yuzu Emulator Project
|
||||
License: GPL-2.0-or-later
|
||||
|
||||
Files: src/yuzu/compatdb.ui
|
||||
src/yuzu/main.ui
|
||||
Copyright: 2014-2017 Citra Emulator Project
|
||||
License: GPL-2.0-or-later
|
||||
|
||||
Files: src/yuzu/loading_screen.ui
|
||||
Copyright: 2019 James Rowe <jroweboy@gmail.com>
|
||||
License: GPL-2.0-or-later
|
||||
|
||||
+47
-39
@@ -28,23 +28,23 @@ if (NOT DEFINED ARCHITECTURE)
|
||||
endif()
|
||||
|
||||
# Needed for FFmpeg w/ VAAPI and DRM
|
||||
if (PLATFORM_OPENBSD)
|
||||
if (OPENBSD)
|
||||
# OpenBSD 7.8 broke libcxx when upgrading, so we must define the PSTL backend manually
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R6/include -D_LIBCPP_PSTL_BACKEND_SERIAL=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R6/include -D_LIBCPP_PSTL_BACKEND_SERIAL=1")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/X11R6/lib")
|
||||
elseif (PLATFORM_NETBSD)
|
||||
elseif (NETBSD)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R7/include -I${CMAKE_SYSROOT}/usr/pkg/include/c++/v1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R7/include -I${CMAKE_SYSROOT}/usr/pkg/include/c++/v1")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/X11R7/lib")
|
||||
endif()
|
||||
|
||||
# NetBSD: Fun for the whole family!
|
||||
if (PLATFORM_NETBSD)
|
||||
if (NETBSD)
|
||||
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig")
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(YUZU_STATIC_ROOM "Build a static room executable only (CI only)" OFF "PLATFORM_LINUX" OFF)
|
||||
cmake_dependent_option(YUZU_STATIC_ROOM "Build a static room executable only (CI only)" OFF "LINUX" OFF)
|
||||
if (YUZU_STATIC_ROOM)
|
||||
set(YUZU_ROOM ON)
|
||||
set(YUZU_ROOM_STANDALONE ON)
|
||||
@@ -79,6 +79,7 @@ set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundl
|
||||
cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
|
||||
|
||||
option(ENABLE_DEBUG_TOOLS "Enable debugging tools (maxwell disassembler, SPIRV translator, etc)" OFF)
|
||||
option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
|
||||
|
||||
# non-linux bundled qt are static
|
||||
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
||||
@@ -157,6 +158,19 @@ if (CXX_CLANG_CL)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-reserved-identifier>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-deprecated-declarations>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-extensions>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++17-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++11-compat-reserved-user-defined-literal>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++11-compat-deprecated-writable-strings>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++11-compat-pedantic>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++11-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++0x-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-c++11-compat-binary-literal>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat-pedantic>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c98-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-extensions>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
|
||||
# REQUIRED CPU features IN Windows-amd64
|
||||
if (ARCHITECTURE_x86_64)
|
||||
@@ -210,7 +224,7 @@ endif()
|
||||
|
||||
# ffmpeg
|
||||
option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT})
|
||||
cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from external source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF)
|
||||
cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from external source" "${SOLARIS}" "NOT WIN32 AND NOT ANDROID" OFF)
|
||||
|
||||
# sirit
|
||||
set(BUNDLED_SIRIT_DEFAULT OFF)
|
||||
@@ -221,7 +235,7 @@ endif()
|
||||
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${BUNDLED_SIRIT_DEFAULT})
|
||||
|
||||
# FreeBSD 15+ has libusb, versions below should disable it
|
||||
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR PLATFORM_FREEBSD OR APPLE" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR LINUX OR FREEBSD OR APPLE" OFF)
|
||||
|
||||
cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT (WIN32 AND ARCHITECTURE_arm64) AND NOT APPLE" OFF)
|
||||
mark_as_advanced(FORCE ENABLE_OPENGL)
|
||||
@@ -235,7 +249,7 @@ option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
|
||||
|
||||
# Install udev rules on Linux (mainly for gyros)
|
||||
# Only acts on joysticks and nothing else.
|
||||
cmake_dependent_option(YUZU_INSTALL_UDEV_RULES "Install udev rules for gyro access" OFF "PLATFORM_LINUX" OFF)
|
||||
cmake_dependent_option(YUZU_INSTALL_UDEV_RULES "Install udev rules for gyro access" OFF "LINUX" OFF)
|
||||
|
||||
option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON)
|
||||
|
||||
@@ -248,7 +262,7 @@ cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable"
|
||||
|
||||
cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "NOT ANDROID" OFF)
|
||||
|
||||
cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR PLATFORM_LINUX" OFF)
|
||||
cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
|
||||
|
||||
option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON)
|
||||
set(YUZU_TZDB_PATH "" CACHE STRING "Path to a pre-downloaded timezone database")
|
||||
@@ -258,7 +272,7 @@ cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib"
|
||||
option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF)
|
||||
|
||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
||||
if (EXT_DEFAULT OR PLATFORM_SUN OR PLATFORM_OPENBSD)
|
||||
if (EXT_DEFAULT OR SOLARIS OR OPENBSD)
|
||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
||||
endif()
|
||||
|
||||
@@ -281,26 +295,7 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(compat_base dist/compatibility_list/compatibility_list)
|
||||
set(compat_qrc ${compat_base}.qrc)
|
||||
set(compat_json ${compat_base}.json)
|
||||
|
||||
configure_file(${PROJECT_SOURCE_DIR}/${compat_qrc}
|
||||
${PROJECT_BINARY_DIR}/${compat_qrc}
|
||||
COPYONLY)
|
||||
|
||||
if (EXISTS ${PROJECT_SOURCE_DIR}/${compat_json})
|
||||
configure_file("${PROJECT_SOURCE_DIR}/${compat_json}"
|
||||
"${PROJECT_BINARY_DIR}/${compat_json}"
|
||||
COPYONLY)
|
||||
endif()
|
||||
|
||||
# TODO: Compat list download
|
||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${compat_json})
|
||||
file(WRITE ${PROJECT_BINARY_DIR}/${compat_json} "")
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX))
|
||||
if (ARCHITECTURE_arm64 AND (ANDROID OR LINUX))
|
||||
set(HAS_NCE 1)
|
||||
add_compile_definitions(HAS_NCE=1)
|
||||
endif()
|
||||
@@ -309,7 +304,7 @@ if (YUZU_ROOM)
|
||||
add_compile_definitions(YUZU_ROOM)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT (PLATFORM_LINUX OR WIN32))
|
||||
if (UNIX AND NOT (LINUX OR WIN32))
|
||||
if(CXX_APPLE OR CXX_CLANG)
|
||||
# libc++ has stop_token and jthread as experimental
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||
@@ -344,13 +339,26 @@ if (CXX_GCC OR CXX_CLANG)
|
||||
endif()
|
||||
elseif(ARCHITECTURE_arm64)
|
||||
# See https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
|
||||
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, armv9, native")
|
||||
set(mtune generic)
|
||||
set(armv8_2_target armv8.2-a+fp16+dotprod)
|
||||
|
||||
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
|
||||
set(march armv8-a)
|
||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
||||
set(march armv9-a)
|
||||
if (ANDROID)
|
||||
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, armv8.2, armv9, native")
|
||||
set(march ${armv8_2_target})
|
||||
|
||||
if (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
||||
set(march armv9-a)
|
||||
endif()
|
||||
else()
|
||||
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, armv8.2, armv9, native")
|
||||
|
||||
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
|
||||
set(march armv8-a)
|
||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv8.2")
|
||||
set(march ${armv8_2_target})
|
||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
||||
set(march armv9-a)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -423,7 +431,7 @@ if (Boost_ADDED)
|
||||
|
||||
if (NOT MSVC OR CXX_CLANG)
|
||||
# boost sucks
|
||||
if (PLATFORM_SUN)
|
||||
if (SOLARIS)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-pthreads>)
|
||||
endif()
|
||||
|
||||
@@ -527,9 +535,9 @@ elseif (WIN32)
|
||||
# PSAPI is the Process Status API
|
||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
|
||||
endif()
|
||||
elseif (PLATFORM_MANAGARM)
|
||||
elseif (MANAGARM)
|
||||
set(PLATFORM_LIBRARIES iconv intl)
|
||||
elseif (PLATFORM_HAIKU)
|
||||
elseif (HAIKUOS)
|
||||
# Haiku is so special :)
|
||||
set(PLATFORM_LIBRARIES bsd /boot/system/lib/libnetwork.so)
|
||||
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
|
||||
@@ -623,7 +631,7 @@ if (ENABLE_QT)
|
||||
|
||||
# Best practice is to ask for all components at once, so they are from the same version
|
||||
set(YUZU_QT_COMPONENTS Core Widgets Charts Concurrent Gui)
|
||||
if (PLATFORM_LINUX OR PLATFORM_FREEBSD)
|
||||
if (LINUX OR FREEBSD)
|
||||
list(APPEND YUZU_QT_COMPONENTS DBus)
|
||||
# yes Qt, we get it
|
||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||
|
||||
+35
-89
@@ -95,7 +95,7 @@ macro(echo)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"${message}")
|
||||
else()
|
||||
message(STATUS "${message}")
|
||||
message(DEBUG "${message}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -120,47 +120,6 @@ macro(sleep time)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${time})
|
||||
endmacro()
|
||||
|
||||
# Analogous to GNU mktemp, with fallbacks
|
||||
function(mktempdir out)
|
||||
# shell out to system mktemp if available
|
||||
find_program(MKTEMP_EXECUTABLE mktemp)
|
||||
if (MKTEMP_EXECUTABLE)
|
||||
execute_process(COMMAND mktemp -d
|
||||
OUTPUT_VARIABLE dir
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE ret)
|
||||
|
||||
if (ret EQUAL 0)
|
||||
set(${out} "${dir}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(RANDOM LENGTH 10 rand_str)
|
||||
set(tmp_str "tmp.${rand_str}")
|
||||
|
||||
# create something in /tmp if it exists
|
||||
if(EXISTS "/tmp" AND IS_DIRECTORY "/tmp")
|
||||
set(dir "/tmp/${tmp_str}")
|
||||
file(MAKE_DIRECTORY "${dir}" RESULT res)
|
||||
if (res EQUAL 0)
|
||||
set(${out} "${dir}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# tmpdir does not exist, extremely legacy mode
|
||||
set(dir "${CMAKE_CURRENT_LIST_DIR}/.tmp/${tmp_str}")
|
||||
file(MAKE_DIRECTORY "${dir}" RESULT res)
|
||||
if (res EQUAL 0)
|
||||
set(${out} "${dir}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
fatal("Fatal: Could not create temporary directory. "
|
||||
"Check write permissions to the current directory")
|
||||
endfunction()
|
||||
|
||||
# Get a package's effective URL.
|
||||
function(get_package_url)
|
||||
set(oneValueArgs
|
||||
@@ -218,6 +177,7 @@ endfunction()
|
||||
# Download a URL to file, with a sha512 hash
|
||||
# And retry 5 times
|
||||
function(cpm_download url file)
|
||||
echo("Downloading ${url} to ${file}")
|
||||
list(LENGTH ARGN argn_len)
|
||||
if(argn_len GREATER 0)
|
||||
list(GET ARGN 0 hash)
|
||||
@@ -229,8 +189,7 @@ function(cpm_download url file)
|
||||
foreach(i RANGE 5)
|
||||
file(DOWNLOAD ${url} ${file}
|
||||
${args}
|
||||
STATUS ret
|
||||
LOG log)
|
||||
STATUS ret)
|
||||
|
||||
list(GET ret 0 code)
|
||||
if (code EQUAL 0)
|
||||
@@ -339,60 +298,47 @@ function(fetch_package)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Temporary directory.
|
||||
mktempdir(TMP)
|
||||
|
||||
# Get filename from URL
|
||||
get_filename_component(base_filename ${ARG_URL} NAME)
|
||||
|
||||
# Download
|
||||
set(file ${TMP}/${base_filename})
|
||||
cpm_download(${ARG_URL} ${file} ${ARG_HASH})
|
||||
message(DEBUG "Downloaded ${base_filename}")
|
||||
|
||||
# Extract the downloaded archive
|
||||
# TODO: Moar error handling
|
||||
set(dir ${TMP}/${base_filename}-extracted)
|
||||
file(MAKE_DIRECTORY ${dir})
|
||||
|
||||
file(ARCHIVE_EXTRACT
|
||||
INPUT ${file}
|
||||
DESTINATION ${dir})
|
||||
|
||||
# This is copied near-verbatim from ExternalProject/extractfile.cmake.in
|
||||
|
||||
# If there's just one subdirectory and nothing else, move it
|
||||
file(GLOB contents "${dir}/*")
|
||||
list(REMOVE_ITEM contents "${dir}/.DS_Store")
|
||||
list(LENGTH contents n)
|
||||
|
||||
# If n == 1 and contents points to a directory, this is a GitHub-style pack
|
||||
# In this case contents points to the subdir which will get renamed
|
||||
# If not, contents will point to the parent dir which will get renamed
|
||||
if (NOT n EQUAL 1 OR NOT IS_DIRECTORY "${contents}")
|
||||
set(contents "${dir}")
|
||||
endif()
|
||||
|
||||
file(REAL_PATH "${contents}" contents_abs)
|
||||
|
||||
# paths
|
||||
cmake_path(ABSOLUTE_PATH ARG_PATH
|
||||
NORMALIZE
|
||||
OUTPUT_VARIABLE abs_path)
|
||||
|
||||
cmake_path(GET abs_path PARENT_PATH path_parent)
|
||||
cmake_path(GET abs_path FILENAME path_name)
|
||||
file(MAKE_DIRECTORY ${path_parent})
|
||||
|
||||
# rename tmp dir
|
||||
set(tmp_renamed "${TMP}/${path_name}")
|
||||
file(RENAME "${contents_abs}" "${tmp_renamed}")
|
||||
# Get filename from URL
|
||||
get_filename_component(base_filename ${ARG_URL} NAME)
|
||||
|
||||
# now copy
|
||||
# TODO: Error handling beyond what cmake does????
|
||||
file(COPY ${tmp_renamed} DESTINATION ${path_parent})
|
||||
# Download
|
||||
set(file ${path_parent}/${base_filename})
|
||||
cpm_download(${ARG_URL} ${file} ${ARG_HASH})
|
||||
echo("Downloaded ${base_filename}")
|
||||
|
||||
# Extract
|
||||
echo("Extracting ${file}...")
|
||||
file(ARCHIVE_EXTRACT
|
||||
INPUT ${file}
|
||||
DESTINATION ${abs_path})
|
||||
|
||||
# This is copied near-verbatim from ExternalProject/extractfile.cmake.in
|
||||
|
||||
# If there's just one subdirectory and nothing else, move it
|
||||
file(GLOB contents "${abs_path}/*")
|
||||
list(REMOVE_ITEM contents "${abs_path}/.DS_Store")
|
||||
list(LENGTH contents n)
|
||||
|
||||
# If n == 1 and contents points to a directory, this is a GitHub-style pack
|
||||
# In this case contents points to the subdir which will get renamed
|
||||
# If not, contents will point to the parent dir which will get renamed
|
||||
if (n EQUAL 1 AND IS_DIRECTORY "${contents}")
|
||||
set(temp_path "${abs_path}_tmp")
|
||||
file(RENAME "${contents}" "${temp_path}")
|
||||
file(REMOVE_RECURSE "${abs_path}")
|
||||
file(RENAME "${temp_path}" "${abs_path}")
|
||||
endif()
|
||||
|
||||
# TODO: only echo this in script mode
|
||||
message(DEBUG "Extracted to ${abs_path}")
|
||||
echo("Extracted to ${abs_path}")
|
||||
|
||||
# Apply patches
|
||||
apply_patches("${ARG_PATCHES}" "${abs_path}")
|
||||
@@ -401,7 +347,7 @@ function(fetch_package)
|
||||
file(WRITE "${abs_path}/.cpm_patch_key" ${ARG_PATCH_KEY})
|
||||
|
||||
# done! :)
|
||||
file(REMOVE_RECURSE ${TMP})
|
||||
file(REMOVE_RECURSE ${file})
|
||||
endfunction()
|
||||
|
||||
# compute a hash of all patch file contents
|
||||
|
||||
@@ -13,7 +13,7 @@ find_package_handle_standard_args(Opus
|
||||
VERSION_VAR OPUS_VERSION
|
||||
)
|
||||
|
||||
if (PLATFORM_MSYS)
|
||||
if (MSYS2)
|
||||
FixMsysPath(PkgConfig::OPUS)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ find_package_handle_standard_args(enet
|
||||
VERSION_VAR ENET_VERSION
|
||||
)
|
||||
|
||||
if (PLATFORM_MSYS)
|
||||
if (MSYS2)
|
||||
FixMsysPath(PkgConfig::ENET)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ find_package_handle_standard_args(libusb
|
||||
VERSION_VAR LIBUSB_VERSION
|
||||
)
|
||||
|
||||
if (PLATFORM_MSYS)
|
||||
if (MSYS2)
|
||||
FixMsysPath(PkgConfig::LIBUSB)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
||||
|
||||
if (PLATFORM_MSYS)
|
||||
if (MSYS2)
|
||||
FixMsysPath(PkgConfig::LZ4)
|
||||
endif()
|
||||
|
||||
|
||||
+6
-2
@@ -21,10 +21,14 @@ Eden is free, open-source, copyleft software, licensed under the terms of the [G
|
||||
### Policies
|
||||
|
||||
- No LLM or AI usage, *period*, for patches, pull requests, issues, comments, debugging, brainstorming, etc.
|
||||
- For details on why, see the [detailed AI policy](docs/AI.md).
|
||||
- For details on why, see the [detailed AI policy](docs/policies/AI.md).
|
||||
- Usage of any form of profanity or otherwise unsavory language is generally discouraged.
|
||||
- This is primarily because it rarely helps to actually understand what's going on.
|
||||
- Remember that your comments should be focused and actually address what's happening. With very few exceptions, expletives are actively detrimental at best.
|
||||
- New code must follow the same general style as the surrounding codebase. Exceptions may be granted in certain cases.
|
||||
- Maintainers reserve the right to change your patches and pull requests at will. We will try to avoid this.
|
||||
- You should respect all decisions made by the [code owners](docs/CODEOWNERS) in your particular subsystem. If you feel they are overstepping or are incorrect, don't be afraid to stand your ground!
|
||||
- You should generally respect all decisions made by the [code owners](docs/CODEOWNERS) in your particular subsystem.
|
||||
- However, if you feel they are overstepping or are incorrect, don't be afraid to stand your ground! Maintainers are not always correct.
|
||||
- While we do *not* adhere to the terms of a formal code of conduct, you will generally be expected to respect other developers, contributors, and community members.
|
||||
- You **must** have basic knowledge of [Git](https://git-scm.com/learn). Knowing how to manage your branches and follow proper fork policies is a necessity.
|
||||
|
||||
|
||||
@@ -65,6 +65,12 @@
|
||||
"repo": "eden-emulator/discord-rpc",
|
||||
"version": "0d8b2d6a37"
|
||||
},
|
||||
"dxbc": {
|
||||
"bundled": true,
|
||||
"hash": "196d26c07747d7aa2ced6fb1a5ae6f665e9b917de223a540038690b037c70a1eeca51c21d42aa5bec9fff7df0a6656a75ee8b4e2cb4008469f18a6812280f831",
|
||||
"repo": "PancakeTAS/dxbc",
|
||||
"version": "78ab59a8aaeb43cd1b0a5e91ba86722433a10b78"
|
||||
},
|
||||
"enet": {
|
||||
"find_args": "MODULE",
|
||||
"hash": "a0d2fa8c957704dd49e00a726284ac5ca034b50b00d2b20a94fa1bbfbb80841467834bfdc84aa0ed0d6aab894608fd6c86c3b94eee46343f0e6d9c22e391dbf9",
|
||||
|
||||
-354
@@ -1,354 +0,0 @@
|
||||
[
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "the-legend-of-zelda-breath-of-the-wild",
|
||||
"releases": [
|
||||
{"id": "01007EF00011E000"}
|
||||
],
|
||||
"title": "The Legend of Zelda: Breath of the Wild"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "super-mario-odyssey",
|
||||
"releases": [
|
||||
{"id": "0100000000010000"}
|
||||
],
|
||||
"title": "Super Mario Odyssey"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "animal-crossing-new-horizons",
|
||||
"releases": [
|
||||
{"id": "01006F8002326000"}
|
||||
],
|
||||
"title": "Animal Crossing: New Horizons"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "pokemon-legends-z-a",
|
||||
"releases": [
|
||||
{"id": "0100F43008C44000"}
|
||||
],
|
||||
"title": "Pokémon Legends: Z-A"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "the-legend-of-zelda-tears-of-the-kingdom",
|
||||
"releases": [
|
||||
{"id": "0100F2C0115B6000"}
|
||||
],
|
||||
"title": "The Legend of Zelda: Tears of the Kingdom"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "super-mario-galaxy",
|
||||
"releases": [
|
||||
{"id": "010099C022B96000"}
|
||||
],
|
||||
"title": "Super Mario Galaxy"
|
||||
},
|
||||
{
|
||||
"compatibility": 3,
|
||||
"directory": "star-wars-republic-commando",
|
||||
"releases": [
|
||||
{"id": "0100FA10115F8000"}
|
||||
],
|
||||
"title": "Star Wars: Republic Commando"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "doki-doki-literature-club-plus",
|
||||
"releases": [
|
||||
{"id": "010086901543E000"}
|
||||
],
|
||||
"title": "Doki Doki Literature Club Plus"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "pokemon-scarlet",
|
||||
"releases": [
|
||||
{"id": "0100A3D008C5C000"}
|
||||
],
|
||||
"title": "Pokémon Scarlet"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "pokemon-violet",
|
||||
"releases": [
|
||||
{"id": "01008F6008C5E000"}
|
||||
],
|
||||
"title": "Pokémon Violet"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "pokemon-legends-arceus",
|
||||
"releases": [
|
||||
{"id": "01001E300D162000"}
|
||||
],
|
||||
"title": "Pokémon Legends: Arceus"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "splatoon-2",
|
||||
"releases": [
|
||||
{"id": "01003BC0000A0000"}
|
||||
],
|
||||
"title": "Splatoon 2"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "super-smash-bros-ultimate",
|
||||
"releases": [
|
||||
{"id": "01006A800016E000"}
|
||||
],
|
||||
"title": "Super Smash Bros. Ultimate"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "mario-kart-8-deluxe",
|
||||
"releases": [
|
||||
{"id": "0100152000022000"}
|
||||
],
|
||||
"title": "Mario Kart 8 Deluxe"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "splatoon-3",
|
||||
"releases": [
|
||||
{"id": "0100C2500FC20000"}
|
||||
],
|
||||
"title": "Splatoon 3"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "new-super-mario-bros-u-deluxe",
|
||||
"releases": [
|
||||
{"id": "0100EA80032EA000"}
|
||||
],
|
||||
"title": "New Super Mario Bros. U Deluxe"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "hyrule-warriors-age-of-calamity",
|
||||
"releases": [
|
||||
{"id": "01002B00111A2000"}
|
||||
],
|
||||
"title": "Hyrule Warriors: Age of Calamity"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "luigis-mansion-3",
|
||||
"releases": [
|
||||
{"id": "0100DCA0064A6000"}
|
||||
],
|
||||
"title": "Luigi's Mansion 3"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "pokemon-brilliant-diamond",
|
||||
"releases": [
|
||||
{"id": "0100000011D90000"}
|
||||
],
|
||||
"title": "Pokémon Brilliant Diamond"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "pokemon-shining-pearl",
|
||||
"releases": [
|
||||
{"id": "010018E011D92000"}
|
||||
],
|
||||
"title": "Pokémon Shining Pearl"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "super-mario-3d-world-bowsers-fury",
|
||||
"releases": [
|
||||
{"id": "010028600EBDA000"}
|
||||
],
|
||||
"title": "Super Mario 3D World + Bowser's Fury"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "the-legend-of-zelda-links-awakening",
|
||||
"releases": [
|
||||
{"id": "01006BB00C6F0000"}
|
||||
],
|
||||
"title": "The Legend of Zelda: Link's Awakening"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "fire-emblem-three-houses",
|
||||
"releases": [
|
||||
{"id": "010055D009F78000"}
|
||||
],
|
||||
"title": "Fire Emblem: Three Houses"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "metroid-dread",
|
||||
"releases": [
|
||||
{"id": "010093801237C000"}
|
||||
],
|
||||
"title": "Metroid Dread"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "paper-mario-the-origami-king",
|
||||
"releases": [
|
||||
{"id": "0100A3900C3E2000"}
|
||||
],
|
||||
"title": "Paper Mario: The Origami King"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "xenoblade-chronicles-definitive-edition",
|
||||
"releases": [
|
||||
{"id": "0100FF500E34A000"}
|
||||
],
|
||||
"title": "Xenoblade Chronicles: Definitive Edition"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "xenoblade-chronicles-3",
|
||||
"releases": [
|
||||
{"id": "010074F013262000"}
|
||||
],
|
||||
"title": "Xenoblade Chronicles 3"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "pikmin-3-deluxe",
|
||||
"releases": [
|
||||
{"id": "0100F8600D4B0000"}
|
||||
],
|
||||
"title": "Pikmin 3 Deluxe"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "donkey-kong-country-tropical-freeze",
|
||||
"releases": [
|
||||
{"id": "0100C1F0054B6000"}
|
||||
],
|
||||
"title": "Donkey Kong Country: Tropical Freeze"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "kirby-and-the-forgotten-land",
|
||||
"releases": [
|
||||
{"id": "01004D300C5AE000"}
|
||||
],
|
||||
"title": "Kirby and the Forgotten Land"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "mario-party-superstars",
|
||||
"releases": [
|
||||
{"id": "01006B400D8B2000"}
|
||||
],
|
||||
"title": "Mario Party Superstars"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "clubhouse-games-51-worldwide-classics",
|
||||
"releases": [
|
||||
{"id": "0100F8600D4B0000"}
|
||||
],
|
||||
"title": "Clubhouse Games: 51 Worldwide Classics"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "ring-fit-adventure",
|
||||
"releases": [
|
||||
{"id": "01006B300BAF8000"}
|
||||
],
|
||||
"title": "Ring Fit Adventure"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "arms",
|
||||
"releases": [
|
||||
{"id": "01009B500007C000"}
|
||||
],
|
||||
"title": "ARMS"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "super-mario-maker-2",
|
||||
"releases": [
|
||||
{"id": "01009B90006DC000"}
|
||||
],
|
||||
"title": "Super Mario Maker 2"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "pokemon-lets-go-pikachu",
|
||||
"releases": [
|
||||
{"id": "010003F003A34000"}
|
||||
],
|
||||
"title": "Pokémon: Let's Go, Pikachu!"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "pokemon-lets-go-eevee",
|
||||
"releases": [
|
||||
{"id": "0100187003A36000"}
|
||||
],
|
||||
"title": "Pokémon: Let's Go, Eevee!"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "pokemon-sword",
|
||||
"releases": [
|
||||
{"id": "0100ABF008968000"}
|
||||
],
|
||||
"title": "Pokémon Sword"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "pokemon-shield",
|
||||
"releases": [
|
||||
{"id": "01008DB008C2C000"}
|
||||
],
|
||||
"title": "Pokémon Shield"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "new-pokemon-snap",
|
||||
"releases": [
|
||||
{"id": "0100F4300C182000"}
|
||||
],
|
||||
"title": "New Pokémon Snap"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "mario-golf-super-rush",
|
||||
"releases": [
|
||||
{"id": "0100C9C00E25C000"}
|
||||
],
|
||||
"title": "Mario Golf: Super Rush"
|
||||
},
|
||||
{
|
||||
"compatibility": 1,
|
||||
"directory": "mario-tennis-aces",
|
||||
"releases": [
|
||||
{"id": "0100BDE00862A000"}
|
||||
],
|
||||
"title": "Mario Tennis Aces"
|
||||
},
|
||||
{
|
||||
"compatibility": 2,
|
||||
"directory": "wario-ware-get-it-together",
|
||||
"releases": [
|
||||
{"id": "0100563010F22000"}
|
||||
],
|
||||
"title": "WarioWare: Get It Together!"
|
||||
},
|
||||
{
|
||||
"compatibility": 0,
|
||||
"directory": "big-brain-academy-brain-vs-brain",
|
||||
"releases": [
|
||||
{"id": "0100190010F24000"}
|
||||
],
|
||||
"title": "Big Brain Academy: Brain vs. Brain"
|
||||
}
|
||||
]
|
||||
@@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="compatibility_list">
|
||||
<file>compatibility_list.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
Vendored
+648
-800
File diff suppressed because it is too large
Load Diff
Vendored
+637
-794
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+626
-786
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+628
-788
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+624
-781
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+625
-784
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+670
-822
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+625
-784
File diff suppressed because it is too large
Load Diff
Vendored
+625
-785
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+625
-785
File diff suppressed because it is too large
Load Diff
Vendored
+625
-784
File diff suppressed because it is too large
Load Diff
Vendored
+625
-782
File diff suppressed because it is too large
Load Diff
Vendored
+625
-783
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
Vendored
+626
-786
File diff suppressed because it is too large
Load Diff
Vendored
+623
-780
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,8 @@ These options control dependencies.
|
||||
- `YUZU_INSTALL_UDEV_RULES` (OFF) Install udev rules to enable hidraw access
|
||||
- Needed for gyroscopes
|
||||
- Only available on Linux
|
||||
- `ENABLE_DEBUG_TOOLS` (OFF) Enables debugging and development tools, see [tools](../tools/README.md).
|
||||
- `ENABLE_WERROR` (ON) Enables warnings as errors (-Werror).
|
||||
|
||||
### Flavors
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
|
||||
- The reason is because the project has `-fno-rtti` disabled by default, due to the costs of dynamic polymorphism.
|
||||
- Always copy-on-value for objects with `sizeof(void *) >= sizeof(T) * 2`, i.e objects sized as 2 pointers or less, for bigger objects you can use ref/pointer as usual.
|
||||
- Try using move semantics instead of references, whenever possible.
|
||||
- Remember function parameters are extremelly cheap as fuck, don't be afraid to place upto 8 parameters on a given function.
|
||||
- Function parameters are cheap. Don't be afraid to use as many as needed (API usability permitting).
|
||||
- Don't save a reference in structures of a parent object, i.e:
|
||||
|
||||
```c++
|
||||
|
||||
@@ -27,3 +27,6 @@ There are two main applications, an SDL-based app (`eden-cli`) and a Qt based ap
|
||||
- `--user/-u`: Specify the user index.
|
||||
- `--version/-v`: Display version and quit.
|
||||
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only).
|
||||
- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings.
|
||||
- `--filter/-x`: Sets the debug log filter irrespective of settings.
|
||||
- `--singlecore/-s`: Forces single-core regardless of settings.
|
||||
|
||||
Vendored
+5
-1
@@ -92,6 +92,10 @@ AddDependentPackages(vulkan-headers vulkan-utility-libraries)
|
||||
# frozen
|
||||
AddJsonPackage(frozen)
|
||||
|
||||
# DXVK's DXBC compiler, used to translate the frame generation shaders
|
||||
# out of a user-supplied Lossless.dll into SPIR-V
|
||||
AddJsonPackage(dxbc)
|
||||
|
||||
# DiscordRPC
|
||||
if (USE_DISCORD_PRESENCE)
|
||||
if (ARCHITECTURE_arm64)
|
||||
@@ -164,7 +168,7 @@ if (NOT ANDROID)
|
||||
AddJsonPackage(sdl3)
|
||||
else()
|
||||
message(STATUS "Using bundled SDL3")
|
||||
if (PLATFORM_FREEBSD)
|
||||
if (FREEBSD)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif()
|
||||
AddJsonPackage(sdl3-ci)
|
||||
|
||||
+23
-80
@@ -1,45 +1,46 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-FileCopyrightText: Copyright 2026 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
## DetectPlatform ##
|
||||
|
||||
# This is a small helper that sets PLATFORM_<platform> variables for various
|
||||
# This is a small helper that sets platform variables for various
|
||||
# operating systems and distributions. Note that Apple, Windows, Android, etc.
|
||||
# are not covered, as CMake already does that for us.
|
||||
|
||||
# It also sets CXX_<compiler> for the C++ compiler.
|
||||
|
||||
# Furthermore, some platforms have really silly requirements/quirks, so this
|
||||
# also does a few of those.
|
||||
|
||||
# This module contains contributions from the Eden Emulator Project,
|
||||
# notably from crueter and Lizzie.
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
|
||||
set(PLATFORM_SUN ON)
|
||||
set(SOLARIS ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenOrbis")
|
||||
set(PLATFORM_PS4 ON)
|
||||
set(OPENORBIS ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "managarm")
|
||||
set(PLATFORM_MANAGARM ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
set(PLATFORM_FREEBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set(PLATFORM_OPENBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
|
||||
set(PLATFORM_NETBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "DragonFly")
|
||||
set(PLATFORM_DRAGONFLYBSD ON)
|
||||
set(MANAGARM ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Haiku")
|
||||
set(PLATFORM_HAIKU ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(PLATFORM_LINUX ON)
|
||||
set(HAIKUOS ON)
|
||||
endif()
|
||||
|
||||
# BSD
|
||||
if (DEFINED BSD)
|
||||
if ("${BSD}" STREQUAL "DragonFlyBSD")
|
||||
set(DRAGONFLYBSD ON)
|
||||
elseif ("${BSD}" STREQUAL "FreeBSD")
|
||||
set(FREEBSD ON)
|
||||
elseif ("${BSD}" STREQUAL "OpenBSD")
|
||||
set(OPENBSD ON)
|
||||
elseif ("${BSD}" STREQUAL "NetBSD")
|
||||
set(NETBSD ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# dumb heuristic to detect msys2
|
||||
if (CMAKE_COMMAND MATCHES "msys64")
|
||||
set(PLATFORM_MSYS ON)
|
||||
set(MSYS2 ON)
|
||||
endif()
|
||||
|
||||
# compiler checks
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(CXX_CLANG ON)
|
||||
if (MSVC)
|
||||
@@ -47,8 +48,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CXX_GCC ON)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(CXX_CL ON)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
||||
set(CXX_ICC ON)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
@@ -61,37 +60,13 @@ if(MINGW AND CXX_CLANG)
|
||||
set(CMAKE_SYSTEM_VERSION 10.0.0)
|
||||
endif()
|
||||
|
||||
# NB: this does not account for SPARC
|
||||
if (PLATFORM_SUN)
|
||||
# Terrific OpenIndiana pkg shenanigans
|
||||
list(APPEND CMAKE_PREFIX_PATH
|
||||
"${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake")
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_SYSROOT}/usr/lib/qt/6.6/lib/amd64/cmake")
|
||||
|
||||
# Amazing - absolutely incredible
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SYSROOT}/usr/lib/amd64/cmake")
|
||||
|
||||
# For some mighty reason, doing a normal release build sometimes
|
||||
# may not trigger the proper -O3 switch to materialize
|
||||
if (CMAKE_BUILD_TYPE MATCHES "Release")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
if (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# MSYS2 utilities
|
||||
|
||||
# Sometimes, PkgConfig modules will incorrectly reference / when CMake
|
||||
# wants you to reference it as C:/msys64/. This function corrects that.
|
||||
# Example in a Find module:
|
||||
#[[
|
||||
if (PLATFORM_MSYS)
|
||||
if (MSYS2)
|
||||
FixMsysPath(PkgConfig::OPUS)
|
||||
endif()
|
||||
]]
|
||||
@@ -116,41 +91,9 @@ function(FixMsysPath target)
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${include_dir})
|
||||
endfunction()
|
||||
|
||||
# MSYSTEM handling + program_path
|
||||
if (PLATFORM_MSYS)
|
||||
# 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()
|
||||
|
||||
# This saves a truly ridiculous amount of time during linking
|
||||
# In my tests, without this, Eden takes 2 mins, with this, it takes 3-5 seconds
|
||||
# or on GitHub Actions, 10 minutes -> 3 seconds
|
||||
# Saves linking time
|
||||
if (MINGW)
|
||||
set(MINGW_FLAGS "-Wl,--strip-all -Wl,--gc-sections")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE
|
||||
"${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${MINGW_FLAGS}")
|
||||
endif()
|
||||
|
||||
# awesome
|
||||
if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD)
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib")
|
||||
endif()
|
||||
|
||||
Vendored
+5
-5
@@ -56,7 +56,7 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (PLATFORM_PS4 OR PLATFORM_MANAGARM)
|
||||
if (OPENORBIS OR MANAGARM)
|
||||
# Doesn't support VA-API, don't go thru the embarrassment of trying to enable it
|
||||
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
|
||||
elseif (ANDROID)
|
||||
@@ -75,7 +75,7 @@ elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING AND NOT ANDROID)
|
||||
if(X11_FOUND)
|
||||
if (NOT APPLE)
|
||||
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
|
||||
if(PLATFORM_SUN)
|
||||
if(SOLARIS)
|
||||
list(APPEND FFmpeg_HWACCEL_LIBRARIES
|
||||
X11
|
||||
"${CMAKE_SYSROOT}/usr/lib/xorg/amd64/libdrm.so")
|
||||
@@ -158,7 +158,7 @@ elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING AND NOT ANDROID)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (PLATFORM_PS4)
|
||||
if (OPENORBIS)
|
||||
list(APPEND FFmpeg_CROSS_COMPILE_LIBS
|
||||
-lkernel
|
||||
-lSceUserService
|
||||
@@ -172,7 +172,7 @@ if (PLATFORM_PS4)
|
||||
--extra-cxxflags=${CMAKE_SYSROOT}/usr/include
|
||||
--extra-libs="${FFmpeg_CROSS_COMPILE_LIBS}"
|
||||
)
|
||||
elseif (PLATFORM_MANAGARM)
|
||||
elseif (MANAGARM)
|
||||
# Required for proper stuff
|
||||
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
|
||||
--disable-pthreads
|
||||
@@ -299,7 +299,7 @@ else()
|
||||
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)
|
||||
if (LINUX OR ANDROID OR APPLE OR WIN32 OR FREEBSD)
|
||||
set(FFmpeg_MAKE_ARGS -j${SYSTEM_THREADS})
|
||||
else()
|
||||
set(FFmpeg_MAKE_ARGS "")
|
||||
|
||||
Vendored
+1
-1
@@ -11,7 +11,7 @@ if (NOT libusb_ADDED)
|
||||
endif()
|
||||
|
||||
# TODO: *BSD fails to compile--may need different configs/symbols
|
||||
if (MINGW OR PLATFORM_LINUX OR APPLE)
|
||||
if (MINGW OR LINUX OR APPLE)
|
||||
set(LIBUSB_FOUND ON CACHE BOOL "libusb is present" FORCE)
|
||||
set(LIBUSB_VERSION "1.0.24" CACHE STRING "libusb version string" FORCE)
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -1177,7 +1177,7 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
|
||||
#endif
|
||||
|
||||
#ifndef STBI_NO_TGA
|
||||
// test tga last because it's a crappy test!
|
||||
// test tga last because it's a bad test!
|
||||
if (stbi__tga_test(s))
|
||||
return stbi__tga_load(s,x,y,comp,req_comp, ri);
|
||||
#endif
|
||||
@@ -7662,7 +7662,7 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
|
||||
if (stbi__hdr_info(s, x, y, comp)) return 1;
|
||||
#endif
|
||||
|
||||
// test tga last because it's a crappy test!
|
||||
// test tga last because it's a bad test!
|
||||
#ifndef STBI_NO_TGA
|
||||
if (stbi__tga_info(s, x, y, comp))
|
||||
return 1;
|
||||
|
||||
+21
-9
@@ -155,12 +155,24 @@ else()
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WERROR)
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=all>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=extra>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=missing-declarations>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=shadow>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=unused>)
|
||||
else()
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wall>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wextra>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wmissing-declarations>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wshadow>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wunused>
|
||||
# Some compilers could particularly misbehave :)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-error-all>)
|
||||
endif()
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=all>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=extra>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=missing-declarations>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=shadow>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=unused>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-attributes>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-invalid-offsetof>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-unused-parameter>
|
||||
@@ -169,9 +181,9 @@ else()
|
||||
if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++
|
||||
if (NOT MSVC)
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=shadow-uncaptured-local>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=implicit-fallthrough>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=type-limits>)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wshadow-uncaptured-local>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wimplicit-fallthrough>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wtype-limits>)
|
||||
endif()
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-braced-scalar-init>
|
||||
@@ -181,7 +193,7 @@ else()
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>)
|
||||
if (PLATFORM_LINUX OR PLATFORM_FREEBSD)
|
||||
if (LINUX OR FREEBSD)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-mtls-dialect=gnu2>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -188,6 +188,7 @@ android {
|
||||
create("mainline") {
|
||||
dimension = "version"
|
||||
isDefault = true
|
||||
minSdk = 33
|
||||
|
||||
manifestPlaceholders += mapOf("appNameBase" to "Eden")
|
||||
resValue("string", "app_name_suffixed", "Eden")
|
||||
@@ -199,6 +200,7 @@ android {
|
||||
|
||||
create("genshinSpoof") {
|
||||
dimension = "version"
|
||||
minSdk = 35
|
||||
manifestPlaceholders += mapOf("appNameBase" to "Eden Optimized")
|
||||
resValue("string", "app_name_suffixed", "Eden Optimized")
|
||||
applicationId = "com.miHoYo.Yuanshen"
|
||||
@@ -216,6 +218,7 @@ android {
|
||||
|
||||
create("legacy") {
|
||||
dimension = "version"
|
||||
minSdk = 29
|
||||
manifestPlaceholders += mapOf("appNameBase" to "Eden Legacy")
|
||||
resValue("string", "app_name_suffixed", "Eden Legacy")
|
||||
applicationId = "dev.legacy.eden_emulator"
|
||||
|
||||
@@ -218,6 +218,8 @@ object NativeLibrary {
|
||||
|
||||
external fun logSettings()
|
||||
|
||||
external fun refreshThreadPolicies()
|
||||
|
||||
external fun getDebugKnobAt(index: Int): Boolean
|
||||
|
||||
/**
|
||||
@@ -537,6 +539,40 @@ object NativeLibrary {
|
||||
*/
|
||||
external fun installKeys(path: String, ext: String): Int
|
||||
|
||||
/**
|
||||
* @return Whether this GPU can run the Lossless Scaling frame generation shaders,
|
||||
* which are built against the Vulkan memory model.
|
||||
*/
|
||||
external fun supportsFrameGeneration(): Boolean
|
||||
|
||||
/**
|
||||
* @return Path the user-supplied Lossless Scaling library is expected at.
|
||||
*/
|
||||
external fun getLosslessDllPath(): String
|
||||
|
||||
/**
|
||||
* Parses the installed Lossless Scaling library and checks that every shader the
|
||||
* frame generation chain needs is present.
|
||||
*
|
||||
* @return The result code, matching the losslessDllResults array.
|
||||
*/
|
||||
external fun validateLosslessDll(): Int
|
||||
|
||||
/**
|
||||
* Translates the frame generation shaders out of the installed Lossless Scaling library
|
||||
* and writes them to the SPIR-V cache. Slow, so call it off the main thread.
|
||||
*
|
||||
* @return The result code, matching the losslessDllResults array.
|
||||
*/
|
||||
external fun prepareLosslessDll(): Int
|
||||
|
||||
/**
|
||||
* Deletes the installed Lossless Scaling library.
|
||||
*
|
||||
* @return Whether the library is gone after the call.
|
||||
*/
|
||||
external fun removeLosslessDll(): Boolean
|
||||
|
||||
/**
|
||||
* Checks the PatchManager for any addons that are available
|
||||
*
|
||||
|
||||
+4
-1
@@ -16,7 +16,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
|
||||
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
|
||||
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
|
||||
ANTIFLICKER("antiflicker"),
|
||||
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
|
||||
EMULATE_BGR565("emulate_bgr565"),
|
||||
RESCALE_HACK("rescale_hack"),
|
||||
@@ -38,6 +37,10 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||
RENDERER_FRAME_GEN("frame_gen"),
|
||||
RENDERER_FRAME_GEN_FP16("frame_gen_fp16"),
|
||||
RENDERER_FRAME_GEN_FLOW_SCALE_AUTO("frame_gen_flow_scale_auto"),
|
||||
RENDERER_FRAME_GEN_DUMP_FLOW("frame_gen_dump_flow"),
|
||||
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
||||
PICTURE_IN_PICTURE("picture_in_picture"),
|
||||
USE_CUSTOM_RTC("custom_rtc_enabled"),
|
||||
|
||||
@@ -19,6 +19,9 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
||||
RENDERER_ACCURACY("gpu_accuracy"),
|
||||
RENDERER_RESOLUTION("resolution_setup"),
|
||||
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
|
||||
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
|
||||
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
|
||||
RENDERER_VSYNC("use_vsync"),
|
||||
RENDERER_SCALING_FILTER("scaling_filter"),
|
||||
RENDERER_ANTI_ALIASING("anti_aliasing"),
|
||||
@@ -27,6 +30,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||
|
||||
RENDERER_DYNA_STATE("dyna_state"),
|
||||
DMA_ACCURACY("dma_accuracy"),
|
||||
GPU_FENCE_BEHAVIOR("gpu_fence_behavior"),
|
||||
FRAME_PACING_MODE("frame_pacing_mode"),
|
||||
AUDIO_OUTPUT_ENGINE("output_engine"),
|
||||
MAX_ANISOTROPY("max_anisotropy"),
|
||||
|
||||
@@ -11,6 +11,7 @@ object Settings {
|
||||
SECTION_ROOT(R.string.advanced_settings),
|
||||
SECTION_SYSTEM(R.string.preferences_system),
|
||||
SECTION_RENDERER(R.string.preferences_graphics),
|
||||
SECTION_FRAME_GEN(R.string.frame_gen),
|
||||
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
||||
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
|
||||
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
|
||||
|
||||
+83
-8
@@ -21,6 +21,7 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.network.NetDataValidators
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
|
||||
/**
|
||||
@@ -65,6 +66,12 @@ abstract class SettingsItem(
|
||||
return NativeLibrary.isFirmwareAvailable()
|
||||
}
|
||||
|
||||
if (setting.key in frameGenKeys &&
|
||||
!(LosslessScalingHelper.isInstalled() && LosslessScalingHelper.isSupportedByGpu())
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Can't edit settings that aren't saveable in per-game config even if they are switchable
|
||||
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
|
||||
return false
|
||||
@@ -89,6 +96,16 @@ abstract class SettingsItem(
|
||||
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
|
||||
|
||||
companion object {
|
||||
private val frameGenKeys = setOf(
|
||||
BooleanSetting.RENDERER_FRAME_GEN.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FP16.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key
|
||||
)
|
||||
|
||||
const val TYPE_HEADER = 0
|
||||
const val TYPE_SWITCH = 1
|
||||
const val TYPE_SINGLE_CHOICE = 2
|
||||
@@ -594,7 +611,7 @@ abstract class SettingsItem(
|
||||
IntSetting.ANDROID_PIPELINE_WORKERS,
|
||||
titleId = R.string.pipeline_worker_cores,
|
||||
descriptionId = R.string.pipeline_worker_cores_description,
|
||||
min = 4,
|
||||
min = 2,
|
||||
max = 8,
|
||||
units = "cores"
|
||||
)
|
||||
@@ -607,6 +624,62 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.rendererAntiAliasingValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN,
|
||||
titleId = R.string.frame_gen,
|
||||
descriptionId = R.string.frame_gen_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER,
|
||||
titleId = R.string.frame_gen_multiplier,
|
||||
descriptionId = R.string.frame_gen_multiplier_description,
|
||||
choicesId = R.array.frameGenMultiplierNames,
|
||||
valuesId = R.array.frameGenMultiplierValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET,
|
||||
titleId = R.string.frame_gen_queue_target,
|
||||
descriptionId = R.string.frame_gen_queue_target_description,
|
||||
choicesId = R.array.frameGenQueueTargetNames,
|
||||
valuesId = R.array.frameGenQueueTargetValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO,
|
||||
titleId = R.string.frame_gen_flow_scale_auto,
|
||||
descriptionId = R.string.frame_gen_flow_scale_auto_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SliderSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE,
|
||||
titleId = R.string.frame_gen_flow_scale,
|
||||
descriptionId = R.string.frame_gen_flow_scale_description,
|
||||
min = 25,
|
||||
max = 100,
|
||||
units = "%"
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FP16,
|
||||
titleId = R.string.frame_gen_fp16,
|
||||
descriptionId = R.string.frame_gen_fp16_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW,
|
||||
titleId = R.string.frame_gen_dump_flow,
|
||||
descriptionId = R.string.frame_gen_dump_flow_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_SCREEN_LAYOUT,
|
||||
@@ -669,6 +742,15 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.dmaAccuracyValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.GPU_FENCE_BEHAVIOR,
|
||||
titleId = R.string.gpu_fence_behavior,
|
||||
descriptionId = R.string.gpu_fence_behavior_description,
|
||||
choicesId = R.array.gpuFenceBehaviorNames,
|
||||
valuesId = R.array.gpuFenceBehaviorValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
|
||||
@@ -757,13 +839,6 @@ abstract class SettingsItem(
|
||||
descriptionId = R.string.skip_cpu_inner_invalidation_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.ANTIFLICKER,
|
||||
titleId = R.string.antiflicker,
|
||||
descriptionId = R.string.antiflicker_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.FIX_BLOOM_EFFECTS,
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||
@@ -169,7 +169,7 @@ class InputDialogFragment : DialogFragment() {
|
||||
NativeInput.onGamePadButtonEvent(
|
||||
controllerData.getGUID(),
|
||||
controllerData.getPort(),
|
||||
event.keyCode,
|
||||
InputHandler.getButtonIdFromEvent(event),
|
||||
action
|
||||
)
|
||||
onInputReceived(event.device)
|
||||
|
||||
+51
@@ -33,6 +33,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.PathSetting
|
||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||
import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment
|
||||
import org.yuzu.yuzu_emu.utils.PathUtil
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
import org.yuzu.yuzu_emu.utils.*
|
||||
@@ -114,6 +115,29 @@ class SettingsFragment : Fragment() {
|
||||
viewLifecycleOwner,
|
||||
resetState = { settingsViewModel.setShouldReloadSettingsList(false) }
|
||||
) { if (it) presenter.loadSettingsList() }
|
||||
settingsViewModel.shouldShowLosslessInstaller.collect(
|
||||
viewLifecycleOwner,
|
||||
resetState = { settingsViewModel.setShouldShowLosslessInstaller(false) }
|
||||
) { if (it) losslessDllPickerLauncher.launch(arrayOf("*/*")) }
|
||||
settingsViewModel.shouldShowLosslessRemoveDialog.collect(
|
||||
viewLifecycleOwner,
|
||||
resetState = { settingsViewModel.setShouldShowLosslessRemoveDialog(false) }
|
||||
) {
|
||||
if (it) {
|
||||
MessageDialogFragment.newInstance(
|
||||
activity = requireActivity(),
|
||||
titleId = R.string.lossless_scaling_remove,
|
||||
descriptionId = R.string.lossless_scaling_remove_confirmation,
|
||||
positiveButtonTitleId = R.string.lossless_scaling_remove,
|
||||
positiveAction = {
|
||||
LosslessScalingHelper.remove()
|
||||
settingsViewModel.setShouldReloadSettingsList(true)
|
||||
},
|
||||
showNegativeButton = true,
|
||||
negativeAction = {}
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
settingsViewModel.adapterItemChanged.collect(
|
||||
viewLifecycleOwner,
|
||||
resetState = { settingsViewModel.setAdapterItemChanged(-1) }
|
||||
@@ -267,6 +291,33 @@ private fun getPlayerIndex(): Int =
|
||||
directoryPickerLauncher.launch(null)
|
||||
}
|
||||
|
||||
private val losslessDllPickerLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.OpenDocument()
|
||||
) { uri ->
|
||||
if (uri == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.lossless_scaling_installing,
|
||||
false
|
||||
) { _, _ ->
|
||||
val result = LosslessScalingHelper.install(uri)
|
||||
if (result == LosslessScalingHelper.RESULT_OK) {
|
||||
getString(R.string.lossless_scaling_install_success)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
titleId = R.string.lossless_scaling_install_failed,
|
||||
descriptionString = resultStrings[result]
|
||||
)
|
||||
}
|
||||
}.apply {
|
||||
onDialogComplete = { settingsViewModel.setShouldReloadSettingsList(true) }
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
private val directoryPickerLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.OpenDocumentTree()
|
||||
) { uri ->
|
||||
|
||||
+75
-4
@@ -27,6 +27,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||
@@ -76,6 +77,67 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFrameGenSettings(sl: ArrayList<SettingsItem>) {
|
||||
sl.apply {
|
||||
val installed = LosslessScalingHelper.isInstalled()
|
||||
val supported = LosslessScalingHelper.isSupportedByGpu()
|
||||
|
||||
add(HeaderSetting(R.string.lossless_scaling))
|
||||
|
||||
if (!supported) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.frame_gen_unsupported,
|
||||
descriptionId = R.string.frame_gen_unsupported_description,
|
||||
isRunnable = false
|
||||
) {}
|
||||
)
|
||||
}
|
||||
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = if (installed) {
|
||||
R.string.lossless_scaling_replace
|
||||
} else {
|
||||
R.string.lossless_scaling_install
|
||||
},
|
||||
descriptionId = if (installed) {
|
||||
R.string.lossless_scaling_replace_description
|
||||
} else {
|
||||
R.string.lossless_scaling_install_description
|
||||
},
|
||||
isRunnable = !NativeLibrary.isRunning(),
|
||||
iconId = R.drawable.ic_install
|
||||
) { settingsViewModel.setShouldShowLosslessInstaller(true) }
|
||||
)
|
||||
|
||||
if (installed) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.lossless_scaling_remove,
|
||||
descriptionId = R.string.lossless_scaling_remove_description,
|
||||
isRunnable = !NativeLibrary.isRunning(),
|
||||
iconId = R.drawable.ic_delete
|
||||
) { settingsViewModel.setShouldShowLosslessRemoveDialog(true) }
|
||||
)
|
||||
}
|
||||
|
||||
add(HeaderSetting(R.string.frame_gen))
|
||||
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN.key)
|
||||
add(IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key)
|
||||
add(IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key)
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
||||
if (!BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.getBoolean(
|
||||
getNeedsGlobalForKey(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
||||
)
|
||||
) {
|
||||
add(IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key)
|
||||
}
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_FP16.key)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSharpnessScalingFilterSelected(): Boolean {
|
||||
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
|
||||
@@ -120,6 +182,7 @@ class SettingsFragmentPresenter(
|
||||
MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
||||
MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
||||
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||
MenuTag.SECTION_FRAME_GEN -> addFrameGenSettings(sl)
|
||||
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
||||
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
||||
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
||||
@@ -165,6 +228,14 @@ class SettingsFragmentPresenter(
|
||||
menuKey = MenuTag.SECTION_RENDERER
|
||||
)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
titleId = R.string.frame_gen,
|
||||
descriptionId = R.string.frame_gen_submenu_description,
|
||||
iconId = R.drawable.ic_duck,
|
||||
menuKey = MenuTag.SECTION_FRAME_GEN
|
||||
)
|
||||
)
|
||||
if (!NativeConfig.isPerGameConfigLoaded()) {
|
||||
add(
|
||||
SubmenuSetting(
|
||||
@@ -250,8 +321,9 @@ class SettingsFragmentPresenter(
|
||||
add(BooleanSetting.USE_CUSTOM_RTC.key)
|
||||
add(LongSetting.CUSTOM_RTC.key)
|
||||
|
||||
add(HeaderSetting(R.string.cpu))
|
||||
add(HeaderSetting(R.string.clocks))
|
||||
add(IntSetting.FAST_CPU_TIME.key)
|
||||
add(IntSetting.FAST_GPU_TIME.key)
|
||||
add(BooleanSetting.CORE_SYNC_CORE_SPEED.key)
|
||||
|
||||
add(IntSetting.MEMORY_LAYOUT.key)
|
||||
@@ -283,6 +355,7 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(IntSetting.RENDERER_ACCURACY.key)
|
||||
add(IntSetting.DMA_ACCURACY.key)
|
||||
add(IntSetting.GPU_FENCE_BEHAVIOR.key)
|
||||
add(IntSetting.MAX_ANISOTROPY.key)
|
||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||
@@ -297,12 +370,9 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(HeaderSetting(R.string.hacks))
|
||||
|
||||
add(IntSetting.FAST_GPU_TIME.key)
|
||||
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
||||
add(BooleanSetting.ANTIFLICKER.key)
|
||||
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
||||
add(BooleanSetting.EMULATE_BGR565.key)
|
||||
add(BooleanSetting.RESCALE_HACK.key)
|
||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||
add(IntSetting.ANDROID_PIPELINE_WORKERS.key)
|
||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
|
||||
@@ -1296,6 +1366,7 @@ class SettingsFragmentPresenter(
|
||||
add(BooleanSetting.DUMP_GUEST_SHADERS.key)
|
||||
add(BooleanSetting.GPU_LOG_SHADER_DUMPS.key)
|
||||
add(BooleanSetting.DUMP_MACROS.key)
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key)
|
||||
add(BooleanSetting.GPU_LOG_MEMORY_TRACKING.key)
|
||||
add(BooleanSetting.GPU_LOG_DRIVER_DEBUG.key)
|
||||
add(IntSetting.GPU_LOG_RING_BUFFER_SIZE.key)
|
||||
|
||||
+14
@@ -36,6 +36,12 @@ class SettingsViewModel : ViewModel() {
|
||||
val shouldReloadSettingsList: StateFlow<Boolean> get() = _shouldReloadSettingsList
|
||||
private val _shouldReloadSettingsList = MutableStateFlow(false)
|
||||
|
||||
val shouldShowLosslessInstaller: StateFlow<Boolean> get() = _shouldShowLosslessInstaller
|
||||
private val _shouldShowLosslessInstaller = MutableStateFlow(false)
|
||||
|
||||
val shouldShowLosslessRemoveDialog: StateFlow<Boolean> get() = _shouldShowLosslessRemoveDialog
|
||||
private val _shouldShowLosslessRemoveDialog = MutableStateFlow(false)
|
||||
|
||||
val sliderProgress: StateFlow<Int> get() = _sliderProgress
|
||||
private val _sliderProgress = MutableStateFlow(-1)
|
||||
|
||||
@@ -85,6 +91,14 @@ class SettingsViewModel : ViewModel() {
|
||||
_shouldReloadSettingsList.value = value
|
||||
}
|
||||
|
||||
fun setShouldShowLosslessInstaller(value: Boolean) {
|
||||
_shouldShowLosslessInstaller.value = value
|
||||
}
|
||||
|
||||
fun setShouldShowLosslessRemoveDialog(value: Boolean) {
|
||||
_shouldShowLosslessRemoveDialog.value = value
|
||||
}
|
||||
|
||||
fun setSliderTextValue(value: Float, units: String) {
|
||||
_sliderProgress.value = value.toInt()
|
||||
_sliderTextValue.value = String.format(
|
||||
|
||||
@@ -1451,6 +1451,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
NativeLibrary.refreshThreadPolicies()
|
||||
val b = _binding ?: return
|
||||
updateStatsPosition(IntSetting.PERF_OVERLAY_POSITION.getInt())
|
||||
updateSocPosition(IntSetting.SOC_OVERLAY_POSITION.getInt())
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
@@ -44,6 +45,7 @@ import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
|
||||
class HomeSettingsFragment : Fragment() {
|
||||
@@ -170,6 +172,18 @@ class HomeSettingsFragment : Fragment() {
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.lossless_scaling,
|
||||
R.string.lossless_scaling_description,
|
||||
R.drawable.ic_frames,
|
||||
{ onLosslessScalingClicked() },
|
||||
{ true },
|
||||
0,
|
||||
0,
|
||||
LosslessScalingHelper.statusText
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.multiplayer,
|
||||
@@ -337,8 +351,51 @@ class HomeSettingsFragment : Fragment() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
driverViewModel.updateDriverNameForGame(null)
|
||||
LosslessScalingHelper.refreshStatus()
|
||||
}
|
||||
|
||||
private fun onLosslessScalingClicked() {
|
||||
if (!LosslessScalingHelper.isInstalled()) {
|
||||
getLosslessDllLauncher.launch(arrayOf("*/*"))
|
||||
return
|
||||
}
|
||||
|
||||
MessageDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
titleId = R.string.lossless_scaling,
|
||||
descriptionId = R.string.lossless_scaling_installed_description,
|
||||
positiveButtonTitleId = R.string.lossless_scaling_replace,
|
||||
positiveAction = { getLosslessDllLauncher.launch(arrayOf("*/*")) },
|
||||
showNegativeButton = true,
|
||||
negativeButtonTitleId = R.string.lossless_scaling_remove,
|
||||
negativeAction = { LosslessScalingHelper.remove() }
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
|
||||
private val getLosslessDllLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.lossless_scaling_installing,
|
||||
false
|
||||
) { _, _ ->
|
||||
val installResult = LosslessScalingHelper.install(result)
|
||||
if (installResult == LosslessScalingHelper.RESULT_OK) {
|
||||
getString(R.string.lossless_scaling_install_success)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
titleId = R.string.lossless_scaling_install_failed,
|
||||
descriptionString = resultStrings[installResult]
|
||||
)
|
||||
}
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.yuzu.yuzu_emu.model.SetupPage
|
||||
import org.yuzu.yuzu_emu.model.PageState
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||
@@ -202,6 +203,24 @@ class SetupFragment : Fragment() {
|
||||
R.string.install_firmware_warning_help,
|
||||
)
|
||||
)
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_frames,
|
||||
R.string.lossless_scaling,
|
||||
R.string.lossless_scaling_setup_description,
|
||||
{
|
||||
pageButtonCallback = it
|
||||
getLosslessDll.launch(arrayOf("*/*"))
|
||||
},
|
||||
{
|
||||
if (LosslessScalingHelper.isInstalled()) {
|
||||
ButtonState.BUTTON_ACTION_COMPLETE
|
||||
} else {
|
||||
ButtonState.BUTTON_ACTION_INCOMPLETE
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_controller,
|
||||
@@ -446,6 +465,32 @@ class SetupFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
val getLosslessDll =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.lossless_scaling_installing,
|
||||
false
|
||||
) { _, _ ->
|
||||
val installResult = LosslessScalingHelper.install(result)
|
||||
if (installResult == LosslessScalingHelper.RESULT_OK) {
|
||||
getString(R.string.lossless_scaling_install_success)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
titleId = R.string.lossless_scaling_install_failed,
|
||||
descriptionString = resultStrings[installResult]
|
||||
)
|
||||
}
|
||||
}.apply {
|
||||
onDialogComplete = { checkForButtonState.invoke() }
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||
if (result != null) {
|
||||
|
||||
@@ -72,6 +72,18 @@ class SystemInfoDialogFragment : DialogFragment() {
|
||||
|
||||
val vulkanDriver = NativeLibrary.getVulkanDriverVersion()
|
||||
appendLine("${getString(R.string.vulkan_driver_version)}: $vulkanDriver")
|
||||
|
||||
val frameGen = NativeLibrary.supportsFrameGeneration()
|
||||
appendLine(
|
||||
"${getString(R.string.frame_generation_support)}: " +
|
||||
getString(
|
||||
if (frameGen) {
|
||||
R.string.frame_generation_supported
|
||||
} else {
|
||||
R.string.frame_generation_unsupported
|
||||
}
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
appendLine("${getString(R.string.error_getting_emulator_info)}: ${e.message}")
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ object InputHandler {
|
||||
MotionEvent.AXIS_RTRIGGER
|
||||
)
|
||||
|
||||
// Currently, Android doesn't support Joy-Con D-pad buttons. We fall back to the scan code
|
||||
private const val LINUX_BUTTON_DPAD_UP = 0x220
|
||||
private const val LINUX_BUTTON_DPAD_DOWN = 0x221
|
||||
private const val LINUX_BUTTON_DPAD_LEFT = 0x222
|
||||
private const val LINUX_BUTTON_DPAD_RIGHT = 0x223
|
||||
|
||||
fun isPhysicalGameController(device: InputDevice?): Boolean {
|
||||
device ?: return false
|
||||
|
||||
@@ -87,12 +93,25 @@ object InputHandler {
|
||||
NativeInput.onGamePadButtonEvent(
|
||||
controllerData.getGUID(),
|
||||
controllerData.getPort(),
|
||||
event.keyCode,
|
||||
getButtonIdFromEvent(event),
|
||||
action
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
fun getButtonIdFromEvent(event: KeyEvent): Int {
|
||||
if (event.keyCode == 0) {
|
||||
return when (event.scanCode) {
|
||||
LINUX_BUTTON_DPAD_UP -> KeyEvent.KEYCODE_DPAD_UP
|
||||
LINUX_BUTTON_DPAD_DOWN -> KeyEvent.KEYCODE_DPAD_DOWN
|
||||
LINUX_BUTTON_DPAD_LEFT -> KeyEvent.KEYCODE_DPAD_LEFT
|
||||
LINUX_BUTTON_DPAD_RIGHT -> KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
else -> return 0
|
||||
}
|
||||
}
|
||||
return event.keyCode
|
||||
}
|
||||
|
||||
fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
||||
val controllerData =
|
||||
androidControllers[event.device.controllerNumber] ?: return false
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.net.Uri
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import java.io.File
|
||||
|
||||
object LosslessScalingHelper {
|
||||
const val RESULT_OK = 0
|
||||
const val RESULT_NOT_INSTALLED = 1
|
||||
|
||||
private val _statusText = MutableStateFlow("")
|
||||
val statusText: StateFlow<String> = _statusText.asStateFlow()
|
||||
|
||||
private var installed: Boolean? = null
|
||||
private var gpuSupported: Boolean? = null
|
||||
|
||||
fun isInstalled(): Boolean = installed ?: refreshStatus()
|
||||
|
||||
fun isSupportedByGpu(): Boolean {
|
||||
val cached = gpuSupported
|
||||
if (cached != null) {
|
||||
return cached
|
||||
}
|
||||
val result = NativeLibrary.supportsFrameGeneration()
|
||||
gpuSupported = result
|
||||
return result
|
||||
}
|
||||
|
||||
fun refreshStatus(): Boolean {
|
||||
val result = NativeLibrary.validateLosslessDll() == RESULT_OK
|
||||
installed = result
|
||||
|
||||
val context = YuzuApplication.appContext
|
||||
_statusText.value = if (result) {
|
||||
context.getString(R.string.lossless_scaling_installed)
|
||||
} else {
|
||||
context.getString(R.string.lossless_scaling_not_installed)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun install(source: Uri): Int {
|
||||
val destination = File(NativeLibrary.getLosslessDllPath())
|
||||
destination.parentFile?.mkdirs()
|
||||
|
||||
val copied = FileUtil.copyUriToInternalStorage(
|
||||
source,
|
||||
destination.parent!!,
|
||||
destination.name
|
||||
)
|
||||
if (copied == null) {
|
||||
refreshStatus()
|
||||
return RESULT_NOT_INSTALLED
|
||||
}
|
||||
|
||||
val result = NativeLibrary.prepareLosslessDll()
|
||||
if (result != RESULT_OK) {
|
||||
NativeLibrary.removeLosslessDll()
|
||||
}
|
||||
refreshStatus()
|
||||
return result
|
||||
}
|
||||
|
||||
fun remove(): Boolean {
|
||||
val removed = NativeLibrary.removeLosslessDll()
|
||||
refreshStatus()
|
||||
return removed
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,8 @@ void AndroidConfig::SaveAllValues() {
|
||||
}
|
||||
|
||||
void AndroidConfig::ReadAndroidValues() {
|
||||
ReadAndroidUIValues();
|
||||
if (global) {
|
||||
ReadAndroidUIValues();
|
||||
ReadUIValues();
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||
Settings::values.ext_content_from_game_dirs = ReadBooleanSetting(
|
||||
@@ -223,8 +223,8 @@ void AndroidConfig::ReadAndroidControlValues() {
|
||||
}
|
||||
|
||||
void AndroidConfig::SaveAndroidValues() {
|
||||
SaveAndroidUIValues();
|
||||
if (global) {
|
||||
SaveAndroidUIValues();
|
||||
SaveUIValues();
|
||||
SaveOverlayValues();
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace AndroidSettings {
|
||||
&show_performance_overlay};
|
||||
|
||||
|
||||
Settings::Setting<s32> pipeline_worker_count{linkage, 4, "pipeline_worker_count",
|
||||
Settings::SwitchableSetting<s32> pipeline_worker_count{linkage, 2, "pipeline_worker_count",
|
||||
Settings::Category::Android,
|
||||
Settings::Specialization::Default,
|
||||
true,
|
||||
|
||||
@@ -124,9 +124,18 @@ float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
||||
return QuantizeFrameRateHint(verified_rate);
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetPresentedFrameMultiplier() {
|
||||
if (!Settings::values.frame_gen.GetValue()) {
|
||||
return 1.0f;
|
||||
}
|
||||
return static_cast<float>(std::clamp<u32>(Settings::values.frame_gen_multiplier.GetValue(), 2, 4));
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameRateHint() const {
|
||||
const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f);
|
||||
const float frame_time_verified_hint = GetFrameTimeVerifiedHint();
|
||||
const float presented_multiplier = GetPresentedFrameMultiplier();
|
||||
const float observed_rate =
|
||||
std::clamp(m_smoothed_present_rate * presented_multiplier, 0.0f, 240.0f);
|
||||
const float frame_time_verified_hint = GetFrameTimeVerifiedHint() * presented_multiplier;
|
||||
|
||||
if (m_last_frame_rate_hint > 0.0f && observed_rate > 0.0f) {
|
||||
const float tolerance = std::max(m_last_frame_rate_hint * 0.12f, 4.0f);
|
||||
@@ -150,9 +159,9 @@ float EmuWindow_Android::GetFrameRateHint() const {
|
||||
return frame_time_verified_hint;
|
||||
}
|
||||
|
||||
constexpr float NominalFrameRate = 60.0f;
|
||||
const float nominal_rate = 60.0f * presented_multiplier;
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
return NominalFrameRate;
|
||||
return QuantizeFrameRateHint(nominal_rate);
|
||||
}
|
||||
|
||||
const u16 speed_limit = Settings::SpeedLimit();
|
||||
@@ -161,7 +170,7 @@ float EmuWindow_Android::GetFrameRateHint() const {
|
||||
}
|
||||
|
||||
const float speed_limited_rate =
|
||||
NominalFrameRate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
|
||||
nominal_rate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
|
||||
return QuantizeFrameRateHint(speed_limited_rate);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
void UpdateObservedFrameRate();
|
||||
[[nodiscard]] float GetFrameRateHint() const;
|
||||
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
|
||||
[[nodiscard]] static float GetPresentedFrameMultiplier();
|
||||
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
||||
|
||||
float m_window_width{};
|
||||
|
||||
@@ -20,132 +20,96 @@ struct RomMetadata {
|
||||
std::vector<u8> icon;
|
||||
bool isHomebrew;
|
||||
};
|
||||
static ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
|
||||
|
||||
ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
|
||||
static RomMetadata CacheRomMetadata(const std::string& path) {
|
||||
auto& instance = EmulationSession::GetInstance();
|
||||
const auto file = Core::GetGameFileFromPath(instance.System().GetFilesystem(), path);
|
||||
if (auto loader = Loader::GetLoader(instance.System(), file, 0, 0); loader) {
|
||||
RomMetadata entry;
|
||||
loader->ReadTitle(entry.title);
|
||||
loader->ReadProgramId(entry.programId);
|
||||
loader->ReadIcon(entry.icon);
|
||||
|
||||
RomMetadata CacheRomMetadata(const std::string& path) {
|
||||
const auto file =
|
||||
Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path);
|
||||
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
|
||||
const FileSys::PatchManager pm{
|
||||
entry.programId,
|
||||
instance.System().GetFileSystemController(),
|
||||
instance.System().GetContentProvider()
|
||||
};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
RomMetadata entry;
|
||||
loader->ReadTitle(entry.title);
|
||||
loader->ReadProgramId(entry.programId);
|
||||
loader->ReadIcon(entry.icon);
|
||||
|
||||
const FileSys::PatchManager pm{
|
||||
entry.programId, EmulationSession::GetInstance().System().GetFileSystemController(),
|
||||
EmulationSession::GetInstance().System().GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
if (control.first != nullptr) {
|
||||
entry.developer = control.first->GetDeveloperName();
|
||||
entry.version = control.first->GetVersionString();
|
||||
} else {
|
||||
FileSys::NACP nacp;
|
||||
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
|
||||
entry.developer = nacp.GetDeveloperName();
|
||||
if (control.first != nullptr) {
|
||||
entry.developer = control.first->GetDeveloperName();
|
||||
entry.version = control.first->GetVersionString();
|
||||
} else {
|
||||
entry.developer = "";
|
||||
FileSys::NACP nacp{};
|
||||
entry.developer = loader->ReadControlData(nacp) == Loader::ResultStatus::Success
|
||||
? nacp.GetDeveloperName()
|
||||
: "";
|
||||
entry.version = "1.0.0";
|
||||
}
|
||||
|
||||
entry.version = "1.0.0";
|
||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||
} else {
|
||||
entry.isHomebrew = false;
|
||||
}
|
||||
m_rom_metadata_cache[path] = entry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||
} else {
|
||||
entry.isHomebrew = false;
|
||||
}
|
||||
|
||||
m_rom_metadata_cache[path] = entry;
|
||||
|
||||
return entry;
|
||||
return {};
|
||||
}
|
||||
|
||||
RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
|
||||
if (reload) {
|
||||
static RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
|
||||
if (reload)
|
||||
return CacheRomMetadata(path);
|
||||
}
|
||||
|
||||
if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
if (auto it = m_rom_metadata_cache.find(path); it != m_rom_metadata_cache.end())
|
||||
return it->second;
|
||||
return CacheRomMetadata(path);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
|
||||
Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read);
|
||||
if (!file) {
|
||||
return false;
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
if (auto const file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read); file) {
|
||||
if (auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file); loader) {
|
||||
auto const file_type = loader->GetFileType();
|
||||
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error)
|
||||
return false;
|
||||
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) && !Loader::IsBootableGameContainer(file, file_type))
|
||||
return false;
|
||||
u64 program_id = 0;
|
||||
return loader->ReadProgramId(program_id) == Loader::ResultStatus::Success;
|
||||
}
|
||||
}
|
||||
|
||||
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file);
|
||||
if (!loader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto file_type = loader->GetFileType();
|
||||
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) &&
|
||||
!Loader::IsBootableGameContainer(file, file_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 program_id = 0;
|
||||
Loader::ResultStatus res = loader->ReadProgramId(program_id);
|
||||
if (res != Loader::ResultStatus::Success) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
return Common::Android::ToJString(
|
||||
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
return Common::Android::ToJString(
|
||||
env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
return Common::Android::ToJString(env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
return Common::Android::ToJString(
|
||||
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj,
|
||||
jstring jpath, jboolean jreload) {
|
||||
return Common::Android::ToJString(
|
||||
env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj, jstring jpath, jboolean jreload) {
|
||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
|
||||
}
|
||||
|
||||
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
auto icon_data = GetRomMetadata(Common::Android::GetJString(env, jpath)).icon;
|
||||
jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size()));
|
||||
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon),
|
||||
reinterpret_cast<jbyte*>(icon_data.data()));
|
||||
jbyteArray icon = env->NewByteArray(jsize(icon_data.size()));
|
||||
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon), reinterpret_cast<jbyte*>(icon_data.data()));
|
||||
return icon;
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj,
|
||||
jstring jpath) {
|
||||
return static_cast<jboolean>(
|
||||
GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj, jstring jpath) {
|
||||
return jboolean(GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) {
|
||||
|
||||
@@ -44,12 +44,14 @@ extern "C" {
|
||||
#include "common/android/android_common.h"
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/dynamic_library.h"
|
||||
#include "common/fs/fs_util.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/thread.h"
|
||||
#include "frontend_common/play_time_manager.h"
|
||||
#include "core/constants.h"
|
||||
#include "core/core.h"
|
||||
@@ -89,6 +91,7 @@ extern "C" {
|
||||
#include "hid_core/hid_types.h"
|
||||
#include "input_common/drivers/virtual_amiibo.h"
|
||||
#include "jni/native.h"
|
||||
#include "video_core/frame_gen/lossless_dll.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||
#include "video_core/capture.h"
|
||||
@@ -1089,6 +1092,34 @@ VkPhysicalDeviceProperties GetVulkanDeviceProperties() {
|
||||
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
|
||||
return physical_device.GetProperties();
|
||||
}
|
||||
|
||||
bool GetVulkanMemoryModelSupport() {
|
||||
Common::DynamicLibrary library;
|
||||
if (!library.Open("libvulkan.so")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vulkan::vk::InstanceDispatch dld;
|
||||
const auto instance = Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1);
|
||||
const auto physical_devices = instance.EnumeratePhysicalDevices();
|
||||
if (physical_devices.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
|
||||
|
||||
VkPhysicalDeviceVulkanMemoryModelFeatures memory_model{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
|
||||
.pNext = nullptr,
|
||||
};
|
||||
VkPhysicalDeviceFeatures2 features{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &memory_model,
|
||||
};
|
||||
physical_device.GetFeatures2(features);
|
||||
|
||||
return memory_model.vulkanMemoryModel == VK_TRUE;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanDriverVersion(JNIEnv* env, jobject jobj) {
|
||||
@@ -1164,6 +1195,14 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanApiVersion(JNIEnv* env, j
|
||||
}
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_supportsFrameGeneration(JNIEnv* env, jobject jobj) {
|
||||
try {
|
||||
return static_cast<jboolean>(GetVulkanMemoryModelSupport());
|
||||
} catch (...) {
|
||||
return static_cast<jboolean>(false);
|
||||
}
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuModel(JNIEnv* env, jobject jobj) {
|
||||
const auto props = GetVulkanDeviceProperties();
|
||||
if (props.deviceID == 0) {
|
||||
@@ -1182,6 +1221,10 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
||||
Settings::LogSettings();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jobject jobj) {
|
||||
Common::RefreshThreadPolicies();
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
|
||||
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
|
||||
}
|
||||
@@ -1385,6 +1428,23 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz
|
||||
return static_cast<int>(FirmwareManager::InstallKeys(path, ext));
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getLosslessDllPath(JNIEnv* env, jclass clazz) {
|
||||
const auto path = VideoCore::FrameGen::GetLosslessDllPath();
|
||||
return Common::Android::ToJString(env, Common::FS::PathToUTF8String(path));
|
||||
}
|
||||
|
||||
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_validateLosslessDll(JNIEnv* env, jclass clazz) {
|
||||
return static_cast<jint>(VideoCore::FrameGen::GetInstalledLosslessStatus());
|
||||
}
|
||||
|
||||
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_prepareLosslessDll(JNIEnv* env, jclass clazz) {
|
||||
return static_cast<jint>(VideoCore::FrameGen::BuildShaderCache());
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_removeLosslessDll(JNIEnv* env, jclass clazz) {
|
||||
return static_cast<jboolean>(VideoCore::FrameGen::RemoveInstalledLosslessDll());
|
||||
}
|
||||
|
||||
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
|
||||
jstring jpath,
|
||||
jstring jprogramId) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M11,10.6a8,5.2 0 1,0 0,10.4a8,5.2 0 1,0 0,-10.4z" />
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M4.6,12.6L0.8,10.2L3.2,15.5z" />
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M15.3,3.5a4,4 0 1,0 0,8a4,4 0 1,0 0,-8zM16.6,4.9a1,1 0 1,0 0,2a1,1 0 1,0 0,-2z" />
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M18.6,6.5L23.2,7.8L18.6,9.3z" />
|
||||
</vector>
|
||||
@@ -473,9 +473,11 @@
|
||||
<string name="advanced">متقدم</string>
|
||||
|
||||
<string name="renderer_accuracy">وضع وحدة معالجة الرسومات</string>
|
||||
<string name="renderer_accuracy_description">يتحكم في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع وضعي سريع أو متوازن، لكن الوضع الدقيق لا يزال مطلوبًا لبعض الألعاب. تميل الجسيمات إلى العرض بشكل صحيح فقط عند استخدام الوضع الدقيق.</string>
|
||||
<string name="renderer_accuracy_description">يتحكم هذا الخيار في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع الوضع السريع، لكن الوضع الدقيق لا يزال ضروريًا لبعضها. تميل الجسيمات إلى الظهور بشكل صحيح فقط مع الوضع الدقيق.</string>
|
||||
<string name="dma_accuracy">دقة DMA</string>
|
||||
<string name="dma_accuracy_description">يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي.</string>
|
||||
<string name="gpu_fence_behavior">سلوك حاجز وحدة معالجة الرسومات</string>
|
||||
<string name="gpu_fence_behavior_description">يتحكم في سلوك تزامن حاجز وحدة معالجة الرسوميات. الخيار الفوري هو الأسرع، لكنه قد يسبب بعض المشاكل. الخيار المتوازن يقدم توافقًا أفضل وقد يصلح مشاكل في بعض الألعاب. الخيار الدقيق يحسن التوافق أكثر لكنه قد يقلل الأداء قليلاً. الخيار الصارم هو الأبطأ، لكنه قد يصلح المشاكل التي تتطلب تزامنًا أكثر صرامة. الإعداد الافتراضي يتبع إعداد دقة وحدة معالجة الرسوميات.</string>
|
||||
<string name="anisotropic_filtering">تصفية متباينة الخواص</string>
|
||||
<string name="anisotropic_filtering_description">يحسن جودة الأنسجة عند عرضها بزوايا مائلة</string>
|
||||
<string name="vram_usage_mode">وضع استخدام ذاكرة VRAM</string>
|
||||
@@ -497,6 +499,8 @@
|
||||
<string name="renderer_reactive_flushing_description">يحسن دقة العرض في بعض الألعاب على حساب الأداء.</string>
|
||||
<string name="enable_buffer_history">تمكين سجل التخزين المؤقت</string>
|
||||
<string name="enable_buffer_history_description">يُتيح هذا الخيار الوصول إلى حالات التخزين المؤقت السابقة. وقد يُحسّن جودة العرض وثبات الأداء في بعض الألعاب.</string>
|
||||
<string name="enable_gpu_buffer_readback">تفعيل قراءة مخزن وحدة معالجة الرسومات</string>
|
||||
<string name="enable_gpu_buffer_readback_description">يحافظ هذا النظام على بيانات المخزن المؤقت المُعدّلة بواسطة وحدة معالجة الرسومات عن طريق قراءتها مرة أخرى قبل التحميل. تتطلب بعض الألعاب ذلك لعرض بعض التأثيرات بشكل صحيح. قد يُسبب ذلك مشاكل إذا لم يتمكن الجهاز من التعامل مع عبء العمل الإضافي.</string>
|
||||
<string name="use_optimized_vertex_buffers">مخازن الرؤوس المُحسّنة</string>
|
||||
<string name="use_optimized_vertex_buffers_description">يُتيح ربطًا مُحسَّنًا لمخازن الرؤوس لتحسين الأداء. يتطلب برامج تشغيل Mesa 26.0+ Turnip/ برامج تشغيل QCOM. قد يتعطل على برامج تشغيل Turnip القديمة (25.3 وما دون).</string>
|
||||
|
||||
@@ -506,8 +510,6 @@
|
||||
<string name="fast_gpu_time_description">يُجبر هذا الخيار معظم الألعاب على العمل بأعلى دقة عرض أصلية. استخدم 256 للحصول على أقصى أداء و512 للحصول على أعلى جودة رسومات.</string>
|
||||
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
|
||||
<string name="antiflicker">مضاد الوميض</string>
|
||||
<string name="antiflicker_description">يُجبر هذا الوضع وظائف وحدة معالجة الرسومات على الانتظار حتى يتم إرسال العمل إليها. استخدمه مع وضع وحدة معالجة الرسومات السريع لتجنب الوميض مع تأثير أقل على الأداء.</string>
|
||||
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
|
||||
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string>
|
||||
<string name="emulate_bgr565">محاكاة BGR565</string>
|
||||
@@ -573,6 +575,12 @@
|
||||
<string name="gpu_log_level_description">مستوى التفاصيل لسجلات وحدة معالجة الرسومات (كلما زاد المستوى، زادت التفاصيل وزادت التكاليف الإضافية)</string>
|
||||
<string name="gpu_log_vulkan_calls">تسجيل استدعاءات واجهة برمجة تطبيقات Vulkan</string>
|
||||
<string name="gpu_log_vulkan_calls_description">تتبع جميع استدعاءات واجهة برمجة تطبيقات Vulkan في المخزن المؤقت الحلقي</string>
|
||||
<string name="gpu_log_shader_dumps">تفريغ مظللات SPIR-V</string>
|
||||
<string name="gpu_log_shader_dumps_description">احفظ ملفات SPIR-V الثنائية المُعاد تجميعها (.spv) في مجلد التفريغ. افحصها باستخدام spirv-dis/spirv-cross/spirv-val.</string>
|
||||
<string name="dump_guest_shaders">تظليلات ضيف التفريغ (ماكسويل)</string>
|
||||
<string name="dump_guest_shaders_description">احفظ ملفات بايت كود برنامج التظليل الضيف الخاص بـ «ماكسويل» (*.ash) في مجلد «dump». افحصها باستخدام nvdisasm.</string>
|
||||
<string name="dump_macros">تفريغ ماكرو ماكسويل</string>
|
||||
<string name="dump_macros_description">احفظ ملفات برامج ماكرو ماكسويل (*.macro) في مجلد «dump». افحصها باستخدام برنامج «envydis».</string>
|
||||
<string name="gpu_log_memory_tracking">تتبع ذاكرة وحدة معالجة الرسومات</string>
|
||||
<string name="gpu_log_memory_tracking_description">مراقبة تخصيصات ذاكرة وحدة معالجة الرسومات وإلغاء تخصيصها</string>
|
||||
<string name="gpu_log_driver_debug">معلومات تصحيح أخطاء برنامج التشغيل</string>
|
||||
@@ -950,7 +958,6 @@
|
||||
<string name="clock_fast">سريع (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">تعطيل</string>
|
||||
<string name="fast_gpu_medium">متوسط (256)</string>
|
||||
<string name="fast_gpu_high">مرتفع (512)</string>
|
||||
|
||||
@@ -992,7 +999,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">سريع</string>
|
||||
<string name="renderer_accuracy_medium">متوازن</string>
|
||||
<string name="renderer_accuracy_high">دقيق</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
@@ -1000,6 +1006,13 @@
|
||||
<string name="dma_accuracy_unsafe">غير آمن</string>
|
||||
<string name="dma_accuracy_safe">آمن</string>
|
||||
|
||||
<!-- GPU Fence Behavior -->
|
||||
<string name="gpu_fence_behavior_default">افتراضي</string>
|
||||
<string name="gpu_fence_behavior_immediate">فوري</string>
|
||||
<string name="gpu_fence_behavior_balanced">متوازن</string>
|
||||
<string name="gpu_fence_behavior_accurate">دقيق</string>
|
||||
<string name="gpu_fence_behavior_strict">صارم</string>
|
||||
|
||||
<string name="vram_usage_conservative">محافظ</string>
|
||||
<string name="vram_usage_aggressive">عدواني</string>
|
||||
|
||||
|
||||
@@ -445,7 +445,6 @@
|
||||
<string name="advanced">Pokročilé</string>
|
||||
|
||||
<string name="renderer_accuracy">Režim GPU</string>
|
||||
<string name="renderer_accuracy_description">Určuje režim emulovaného GPU. Většina her běží bez problémů v rychlém, nebo vyváženém režimu, ale některé stále vyžadují přesný režim. Částicové efekty se většinou zobrazují korektně pouze v přesném režimu. </string>
|
||||
<string name="dma_accuracy">Přesnost DMA</string>
|
||||
<string name="dma_accuracy_description">Ovládá přesnost DMA. Bezpečná přesnost může vyřešit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, použijte výchozí nastavení.</string>
|
||||
<string name="anisotropic_filtering">Anizotropní filtrování</string>
|
||||
@@ -707,7 +706,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Rychlý</string>
|
||||
<string name="renderer_accuracy_medium">Vyvážený</string>
|
||||
<string name="renderer_accuracy_high">Přesný</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -457,7 +457,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
||||
<string name="advanced">Erweitert</string>
|
||||
|
||||
<string name="renderer_accuracy">GPU-Modus</string>
|
||||
<string name="renderer_accuracy_description">Steuert den GPU-Emulationsmodus. Die meisten Spiele werden im Modus \"Fast\" oder \"Balanced\" gut gerendert, für einige ist jedoch weiterhin der Modus \"Accurate\" erforderlich. Partikel werden in der Regel nur im Modus \"Accurate\" korrekt gerendert.</string>
|
||||
<string name="dma_accuracy">DMA-Genauigkeit</string>
|
||||
<string name="dma_accuracy_description">Steuert die DMA-Präzisionsgenauigkeit. Sichere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel lassen Sie dies auf Standard stehen.</string>
|
||||
<string name="anisotropic_filtering">Anisotrope Filterung</string>
|
||||
@@ -885,7 +884,6 @@ Wirklich fortfahren?</string>
|
||||
<string name="clock_fast">Schnell (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Aus</string>
|
||||
<string name="fast_gpu_medium">Mittel (256)</string>
|
||||
<string name="fast_gpu_high">Hoch (512)</string>
|
||||
|
||||
@@ -927,7 +925,6 @@ Wirklich fortfahren?</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Schnell</string>
|
||||
<string name="renderer_accuracy_medium">Ausgeglichen</string>
|
||||
<string name="renderer_accuracy_high">Genau</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -467,9 +467,9 @@
|
||||
<string name="advanced">Avanzado</string>
|
||||
|
||||
<string name="renderer_accuracy">Modo de la GPU</string>
|
||||
<string name="renderer_accuracy_description">Controla el modo de la emulación de la GPU. La mayoría de los juegos se renderizan correctamente en los modos Rápido o Equilibrado, pero algunos requieren Preciso. Las partículas tienden a renderizarse correctamente solo con el modo Preciso.</string>
|
||||
<string name="dma_accuracy">Precisión de DMA</string>
|
||||
<string name="dma_accuracy_description">Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado.</string>
|
||||
<string name="gpu_fence_behavior">Comportamiento de vallado de la GPU</string>
|
||||
<string name="anisotropic_filtering">Filtrado anisotrópico</string>
|
||||
<string name="anisotropic_filtering_description">Mejora la calidad de las texturas al ser observadas desde ángulos oblicuos</string>
|
||||
<string name="vram_usage_mode">Modo de uso de VRAM</string>
|
||||
@@ -502,8 +502,6 @@
|
||||
<string name="fast_gpu_time_description">Fuerza a la mayoría de los juegos a ejecutarse a su resolución nativa más alta. Usa 256 para un máximo rendimiento y 512 para una fidelidad gráfica óptima.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
||||
<string name="antiflicker">Antiparpadeo</string>
|
||||
<string name="antiflicker_description">Fuerza a las funciones de devolución de llamada de la GPU a esperar a que se envíen las tareas a la GPU.\nÚsalo con el modo de GPU rápida para evitar el parpadeo con un menor impacto en el rendimiento.</string>
|
||||
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
||||
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
|
||||
<string name="emulate_bgr565">Emular BGR565</string>
|
||||
@@ -952,7 +950,6 @@
|
||||
<string name="clock_fast">Rápido (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Desactivado</string>
|
||||
<string name="fast_gpu_medium">Medio (256)</string>
|
||||
<string name="fast_gpu_high">Alto (512)</string>
|
||||
|
||||
@@ -994,7 +991,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Rápido</string>
|
||||
<string name="renderer_accuracy_medium">Equilibrado</string>
|
||||
<string name="renderer_accuracy_high">Preciso</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
@@ -1002,6 +998,13 @@
|
||||
<string name="dma_accuracy_unsafe">Inseguro</string>
|
||||
<string name="dma_accuracy_safe">Seguro</string>
|
||||
|
||||
<!-- GPU Fence Behavior -->
|
||||
<string name="gpu_fence_behavior_default">Predeterminado</string>
|
||||
<string name="gpu_fence_behavior_immediate">Inmediato</string>
|
||||
<string name="gpu_fence_behavior_balanced">Equilibrado</string>
|
||||
<string name="gpu_fence_behavior_accurate">Preciso</string>
|
||||
<string name="gpu_fence_behavior_strict">Estricto</string>
|
||||
|
||||
<string name="vram_usage_conservative">Conservador</string>
|
||||
<string name="vram_usage_aggressive">Agresivo</string>
|
||||
|
||||
|
||||
@@ -897,7 +897,6 @@
|
||||
<string name="clock_fast">Rapide (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Désactivé</string>
|
||||
<string name="fast_gpu_medium">Moyen (256)</string>
|
||||
<string name="fast_gpu_high">Élevé (512)</string>
|
||||
|
||||
@@ -939,7 +938,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Rapide</string>
|
||||
<string name="renderer_accuracy_medium">Moyen</string>
|
||||
<string name="renderer_accuracy_high">Précis</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -445,7 +445,6 @@
|
||||
<string name="advanced">Zaawansowane</string>
|
||||
|
||||
<string name="renderer_accuracy">Tryb GPU</string>
|
||||
<string name="renderer_accuracy_description">Steruje trybem emulacji GPU. Większość gier renderuje się poprawnie w trybach Szybki lub Zrównoważony, ale dla niektórych nadal wymagany jest tryb Dokładny. Efekty cząsteczkowe zwykle renderują się poprawnie tylko w trybie Dokładnym.</string>
|
||||
<string name="dma_accuracy">Dokładność DMA</string>
|
||||
<string name="dma_accuracy_description">Kontroluje dokładność precyzji DMA. Bezpieczna precyzja może naprawić problemy w niektórych grach, ale w niektórych przypadkach może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość Domyślną.</string>
|
||||
<string name="anisotropic_filtering">Filtrowanie anizotropowe</string>
|
||||
@@ -872,7 +871,6 @@
|
||||
<string name="clock_fast">Szybkie (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Wyłączone</string>
|
||||
<string name="fast_gpu_medium">Średnie (256)</string>
|
||||
<string name="fast_gpu_high">Wysokie (512)</string>
|
||||
|
||||
@@ -893,7 +891,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Szybkie</string>
|
||||
<string name="renderer_accuracy_medium">Zrównoważony</string>
|
||||
<string name="renderer_accuracy_high">Dokładny</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -840,7 +840,6 @@
|
||||
|
||||
<string name="renderer_none">Nenhum</string>
|
||||
|
||||
<string name="renderer_accuracy_medium">Média</string>
|
||||
<string name="renderer_accuracy_high">Alta</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -424,6 +424,9 @@
|
||||
<string name="cpu_accuracy">Точность ЦП</string>
|
||||
<string name="value_with_units">%1$s%2$s</string>
|
||||
|
||||
<string name="program_args">Аргументы Homebrew</string>
|
||||
<string name="program_args_description">Аргументы командной строки, переданные Homebrew при запуске (например, -noglsl)</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="device_name">Название устройства</string>
|
||||
<string name="use_docked_mode">Режим док-станции</string>
|
||||
@@ -466,9 +469,11 @@
|
||||
<string name="advanced">Расширенные</string>
|
||||
|
||||
<string name="renderer_accuracy">Режим ГПУ</string>
|
||||
<string name="renderer_accuracy_description">Управляет режимом эмуляции графического процессора. Большинство игр нормально отображаются в режимах «Быстрый» или «Сбалансированный», но для некоторых требуется режим «Точный». Частицы обычно корректно отображаются только в режиме «Точный».</string>
|
||||
<string name="renderer_accuracy_description">Управляет режимом эмуляции ГПУ. Большинство игр нормально отображаются в режиме Быстрый, но для некоторых требуется режим Точный. Частицы обычно корректно отображаются только в режиме Точный.</string>
|
||||
<string name="dma_accuracy">Точность DMA</string>
|
||||
<string name="dma_accuracy_description">Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию.</string>
|
||||
<string name="gpu_fence_behavior">Поведение барьеров ГПУ</string>
|
||||
<string name="gpu_fence_behavior_description">Управляет поведением синхронизации через барьеры ГПУ. Мгновенный — самый быстрый вариант, но может вызывать некоторые проблемы. Сбалансированный обеспечивает лучшую совместимость и может исправлять проблемы в некоторых играх. Точный ещё больше повышает совместимость ценой некоторого снижения производительности. Строгий — самый медленный вариант, но может исправлять проблемы, требующие более строгой синхронизации. По умолчанию соответствует настройке точности ГПУ.</string>
|
||||
<string name="anisotropic_filtering">Анизотропная фильтрация</string>
|
||||
<string name="anisotropic_filtering_description">Улучшает качество текстур под углом</string>
|
||||
<string name="vram_usage_mode">Режим VRAM</string>
|
||||
@@ -490,6 +495,8 @@
|
||||
<string name="renderer_reactive_flushing_description">Повышение точности рендеринга в некоторых играх за счет снижения производительности.</string>
|
||||
<string name="enable_buffer_history">Включить историю буфера</string>
|
||||
<string name="enable_buffer_history_description">Позволяет обращаться к предыдущим состояниям буфера. Эта опция может повысить качество рендеринга и стабильность производительности в некоторых играх.</string>
|
||||
<string name="enable_gpu_buffer_readback">Включить обратное чтение буфера ГПУ</string>
|
||||
<string name="enable_gpu_buffer_readback_description">Сохраняет измененные ГПУ данные буфера путем чтения их обратно перед выгрузками. Некоторые игры требуют этого, чтобы рендерить определенные эффекты правильно. Может вызывать проблемы если оборудование не может обработать дополнительную рабочую нагрузку.</string>
|
||||
<string name="use_optimized_vertex_buffers">Оптимизированные вершинные буферы</string>
|
||||
<string name="use_optimized_vertex_buffers_description">Включает оптимизированную привязку вершинного буфера для повышения производительности. Требует Mesa Turnip 26.0+ / QCOM. Приводит к вылету на старых версиях драйверов Turnip (25.3 и ниже).</string>
|
||||
|
||||
@@ -499,8 +506,6 @@
|
||||
<string name="fast_gpu_time_description">Принудительно запускает большинство игр в их максимальном нативном разрешении. Используйте значение 256 для максимальной производительности и 512 для максимального качества графики.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
||||
<string name="antiflicker">Анти-мерцание</string>
|
||||
<string name="antiflicker_description">Принудительно заставляет обратные вызовы ГПУ-фильтра ожидать выполнения отправленных задач на ГПУ. Используйте с Быстрым режимом ГПУ, что бы избежать мерцаний с меньшим влиянием на производительность.</string>
|
||||
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
||||
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
|
||||
<string name="emulate_bgr565">Эмулировать BGR565</string>
|
||||
@@ -566,6 +571,12 @@
|
||||
<string name="gpu_log_level_description">Уровень детализации логов ГПУ (больше значение = больше деталей, выше нагрузка)</string>
|
||||
<string name="gpu_log_vulkan_calls">Записывать вызовы Vulkan API</string>
|
||||
<string name="gpu_log_vulkan_calls_description">Отслеживать все вызовы Vulkan API в кольцевом буфере</string>
|
||||
<string name="gpu_log_shader_dumps">Выгрузить SPIR-V шейдеры</string>
|
||||
<string name="gpu_log_shader_dumps_description">Сохранять перекомпилированные SPIR-V бинарные файлы (.spv) в папку дампа. Проверять с помощью spirv-dis/spirv-cross/spirv-val.</string>
|
||||
<string name="dump_guest_shaders">Выгрузить гостевые (Maxwell) шейдеры</string>
|
||||
<string name="dump_guest_shaders_description">Сохранять файлы байткода гостевых шейдеров Maxwell (*.ash) в папку дампа. Проверять с помощью nvdisasm.</string>
|
||||
<string name="dump_macros">Выгрузить макросы Maxwell</string>
|
||||
<string name="dump_macros_description">Сохранять файлы макропрограмм Maxwell (*.macro) в папку дампа. Проверять с помощью envydis.</string>
|
||||
<string name="gpu_log_memory_tracking">Отслеживать память ГПУ</string>
|
||||
<string name="gpu_log_memory_tracking_description">Мониторить выделение и освобождение памяти ГПУ</string>
|
||||
<string name="gpu_log_driver_debug">Отладочная информация драйвера</string>
|
||||
@@ -943,7 +954,6 @@
|
||||
<string name="clock_fast">Быстрая (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Выкл.</string>
|
||||
<string name="fast_gpu_medium">Среднее (256)</string>
|
||||
<string name="fast_gpu_high">Высокое (512)</string>
|
||||
|
||||
@@ -985,7 +995,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Быстрый</string>
|
||||
<string name="renderer_accuracy_medium">Сбалансированный</string>
|
||||
<string name="renderer_accuracy_high">Точный</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
@@ -993,6 +1002,13 @@
|
||||
<string name="dma_accuracy_unsafe">Небезопасно</string>
|
||||
<string name="dma_accuracy_safe">Безопасный</string>
|
||||
|
||||
<!-- GPU Fence Behavior -->
|
||||
<string name="gpu_fence_behavior_default">По умолчанию</string>
|
||||
<string name="gpu_fence_behavior_immediate">Мгновенный</string>
|
||||
<string name="gpu_fence_behavior_balanced">Сбалансированный</string>
|
||||
<string name="gpu_fence_behavior_accurate">Точный</string>
|
||||
<string name="gpu_fence_behavior_strict">Строгий</string>
|
||||
|
||||
<string name="vram_usage_conservative">Консервативный</string>
|
||||
<string name="vram_usage_aggressive">Агрессивный</string>
|
||||
|
||||
|
||||
@@ -469,7 +469,6 @@
|
||||
<string name="advanced">Додаткові</string>
|
||||
|
||||
<string name="renderer_accuracy">Режим ГП</string>
|
||||
<string name="renderer_accuracy_description">Керує режимом емуляції ГП. Більшість ігор добре візуалізуються з режимами «Швидко» або «Збалансовано», але деякі ігри можуть потребувати режиму «Точно». Частинки зазвичай правильно візуалізуються лише з режимом «Точно».</string>
|
||||
<string name="dma_accuracy">Точність DMA</string>
|
||||
<string name="dma_accuracy_description">Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням.</string>
|
||||
<string name="anisotropic_filtering">Анізотропне фільтрування</string>
|
||||
@@ -502,8 +501,6 @@
|
||||
<string name="fast_gpu_time_description">Примушує більшість ігор працювати на їхній максимальній нативній роздільності. Використовуйте 256 для максимальної продуктивності та 512 для найкращої якості.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
|
||||
<string name="antiflicker">Антимерехтіння</string>
|
||||
<string name="antiflicker_description">Змушує механізм синхронізації чекати, доки ГП завершить подані завдання. Використовуйте з режимом ГП «Швидко», щоб уникнути мерехтіння з меншими втратами продуктивності.</string>
|
||||
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
|
||||
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XX–A7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
|
||||
<string name="emulate_bgr565">Емулювати BGR565</string>
|
||||
@@ -946,7 +943,6 @@
|
||||
<string name="clock_fast">Швидко (2000 МГц)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Вимкнено</string>
|
||||
<string name="fast_gpu_medium">Середньо (256)</string>
|
||||
<string name="fast_gpu_high">Високо (512)</string>
|
||||
|
||||
@@ -988,7 +984,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Швидко</string>
|
||||
<string name="renderer_accuracy_medium">Збалансовано</string>
|
||||
<string name="renderer_accuracy_high">Точно</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<string name="show_shaders_building">显示着色器编译信息</string>
|
||||
<string name="show_shaders_building_description">显示当前正在编译的着色器数量</string>
|
||||
<string name="pipeline_worker_cores">管线工作线程</string>
|
||||
<string name="pipeline_worker_cores_description">管理用于构建 Vulkan 管线的核心数量,数值越高则管线编译性能越好,但温度也会随之升高。</string>
|
||||
<string name="pipeline_worker_cores_description">管理用于构建 Vulkan 管线的核心数量,较高的值可提升管线编译性能,但温度也会随之升高。</string>
|
||||
<string name="overlay_position">叠加层位置</string>
|
||||
<string name="overlay_position_description">选择叠加层在屏幕上显示的位置</string>
|
||||
<string name="overlay_position_top_left">左上</string>
|
||||
@@ -185,7 +185,7 @@
|
||||
<string name="multiplayer_preferred_game_name">首选游戏</string>
|
||||
<string name="multiplayer_lobby_type">游戏大厅类型</string>
|
||||
<string name="multiplayer_room_name_error">长度需为3-20个字符</string>
|
||||
<string name="multiplayer_required">必填</string>
|
||||
<string name="multiplayer_required">需要</string>
|
||||
<string name="multiplayer_token_required">需要Web令牌,请前往高级设置 -> 系统 -> 网络</string>
|
||||
<string name="multiplayer_ip_error">IP格式无效</string>
|
||||
<string name="multiplayer_username_error">必须为4至20个字符,且仅包含字母、数字、点号、连字符、下划线和空格</string>
|
||||
@@ -287,7 +287,7 @@
|
||||
<string name="warning_skip">跳过</string>
|
||||
<string name="warning_cancel">取消</string>
|
||||
<string name="install_amiibo_keys">安装 Amiibo 密钥文件</string>
|
||||
<string name="install_amiibo_keys_description">在遊戏中使用 Amiibo 时必需</string>
|
||||
<string name="install_amiibo_keys_description">在遊戏中使用 Amiibo 时需要</string>
|
||||
<string name="gpu_driver_fetcher">GPU驱动获取器</string>
|
||||
<string name="gpu_driver_manager">GPU 驱动管理器</string>
|
||||
<string name="install_gpu_driver_description">安装替代的驱动程序以获得更好的性能和精度</string>
|
||||
@@ -463,11 +463,13 @@
|
||||
<string name="advanced">高级</string>
|
||||
|
||||
<string name="renderer_accuracy">GPU 模式</string>
|
||||
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”或“平衡”模式下都能正常渲染,但有些游戏仍需使用“精确”模式。粒子效果通常只有在“精确”模式下才能正确渲染。</string>
|
||||
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”模式下渲染效果良好,但有些游戏仍需使用“精确”模式。而粒子效果通常只有在“精确”模式下才能正确渲染。</string>
|
||||
<string name="dma_accuracy">DMA 精度</string>
|
||||
<string name="dma_accuracy_description">控制 DMA 的精准度。安全精度可以修复存在于某些游戏中的问题,但在某些情况下也会对性能造成影响。如不确定,请保持“默认”。</string>
|
||||
<string name="gpu_fence_behavior">GPU 围栏行为</string>
|
||||
<string name="gpu_fence_behavior_description">控制 GPU 围栏同步行为。“即时”是速度最快的选项,但可能会引入一些问题。“均衡”提供了更好的兼容性,可能修复某些游戏中的问题。“精确”在牺牲部分性能的前提下进一步提升兼容性。“严格”是速度最慢的选项,但可以修复那些要求更严格同步的问题。默认遵循 GPU “精确”设定。</string>
|
||||
<string name="anisotropic_filtering">各向异性过滤</string>
|
||||
<string name="anisotropic_filtering_description">提高斜角的纹理质量</string>
|
||||
<string name="anisotropic_filtering_description">提升斜视角下的纹理质量</string>
|
||||
<string name="vram_usage_mode">显存使用模式</string>
|
||||
<string name="vram_usage_mode_description">控制显存分配与释放策略</string>
|
||||
<string name="accelerate_astc">ASTC解码方式</string>
|
||||
@@ -488,7 +490,7 @@
|
||||
<string name="enable_buffer_history">启用缓冲区历史</string>
|
||||
<string name="enable_buffer_history_description">启用对先前缓冲区状态的访问。此选项可在某些游戏中提升渲染质量并保持性能的一致性。</string>
|
||||
<string name="enable_gpu_buffer_readback">启用 GPU 缓冲区回读</string>
|
||||
<string name="enable_gpu_buffer_readback_description">在上传前回读经由 GPU 修改过的缓冲区数据,以将其保留。一些游戏需要这样做才能正确渲染某些效果。如果硬件无法处理额外的工作负载,则可能会导致问题。</string>
|
||||
<string name="enable_gpu_buffer_readback_description">在上传前回读经由 GPU 修改过的缓冲区数据,以将其保留。一些游戏会用到这项设定以正确渲染某些效果。如果硬件无法处理额外的工作负载,则可能会导致问题。</string>
|
||||
<string name="use_optimized_vertex_buffers">优化顶点缓冲区</string>
|
||||
<string name="use_optimized_vertex_buffers_description">启用经过优化的顶点缓冲区绑定以提升性能。需要 Mesa 26.0 及以上版本的 Turnip 或 QCOM 驱动程序。若使用较旧版本的 Turnip 驱动 (25.3 及以下版本) 则会导致崩溃。</string>
|
||||
|
||||
@@ -498,8 +500,6 @@
|
||||
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。设置为 256 可获得最佳性能,设置为 512 可获得最佳画面保真度。</string>
|
||||
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string>
|
||||
<string name="antiflicker">防闪烁</string>
|
||||
<string name="antiflicker_description">强制 GPU 围栏回调等待已提交的 GPU 任务。配合“快速 GPU 模式”一起使用,以牺牲少量性能为代价来避免画面闪烁现象。</string>
|
||||
<string name="fix_bloom_effects">修复 Bloom 效果</string>
|
||||
<string name="fix_bloom_effects_description">减少《智慧的再现》和《众神的三角力量2》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
|
||||
<string name="emulate_bgr565">模拟 BGR565</string>
|
||||
@@ -513,7 +513,7 @@
|
||||
<string name="gpu_unswizzle_enable">启用 GPU Unswizzle</string>
|
||||
<string name="gpu_unswizzle_disabled">禁用</string>
|
||||
<string name="gpu_unswizzle_texture_size">GPU Unswizzle 最大纹理尺寸</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">设置基于 GPU 的纹理 unswizzling 的最大尺寸(MB)。虽然 GPU 处理中等和大型纹理的速度更快,但对于非常小的纹理,CPU 可能更为高效。通过调节此项设置,以尝试在 GPU 加速与 CPU 开销之间找到平衡。</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">设置基于 GPU 的纹理 unswizzling 的最大尺寸(MB)。虽然 GPU 处理中等和大型纹理的速度更快,但对于非常小的纹理,CPU 可能更为高效。通过调节此项设置,以平衡GPU 加速与 CPU 开销。</string>
|
||||
<string name="gpu_unswizzle_stream_size">GPU Unswizzle 流大小</string>
|
||||
<string name="gpu_unswizzle_stream_size_description">设置用于 unswizzling 大型纹理时的每帧数据限制。较高的数值可以加速纹理的加载过程,但会带来更高的帧延迟。而较低的数值则可以降低 GPU 的开销,但也可能会导致可见的纹理闪现。</string>
|
||||
<string name="gpu_unswizzle_chunk_size">GPU Unswizzle 块大小</string>
|
||||
@@ -948,7 +948,6 @@
|
||||
<string name="clock_fast">快速 (2000MHz)</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">关闭</string>
|
||||
<string name="fast_gpu_medium">中 (256)</string>
|
||||
<string name="fast_gpu_high">高 (512)</string>
|
||||
|
||||
@@ -990,7 +989,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">快速</string>
|
||||
<string name="renderer_accuracy_medium">平衡</string>
|
||||
<string name="renderer_accuracy_high">精确</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
@@ -998,6 +996,13 @@
|
||||
<string name="dma_accuracy_unsafe">不安全</string>
|
||||
<string name="dma_accuracy_safe">安全</string>
|
||||
|
||||
<!-- GPU Fence Behavior -->
|
||||
<string name="gpu_fence_behavior_default">默认</string>
|
||||
<string name="gpu_fence_behavior_immediate">即时</string>
|
||||
<string name="gpu_fence_behavior_balanced">均衡</string>
|
||||
<string name="gpu_fence_behavior_accurate">精确</string>
|
||||
<string name="gpu_fence_behavior_strict">严格</string>
|
||||
|
||||
<string name="vram_usage_conservative">保守式</string>
|
||||
<string name="vram_usage_aggressive">主动式</string>
|
||||
|
||||
@@ -1021,7 +1026,7 @@
|
||||
<string name="ratio_stretch">拉伸窗口</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">精准</string>
|
||||
<string name="cpu_accuracy_accurate">精确</string>
|
||||
<string name="cpu_accuracy_unsafe">不安全</string>
|
||||
<string name="cpu_accuracy_paranoid">极致</string>
|
||||
<string name="cpu_accuracy_debugging">调试</string>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<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_description">發生錯誤時顯示通知。</string>
|
||||
<string name="notice_notification_channel_description">發生錯誤時顯示通知</string>
|
||||
<string name="notification_permission_not_granted">未授予通知權限!</string>
|
||||
<string name="app_notification_channel_description">Eden模擬器通知</string>
|
||||
<string name="app_notification_running">Eden正在執行</string>
|
||||
@@ -16,7 +16,7 @@
|
||||
<string name="value_too_high">範圍最大必須為%1$d</string>
|
||||
<string name="invalid_value">無效的範圍</string>
|
||||
|
||||
<string name="using_per_game_config">使用自定義組態中</string>
|
||||
<string name="using_per_game_config">使用個別設定中</string>
|
||||
|
||||
<!-- Input Overlay -->
|
||||
<string name="show_input_overlay">顯示虛擬按鍵</string>
|
||||
@@ -25,7 +25,7 @@
|
||||
<string name="overlay_snap_to_grid_description">編輯時將虛擬按鍵與網格對齊</string>
|
||||
<string name="overlay_grid_size">網格大小</string>
|
||||
<string name="overlay_grid_size_description">調整網格格線間距</string>
|
||||
<string name="input_overlay_behavior">行為模式</string>
|
||||
<string name="input_overlay_behavior">隱藏</string>
|
||||
<string name="overlay_auto_hide">自動隱藏虛擬按鍵</string>
|
||||
<string name="overlay_auto_hide_description">在未使用虛擬按鍵幾秒後自動隱藏</string>
|
||||
<string name="enable_input_overlay_auto_hide">啟用自動隱藏虛擬按鍵</string>
|
||||
@@ -46,26 +46,28 @@
|
||||
<string name="shaders_suffix">著色器</string>
|
||||
<string name="charging">(充電中)</string>
|
||||
|
||||
<string name="system_info_label">系統:</string>
|
||||
<string name="system_info_label">系統:</string>
|
||||
<string name="show_stats_overlay">顯示效能統計疊加層</string>
|
||||
<string name="stats_overlay_customization">自訂</string>
|
||||
<string name="stats_overlay_items">可見項目</string>
|
||||
<string name="stats_overlay_options">疊加層</string>
|
||||
<string name="enable_stats_overlay_">啟用效能統計疊加層</string>
|
||||
<string name="stats_overlay_options_description">設定疊加層中顯示的資訊</string>
|
||||
<string name="show_fps">顯示FPS</string>
|
||||
<string name="show_fps_description">顯示當前幀率</string>
|
||||
<string name="show_frametime">顯示幀時間</string>
|
||||
<string name="show_fps">顯示影格率</string>
|
||||
<string name="show_fps_description">顯示當前影格率</string>
|
||||
<string name="show_frametime">顯示影格時間</string>
|
||||
<string name="show_app_ram_usage">顯示應用程式的記憶體用量</string>
|
||||
<string name="show_app_ram_usage_description">顯示模擬器正在使用的記憶體量</string>
|
||||
<string name="show_app_ram_usage_description">顯示模擬器的記憶體用量</string>
|
||||
<string name="show_system_ram_usage">顯示系統記憶體用量</string>
|
||||
<string name="show_system_ram_usage_description">顯示系統使用的記憶體量</string>
|
||||
<string name="show_system_ram_usage_description">顯示系統的記憶體用量</string>
|
||||
<string name="show_bat_temperature">顯示電池溫度</string>
|
||||
<string name="bat_temperature_unit">電池溫度單位</string>
|
||||
<string name="show_power_info">顯示電池資訊</string>
|
||||
<string name="show_power_info_description">顯示當前功耗和電池可續航時間</string>
|
||||
<string name="show_shaders_building">當著色器在編譯時顯示</string>
|
||||
<string name="show_shaders_building_description">顯示正在編譯的著色器數量</string>
|
||||
<string name="pipeline_worker_cores">管線工作執行緒</string>
|
||||
<string name="pipeline_worker_cores_description">設定用於建置 Vulkan 管線的 CPU 核心數量,設定的數值越大效能越好,但溫度也會上升更快</string>
|
||||
<string name="overlay_position">疊加層位置</string>
|
||||
<string name="overlay_position_description">選擇疊加層在畫面上的顯示位置</string>
|
||||
<string name="overlay_position_top_left">左上</string>
|
||||
@@ -78,10 +80,10 @@
|
||||
<string name="perf_overlay_background_description">為疊加層添加背景以提高可讀性</string>
|
||||
|
||||
<!-- Device Overlay settings -->
|
||||
<string name="show_soc_overlay">顯示裝置資訊浮層</string>
|
||||
<string name="enable_soc_overlay">啟用裝置浮層</string>
|
||||
<string name="soc_overlay_options">裝置浮層</string>
|
||||
<string name="soc_overlay_options_description">設定裝置浮層中顯示的資訊</string>
|
||||
<string name="show_soc_overlay">顯示裝置資訊疊加層</string>
|
||||
<string name="enable_soc_overlay">啟用裝置疊加層</string>
|
||||
<string name="soc_overlay_options">裝置疊加層</string>
|
||||
<string name="soc_overlay_options_description">設定裝置疊加層中顯示的資訊</string>
|
||||
|
||||
<string name="show_build_id">顯示Eden的組建版本</string>
|
||||
<string name="show_driver_version">顯示圖形驅動程式的版本</string>
|
||||
@@ -92,10 +94,10 @@
|
||||
|
||||
<!-- Eden\'s Veil -->
|
||||
<string name="buffer_reorder_disable">停用緩衝區重新排序</string>
|
||||
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能。</string>
|
||||
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能</string>
|
||||
|
||||
<string name="use_sync_core">同步核心速度</string>
|
||||
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能。</string>
|
||||
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
|
||||
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
|
||||
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
|
||||
<string name="debug_knobs">偵錯開關</string>
|
||||
@@ -171,7 +173,7 @@
|
||||
<string name="multiplayer_ban">封鎖使用者</string>
|
||||
<string name="multiplayer_room_browser">公開房間</string>
|
||||
<string name="multiplayer_no_rooms_found">未找到公開房間</string>
|
||||
<string name="multiplayer_password_required">需輸入密碼</string>
|
||||
<string name="multiplayer_password_required">需要輸入密碼</string>
|
||||
<string name="multiplayer_player_count">:%1$d/%2$d</string>
|
||||
<string name="multiplayer_game">遊戲</string>
|
||||
<string name="multiplayer_no_game_info">任意遊戲</string>
|
||||
@@ -190,7 +192,7 @@
|
||||
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
|
||||
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
|
||||
<string name="multiplayer_port_error">埠號需為1-65535</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="cancel">略過</string>
|
||||
<string name="ok">確定</string>
|
||||
<string name="refresh">重新整理</string>
|
||||
<string name="room_list">房間列表</string>
|
||||
@@ -244,21 +246,21 @@
|
||||
<string name="home_search_games">搜尋遊戲</string>
|
||||
<string name="search_settings">搜尋設定</string>
|
||||
<string name="install_prod_keys">安裝 prod.keys</string>
|
||||
<string name="install_prod_keys_description">需要解密零售遊戲</string>
|
||||
<string name="install_prod_keys_description">需要用來解密零售遊戲</string>
|
||||
<string name="install_prod_keys_warning">跳過安裝金鑰?</string>
|
||||
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,若要繼續,將僅有自製遊戲可以運作。</string>
|
||||
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,如果不安裝將僅有自製遊戲可以運作</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
||||
<string name="install_firmware_warning">跳過安裝韌體?</string>
|
||||
<string name="emulator_data">設定模擬器資料</string>
|
||||
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動QLaunch小程式</string>
|
||||
<string name="permissions">授予權限</string>
|
||||
<string name="permissions_description">授予權限以使用模擬器的特定功能</string>
|
||||
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作。</string>
|
||||
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
|
||||
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">通知</string>
|
||||
<string name="notifications_description">使用下方的按鈕授予通知權限。</string>
|
||||
<string name="notifications_description">使用下方的按鈕授予通知權限</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_description">組建版本、製作群、以及更多</string>
|
||||
<string name="system_information">裝置資訊</string>
|
||||
@@ -285,7 +287,7 @@
|
||||
<string name="warning_skip">跳過</string>
|
||||
<string name="warning_cancel">取消</string>
|
||||
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
|
||||
<string name="install_amiibo_keys_description">需要在遊戲中使用 Amiibo</string>
|
||||
<string name="install_amiibo_keys_description">若要在遊戲中使用 Amiibo 得先安裝</string>
|
||||
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
|
||||
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
||||
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
||||
@@ -298,16 +300,16 @@
|
||||
<string name="app_settings_description">自訂Eden的主題與介面</string>
|
||||
<string name="no_file_manager">找不到檔案管理員</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_description">已找到儲存資料,請選取下方的選項。</string>
|
||||
<string name="manage_save_data_description">導入/導出遊戲的儲存資料\n\n壓縮檔中首個子資料夾名稱必須為遊戲 ID</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_exporting">正在導出儲存資料…</string>
|
||||
<string name="save_file_imported_success">已成功導入</string>
|
||||
<string name="save_file_invalid_zip_structure">無效的儲存目錄結構</string>
|
||||
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲標題 ID。</string>
|
||||
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲 ID</string>
|
||||
<string name="install_firmware">安裝韌體</string>
|
||||
<string name="install_firmware_description">韌體必須為 ZIP 壓縮檔,將會用於部分遊戲的啟動</string>
|
||||
<string name="firmware_installing">正在安裝韌體</string>
|
||||
@@ -317,12 +319,15 @@
|
||||
<string name="share_log">分享偵錯記錄</string>
|
||||
<string name="share_log_description">分享 Eden 的記錄檔以便對相關問題進行偵錯</string>
|
||||
<string name="share_log_missing">找不到日誌檔案</string>
|
||||
<string name="share_gpu_log">分享 GPU 日誌</string>
|
||||
<string name="share_gpu_log_description">分享 Eden 的 GPU 日誌以對圖形問題進行偵錯</string>
|
||||
<string name="share_gpu_log_missing">找不到 GPU 日誌檔案</string>
|
||||
<string name="install_game_content">安裝遊戲內容</string>
|
||||
<string name="install_game_content_description">安裝遊戲更新或 DLC</string>
|
||||
<string name="installing_game_content">正在安裝內容…</string>
|
||||
<string name="install_game_content_failure">安裝檔案至 NAND 時發生錯誤</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_description">請確保內容有效並且 prod.keys 檔案已安裝</string>
|
||||
<string name="install_game_content_failure_base">為避免產生衝突,無法直接安裝遊戲本體</string>
|
||||
<string name="install_game_content_failed_count">%1$d 安裝錯誤</string>
|
||||
<string name="install_game_content_success">遊戲內容已成功安裝</string>
|
||||
<string name="install_game_content_success_install">%1$d 安裝成功</string>
|
||||
@@ -331,12 +336,12 @@
|
||||
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
|
||||
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式。\n請以後再來查看是否已新增支援!</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="deep_scan">深度掃描</string>
|
||||
<string name="add_game_folder">新增遊戲資料夾</string>
|
||||
<string name="folder_already_added">這個資料夾已經新增過了!</string>
|
||||
<string name="game_folder_properties">遊戲資料夾屬性</string>
|
||||
<string name="game_folder_properties">遊戲資料夾設定</string>
|
||||
<plurals name="saves_import_failed">
|
||||
<item quantity="other">%d 個存檔導入失敗</item>
|
||||
</plurals>
|
||||
@@ -347,28 +352,30 @@
|
||||
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
||||
<string name="verify_installed_content_description">檢查所有已安裝的內容是否有損壞</string>
|
||||
|
||||
<string name="keys_missing">缺少解密金鑰</string>
|
||||
<string name="keys_missing">缺少 prod.keys</string>
|
||||
<string name="keys_missing_description">無法解密韌體和零售遊戲</string>
|
||||
<string name="keys_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
|
||||
|
||||
<string name="uninstall_firmware">解除安裝韌體</string>
|
||||
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性。</string>
|
||||
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性</string>
|
||||
<string name="firmware_uninstalling">正在解除安裝韌體...</string>
|
||||
<string name="firmware_uninstalled_success">韌體解除安裝成功</string>
|
||||
|
||||
|
||||
<string name="keys_failed">金鑰安裝失敗</string>
|
||||
<string name="keys_install_success">金鑰安裝成功</string>
|
||||
<string name="error_keys_copy_failed">一個或多個金鑰複製失敗。</string>
|
||||
<string name="error_keys_copy_failed">一個或多個金鑰安裝失敗</string>
|
||||
<string name="error_keys_invalid_filename">請確保金鑰檔案具有.keys副檔名後重試。</string>
|
||||
<string name="error_keys_failed_init">金鑰初始化失敗。請檢查您的轉儲工具是否為最新版本並重新轉儲金鑰。</string>
|
||||
|
||||
<!-- Applet launcher strings -->
|
||||
<string name="qlaunch_applet">Qlaunch</string>
|
||||
<string name="qlaunch_description">從系統主畫面啟動應用程式</string>
|
||||
<string name="qlaunch_description">從Switch系統主畫面啟動應用程式(目前僅支援英文)</string>
|
||||
<string name="applets">小程式啟動器</string>
|
||||
<string name="applets_description">使用已安裝的韌體啟動系統小程式</string>
|
||||
<string name="applets_error_firmware">未安裝韌體</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>已安裝並重試]]></string>
|
||||
<string name="album_applet">相簿</string>
|
||||
<string name="album_applet_description">使用系統相片檢視器查看儲存在使用者螢幕截圖資料夾中的影像</string>
|
||||
<string name="mii_edit_applet">Mii 編輯</string>
|
||||
@@ -377,47 +384,58 @@
|
||||
<string name="cabinet_applet_description">編輯、刪除儲存在 amiibo 上的資料</string>
|
||||
<string name="cabinet_launcher">Cabinet 啟動器</string>
|
||||
<string name="cabinet_nickname_and_owner">暱稱和擁有者設定</string>
|
||||
<string name="cabinet_game_data_eraser">遊戲資料橡皮擦</string>
|
||||
<string name="cabinet_game_data_eraser">刪除遊戲資料</string>
|
||||
<string name="cabinet_restorer">還原程式</string>
|
||||
<string name="cabinet_formatter">格式化程式</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia不是真的</string>
|
||||
<string name="gaia_is_not_real">Gaia 不存在</string>
|
||||
<string name="copied_to_clipboard">已複製到剪貼簿</string>
|
||||
<string name="about_app_description">一個開放原始碼的 Switch 模擬器</string>
|
||||
<string name="contributors">參與者</string>
|
||||
<string name="contributors_description">這些人讓 Eden Android 版成為可能</string>
|
||||
<string name="licenses_description">這些專案使 Eden Android 版成為可能</string>
|
||||
<string name="build">組建版本</string>
|
||||
<string name="user_data">使用者資料</string>
|
||||
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入資料可能會出現問題,建議手動導入所有所需資料。</string>
|
||||
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入使用者資料可能會出現問題,建議手動導入所有所需資料。</string>
|
||||
<string name="exporting_user_data">正在導出使用者資料…</string>
|
||||
<string name="importing_user_data">正在導入使用者資料…</string>
|
||||
<string name="invalid_yuzu_backup">無效的 Eden 備份</string>
|
||||
<string name="user_data_export_success">使用者資料導出成功</string>
|
||||
<string name="user_data_import_success">使用者資料導入成功</string>
|
||||
<string name="user_data_export_cancelled">導出已取消</string>
|
||||
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次。</string>
|
||||
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次</string>
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">限制速度</string>
|
||||
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比。</string>
|
||||
<string name="frame_limit_enable">限制模擬速度</string>
|
||||
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比</string>
|
||||
<string name="frame_limit_slider">限制速度百分比</string>
|
||||
<string name="frame_limit_slider_description">指定限制模擬速度的百分比。100% 為標準速度,更高或更低的值將會增加或減少速度限制。</string>
|
||||
<string name="frame_limit_slider_description">指定模擬速度的百分比。100% 為標準速度,更高或更低的值將會減少或增加速度限制</string>
|
||||
<string name="turbo_speed_limit">加速模式</string>
|
||||
<string name="turbo_speed_limit_description">當開啟加速模式時,模擬器將以此速度執行</string>
|
||||
<string name="slow_speed_limit">慢速模式</string>
|
||||
<string name="slow_speed_limit_description">當慢速模式開啟時,模擬器將會以此速度執行</string>
|
||||
<string name="cpu_backend">CPU 後端</string>
|
||||
<string name="cpu_accuracy">CPU 準確度</string>
|
||||
<string name="value_with_units">%1$s%2$s</string>
|
||||
|
||||
<string name="program_args">Homebrew 參數</string>
|
||||
<string name="program_args_description">在啟動時傳遞給 Homebrew 的命令列參數(例如:-noglsl)</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="device_name">裝置名稱</string>
|
||||
<string name="use_docked_mode">底座模式</string>
|
||||
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能。</string>
|
||||
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能</string>
|
||||
<string name="emulated_region">模擬區域</string>
|
||||
<string name="emulated_language">模擬語言</string>
|
||||
<string name="select_rtc_date">選擇 RTC 日期</string>
|
||||
<string name="select_rtc_time">選擇 RTC 時間</string>
|
||||
<string name="use_custom_rtc">自訂 RTC</string>
|
||||
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間。</string>
|
||||
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
|
||||
<string name="set_custom_rtc">設定自訂 RTC</string>
|
||||
|
||||
<!-- CPU -->
|
||||
<string name="fast_cpu_time">CPU 超頻</string>
|
||||
<string name="fast_cpu_time_description">強制模擬 CPU 以更高的時脈運作,減少某些 FPS 限制。使用 加速 (1700MHz) 以 Switch 的最高原生時脈執行,或 高速 (2000MHz) 以雙倍時脈執行</string>
|
||||
<string name="custom_cpu_ticks">自訂CPU時脈</string>
|
||||
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
|
||||
<string name="cpu_ticks">時脈</string>
|
||||
@@ -428,33 +446,41 @@
|
||||
|
||||
<!-- Network settings strings -->
|
||||
<string name="web_token">網路令牌</string>
|
||||
<string name="web_token_description">用於建立公開大廳的網路令牌。它是由48個小寫字母a-z組成的字串。</string>
|
||||
<string name="web_token_description">用於建立公開大廳的網路令牌。由48個小寫字母a-z組成</string>
|
||||
<string name="web_username">網路使用者名稱</string>
|
||||
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)。</string>
|
||||
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)</string>
|
||||
<string name="network">網路</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_resolution">解析度 (手提/底座)</string>
|
||||
<string name="renderer_vsync">垂直同步</string>
|
||||
<string name="renderer_scaling_filter">視窗適應過濾器</string>
|
||||
<string name="renderer_scaling_filter">視窗自適應濾波器</string>
|
||||
<string name="fsr_sharpness">FSR/SGSR 銳化度</string>
|
||||
<string name="fsr_sharpness_description">使用 FSR/SGSR 時圖片的銳化程度</string>
|
||||
<string name="renderer_anti_aliasing">抗鋸齒</string>
|
||||
|
||||
|
||||
<string name="advanced">進階</string>
|
||||
|
||||
<string name="renderer_accuracy">GPU 模式</string>
|
||||
<string name="renderer_accuracy_description">設定 GPU 模擬的準確度。大多數遊戲在設定為快速時即可正常渲染,但有些需要渲染粒子的遊戲仍需設為準確來避免圖形錯誤</string>
|
||||
<string name="dma_accuracy">DMA 準確度</string>
|
||||
<string name="dma_accuracy_description">控制 DMA 準確度。安全準確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。</string>
|
||||
<string name="dma_accuracy_description">控制 DMA 準確度。將準確度設為穩定可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為預設</string>
|
||||
<string name="gpu_fence_behavior">GPU 同步柵欄模式</string>
|
||||
<string name="gpu_fence_behavior_description">控制 GPU 同步柵欄模式。即時是速度最快的選項,但可能會導致一些問題。使用平衡可以提供更好的相容性並修復某些遊戲中的錯誤。準確則是在犧牲部分效能的情況下進一步提升相容性。嚴格是最慢的選項,但可以修復那些對同步要求更嚴格的遊戲中的問題。預設則會依照 GPU 準確度設定</string>
|
||||
<string name="anisotropic_filtering">各向異性過濾</string>
|
||||
<string name="anisotropic_filtering_description">改善斜角檢視時的紋理品質</string>
|
||||
<string name="vram_usage_mode">VRAM使用模式</string>
|
||||
<string name="vram_usage_mode_description">控制GPU記憶體的分配與釋放策略</string>
|
||||
<string name="accelerate_astc">ASTC解碼方式</string>
|
||||
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、安全)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
|
||||
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、穩定)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
|
||||
|
||||
<string name="sync_memory_operations">同步記憶體操作</string>
|
||||
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大。</string>
|
||||
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大</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="renderer_force_max_clock">強制使用最大時脈 (僅限Adreno)</string>
|
||||
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)。</string>
|
||||
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)</string>
|
||||
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
|
||||
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
|
||||
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
|
||||
@@ -603,7 +629,7 @@
|
||||
<string name="import_complete">導入完成</string>
|
||||
<string name="use_global_setting">使用全域設定</string>
|
||||
<string name="operation_completed_successfully">操作已成功完成</string>
|
||||
<string name="confirm">確定</string>
|
||||
<string name="confirm">下載</string>
|
||||
<string name="load">載入</string>
|
||||
<string name="save">儲存</string>
|
||||
|
||||
@@ -821,8 +847,8 @@
|
||||
|
||||
<!-- Memory Layouts -->
|
||||
<string name="memory_4gb">4GB (推薦)</string>
|
||||
<string name="memory_6gb">6GB (不安全)</string>
|
||||
<string name="memory_8gb">8GB (不安全)</string>
|
||||
<string name="memory_6gb">6GB (不穩定)</string>
|
||||
<string name="memory_8gb">8GB (不穩定)</string>
|
||||
|
||||
<!--CPU clock speeds-->
|
||||
<string name="clock_boost">加速 (1700MHz)</string>
|
||||
@@ -843,13 +869,12 @@
|
||||
|
||||
<string name="renderer_none">無</string>
|
||||
|
||||
<string name="renderer_accuracy_medium">平衡</string>
|
||||
<string name="renderer_accuracy_high">準確</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
<string name="dma_accuracy_default">預設</string>
|
||||
<string name="dma_accuracy_unsafe">不安全</string>
|
||||
<string name="dma_accuracy_safe">安全</string>
|
||||
<string name="dma_accuracy_unsafe">不穩定</string>
|
||||
<string name="dma_accuracy_safe">穩定</string>
|
||||
|
||||
<string name="vram_usage_conservative">保守</string>
|
||||
<string name="vram_usage_aggressive">積極</string>
|
||||
@@ -875,7 +900,7 @@
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">高準確度</string>
|
||||
<string name="cpu_accuracy_unsafe">低準確度(不安全)</string>
|
||||
<string name="cpu_accuracy_unsafe">低準確度(不穩定)</string>
|
||||
<string name="cpu_accuracy_paranoid">不合理</string>
|
||||
<string name="cpu_accuracy_debugging">偵錯</string>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</integer-array>
|
||||
|
||||
<string-array name="clockNames">
|
||||
<item>@string/off</item>
|
||||
<item>@string/clock_normal</item>
|
||||
<item>@string/clock_boost</item>
|
||||
<item>@string/clock_fast</item>
|
||||
</string-array>
|
||||
@@ -103,14 +103,12 @@
|
||||
|
||||
<string-array name="rendererAccuracyNames">
|
||||
<item>@string/renderer_accuracy_low</item>
|
||||
<item>@string/renderer_accuracy_medium</item>
|
||||
<item>@string/renderer_accuracy_high</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="rendererAccuracyValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- VRAM USAGE MODE CHOICES -->
|
||||
@@ -164,6 +162,30 @@
|
||||
<item>@string/resolution_four</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="frameGenMultiplierNames">
|
||||
<item>@string/frame_gen_multiplier_2x</item>
|
||||
<item>@string/frame_gen_multiplier_3x</item>
|
||||
<item>@string/frame_gen_multiplier_4x</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="frameGenMultiplierValues">
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="frameGenQueueTargetNames">
|
||||
<item>@string/frame_gen_queue_target_0</item>
|
||||
<item>@string/frame_gen_queue_target_1</item>
|
||||
<item>@string/frame_gen_queue_target_2</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="frameGenQueueTargetValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="rendererVSyncNames">
|
||||
<item>@string/renderer_vsync_immediate</item>
|
||||
<item>@string/renderer_vsync_mailbox</item>
|
||||
@@ -522,6 +544,21 @@
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="gpuFenceBehaviorNames">
|
||||
<item>@string/gpu_fence_behavior_default</item>
|
||||
<item>@string/gpu_fence_behavior_immediate</item>
|
||||
<item>@string/gpu_fence_behavior_balanced</item>
|
||||
<item>@string/gpu_fence_behavior_accurate</item>
|
||||
<item>@string/gpu_fence_behavior_strict</item>
|
||||
</string-array>
|
||||
<integer-array name="gpuFenceBehaviorValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
|
||||
<string-array name="appletEntries">
|
||||
<item>@string/applet_hle</item>
|
||||
@@ -534,7 +571,7 @@
|
||||
</integer-array>
|
||||
|
||||
<string-array name="gpuEntries">
|
||||
<item>@string/off</item>
|
||||
<item>@string/fast_gpu_normal</item>
|
||||
<item>@string/fast_gpu_medium</item>
|
||||
<item>@string/fast_gpu_high</item>
|
||||
</string-array>
|
||||
@@ -625,6 +662,16 @@
|
||||
<item>@string/error_keys_failed_init</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="losslessDllResults">
|
||||
<item>""</item>
|
||||
<item>@string/error_lossless_copy_failed</item>
|
||||
<item>@string/error_lossless_unreadable</item>
|
||||
<item>@string/error_lossless_not_pe</item>
|
||||
<item>@string/error_lossless_missing_shaders</item>
|
||||
<item>@string/error_lossless_translation_failed</item>
|
||||
<item>@string/error_lossless_cache_failed</item>
|
||||
</string-array>
|
||||
|
||||
<!-- GPU Logging Arrays -->
|
||||
<string-array name="gpuLogLevelEntries">
|
||||
<item>Off</item>
|
||||
|
||||
@@ -298,6 +298,54 @@
|
||||
<string name="gpu_driver_fetcher">GPU driver fetcher</string>
|
||||
<string name="gpu_driver_manager">GPU driver manager</string>
|
||||
<string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
|
||||
<string name="frame_gen">Frame generation</string>
|
||||
<string name="frame_gen_submenu_description">Manage and configure frame generation</string>
|
||||
<string name="frame_gen_description">Insert interpolated frames between rendered ones using Lossless Scaling. Forces FIFO presentation while enabled.</string>
|
||||
<string name="frame_gen_multiplier">Frame multiplier</string>
|
||||
<string name="frame_gen_multiplier_description">How many frames to display for each rendered frame. Higher values cost proportionally more GPU time. Asking for more than your display can present will slow emulation down.</string>
|
||||
<string name="frame_gen_multiplier_2x">2x</string>
|
||||
<string name="frame_gen_multiplier_3x">3x</string>
|
||||
<string name="frame_gen_multiplier_4x">4x</string>
|
||||
<string name="frame_gen_queue_target">Frame queue target</string>
|
||||
<string name="frame_gen_queue_target_description">How many finished frames may wait ahead of the display. Larger queues absorb GPU spikes at the cost of input latency.</string>
|
||||
<string name="frame_gen_queue_target_0">Unbuffered (lowest latency)</string>
|
||||
<string name="frame_gen_queue_target_1">One frame (balanced)</string>
|
||||
<string name="frame_gen_queue_target_2">Two frames (smoothest)</string>
|
||||
<string name="frame_gen_flow_scale_auto">Match motion estimation to the game</string>
|
||||
<string name="frame_gen_flow_scale_auto_description">Estimate motion at the resolution the game actually renders instead of the upscaled output. Costs nothing in accuracy, since upscaling adds no motion detail.</string>
|
||||
<string name="frame_gen_flow_scale">Motion estimation resolution</string>
|
||||
<string name="frame_gen_flow_scale_description">Resolution of the optical flow pass, as a fraction of the output. Lowering it is the cheapest way to reclaim performance.</string>
|
||||
<string name="frame_gen_fp16">Half precision shaders</string>
|
||||
<string name="frame_gen_fp16_description">Use the 16-bit shader variant shipped in Lossless.dll. Falls back automatically if the driver or the file lacks it.</string>
|
||||
<string name="frame_gen_dump_flow">Dump generated frame</string>
|
||||
<string name="frame_gen_dump_flow_description">Write the optical flow mip levels and the interpolated frame to the lossless/debug folder once, for troubleshooting</string>
|
||||
<string name="frame_gen_unsupported">Frame generation unavailable</string>
|
||||
<string name="frame_gen_unsupported_description">This GPU driver does not support the Vulkan memory model, which the Lossless Scaling shaders require.</string>
|
||||
<string name="lossless_scaling_setup_description">Optional. Provide your own Lossless.dll to enable frame generation later</string>
|
||||
<string name="lossless_scaling_install">Install Lossless.dll</string>
|
||||
<string name="lossless_scaling_install_description">Frame generation needs your own legal copy of Lossless.dll from Lossless Scaling</string>
|
||||
<string name="lossless_scaling_replace_description">Select a different copy of Lossless.dll</string>
|
||||
<string name="frame_generation_support">Frame generation</string>
|
||||
<string name="frame_generation_supported">Supported</string>
|
||||
<string name="frame_generation_unsupported">Unsupported (no Vulkan memory model)</string>
|
||||
<string name="lossless_scaling">Lossless Scaling</string>
|
||||
<string name="lossless_scaling_description">Provide your own copy of Lossless.dll to enable frame generation</string>
|
||||
<string name="lossless_scaling_installed">Installed</string>
|
||||
<string name="lossless_scaling_not_installed">Not installed</string>
|
||||
<string name="lossless_scaling_installed_description">Lossless.dll is installed and contains every shader frame generation needs.</string>
|
||||
<string name="lossless_scaling_replace">Replace</string>
|
||||
<string name="lossless_scaling_remove">Remove</string>
|
||||
<string name="lossless_scaling_remove_description">Delete the installed Lossless.dll and its prepared shaders</string>
|
||||
<string name="lossless_scaling_remove_confirmation">Frame generation will stop working until you install Lossless.dll again. Your original file is not affected.</string>
|
||||
<string name="lossless_scaling_installing">Preparing frame generation shaders…</string>
|
||||
<string name="lossless_scaling_install_success">Lossless.dll installed successfully</string>
|
||||
<string name="lossless_scaling_install_failed">Could not install Lossless.dll</string>
|
||||
<string name="error_lossless_copy_failed">The selected file could not be copied.</string>
|
||||
<string name="error_lossless_unreadable">The selected file could not be read.</string>
|
||||
<string name="error_lossless_not_pe">The selected file is not a Windows library. Select Lossless.dll from your Lossless Scaling installation.</string>
|
||||
<string name="error_lossless_missing_shaders">This copy of Lossless.dll does not contain the frame generation shaders. Update Lossless Scaling and try again.</string>
|
||||
<string name="error_lossless_translation_failed">The frame generation shaders could not be translated. This version of Lossless Scaling is not supported yet.</string>
|
||||
<string name="error_lossless_cache_failed">The translated shaders could not be written to storage. Check that there is free space available.</string>
|
||||
<string name="advanced_settings">Advanced settings</string>
|
||||
<string name="settings_description">Configure emulator settings</string>
|
||||
<string name="search_recently_played">Recently played</string>
|
||||
@@ -450,8 +498,8 @@
|
||||
<string name="set_custom_rtc">Set custom RTC</string>
|
||||
|
||||
<!-- CPU -->
|
||||
<string name="fast_cpu_time">CPU Overclock</string>
|
||||
<string name="fast_cpu_time_description">Forces the emulated CPU to run at a higher clock, reducing certain FPS limiters. Use Boost (1700MHz) to run at the Switch\'s highest native clock, or Fast (2000MHz) to run at 2x clock.</string>
|
||||
<string name="fast_cpu_time">CPU Clocks</string>
|
||||
<string name="fast_cpu_time_description">Raises the clock the emulated CPU reports, which removes some FPS limiters. Weaker CPUs may see reduced performance, and certain games may behave improperly.</string>
|
||||
<string name="custom_cpu_ticks">Custom CPU Ticks</string>
|
||||
<string name="custom_cpu_ticks_description">Set a custom value of CPU ticks. Higher values can increase performance, but may also cause the game to freeze. A range of 77–21000 is recommended.</string>
|
||||
<string name="cpu_ticks">Ticks</string>
|
||||
@@ -479,9 +527,11 @@
|
||||
<string name="advanced">Advanced</string>
|
||||
|
||||
<string name="renderer_accuracy">GPU Mode</string>
|
||||
<string name="renderer_accuracy_description">Controls the GPU emulation mode. Most games render fine with Fast or Balanced modes, but Accurate is still required for some. Particles tend to only render correctly with Accurate mode.</string>
|
||||
<string name="renderer_accuracy_description">Controls the GPU emulation mode. Most games render fine with Fast, but Accurate is still required for some. Particles tend to only render correctly with Accurate mode.</string>
|
||||
<string name="dma_accuracy">DMA Accuracy</string>
|
||||
<string name="dma_accuracy_description">Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave this on Default.</string>
|
||||
<string name="gpu_fence_behavior">GPU Fence Behavior</string>
|
||||
<string name="gpu_fence_behavior_description">Controls the GPU fence synchronization behavior. Immediate is the fastest option, but can introduce some issues. Balanced offers better compatibility and may fix issues in some games. Accurate further improves compatibility at the cost of some performance. Strict is the slowest option, but can fix issues that require stricter synchronization. Default follows the GPU Accuracy setting.</string>
|
||||
<string name="anisotropic_filtering">Anisotropic filtering</string>
|
||||
<string name="anisotropic_filtering_description">Improves the quality of textures when viewed at oblique angles</string>
|
||||
<string name="vram_usage_mode">VRAM Usage Mode</string>
|
||||
@@ -510,12 +560,10 @@
|
||||
|
||||
<string name="hacks">Hacks</string>
|
||||
|
||||
<string name="fast_gpu_time">Fast GPU Time</string>
|
||||
<string name="fast_gpu_time_description">Forces most games to run at their highest native resolution. Use 256 for maximal performance and 512 for maximal graphics fidelity.</string>
|
||||
<string name="fast_gpu_time">GPU Clocks</string>
|
||||
<string name="fast_gpu_time_description">Makes the game believe GPU work finishes faster than it does, so it stops lowering resolution and render distance to fit the Switch\'s clocks.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
|
||||
<string name="antiflicker">Anti-Flicker</string>
|
||||
<string name="antiflicker_description">Forces GPU fence callbacks to wait for submitted GPU work. Use with Fast GPU mode, to avoid flicker with lower performance impact.</string>
|
||||
<string name="fix_bloom_effects">Fix Bloom Effects</string>
|
||||
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
|
||||
<string name="emulate_bgr565">Emulate BGR565</string>
|
||||
@@ -560,6 +608,7 @@
|
||||
|
||||
<!-- Debug settings strings -->
|
||||
<string name="cpu">CPU</string>
|
||||
<string name="clocks">Clocks</string>
|
||||
<string name="use_auto_stub">Use Auto Stub</string>
|
||||
<string name="use_auto_stub_description">Automatically stub missing services and functions. This may improve compatibility but can cause crashes and stability issues.</string>
|
||||
|
||||
@@ -968,14 +1017,15 @@
|
||||
<string name="memory_6gb">6GB (Unsafe)</string>
|
||||
<string name="memory_8gb">8GB (Unsafe)</string>
|
||||
|
||||
<!--CPU clock speeds-->
|
||||
<string name="clock_boost">Boost (1700MHz)</string>
|
||||
<string name="clock_fast">Fast (2000MHz)</string>
|
||||
<!-- CPU clock levels -->
|
||||
<string name="clock_normal">Normal</string>
|
||||
<string name="clock_boost">Boost</string>
|
||||
<string name="clock_fast">Overclock</string>
|
||||
|
||||
<!-- GPU overclock factors -->
|
||||
<string name="off">Off</string>
|
||||
<string name="fast_gpu_medium">Medium (256)</string>
|
||||
<string name="fast_gpu_high">High (512)</string>
|
||||
<!-- GPU clock levels -->
|
||||
<string name="fast_gpu_normal">Normal</string>
|
||||
<string name="fast_gpu_medium">Boost</string>
|
||||
<string name="fast_gpu_high">Overclock</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Very Small (16 MB)</string>
|
||||
@@ -1039,7 +1089,6 @@
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_low">Fast</string>
|
||||
<string name="renderer_accuracy_medium">Balanced</string>
|
||||
<string name="renderer_accuracy_high">Accurate</string>
|
||||
|
||||
<!-- DMA Accuracy -->
|
||||
@@ -1047,6 +1096,13 @@
|
||||
<string name="dma_accuracy_unsafe">Unsafe</string>
|
||||
<string name="dma_accuracy_safe">Safe</string>
|
||||
|
||||
<!-- GPU Fence Behavior -->
|
||||
<string name="gpu_fence_behavior_default">Default</string>
|
||||
<string name="gpu_fence_behavior_immediate">Immediate</string>
|
||||
<string name="gpu_fence_behavior_balanced">Balanced</string>
|
||||
<string name="gpu_fence_behavior_accurate">Accurate</string>
|
||||
<string name="gpu_fence_behavior_strict">Strict</string>
|
||||
|
||||
<!-- ASTC Decoding Method Choices -->
|
||||
<string name="accelerate_astc_cpu" translatable="false">CPU</string>
|
||||
<string name="accelerate_astc_gpu" translatable="false">GPU</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<game-mode-config
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:supportsBatteryGameMode="true"
|
||||
android:supportsBatteryGameMode="false"
|
||||
android:supportsPerformanceGameMode="true"
|
||||
android:allowGameDownscaling="false"
|
||||
android:allowGameFpsOverride="false"/>
|
||||
@@ -222,7 +222,7 @@ if (MSVC)
|
||||
)
|
||||
else()
|
||||
target_compile_options(audio_core PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=conversion>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wconversion>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-sign-conversion>)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
@@ -147,7 +147,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out
|
||||
auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
|
||||
OpusPacketHeader header{ReverseHeader(*header_p)};
|
||||
|
||||
LOG_TRACE(Service_Audio, "header size {:#X} input data size 0x{:X} in_data size 0x{:X}",
|
||||
LOG_TRACE(Service_Audio, "header size {:#x} input data size {:#x} in_data size {:#x}",
|
||||
header.size, input_data.size_bytes(), in_data.size_bytes());
|
||||
|
||||
R_UNLESS(in_data.size_bytes() >= header.size &&
|
||||
|
||||
@@ -369,7 +369,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
|
||||
if (mix_count < 0 || mix_count > 0x100) {
|
||||
LOG_ERROR(
|
||||
Service_Audio,
|
||||
"Invalid mix count from dirty parameter: count={}, magic=0x{:X}, expected_size={}",
|
||||
"Invalid mix count from dirty parameter: count={}, magic={:#x}, expected_size={}",
|
||||
mix_count, in_dirty_params->magic, in_header->mix_size);
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
@@ -18,20 +18,15 @@
|
||||
namespace AudioCore::Renderer {
|
||||
|
||||
constexpr u32 TempBufferSize = 0x3F00;
|
||||
constexpr std::array<u8, 3> PitchBySrcQuality = {4, 8, 4};
|
||||
|
||||
/**
|
||||
* Decode PCM data. Only s16 or f32 is supported.
|
||||
*
|
||||
* @tparam T - Type to decode. Only s16 and f32 are supported.
|
||||
* @param memory - Core memory for reading samples.
|
||||
* @param out_buffer - Output mix buffer to receive the samples.
|
||||
* @param req - Information for how to decode.
|
||||
* @return Number of samples decoded.
|
||||
*/
|
||||
/// @brief Decode PCM data. Only s16 or f32 is supported.
|
||||
/// @tparam T - Type to decode. Only s16 and f32 are supported.
|
||||
/// @param memory - Core memory for reading samples.
|
||||
/// @param out_buffer - Output mix buffer to receive the samples.
|
||||
/// @param req - Information for how to decode.
|
||||
/// @return Number of samples decoded.
|
||||
template <typename T>
|
||||
static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
const DecodeArg& req) {
|
||||
static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer, const DecodeArg& req) {
|
||||
constexpr s32 min{(std::numeric_limits<s16>::min)()};
|
||||
constexpr s32 max{(std::numeric_limits<s16>::max)()};
|
||||
|
||||
@@ -94,16 +89,12 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
return samples_to_decode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode ADPCM data.
|
||||
*
|
||||
* @param memory - Core memory for reading samples.
|
||||
* @param out_buffer - Output mix buffer to receive the samples.
|
||||
* @param req - Information for how to decode.
|
||||
* @return Number of samples decoded.
|
||||
*/
|
||||
static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
const DecodeArg& req) {
|
||||
/// @brief Decode ADPCM data.
|
||||
/// @param memory - Core memory for reading samples.
|
||||
/// @param out_buffer - Output mix buffer to receive the samples.
|
||||
/// @param req - Information for how to decode.
|
||||
/// @return Number of samples decoded.
|
||||
static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer, const DecodeArg& req) {
|
||||
constexpr u32 SamplesPerFrame{14};
|
||||
constexpr u32 NibblesPerFrame{16};
|
||||
|
||||
@@ -115,8 +106,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto end{(req.end_offset % SamplesPerFrame) +
|
||||
NibblesPerFrame * (req.end_offset / SamplesPerFrame)};
|
||||
auto end{(req.end_offset % SamplesPerFrame) + NibblesPerFrame * (req.end_offset / SamplesPerFrame)};
|
||||
if (req.end_offset % SamplesPerFrame) {
|
||||
end += 3;
|
||||
} else {
|
||||
@@ -133,52 +123,49 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto samples_to_read{samples_to_process};
|
||||
auto samples_remaining_in_frame{start_pos % SamplesPerFrame};
|
||||
auto position_in_frame{(start_pos / SamplesPerFrame) * NibblesPerFrame +
|
||||
samples_remaining_in_frame};
|
||||
|
||||
auto samples_to_read = samples_to_process;
|
||||
auto samples_remaining_in_frame = start_pos % SamplesPerFrame;
|
||||
auto position_in_frame = (start_pos / SamplesPerFrame) * NibblesPerFrame + samples_remaining_in_frame;
|
||||
if (samples_remaining_in_frame) {
|
||||
position_in_frame += 2;
|
||||
}
|
||||
|
||||
const auto size{(std::max)((samples_to_process / 8U) * SamplesPerFrame, 8U)};
|
||||
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> wavebuffer(
|
||||
memory, req.buffer + position_in_frame / 2, size);
|
||||
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> wavebuffer(memory, req.buffer + position_in_frame / 2, size);
|
||||
|
||||
auto context{req.adpcm_context};
|
||||
auto header{context->header};
|
||||
u8 coeff_index{static_cast<u8>((header >> 4U) & 0xFU)};
|
||||
u8 scale{static_cast<u8>(header & 0xFU)};
|
||||
s32 coeff0{req.coefficients[coeff_index * 2 + 0]};
|
||||
s32 coeff1{req.coefficients[coeff_index * 2 + 1]};
|
||||
auto context = req.adpcm_context;
|
||||
auto header = context->header;
|
||||
u8 scale = u8(header & 0xfU);
|
||||
u8 coeff_index = u8((header >> 4U) & 0x7u);
|
||||
s32 coeff0 = req.coefficients[coeff_index * 2 + 0];
|
||||
s32 coeff1 = req.coefficients[coeff_index * 2 + 1];
|
||||
|
||||
auto yn0{context->yn0};
|
||||
auto yn1{context->yn1};
|
||||
|
||||
static constexpr std::array<s32, 16> Steps{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
|
||||
auto yn0 = context->yn0;
|
||||
auto yn1 = context->yn1;
|
||||
auto const get_step = [](u32 index) {
|
||||
// Emulates the following table
|
||||
// 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
|
||||
constexpr u64 steps_table = 0x1234567876543210ull;
|
||||
constexpr u64 steps_sign = 0b1111111100000000ull;
|
||||
auto const r = s32((steps_table >> (index * 4)) & 0xf);
|
||||
return ((steps_sign >> index) & 1) == 0 ? -r : r;
|
||||
};
|
||||
|
||||
const auto decode_sample = [&](const s32 code) -> s16 {
|
||||
auto const decode_sample = [&](const s32 code) -> s16 {
|
||||
const auto xn = code * (1 << scale);
|
||||
const auto prediction = coeff0 * yn0 + coeff1 * yn1;
|
||||
const auto sample = ((xn << 11) + 0x400 + prediction) >> 11;
|
||||
const auto saturated = std::clamp<s32>(sample, -0x8000, 0x7FFF);
|
||||
yn1 = yn0;
|
||||
yn0 = static_cast<s16>(saturated);
|
||||
return yn0;
|
||||
return yn0 = s16(saturated);
|
||||
};
|
||||
|
||||
u32 read_index{0};
|
||||
u32 write_index{0};
|
||||
|
||||
while (samples_to_read > 0) {
|
||||
u32 read_index = 0;
|
||||
for (u32 write_index = 0; samples_to_read > 0 && write_index < out_buffer.size(); ) {
|
||||
// Are we at a new frame?
|
||||
if ((position_in_frame % NibblesPerFrame) == 0) {
|
||||
header = wavebuffer[read_index++];
|
||||
coeff_index = (header >> 4) & 0xF;
|
||||
scale = header & 0xF;
|
||||
scale = header & 0xFu;
|
||||
coeff_index = (header >> 4) & 0x7u;
|
||||
coeff0 = req.coefficients[coeff_index * 2 + 0];
|
||||
coeff1 = req.coefficients[coeff_index * 2 + 1];
|
||||
position_in_frame += 2;
|
||||
@@ -187,14 +174,12 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
if (samples_to_read >= SamplesPerFrame) {
|
||||
// Can grab all samples until the next header
|
||||
for (u32 i = 0; i < SamplesPerFrame / 2; i++) {
|
||||
auto code0{Steps[(wavebuffer[read_index] >> 4) & 0xF]};
|
||||
auto code1{Steps[wavebuffer[read_index] & 0xF]};
|
||||
read_index++;
|
||||
|
||||
auto code0 = get_step((wavebuffer[read_index + i] >> 4) & 0xF);
|
||||
auto code1 = get_step(wavebuffer[read_index + i] & 0xF);
|
||||
out_buffer[write_index++] = decode_sample(code0);
|
||||
out_buffer[write_index++] = decode_sample(code1);
|
||||
}
|
||||
|
||||
read_index += SamplesPerFrame / 2;
|
||||
position_in_frame += SamplesPerFrame;
|
||||
samples_to_read -= SamplesPerFrame;
|
||||
continue;
|
||||
@@ -202,15 +187,14 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
}
|
||||
|
||||
// Decode a single sample
|
||||
auto code{wavebuffer[read_index]};
|
||||
auto code = wavebuffer[read_index];
|
||||
if (position_in_frame & 1) {
|
||||
code &= 0xF;
|
||||
read_index++;
|
||||
} else {
|
||||
code >>= 4;
|
||||
}
|
||||
|
||||
out_buffer[write_index++] = decode_sample(Steps[code]);
|
||||
out_buffer[write_index++] = decode_sample(get_step(code));
|
||||
|
||||
position_in_frame++;
|
||||
samples_to_read--;
|
||||
@@ -219,27 +203,21 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||
context->header = header;
|
||||
context->yn0 = yn0;
|
||||
context->yn1 = yn1;
|
||||
|
||||
return samples_to_process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode implementation.
|
||||
* Decode wavebuffers according to the given args.
|
||||
*
|
||||
* @param memory - Core memory to read data from.
|
||||
* @param args - The wavebuffer data, and information for how to decode it.
|
||||
*/
|
||||
/// @brief Decode implementation.
|
||||
/// Decode wavebuffers according to the given args.
|
||||
///
|
||||
/// @param memory - Core memory to read data from.
|
||||
/// @param args - The wavebuffer data, and information for how to decode it.
|
||||
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) {
|
||||
static constexpr auto EndWaveBuffer = [](auto& voice_state, auto& wavebuffer, auto& index,
|
||||
auto& played_samples, auto& consumed) -> void {
|
||||
constexpr auto EndWaveBuffer = [](auto& voice_state, auto& wavebuffer, auto& index, auto& played_samples, auto& consumed) -> void {
|
||||
voice_state.wave_buffer_valid[index] = false;
|
||||
voice_state.loop_count = 0;
|
||||
|
||||
if (wavebuffer.stream_ended) {
|
||||
played_samples = 0;
|
||||
}
|
||||
|
||||
index = (index + 1) % MaxWaveBuffers;
|
||||
consumed++;
|
||||
};
|
||||
@@ -255,8 +233,9 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||
return;
|
||||
}
|
||||
|
||||
auto pitch{PitchBySrcQuality[static_cast<u32>(args.src_quality)]};
|
||||
if (static_cast<u32>(pitch + size_required.to_int_floor()) > TempBufferSize) {
|
||||
// 0 -> 4, 1 -> 8, 2 -> 4
|
||||
auto pitch = u32((0x040804ul >> (u32(args.src_quality) * 8)) & 0xfful);
|
||||
if (u32(pitch + size_required.to_int_floor()) > TempBufferSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,7 +251,7 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||
bool is_buffer_starved{false};
|
||||
u32 offset{voice_state.offset};
|
||||
|
||||
auto output_buffer{args.output};
|
||||
auto output_buffer = args.output;
|
||||
std::array<s16, TempBufferSize> temp_buffer{};
|
||||
|
||||
while (remaining_sample_count > 0) {
|
||||
@@ -294,8 +273,8 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||
if (wavebuffer_index >= MaxWaveBuffers) {
|
||||
LOG_ERROR(Service_Audio, "Invalid wavebuffer index! {}", wavebuffer_index);
|
||||
wavebuffer_index = 0;
|
||||
voice_state.wave_buffer_valid.fill(false);
|
||||
wavebuffers_consumed = MaxWaveBuffers;
|
||||
voice_state.wave_buffer_valid.fill(false);
|
||||
}
|
||||
|
||||
if (!voice_state.wave_buffer_valid[wavebuffer_index]) {
|
||||
@@ -303,12 +282,9 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||
break;
|
||||
}
|
||||
|
||||
auto& wavebuffer{args.wave_buffers[wavebuffer_index]};
|
||||
|
||||
if (offset == 0 && args.sample_format == SampleFormat::Adpcm &&
|
||||
wavebuffer.context != 0) {
|
||||
memory.ReadBlockUnsafe(wavebuffer.context, &voice_state.adpcm_context,
|
||||
wavebuffer.context_size);
|
||||
auto& wavebuffer = args.wave_buffers[wavebuffer_index];
|
||||
if (offset == 0 && args.sample_format == SampleFormat::Adpcm && wavebuffer.context != 0) {
|
||||
memory.ReadBlockUnsafe(wavebuffer.context, &voice_state.adpcm_context, wavebuffer.context_size);
|
||||
}
|
||||
|
||||
auto start_offset{wavebuffer.start_offset};
|
||||
@@ -351,9 +327,7 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||
case SampleFormat::Adpcm: {
|
||||
decode_arg.adpcm_context = &voice_state.adpcm_context;
|
||||
memory.ReadBlockUnsafe(args.data_address, &decode_arg.coefficients, args.data_size);
|
||||
samples_decoded = DecodeAdpcm(
|
||||
memory, {&temp_buffer[temp_buffer_pos], TempBufferSize - temp_buffer_pos},
|
||||
decode_arg);
|
||||
samples_decoded = DecodeAdpcm( memory, {&temp_buffer[temp_buffer_pos], TempBufferSize - temp_buffer_pos}, decode_arg);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -5,21 +8,13 @@
|
||||
|
||||
namespace AudioCore::Renderer {
|
||||
|
||||
static void ResampleLowQuality(std::span<s32> output, std::span<const s16> input,
|
||||
const Common::FixedPoint<49, 15>& sample_rate_ratio,
|
||||
Common::FixedPoint<49, 15>& fraction, const u32 samples_to_write) {
|
||||
if (sample_rate_ratio == 1.0f) {
|
||||
for (u32 i = 0; i < samples_to_write; i++) {
|
||||
output[i] = input[i];
|
||||
}
|
||||
} else {
|
||||
u32 read_index{0};
|
||||
for (u32 i = 0; i < samples_to_write; i++) {
|
||||
output[i] = input[read_index + (fraction >= 0.5f)];
|
||||
fraction += sample_rate_ratio;
|
||||
read_index += static_cast<u32>(fraction.to_int_floor());
|
||||
fraction.clear_int();
|
||||
}
|
||||
static void ResampleLowQuality(std::span<s32> output, std::span<const s16> input, const Common::FixedPoint<49, 15>& sample_rate_ratio, Common::FixedPoint<49, 15>& fraction, const u32 samples_to_write) {
|
||||
u32 read_index{0};
|
||||
for (u32 i = 0; i < samples_to_write; i++) {
|
||||
output[i] = input[read_index + (fraction >= 0.5f)];
|
||||
fraction += sample_rate_ratio;
|
||||
read_index += u32(fraction.to_int_floor());
|
||||
fraction.clear_int();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +290,7 @@ static void ResampleNormalQuality(std::span<s32> output, std::span<const s16> in
|
||||
auto lut{get_lut()};
|
||||
u32 read_index{0};
|
||||
for (u32 i = 0; i < samples_to_write; i++) {
|
||||
const auto lut_index{(fraction.get_frac() >> 8) * 4};
|
||||
const auto lut_index = ((fraction.get_frac() >> 8) << 2) & 511;
|
||||
const Common::FixedPoint<56, 8> sample0{input[read_index + 0] * lut[lut_index + 0]};
|
||||
const Common::FixedPoint<56, 8> sample1{input[read_index + 1] * lut[lut_index + 1]};
|
||||
const Common::FixedPoint<56, 8> sample2{input[read_index + 2] * lut[lut_index + 2]};
|
||||
@@ -845,7 +840,7 @@ static void ResampleHighQuality(std::span<s32> output, std::span<const s16> inpu
|
||||
auto lut{get_lut()};
|
||||
u32 read_index{0};
|
||||
for (u32 i = 0; i < samples_to_write; i++) {
|
||||
const auto lut_index{(fraction.get_frac() >> 8) * 8};
|
||||
const auto lut_index = ((fraction.get_frac() >> 8) << 3) & 1023;
|
||||
const Common::FixedPoint<56, 8> sample0{input[read_index + 0] * lut[lut_index + 0]};
|
||||
const Common::FixedPoint<56, 8> sample1{input[read_index + 1] * lut[lut_index + 1]};
|
||||
const Common::FixedPoint<56, 8> sample2{input[read_index + 2] * lut[lut_index + 2]};
|
||||
|
||||
@@ -121,6 +121,8 @@ add_library(
|
||||
swap.h
|
||||
thread.cpp
|
||||
thread.h
|
||||
adpf.cpp
|
||||
adpf.h
|
||||
thread_queue_list.h
|
||||
thread_worker.h
|
||||
threadsafe_queue.h
|
||||
@@ -218,7 +220,7 @@ endif()
|
||||
if(CXX_CLANG)
|
||||
target_compile_options(common PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-fsized-deallocation>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Werror=unreachable-code-aggressive>)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wunreachable-code-aggressive>)
|
||||
target_compile_definitions(
|
||||
common
|
||||
PRIVATE
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -43,13 +46,13 @@ MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInf
|
||||
|
||||
if (virt_end > va_limit) {
|
||||
ASSERT_MSG(false,
|
||||
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
|
||||
"Trying to map a block past the VA limit: virt_end: {:#x}, va_limit: {:#x}",
|
||||
virt_end, va_limit);
|
||||
}
|
||||
|
||||
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
||||
if (block_end_successor == blocks.begin()) {
|
||||
ASSERT_MSG(false, "Trying to map a block before the VA start: virt_end: 0x{:X}", virt_end);
|
||||
ASSERT_MSG(false, "Trying to map a block before the VA start: virt_end: {:#x}", virt_end);
|
||||
}
|
||||
|
||||
auto block_end_predecessor{std::prev(block_end_successor)};
|
||||
@@ -124,7 +127,7 @@ MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInf
|
||||
|
||||
// Check that the start successor is either the end block or something in between
|
||||
if (block_start_successor->virt > virt_end) {
|
||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
|
||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: {:#x}", block_start_successor->virt);
|
||||
} else if (block_start_successor->virt == virt_end) {
|
||||
// We need to create a new block as there are none spare that we would overwrite
|
||||
blocks.insert(block_start_successor, Block(virt, phys, extra_info));
|
||||
@@ -150,13 +153,13 @@ MAP_MEMBER(void)::UnmapLocked(VaType virt, VaType size) {
|
||||
|
||||
if (virt_end > va_limit) {
|
||||
ASSERT_MSG(false,
|
||||
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
|
||||
"Trying to map a block past the VA limit: virt_end: {:#x}, va_limit: {:#x}",
|
||||
virt_end, va_limit);
|
||||
}
|
||||
|
||||
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
||||
if (block_end_successor == blocks.begin()) {
|
||||
ASSERT_MSG(false, "Trying to unmap a block before the VA start: virt_end: 0x{:X}",
|
||||
ASSERT_MSG(false, "Trying to unmap a block before the VA start: virt_end: {:#x}",
|
||||
virt_end);
|
||||
}
|
||||
|
||||
@@ -257,7 +260,7 @@ MAP_MEMBER(void)::UnmapLocked(VaType virt, VaType size) {
|
||||
auto block_start_successor{std::next(block_start_predecessor)};
|
||||
|
||||
if (block_start_successor->virt > virt_end) {
|
||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
|
||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: {:#x}", block_start_successor->virt);
|
||||
} else if (block_start_successor->virt == virt_end) {
|
||||
// There are no blocks between the start and the end that would let us skip inserting a new
|
||||
// one for head
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "common/adpf.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/logging.h"
|
||||
|
||||
namespace Common::ADPF {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::chrono::nanoseconds DEFAULT_TARGET = std::chrono::nanoseconds{16'666'667};
|
||||
|
||||
struct AHintManager;
|
||||
struct AHintSession;
|
||||
|
||||
using PFN_GetManager = AHintManager* (*)();
|
||||
using PFN_CreateSession = AHintSession* (*)(AHintManager*, const s32*, size_t, s64);
|
||||
using PFN_CloseSession = void (*)(AHintSession*);
|
||||
using PFN_UpdateTarget = int (*)(AHintSession*, s64);
|
||||
using PFN_ReportActual = int (*)(AHintSession*, s64);
|
||||
using PFN_SetThreads = int (*)(AHintSession*, const pid_t*, size_t);
|
||||
using PFN_SetPowerEfficiency = int (*)(AHintSession*, bool);
|
||||
|
||||
struct Api {
|
||||
PFN_GetManager get_manager = nullptr;
|
||||
PFN_CreateSession create_session = nullptr;
|
||||
PFN_CloseSession close_session = nullptr;
|
||||
PFN_UpdateTarget update_target = nullptr;
|
||||
PFN_ReportActual report_actual = nullptr;
|
||||
PFN_SetThreads set_threads = nullptr;
|
||||
PFN_SetPowerEfficiency set_power_efficiency = nullptr;
|
||||
AHintManager* manager = nullptr;
|
||||
bool usable = false;
|
||||
};
|
||||
|
||||
const Api& Resolve() {
|
||||
static const Api api = [] {
|
||||
Api resolved;
|
||||
void* library = dlopen("libandroid.so", RTLD_NOW);
|
||||
if (library == nullptr) {
|
||||
LOG_INFO(Common, "libandroid.so unavailable, ADPF is disabled");
|
||||
return resolved;
|
||||
}
|
||||
const auto load = [library](const char* name) { return dlsym(library, name); };
|
||||
|
||||
resolved.get_manager = reinterpret_cast<PFN_GetManager>(load("APerformanceHint_getManager"));
|
||||
resolved.create_session =
|
||||
reinterpret_cast<PFN_CreateSession>(load("APerformanceHint_createSession"));
|
||||
resolved.close_session =
|
||||
reinterpret_cast<PFN_CloseSession>(load("APerformanceHint_closeSession"));
|
||||
resolved.update_target =
|
||||
reinterpret_cast<PFN_UpdateTarget>(load("APerformanceHint_updateTargetWorkDuration"));
|
||||
resolved.report_actual =
|
||||
reinterpret_cast<PFN_ReportActual>(load("APerformanceHint_reportActualWorkDuration"));
|
||||
resolved.set_threads =
|
||||
reinterpret_cast<PFN_SetThreads>(load("APerformanceHint_setThreads"));
|
||||
resolved.set_power_efficiency = reinterpret_cast<PFN_SetPowerEfficiency>(
|
||||
load("APerformanceHint_setPreferPowerEfficiency"));
|
||||
|
||||
if (resolved.get_manager == nullptr || resolved.create_session == nullptr ||
|
||||
resolved.close_session == nullptr || resolved.update_target == nullptr ||
|
||||
resolved.report_actual == nullptr) {
|
||||
LOG_INFO(Common, "Performance hint API not exported, ADPF is disabled");
|
||||
return resolved;
|
||||
}
|
||||
|
||||
resolved.manager = resolved.get_manager();
|
||||
if (resolved.manager == nullptr) {
|
||||
LOG_INFO(Common, "Device does not provide a performance hint manager");
|
||||
return resolved;
|
||||
}
|
||||
|
||||
resolved.usable = true;
|
||||
LOG_INFO(Common, "ADPF available, setThreads {}, power efficiency {}",
|
||||
resolved.set_threads != nullptr ? "yes" : "no",
|
||||
resolved.set_power_efficiency != nullptr ? "yes" : "no");
|
||||
return resolved;
|
||||
}();
|
||||
return api;
|
||||
}
|
||||
|
||||
struct SessionState {
|
||||
AHintSession* handle = nullptr;
|
||||
std::vector<pid_t> threads;
|
||||
bool unsupported = false;
|
||||
};
|
||||
|
||||
std::mutex g_mutex;
|
||||
std::array<SessionState, 2> g_sessions;
|
||||
|
||||
constexpr s64 MAX_REPORTED_TARGETS = 4;
|
||||
|
||||
std::atomic<s64> g_target_ns{DEFAULT_TARGET.count()};
|
||||
thread_local std::chrono::steady_clock::time_point t_last_frame{};
|
||||
|
||||
SessionState& StateOf(Session session) {
|
||||
return g_sessions[static_cast<size_t>(session)];
|
||||
}
|
||||
|
||||
bool IsBackgroundUsable(const Api& api) {
|
||||
return api.set_power_efficiency != nullptr;
|
||||
}
|
||||
|
||||
void CloseLocked(SessionState& state) {
|
||||
if (state.handle != nullptr) {
|
||||
Resolve().close_session(state.handle);
|
||||
state.handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AHintSession* CreateSessionFor(Session session, const std::vector<pid_t>& threads) {
|
||||
const Api& api = Resolve();
|
||||
const s64 target = session == Session::Render ? g_target_ns.load(std::memory_order_relaxed) : 0;
|
||||
|
||||
std::vector<s32> ids;
|
||||
ids.reserve(threads.size());
|
||||
for (const pid_t tid : threads) {
|
||||
ids.push_back(static_cast<s32>(tid));
|
||||
}
|
||||
|
||||
AHintSession* handle = api.create_session(api.manager, ids.data(), ids.size(), target);
|
||||
if (handle == nullptr && target == 0) {
|
||||
handle = api.create_session(api.manager, ids.data(), ids.size(), DEFAULT_TARGET.count());
|
||||
}
|
||||
if (handle == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (session == Session::Background && api.set_power_efficiency != nullptr) {
|
||||
api.set_power_efficiency(handle, true);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
bool SyncLocked(Session session, SessionState& state) {
|
||||
if (state.threads.empty()) {
|
||||
CloseLocked(state);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Api& api = Resolve();
|
||||
if (state.handle != nullptr && api.set_threads != nullptr) {
|
||||
std::vector<pid_t> ids = state.threads;
|
||||
if (api.set_threads(state.handle, ids.data(), ids.size()) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AHintSession* const replacement = CreateSessionFor(session, state.threads);
|
||||
if (replacement == nullptr) {
|
||||
if (state.handle == nullptr) {
|
||||
state.unsupported = true;
|
||||
}
|
||||
LOG_WARNING(Common, "Could not open a performance hint session for {} threads, falling back",
|
||||
state.threads.size());
|
||||
return false;
|
||||
}
|
||||
CloseLocked(state);
|
||||
state.handle = replacement;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
bool IsSessionSupported(Session session) {
|
||||
const Api& api = Resolve();
|
||||
if (!api.usable) {
|
||||
return false;
|
||||
}
|
||||
if (session == Session::Background && !IsBackgroundUsable(api)) {
|
||||
return false;
|
||||
}
|
||||
std::scoped_lock lock{g_mutex};
|
||||
return !StateOf(session).unsupported;
|
||||
}
|
||||
|
||||
bool AddCurrentThread(Session session) {
|
||||
if (!IsSessionSupported(session)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pid_t tid = gettid();
|
||||
std::scoped_lock lock{g_mutex};
|
||||
|
||||
for (size_t i = 0; i < g_sessions.size(); ++i) {
|
||||
SessionState& state = g_sessions[i];
|
||||
if (static_cast<size_t>(session) == i) {
|
||||
continue;
|
||||
}
|
||||
const auto it = std::find(state.threads.begin(), state.threads.end(), tid);
|
||||
if (it != state.threads.end()) {
|
||||
state.threads.erase(it);
|
||||
SyncLocked(static_cast<Session>(i), state);
|
||||
}
|
||||
}
|
||||
|
||||
SessionState& state = StateOf(session);
|
||||
const bool added =
|
||||
std::find(state.threads.begin(), state.threads.end(), tid) == state.threads.end();
|
||||
if (added) {
|
||||
state.threads.push_back(tid);
|
||||
}
|
||||
if (!SyncLocked(session, state)) {
|
||||
if (added) {
|
||||
std::erase(state.threads, tid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveCurrentThread() {
|
||||
if (!Resolve().usable) {
|
||||
return;
|
||||
}
|
||||
const pid_t tid = gettid();
|
||||
std::scoped_lock lock{g_mutex};
|
||||
for (size_t i = 0; i < g_sessions.size(); ++i) {
|
||||
SessionState& state = g_sessions[i];
|
||||
if (std::erase(state.threads, tid) != 0) {
|
||||
SyncLocked(static_cast<Session>(i), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetTargetWorkDuration(std::chrono::nanoseconds target) {
|
||||
const Api& api = Resolve();
|
||||
if (!api.usable || target.count() <= 0) {
|
||||
return;
|
||||
}
|
||||
if (g_target_ns.exchange(target.count(), std::memory_order_relaxed) == target.count()) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock{g_mutex};
|
||||
SessionState& state = StateOf(Session::Render);
|
||||
if (state.handle != nullptr) {
|
||||
api.update_target(state.handle, target.count());
|
||||
}
|
||||
}
|
||||
|
||||
void ReportFrameInterval() {
|
||||
const Api& api = Resolve();
|
||||
if (!api.usable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto previous = t_last_frame;
|
||||
t_last_frame = now;
|
||||
if (previous.time_since_epoch().count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
s64 actual = std::chrono::duration_cast<std::chrono::nanoseconds>(now - previous).count();
|
||||
if (actual <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const s64 ceiling = g_target_ns.load(std::memory_order_relaxed) * MAX_REPORTED_TARGETS;
|
||||
actual = (std::min)(actual, ceiling);
|
||||
|
||||
std::scoped_lock lock{g_mutex};
|
||||
SessionState& state = StateOf(Session::Render);
|
||||
if (state.handle != nullptr) {
|
||||
api.report_actual(state.handle, actual);
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
if (!Resolve().usable) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock{g_mutex};
|
||||
for (SessionState& state : g_sessions) {
|
||||
CloseLocked(state);
|
||||
state.threads.clear();
|
||||
state.unsupported = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Common::ADPF
|
||||
|
||||
#else
|
||||
|
||||
namespace Common::ADPF {
|
||||
|
||||
bool IsSessionSupported(Session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AddCurrentThread(Session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoveCurrentThread() {}
|
||||
|
||||
void SetTargetWorkDuration(std::chrono::nanoseconds) {}
|
||||
|
||||
void ReportFrameInterval() {}
|
||||
|
||||
void Shutdown() {}
|
||||
|
||||
} // namespace Common::ADPF
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace Common::ADPF {
|
||||
|
||||
enum class Session {
|
||||
Render,
|
||||
Background,
|
||||
};
|
||||
|
||||
bool IsSessionSupported(Session session);
|
||||
|
||||
bool AddCurrentThread(Session session);
|
||||
void RemoveCurrentThread();
|
||||
|
||||
void SetTargetWorkDuration(std::chrono::nanoseconds target);
|
||||
|
||||
void ReportFrameInterval();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
} // namespace Common::ADPF
|
||||
@@ -20,6 +20,7 @@
|
||||
#define KEYS_DIR "keys"
|
||||
#define LOAD_DIR "load"
|
||||
#define LOG_DIR "log"
|
||||
#define LOSSLESS_DIR "lossless"
|
||||
#define NAND_DIR "nand"
|
||||
#define PLAY_TIME_DIR "play_time"
|
||||
#define SCREENSHOTS_DIR "screenshots"
|
||||
@@ -37,3 +38,5 @@
|
||||
|
||||
// yuzu-specific files
|
||||
#define LOG_FILE "eden_log.txt"
|
||||
#define LOSSLESS_DLL_FILE "Lossless.dll"
|
||||
#define LOSSLESS_CACHE_FILE "lsfg_spirv.cache"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user