mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-29 09:58:05 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b60cbf8023 | |||
| 54cd5fb8eb | |||
| 119291dc77 | |||
| f7dbff2157 | |||
| b859d7fdf4 | |||
| f635827fa6 | |||
| 243453c172 | |||
| 39158b67a7 | |||
| 50cb8fd1c9 | |||
| faaf1bac64 | |||
| 0295dc5fff | |||
| 60a474b8df | |||
| d9336ce6ce | |||
| 4eb8dd1458 | |||
| 4a3cc9a3c2 | |||
| 86ba79b1ba | |||
| b610b03d29 | |||
| 421e0b834c | |||
| 55acf5d260 | |||
| 3e07b466eb | |||
| 5b86242313 | |||
| d24e79c991 | |||
| df05d3de23 | |||
| c249ff462b | |||
| 056d11027c | |||
| 61ffb309a3 | |||
| 65a3cfd2be | |||
| 5c54abf353 | |||
| 0465292a81 | |||
| a41a98028a | |||
| 265c27f391 | |||
| fb2202d69c | |||
| 2000fdfb7b | |||
| dc95cd09ee | |||
| e7a931d06b |
+6
-4
@@ -81,6 +81,9 @@ cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSV
|
|||||||
option(ENABLE_DEBUG_TOOLS "Enable debugging tools (maxwell disassembler, SPIRV translator, etc)" OFF)
|
option(ENABLE_DEBUG_TOOLS "Enable debugging tools (maxwell disassembler, SPIRV translator, etc)" OFF)
|
||||||
option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
|
option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
|
||||||
|
|
||||||
|
# Lossless Scaling frame generation. Only Android.
|
||||||
|
cmake_dependent_option(ENABLE_LSFG "Enable Lossless Scaling frame generation" ON "ANDROID" OFF)
|
||||||
|
|
||||||
# non-linux bundled qt are static
|
# non-linux bundled qt are static
|
||||||
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
||||||
set(YUZU_STATIC_BUILD ON)
|
set(YUZU_STATIC_BUILD ON)
|
||||||
@@ -169,8 +172,6 @@ if (CXX_CLANG_CL)
|
|||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat-pedantic>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat-pedantic>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-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>)
|
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
|
||||||
# REQUIRED CPU features IN Windows-amd64
|
# REQUIRED CPU features IN Windows-amd64
|
||||||
if (ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86_64)
|
||||||
@@ -339,11 +340,12 @@ if (CXX_GCC OR CXX_CLANG)
|
|||||||
endif()
|
endif()
|
||||||
elseif(ARCHITECTURE_arm64)
|
elseif(ARCHITECTURE_arm64)
|
||||||
# See https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
|
# 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(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, optimized, armv9, native")
|
||||||
set(mtune generic)
|
set(mtune generic)
|
||||||
|
|
||||||
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
|
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
|
||||||
set(march armv8-a)
|
set(march armv8-a)
|
||||||
|
elseif (${YUZU_BUILD_PRESET} STREQUAL "optimized")
|
||||||
|
set(march armv8.2-a+lse+rcpc)
|
||||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
||||||
set(march armv9-a)
|
set(march armv9-a)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<h4 align="center"><b>Eden</b> is a free and opensource (FOSS) Switch 1 emulator, derived from Yuzu and Sudachi - started by developer Camille LaVey.
|
<h4 align="center"><b>Eden</b> is a free and opensource (FOSS) Switch 1 emulator started by developer Camille LaVey.
|
||||||
It's written in C++ with portability in mind, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
|
<br>
|
||||||
|
Written in C++, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -73,3 +74,17 @@ Save us some bandwidth! We have [mirrors available](./docs/user/ThirdParty.md#mi
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file.
|
Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file.
|
||||||
|
|
||||||
|
## Special thanks
|
||||||
|
|
||||||
|
Super special thanks to Cloudflare for preventing the git server from blowing up.
|
||||||
|
|
||||||
|
- Yuzu
|
||||||
|
- Ryujinx
|
||||||
|
- Sudachi
|
||||||
|
- Citron
|
||||||
|
- Torzu
|
||||||
|
- Suyu
|
||||||
|
- Ryubing
|
||||||
|
|
||||||
|
And everyone who continues or had contributed to the project! <3
|
||||||
|
|||||||
Vendored
+2
-2
@@ -3825,12 +3825,12 @@ Would you like to delete the old save data?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
||||||
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
||||||
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>(يتطلب إعادة التشغيل) SDL WGI/XInput تعطيل</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|||||||
Vendored
+49
-48
@@ -429,13 +429,14 @@ Can help reduce stuttering at lower framerates.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
||||||
<source>CPU Clocks</source>
|
<source>CPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>CPU 클럭</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
||||||
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
||||||
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>에뮬레이트된 CPU가 보고하는 클럭 속도를 높여 일부 FPS 제한을 해제합니다.
|
||||||
|
성능이 낮은 CPU의 경우 성능이 저하될 수 있으며, 일부 게임은 제대로 작동하지 않을 수 있습니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
||||||
@@ -856,12 +857,12 @@ Some games require this to render certain effects properly.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
||||||
<source>GPU Clocks</source>
|
<source>GPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>GPU 클럭</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
||||||
<source>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.</source>
|
<source>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.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>게임이 GPU 작업이 실제보다 더 빨리 완료된다고 착각하게 만들어, 스위치의 클럭 속도에 맞추기 위해 해상도와 렌더 거리를 낮추는 작업을 중단하게 합니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
||||||
@@ -2052,19 +2053,19 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
||||||
<source>Normal</source>
|
<source>Normal</source>
|
||||||
<translation type="unfinished"/>
|
<translation>보통</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
||||||
<source>Boost</source>
|
<source>Boost</source>
|
||||||
<translation type="unfinished"/>
|
<translation>부스트</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
||||||
<source>Overclock</source>
|
<source>Overclock</source>
|
||||||
<translation type="unfinished"/>
|
<translation>오버클럭</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
||||||
@@ -2604,7 +2605,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="318"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="318"/>
|
||||||
<source>Arguments String</source>
|
<source>Arguments String</source>
|
||||||
<translation>실행인수</translation>
|
<translation>인수 문자열</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="335"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="335"/>
|
||||||
@@ -3140,7 +3141,7 @@ WARNING: This will overwrite any conflicting saves in the new location!</source>
|
|||||||
이전 위치: %1
|
이전 위치: %1
|
||||||
새 위치: %2
|
새 위치: %2
|
||||||
|
|
||||||
이전 위치의 저장 데이터를 옮기시겠습니까?
|
이전 위치의 저장 데이터를 옮기겠습니까?
|
||||||
경고: 새 위치에 있는 충돌하는 저장 데이터는 덮어쓰여집니다!</translation>
|
경고: 새 위치에 있는 충돌하는 저장 데이터는 덮어쓰여집니다!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
@@ -3824,7 +3825,7 @@ Would you like to delete the old save data?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2726"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2726"/>
|
||||||
<source>Enable direct Pro Controller driver [EXPERIMENTAL]</source>
|
<source>Enable direct Pro Controller driver [EXPERIMENTAL]</source>
|
||||||
<translation>다이렉트 Pro 컨트롤러 드라이버 활성화[실험적] </translation>
|
<translation>다이렉트 Pro 컨트롤러 드라이버 활성화[실험적]</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2733"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2733"/>
|
||||||
@@ -3844,12 +3845,12 @@ Would you like to delete the old save data?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
||||||
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
||||||
<translation type="unfinished"/>
|
<translation>SDL GUIDE 버튼 해킹을 비활성화하는 것을 목표로 합니다: SELECT(-) + START(+) 버튼을 동시에 눌렀을 때 GUIDE(HOME) 이벤트를 인위적으로 발생시킵니다. Win 관련 트리거/진동 기능 등에 영향을 줄 수 있습니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
||||||
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>SDL WGI/XInput 비활성화(재시작 필요)</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -4277,7 +4278,7 @@ To invert the axes, first move your joystick vertically, and then horizontally.<
|
|||||||
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="753"/>
|
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="753"/>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1098"/>
|
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1098"/>
|
||||||
<source>Pro Controller</source>
|
<source>Pro Controller</source>
|
||||||
<translation>프로 컨트롤러</translation>
|
<translation>Pro 컨트롤러</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1102"/>
|
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1102"/>
|
||||||
@@ -4378,7 +4379,7 @@ To invert the axes, first move your joystick vertically, and then horizontally.<
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1587"/>
|
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1587"/>
|
||||||
<source>The given profile name is not valid!</source>
|
<source>The given profile name is not valid!</source>
|
||||||
<translation>해당 프로필 이름은 사용할 수 없습니다!</translation>
|
<translation>지정된 프로필 이름이 유효하지 않습니다!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1595"/>
|
<location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1595"/>
|
||||||
@@ -4476,7 +4477,7 @@ To invert the axes, first move your joystick vertically, and then horizontally.<
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="91"/>
|
<location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="91"/>
|
||||||
<source>You may use any Cemuhook compatible UDP input source to provide motion and touch input.</source>
|
<source>You may use any Cemuhook compatible UDP input source to provide motion and touch input.</source>
|
||||||
<translation>Cemuhook 호환이 가능한 모든 UDP 인풋 장치를 모션 컨트롤과 터치 입력용으로 사용할 수 있습니다.</translation>
|
<translation>모션 및 터치 입력을 제공하기 위해 Cemuhook과 호환되는 모든 UDP 입력 소스를 사용할 수 있습니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="134"/>
|
<location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="134"/>
|
||||||
@@ -4562,7 +4563,7 @@ To invert the axes, first move your joystick vertically, and then horizontally.<
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="250"/>
|
<location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="250"/>
|
||||||
<source>Successfully received data from the server.</source>
|
<source>Successfully received data from the server.</source>
|
||||||
<translation>서버에서 성공적으로 데이터를 받았습니다.</translation>
|
<translation>서버에서 데이터를 성공적으로 수신했습니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="252"/>
|
<location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="252"/>
|
||||||
@@ -4972,7 +4973,7 @@ Once deleted, these can NOT be recovered. Are you 100% sure you want to delete t
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="138"/>
|
<location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="138"/>
|
||||||
<source>Profile management is available only when game is not running.</source>
|
<source>Profile management is available only when game is not running.</source>
|
||||||
<translation>프로필 관리자는 게임이 작동 중이지 않을 때만 사용 가능합니다.</translation>
|
<translation>프로필 관리는 게임이 실행 중이 아닐 때만 가능합니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="58"/>
|
<location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="58"/>
|
||||||
@@ -5255,7 +5256,7 @@ UUID: %2</translation>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_tas.ui" line="77"/>
|
<location filename="../../src/yuzu/configuration/configure_tas.ui" line="77"/>
|
||||||
<source>Pause execution during loads</source>
|
<source>Pause execution during loads</source>
|
||||||
<translation>불러오는 중 실행 일시 중지</translation>
|
<translation>불러오는 동안 실행 일시 중지</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_tas.ui" line="84"/>
|
<location filename="../../src/yuzu/configuration/configure_tas.ui" line="84"/>
|
||||||
@@ -5365,7 +5366,7 @@ Drag points to change position, or double-click table cells to edit values.</sou
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="206"/>
|
<location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="206"/>
|
||||||
<source>Delete profile %1?</source>
|
<source>Delete profile %1?</source>
|
||||||
<translation>%1 프로필을 삭제하시겠습니까?</translation>
|
<translation>%1 프로필을 삭제하겠습니까?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="219"/>
|
<location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="219"/>
|
||||||
@@ -5452,7 +5453,7 @@ Drag points to change position, or double-click table cells to edit values.</sou
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="44"/>
|
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="44"/>
|
||||||
<source>Filetype</source>
|
<source>Filetype</source>
|
||||||
<translation>파일타입</translation>
|
<translation>파일 형식</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="45"/>
|
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="45"/>
|
||||||
@@ -5580,7 +5581,7 @@ Drag points to change position, or double-click table cells to edit values.</sou
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="228"/>
|
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="228"/>
|
||||||
<source>English</source>
|
<source>English</source>
|
||||||
<translation>영어</translation>
|
<translation>English</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="311"/>
|
<location filename="../../src/yuzu/configuration/configure_ui.cpp" line="311"/>
|
||||||
@@ -5714,7 +5715,7 @@ Drag points to change position, or double-click table cells to edit values.</sou
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_web.ui" line="148"/>
|
<location filename="../../src/yuzu/configuration/configure_web.ui" line="148"/>
|
||||||
<source>Show Current Game in your Discord Status</source>
|
<source>Show Current Game in your Discord Status</source>
|
||||||
<translation>디스코드에 실행중인 게임을 나타낼 수 있습니다.</translation>
|
<translation>Discord 상태에 현재 게임 표시</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_web.cpp" line="110"/>
|
<location filename="../../src/yuzu/configuration/configure_web.cpp" line="110"/>
|
||||||
@@ -6082,7 +6083,7 @@ Please go to Configure -> System -> Network and make a selection.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/game/game_list.cpp" line="451"/>
|
<location filename="../../src/yuzu/game/game_list.cpp" line="451"/>
|
||||||
<source>Favorite</source>
|
<source>Favorite</source>
|
||||||
<translation>선호하는 게임</translation>
|
<translation>즐겨찾는 게임</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/game/game_list.cpp" line="453"/>
|
<location filename="../../src/yuzu/game/game_list.cpp" line="453"/>
|
||||||
@@ -6157,7 +6158,7 @@ Please go to Configure -> System -> Network and make a selection.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/game/game_list.cpp" line="472"/>
|
<location filename="../../src/yuzu/game/game_list.cpp" line="472"/>
|
||||||
<source>Remove All Installed Contents</source>
|
<source>Remove All Installed Contents</source>
|
||||||
<translation>설치된 모든 컨텐츠 제거</translation>
|
<translation>설치된 모든 콘텐츠 제거</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/game/game_list.cpp" line="473"/>
|
<location filename="../../src/yuzu/game/game_list.cpp" line="473"/>
|
||||||
@@ -6296,7 +6297,7 @@ Please go to Configure -> System -> Network and make a selection.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/game_list/game_list_p.h" line="201"/>
|
<location filename="../../src/qt_common/game_list/game_list_p.h" line="201"/>
|
||||||
<source>The game crashes when attempting to startup.</source>
|
<source>The game crashes when attempting to startup.</source>
|
||||||
<translation>게임 실행 시 크래시가 일어납니다.</translation>
|
<translation>게임 실행 시 게임이 튕깁니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/game_list/game_list_p.h" line="202"/>
|
<location filename="../../src/qt_common/game_list/game_list_p.h" line="202"/>
|
||||||
@@ -6538,7 +6539,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="44"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="44"/>
|
||||||
<source>Exit Fullscreen</source>
|
<source>Exit Fullscreen</source>
|
||||||
<translation>전체화면 종료</translation>
|
<translation>전체 화면 종료</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="45"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="45"/>
|
||||||
@@ -6548,7 +6549,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="46"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="46"/>
|
||||||
<source>Fullscreen</source>
|
<source>Fullscreen</source>
|
||||||
<translation>전체화면</translation>
|
<translation>전체 화면</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="47"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="47"/>
|
||||||
@@ -6608,12 +6609,12 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="58"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="58"/>
|
||||||
<source>TAS Start/Stop</source>
|
<source>TAS Start/Stop</source>
|
||||||
<translation>TAS 시작/멈춤</translation>
|
<translation>TAS 시작/중지</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="59"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="59"/>
|
||||||
<source>Toggle Filter Bar</source>
|
<source>Toggle Filter Bar</source>
|
||||||
<translation>필터 창 토글</translation>
|
<translation>필터 바 토글</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/uisettings.cpp" line="60"/>
|
<location filename="../../src/qt_common/config/uisettings.cpp" line="60"/>
|
||||||
@@ -6936,7 +6937,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="259"/>
|
<location filename="../../src/yuzu/main.ui" line="259"/>
|
||||||
<source>L&oad File...</source>
|
<source>L&oad File...</source>
|
||||||
<translation>파일 불러오기...(&L)</translation>
|
<translation>파일 불러오기...(&o)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="264"/>
|
<location filename="../../src/yuzu/main.ui" line="264"/>
|
||||||
@@ -6946,7 +6947,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="269"/>
|
<location filename="../../src/yuzu/main.ui" line="269"/>
|
||||||
<source>E&xit</source>
|
<source>E&xit</source>
|
||||||
<translation>종료(&X)</translation>
|
<translation>종료(&x)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="277"/>
|
<location filename="../../src/yuzu/main.ui" line="277"/>
|
||||||
@@ -6992,17 +6993,17 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="330"/>
|
<location filename="../../src/yuzu/main.ui" line="330"/>
|
||||||
<source>Show &Filter Bar</source>
|
<source>Show &Filter Bar</source>
|
||||||
<translation>필터링 바 표시(&F)</translation>
|
<translation>필터 바 표시(&F)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="338"/>
|
<location filename="../../src/yuzu/main.ui" line="338"/>
|
||||||
<source>Show &Status Bar</source>
|
<source>Show &Status Bar</source>
|
||||||
<translation>상태 표시줄 보이기(&S)</translation>
|
<translation>상태 표시줄 표시(&S)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="341"/>
|
<location filename="../../src/yuzu/main.ui" line="341"/>
|
||||||
<source>Show Status Bar</source>
|
<source>Show Status Bar</source>
|
||||||
<translation>상태 표시줄 보이기</translation>
|
<translation>상태 표시줄 표시</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="349"/>
|
<location filename="../../src/yuzu/main.ui" line="349"/>
|
||||||
@@ -7017,7 +7018,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="365"/>
|
<location filename="../../src/yuzu/main.ui" line="365"/>
|
||||||
<source>&Leave Room</source>
|
<source>&Leave Room</source>
|
||||||
<translation>방에서 나가기(&L)</translation>
|
<translation>방 나가기(&L)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="370"/>
|
<location filename="../../src/yuzu/main.ui" line="370"/>
|
||||||
@@ -7047,7 +7048,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="407"/>
|
<location filename="../../src/yuzu/main.ui" line="407"/>
|
||||||
<source>Open &Mods Page</source>
|
<source>Open &Mods Page</source>
|
||||||
<translation>게임 모드 페이지 열기(&M)</translation>
|
<translation>모드 페이지 열기(&M)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="412"/>
|
<location filename="../../src/yuzu/main.ui" line="412"/>
|
||||||
@@ -7062,7 +7063,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="425"/>
|
<location filename="../../src/yuzu/main.ui" line="425"/>
|
||||||
<source>&Capture Screenshot</source>
|
<source>&Capture Screenshot</source>
|
||||||
<translation>스크린샷 찍기(&C)</translation>
|
<translation>스크린샷 캡처(&C)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="430"/>
|
<location filename="../../src/yuzu/main.ui" line="430"/>
|
||||||
@@ -7102,7 +7103,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="471"/>
|
<location filename="../../src/yuzu/main.ui" line="471"/>
|
||||||
<source>Configure C&urrent Game...</source>
|
<source>Configure C&urrent Game...</source>
|
||||||
<translation>실행 중인 게임 맞춤 구성...(&u)</translation>
|
<translation>현재 게임 구성...(&u)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="482"/>
|
<location filename="../../src/yuzu/main.ui" line="482"/>
|
||||||
@@ -7262,7 +7263,7 @@ Debug Message: </source>
|
|||||||
<location filename="../../src/yuzu/main_window.cpp" line="493"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="493"/>
|
||||||
<source>Running a game</source>
|
<source>Running a game</source>
|
||||||
<extracomment>TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the computer from sleeping</extracomment>
|
<extracomment>TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the computer from sleeping</extracomment>
|
||||||
<translation>게임 실행중</translation>
|
<translation>게임 실행 중</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="827"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="827"/>
|
||||||
@@ -7295,7 +7296,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="1000"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="1000"/>
|
||||||
<source>Current emulation speed. Values higher or lower than 100% indicate emulation is running faster or slower than a Switch.</source>
|
<source>Current emulation speed. Values higher or lower than 100% indicate emulation is running faster or slower than a Switch.</source>
|
||||||
<translation>현재 에뮬레이션 속도입니다. 100%보다 높거나 낮은 값은 에뮬레이션이 닌텐도 스위치보다 빠르거나 느리게 실행되고 있음을 나타냅니다.</translation>
|
<translation>현재 에뮬레이션 속도입니다. 100%보다 높거나 낮은 값은 에뮬레이션이 스위치보다 빠르거나 느리게 실행되고 있음을 나타냅니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="1003"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="1003"/>
|
||||||
@@ -7759,7 +7760,7 @@ Please, only use this feature to install updates and DLC.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="3549"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="3549"/>
|
||||||
<source>Handheld controller can't be used on docked mode. Pro controller will be selected.</source>
|
<source>Handheld controller can't be used on docked mode. Pro controller will be selected.</source>
|
||||||
<translation>휴대 모드 컨트롤러는 독 모드에서 사용할 수 없습니다. 프로 컨트롤러로 선택됩니다.</translation>
|
<translation>휴대 모드 컨트롤러는 독 모드에서 사용할 수 없습니다. Pro 컨트롤러로 선택됩니다.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="3700"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="3700"/>
|
||||||
@@ -8320,8 +8321,8 @@ Debug Message: </source>
|
|||||||
<location filename="../../src/yuzu/multiplayer/message.cpp" line="69"/>
|
<location filename="../../src/yuzu/multiplayer/message.cpp" line="69"/>
|
||||||
<source>Joining a room when the game is already running is discouraged and can cause the room feature not to work correctly.
|
<source>Joining a room when the game is already running is discouraged and can cause the room feature not to work correctly.
|
||||||
Proceed anyway?</source>
|
Proceed anyway?</source>
|
||||||
<translation>게임이 이미 실행 중일 때 방에 참여하는 것은 권장되지 않으며 방 기능이 제대로 작동하지 않을 수 있습니다.
|
<translation>게임이 이미 실행 중일 때 방에 참여하는 것은 권장되지 않으며, 방 기능이 제대로 작동하지 않을 수 있습니다.
|
||||||
그래도 진행하시겠습니까?</translation>
|
그래도 진행하겠습니까?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/multiplayer/message.cpp" line="75"/>
|
<location filename="../../src/yuzu/multiplayer/message.cpp" line="75"/>
|
||||||
@@ -9781,7 +9782,7 @@ Would you like to manually select a portable folder to use?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/util/game.cpp" line="391"/>
|
<location filename="../../src/qt_common/util/game.cpp" line="391"/>
|
||||||
<source>This will create a shortcut to the current AppImage. This may not work well if you update. Continue?</source>
|
<source>This will create a shortcut to the current AppImage. This may not work well if you update. Continue?</source>
|
||||||
<translation>이렇게 하면 현재 앱 이미지에 대한 바로가기가 생성됩니다. 업데이트 후에는 제대로 작동하지 않을 수 있습니다. 계속하시겠습니까?</translation>
|
<translation>이렇게 하면 현재 앱 이미지에 대한 바로가기가 생성됩니다. 업데이트 후에는 제대로 작동하지 않을 수 있습니다. 계속하겠습니까?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/util/game.cpp" line="397"/>
|
<location filename="../../src/qt_common/util/game.cpp" line="397"/>
|
||||||
@@ -10390,7 +10391,7 @@ Please try again or contact the developer of the software.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="203"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="203"/>
|
||||||
<source>Who is using Nintendo eShop?</source>
|
<source>Who is using Nintendo eShop?</source>
|
||||||
<translation>누가 닌텐도 e숍을 사용하고 있습니까?</translation>
|
<translation>누가 닌텐도 e숍을 사용하고 있나요?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="206"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="206"/>
|
||||||
@@ -10410,12 +10411,12 @@ Please try again or contact the developer of the software.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="215"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="215"/>
|
||||||
<source>Change settings for which user?</source>
|
<source>Change settings for which user?</source>
|
||||||
<translation>어떤 유저의 설정을 변경하겠습니까?</translation>
|
<translation>어떤 유저의 설정을 변경할까요?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="218"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="218"/>
|
||||||
<source>Format data for which user?</source>
|
<source>Format data for which user?</source>
|
||||||
<translation>어떤 유저의 데이터를 포맷하겠습니까?</translation>
|
<translation>어떤 유저의 데이터를 포맷할까요?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="221"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="221"/>
|
||||||
@@ -10425,7 +10426,7 @@ Please try again or contact the developer of the software.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="224"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="224"/>
|
||||||
<source>Send save data for which user?</source>
|
<source>Send save data for which user?</source>
|
||||||
<translation>어떤 유저의 저장 데이터를 보내겠습니까?</translation>
|
<translation>어떤 유저의 저장 데이터를 보낼까요?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="228"/>
|
<location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="228"/>
|
||||||
|
|||||||
Vendored
+39
-30
@@ -429,13 +429,14 @@ Can help reduce stuttering at lower framerates.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
||||||
<source>CPU Clocks</source>
|
<source>CPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Частоты CPU</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
||||||
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
||||||
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Увеличивает частоту, которую сообщает эмулируемый CPU, из-за чего могут быть убраны некоторые ограничители FPS.
|
||||||
|
Слабые процессоры могут потерять производительность, а некоторые игры могут работать неправильно.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
||||||
@@ -789,7 +790,7 @@ Safe to set at 16x on most GPUs.</source>
|
|||||||
<source>Controls the GPU emulation mode.
|
<source>Controls the GPU emulation mode.
|
||||||
Most games render fine with Fast, but Accurate is still required for some.
|
Most games render fine with Fast, but Accurate is still required for some.
|
||||||
Particles tend to only render correctly with Accurate mode.</source>
|
Particles tend to only render correctly with Accurate mode.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Управляет режимом эмуляции ГПУ. Большинство игр нормально отображаются в режиме Быстрый, но для некоторых требуется режим Точный. Частицы обычно корректно отображаются только в режиме Точный.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="222"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="222"/>
|
||||||
@@ -801,12 +802,14 @@ Particles tend to only render correctly with Accurate mode.</source>
|
|||||||
<source>Controls the DMA read mode.
|
<source>Controls the DMA read mode.
|
||||||
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
||||||
Default follows the GPU Accuracy setting.</source>
|
Default follows the GPU Accuracy setting.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Управляет режимом чтения DMA.
|
||||||
|
Небезопасный быстрее, а Безопасный стабильнее и может исправить проблемы в некоторых играх.
|
||||||
|
По умолчанию соответствует настройке точности ГПУ.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="224"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="224"/>
|
||||||
<source>GPU Fence Behavior:</source>
|
<source>GPU Fence Behavior:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Поведение барьеров ГПУ:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
||||||
@@ -816,18 +819,24 @@ Balanced offers better compatibility and may fix issues in some games.
|
|||||||
Accurate further improves compatibility at the cost of some performance.
|
Accurate further improves compatibility at the cost of some performance.
|
||||||
Strict is the slowest option, but can fix issues that require stricter synchronization.
|
Strict is the slowest option, but can fix issues that require stricter synchronization.
|
||||||
Default follows the GPU Accuracy setting.</source>
|
Default follows the GPU Accuracy setting.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Управляет поведением синхронизации через барьеры ГПУ.
|
||||||
|
Мгновенный — самый быстрый вариант, но может вызывать некоторые проблемы.
|
||||||
|
Сбалансированный обеспечивает лучшую совместимость и может исправлять проблемы в некоторых играх.
|
||||||
|
Точный ещё больше повышает совместимость ценой некоторого снижения производительности.
|
||||||
|
Строгий — самый медленный вариант, но может исправлять проблемы, требующие более строгой синхронизации.
|
||||||
|
По умолчанию соответствует настройке точности ГПУ.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="226"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="226"/>
|
||||||
<source>Enable GPU buffer readback</source>
|
<source>Enable GPU buffer readback</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Включить обратное чтение буфера ГПУ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
||||||
<source>Preserves GPU-modified data by reading it back before uploading.
|
<source>Preserves GPU-modified data by reading it back before uploading.
|
||||||
Some games require this to render certain effects properly.</source>
|
Some games require this to render certain effects properly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Сохраняет измененные ГПУ данные путем чтения их обратно перед выгрузками.
|
||||||
|
Некоторые игры требуют этого, чтобы рендерить определенные эффекты правильно.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="228"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="228"/>
|
||||||
@@ -842,12 +851,12 @@ Some games require this to render certain effects properly.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
||||||
<source>GPU Clocks</source>
|
<source>GPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Частоты GPU</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
||||||
<source>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.</source>
|
<source>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.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Заставляет игру думать, что GPU завершает свою работу быстрее, чем на самом деле, чтобы она перестала подстраиваться под частоты Switch, понижать разрешение и дальность прорисовки.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
||||||
@@ -1343,7 +1352,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="438"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="438"/>
|
||||||
<source>Immediate</source>
|
<source>Immediate</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Мгновенный</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="439"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="439"/>
|
||||||
@@ -1353,7 +1362,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="441"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="441"/>
|
||||||
<source>Strict</source>
|
<source>Strict</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Строгий</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="448"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="448"/>
|
||||||
@@ -2038,19 +2047,19 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
||||||
<source>Normal</source>
|
<source>Normal</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Нормальная</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
||||||
<source>Boost</source>
|
<source>Boost</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ускоренная</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
||||||
<source>Overclock</source>
|
<source>Overclock</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Разгон</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
||||||
@@ -2530,37 +2539,37 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="224"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="224"/>
|
||||||
<source>GPU Logging/Level</source>
|
<source>GPU Logging/Level</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Уровень ведения журнала ГПУ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="231"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="231"/>
|
||||||
<source>Detail level for GPU logs. Off disables logging entirely.</source>
|
<source>Detail level for GPU logs. Off disables logging entirely.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Уровень подробностей для журнала GPU.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="235"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="235"/>
|
||||||
<source>Off</source>
|
<source>Off</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Выкл.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="240"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="240"/>
|
||||||
<source>Errors</source>
|
<source>Errors</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ошибки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="245"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="245"/>
|
||||||
<source>Standard</source>
|
<source>Standard</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Стандартный</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="250"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="250"/>
|
||||||
<source>Verbose</source>
|
<source>Verbose</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Подробный (Verbose)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="255"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="255"/>
|
||||||
<source>All</source>
|
<source>All</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Все</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="266"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="266"/>
|
||||||
@@ -2630,12 +2639,12 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="377"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="377"/>
|
||||||
<source>When checked, it will dump original Maxwell guest shader bytecode (the input to the recompiler) as .ash files under DumpDir/shaders/. Useful for inspection with nvdisasm.</source>
|
<source>When checked, it will dump original Maxwell guest shader bytecode (the input to the recompiler) as .ash files under DumpDir/shaders/. Useful for inspection with nvdisasm.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Если включено, будет дампать оригинальный байткод Maxwell guest shader (Входные данные для рекомпилятора) как .ash файлы в папку DumpDir/shaders/. Полезно для анализа с помощью nvdisasm.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="380"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="380"/>
|
||||||
<source>Dump Guest (Maxwell) Shaders</source>
|
<source>Dump Guest (Maxwell) Shaders</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Дампать шейдеры Guest (Maxwell)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="387"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="387"/>
|
||||||
@@ -2695,12 +2704,12 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="469"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="469"/>
|
||||||
<source>When checked, it will dump the recompiler's output SPIR-V binaries (.spv) under LogDir/shaders/. Inspect via SPIRV-Tools (spirv-dis / spirv-cross / spirv-val) or RenderDoc.</source>
|
<source>When checked, it will dump the recompiler's output SPIR-V binaries (.spv) under LogDir/shaders/. Inspect via SPIRV-Tools (spirv-dis / spirv-cross / spirv-val) or RenderDoc.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Если включено, будет дампать выходные SPIR-V binaries (.spv) рекомпилятора в папку LogDir/shaders/. Исследуйте с помощью SPIRV-Tools (spirv-dis / spirv-cross / spirv-val) или RenderDoc.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="472"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="472"/>
|
||||||
<source>Dump SPIR-V Shaders</source>
|
<source>Dump SPIR-V Shaders</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Дампать шейдеры SPIR-V</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="482"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="482"/>
|
||||||
@@ -2760,7 +2769,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="632"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="632"/>
|
||||||
<source>Debug Knobs:</source>
|
<source>Debug Knobs:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Параметры отладки: </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="645"/>
|
<location filename="../../src/yuzu/configuration/configure_debug.ui" line="645"/>
|
||||||
@@ -3830,12 +3839,12 @@ Would you like to delete the old save data?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
||||||
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Направлер на отключение хака кнопки SDL GUIDE: симулированное событие GUIDE(HOME), когда нажаты SELECT(MINUS) + START(PLUS). Может влияет на вещи Windows: триггеры, вибрация и т. д.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
||||||
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Отключить SDL WGI/XInput (Требуется перезагрзка)</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -7214,7 +7223,7 @@ Debug Message: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main.ui" line="618"/>
|
<location filename="../../src/yuzu/main.ui" line="618"/>
|
||||||
<source>&Carousel View</source>
|
<source>&Carousel View</source>
|
||||||
<translation type="unfinished"/>
|
<translation>&В Виде Карусели</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/main_window.cpp" line="326"/>
|
<location filename="../../src/yuzu/main_window.cpp" line="326"/>
|
||||||
|
|||||||
Vendored
+26
-16
@@ -429,13 +429,14 @@ Can help reduce stuttering at lower framerates.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="95"/>
|
||||||
<source>CPU Clocks</source>
|
<source>CPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>CPU 时钟频率</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="96"/>
|
||||||
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
<source>Raises the clock the emulated CPU reports, which removes some FPS limiters.
|
||||||
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
Weaker CPUs may see reduced performance, and certain games may behave improperly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>提高模拟 CPU 报告的时钟频率,从而消除部分帧率限制。
|
||||||
|
性能较弱的 CPU 可能会出现可见性能下降,甚至会导致某些游戏运行异常。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="100"/>
|
||||||
@@ -794,7 +795,8 @@ Safe to set at 16x on most GPUs.</source>
|
|||||||
<source>Controls the GPU emulation mode.
|
<source>Controls the GPU emulation mode.
|
||||||
Most games render fine with Fast, but Accurate is still required for some.
|
Most games render fine with Fast, but Accurate is still required for some.
|
||||||
Particles tend to only render correctly with Accurate mode.</source>
|
Particles tend to only render correctly with Accurate mode.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>控制 GPU 模拟模式。
|
||||||
|
大多数游戏在“快速”模式下渲染效果良好,但有些游戏仍需使用“精确”模式。而粒子效果通常只有在“精确”模式下才能正确渲染。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="222"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="222"/>
|
||||||
@@ -806,12 +808,14 @@ Particles tend to only render correctly with Accurate mode.</source>
|
|||||||
<source>Controls the DMA read mode.
|
<source>Controls the DMA read mode.
|
||||||
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
||||||
Default follows the GPU Accuracy setting.</source>
|
Default follows the GPU Accuracy setting.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>控制 DMA 读取模式。
|
||||||
|
不安全模式速度更快,而安全模式更稳定,并且可以修复某些游戏中的问题。
|
||||||
|
默认使用 GPU 精度设置。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="224"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="224"/>
|
||||||
<source>GPU Fence Behavior:</source>
|
<source>GPU Fence Behavior:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>GPU 围栏行为:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
||||||
@@ -821,7 +825,12 @@ Balanced offers better compatibility and may fix issues in some games.
|
|||||||
Accurate further improves compatibility at the cost of some performance.
|
Accurate further improves compatibility at the cost of some performance.
|
||||||
Strict is the slowest option, but can fix issues that require stricter synchronization.
|
Strict is the slowest option, but can fix issues that require stricter synchronization.
|
||||||
Default follows the GPU Accuracy setting.</source>
|
Default follows the GPU Accuracy setting.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>控制 GPU 围栏同步行为。
|
||||||
|
“即时”是速度最快的选项,但可能会引入一些问题。
|
||||||
|
“均衡”提供了更好的兼容性,可能修复某些游戏中的问题。
|
||||||
|
“精确”在牺牲部分性能的前提下进一步提升兼容性。
|
||||||
|
“严格”是速度最慢的选项,但可以修复那些要求更严格同步的问题。
|
||||||
|
默认遵循 GPU “精确”设定。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="226"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="226"/>
|
||||||
@@ -832,7 +841,8 @@ Default follows the GPU Accuracy setting.</source>
|
|||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
||||||
<source>Preserves GPU-modified data by reading it back before uploading.
|
<source>Preserves GPU-modified data by reading it back before uploading.
|
||||||
Some games require this to render certain effects properly.</source>
|
Some games require this to render certain effects properly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>通过在上传前读取来保留 GPU 修改的数据。
|
||||||
|
某些游戏需要这样才能正确渲染某些效果。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="228"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="228"/>
|
||||||
@@ -847,12 +857,12 @@ Some games require this to render certain effects properly.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="230"/>
|
||||||
<source>GPU Clocks</source>
|
<source>GPU Clocks</source>
|
||||||
<translation type="unfinished"/>
|
<translation>GPU 时钟频率</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="231"/>
|
||||||
<source>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.</source>
|
<source>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.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>通过让游戏误以为 GPU 的处理速度比实际更快,以避免游戏为了适应 Switch 的时钟频率而降低分辨率和渲染距离。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="233"/>
|
||||||
@@ -1346,7 +1356,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="438"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="438"/>
|
||||||
<source>Immediate</source>
|
<source>Immediate</source>
|
||||||
<translation type="unfinished"/>
|
<translation>即时</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="439"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="439"/>
|
||||||
@@ -1356,7 +1366,7 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="441"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="441"/>
|
||||||
<source>Strict</source>
|
<source>Strict</source>
|
||||||
<translation type="unfinished"/>
|
<translation>严格</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="448"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="448"/>
|
||||||
@@ -2041,19 +2051,19 @@ When a program attempts to open the controller applet, it is immediately closed.
|
|||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="639"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="652"/>
|
||||||
<source>Normal</source>
|
<source>Normal</source>
|
||||||
<translation type="unfinished"/>
|
<translation>正常</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="640"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="653"/>
|
||||||
<source>Boost</source>
|
<source>Boost</source>
|
||||||
<translation type="unfinished"/>
|
<translation>升频</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="641"/>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="654"/>
|
||||||
<source>Overclock</source>
|
<source>Overclock</source>
|
||||||
<translation type="unfinished"/>
|
<translation>超频</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="646"/>
|
||||||
@@ -3821,12 +3831,12 @@ Would you like to delete the old save data?</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2763"/>
|
||||||
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
<source>Aimed to disable SDL GUIDE button hack: synthetic GUIDE(HOME) event when SELECT(MINUS) + START(PLUS) pressed. May impact Win related trigger/rumble/etc stuff</source>
|
||||||
<translation type="unfinished"/>
|
<translation>旨在禁用 SDL GUIDE 按钮作弊:当按下 SELECT(减号) + START(加号) 时,会触发合成的 GUIDE(HOME) 事件。可能影响 Windows 相关的触发/震动等功能</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
<location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2772"/>
|
||||||
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
<source>Disable SDL WGI/XInput (Requires restart)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>禁用 SDL WGI/XInput (需要重启)</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Design Overview
|
||||||
|
|
||||||
|
Modern game consoles require heavy power to be emulated appropriatedly. This is why the emulator uses an approach known as HLE (High-Level-Emulation), in a nuthsell: Instead of accurately emulating every subsystem that forms part of a component, emulate the resulting visible I/O interface instead.
|
||||||
|
|
||||||
|
For example, take a disk write, instead of emulating a proper SD card we instead use the C++ standard library for I/O. Additionally we use the abstractions provided by the `fs` service to "lie" to programs about certain SD card properties. Notably this includes making up sizes for the fake SD card, giving "realistic" values or expected outputs for a given card, and so on. And instead of writing to an actual SD card, the emulator simply writes to a file.
|
||||||
|
|
||||||
|
This also means grand part of the emulator consists of just re-implementing firmware but using HLE primitives; for example audio doesn't go to an emulated audio device, but rather gets processed on the fly by a dedicated service and then passed to SDL3/cubeb/etc.
|
||||||
|
|
||||||
|
As such, many of the systems implemented are not 100% accurate to the original software, but they're "good enough" to pass as being so. While we do strive to maintain high compatibility (especially with homebrew), there are realistic limitations to these approaches.
|
||||||
|
|
||||||
|
No formal fuzzing or formal verification has been done on the emulator as a whole, this means there may be hundreds of bugs hiding in each subsystem. As such, output may also not correctly match due to those aforementioned issues.
|
||||||
|
|
||||||
|
## src/android/
|
||||||
|
|
||||||
|
Entire Android frontend, written mostly in Kotlin and generally having asinine hacks (thanks Android) due to the particularly horrific (and particular way) to do things.
|
||||||
|
|
||||||
|
## src/audio_core/
|
||||||
|
|
||||||
|
Handles everything related to audio, this is where most of the filtering and processing occurs (CPU intensive task!).
|
||||||
|
|
||||||
|
## src/common/
|
||||||
|
|
||||||
|
The [common](../src/common) folder contains just your basic pollyfills for whatever missing functionality. We heavily encourage new PRs to make use of one of the dependencies, or the standard C++ library. Minimizing the amount of things we reinvent the wheel for is always a good thing.
|
||||||
|
|
||||||
|
## src/core/
|
||||||
|
|
||||||
|
The [core folder](../src/core) is the main heart of the emulator, while we don't officially support having other frontends out of the box (RetroArch, for example); any prospective developer can reuse this library (compiled as one by CMake) to stitch up their own RetroArch core, for example.
|
||||||
|
|
||||||
|
## src/dynarmic/
|
||||||
|
|
||||||
|
See [Dynarmic](./dynarmic).
|
||||||
|
|
||||||
|
## src/hid_core/
|
||||||
|
|
||||||
|
Input, joysticks, controllers and everything related to input devices.
|
||||||
|
|
||||||
|
## src/shader_recompiler/
|
||||||
|
|
||||||
|
Dedicated shader recompiler to translate Maxwell assembly code to either SPIR-V, GLSL or GLASM.
|
||||||
|
|
||||||
|
## src/video_core/
|
||||||
|
|
||||||
|
Most of the things here have their own dedicated section. In short this is basically the entire Tegra NVIDIA Maxwell GPU emulation. Additionally it includes some [extra effects](../src/video_core/host_ahders) to emulate MSAA, D24 copies or as polyfill.
|
||||||
|
|
||||||
|
Available backends are: Null, Vulkan, and OpenGL.
|
||||||
|
|
||||||
|
See [NVIDIA GPU](./NvidiaGpu.md).
|
||||||
@@ -20,6 +20,7 @@ This contains documentation created by developers. This contains build instructi
|
|||||||
- **[Driver Bugs](./DriverBugs.md)**
|
- **[Driver Bugs](./DriverBugs.md)**
|
||||||
- **[Building Older Commits](./build/OlderCommits.md)**
|
- **[Building Older Commits](./build/OlderCommits.md)**
|
||||||
- Subsystems:
|
- Subsystems:
|
||||||
|
- **[Design Overview](./DesignOverview.md)**
|
||||||
- **[Dynarmic](./dynarmic/README.md)**
|
- **[Dynarmic](./dynarmic/README.md)**
|
||||||
- **[HOS Kernel](./HosKernel.md)**
|
- **[HOS Kernel](./HosKernel.md)**
|
||||||
- **[Settings](./Settings.md)**
|
- **[Settings](./Settings.md)**
|
||||||
|
|||||||
+27
-11
@@ -43,6 +43,7 @@ This guide will walk you through adding a new boolean toggle setting to Eden's c
|
|||||||
Firstly add your desired toggle:
|
Firstly add your desired toggle:
|
||||||
|
|
||||||
Example: `src/common/setting.h`
|
Example: `src/common/setting.h`
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
|
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
|
||||||
```
|
```
|
||||||
@@ -67,6 +68,7 @@ Common Categories:
|
|||||||
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
|
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
|
||||||
|
|
||||||
Example: `src/qt_common/config/shared_translation.cpp`
|
Example: `src/qt_common/config/shared_translation.cpp`
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
INSERT(Settings,
|
INSERT(Settings,
|
||||||
your_setting_name,
|
your_setting_name,
|
||||||
@@ -91,6 +93,7 @@ INSERT(Settings,
|
|||||||
Add where it should be in the settings.
|
Add where it should be in the settings.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
||||||
```
|
```
|
||||||
@@ -106,6 +109,7 @@ RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
|||||||
Add the toggle to the Kotlin (Android) UI
|
Add the toggle to the Kotlin (Android) UI
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
@@ -123,6 +127,7 @@ put(
|
|||||||
Add your setting within the right category.
|
Add your setting within the right category.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
||||||
```
|
```
|
||||||
@@ -137,6 +142,7 @@ add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
|||||||
Add your setting and description in the appropriate place.
|
Add your setting and description in the appropriate place.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/res/values/strings.xml`
|
Example: `src/android/app/src/main/res/values/strings.xml`
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<string name="your_setting_name">Your Setting Display Name</string>
|
<string name="your_setting_name">Your Setting Display Name</string>
|
||||||
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
|
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
|
||||||
@@ -150,6 +156,7 @@ Now the UI part is done find a place in the code for the toggle,
|
|||||||
And use it to your heart's desire!
|
And use it to your heart's desire!
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const bool your_value = Settings::values.your_setting_name.GetValue();
|
const bool your_value = Settings::values.your_setting_name.GetValue();
|
||||||
|
|
||||||
@@ -196,25 +203,31 @@ Common advantages recap:
|
|||||||
|
|
||||||
#### Accessing Debug Knobs (dev side)
|
#### Accessing Debug Knobs (dev side)
|
||||||
|
|
||||||
Use the `Settings::getDebugKnobAt(u8 i)` function to check if a specific bit is set:
|
Use the `Settings::GetDebugKnobAt(u8 i)` function to check if a specific bit is set:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
//cpp side
|
//cpp side
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
|
||||||
|
//To use it as a general purpose uint var:
|
||||||
|
unsigned int debug_knobs = Settings::values.debug_knobs.GetValue();
|
||||||
|
|
||||||
// Check if bit 0 is set
|
// Check if bit 0 is set
|
||||||
bool feature_enabled = Settings::getDebugKnobAt(0);
|
bool feature_enabled = Settings::GetDebugKnobAt(0);
|
||||||
|
|
||||||
// Check if bit 15 is set
|
// Check if bit 15 is set
|
||||||
bool another_feature = Settings::getDebugKnobAt(15);
|
bool another_feature = Settings::GetDebugKnobAt(15);
|
||||||
```
|
```
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
//kotlin side
|
//kotlin side
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
|
|
||||||
|
//To use it as a general purpose uint var
|
||||||
|
val debug_knobs: Int = UShortSetting.DEBUG_KNOBS.getInt()
|
||||||
|
|
||||||
// Check if bit x is set
|
// Check if bit x is set
|
||||||
bool feature_enabled = Settings.getDebugKnobAt(x); //x as integer from 0 to 15
|
bool feature_enabled = Settings.GetDebugKnobAt(x); //x as integer from 0 to 15
|
||||||
```
|
```
|
||||||
|
|
||||||
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
|
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
|
||||||
@@ -247,6 +260,7 @@ There are two main confusions when talking about knobs:
|
|||||||
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
|
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
|
||||||
|
|
||||||
Debug knobs are **zero-based**, which means:
|
Debug knobs are **zero-based**, which means:
|
||||||
|
|
||||||
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
|
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
|
||||||
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
|
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
|
||||||
|
|
||||||
@@ -259,6 +273,7 @@ Whenever you're instructing tests or reporting results, be precise about whether
|
|||||||
|
|
||||||
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
|
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- **knobs=0**: no knobs enabled
|
- **knobs=0**: no knobs enabled
|
||||||
- **knobs=1**: knob0 enabled, others disabled
|
- **knobs=1**: knob0 enabled, others disabled
|
||||||
- **knobs=2**: knob1 enabled, others disabled
|
- **knobs=2**: knob1 enabled, others disabled
|
||||||
@@ -270,6 +285,7 @@ Examples:
|
|||||||
|
|
||||||
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
|
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- **knob0**: knob 0 enabled, others disabled
|
- **knob0**: knob 0 enabled, others disabled
|
||||||
- **knob1**: knob 1 enabled, others disabled
|
- **knob1**: knob 1 enabled, others disabled
|
||||||
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
|
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
|
||||||
@@ -282,12 +298,12 @@ Examples:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SomeFunction() {
|
void SomeFunction() {
|
||||||
if (Settings::getDebugKnobAt(0)) {
|
if (Settings::GetDebugKnobAt(0)) {
|
||||||
LOG_DEBUG(Common, "Debug feature 0 is enabled");
|
LOG_DEBUG(Common, "Debug feature 0 is enabled");
|
||||||
// Additional debug code here
|
// Additional debug code here
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::getDebugKnobAt(1)) {
|
if (Settings::GetDebugKnobAt(1)) {
|
||||||
LOG_DEBUG(Common, "Debug feature 1 is enabled");
|
LOG_DEBUG(Common, "Debug feature 1 is enabled");
|
||||||
// Different debug behavior
|
// Different debug behavior
|
||||||
}
|
}
|
||||||
@@ -299,7 +315,7 @@ void SomeFunction() {
|
|||||||
```cpp
|
```cpp
|
||||||
bool UseOptimizedPath() {
|
bool UseOptimizedPath() {
|
||||||
// Skip optimization if debug bit 2 is set for testing
|
// Skip optimization if debug bit 2 is set for testing
|
||||||
return !Settings::getDebugKnobAt(2);
|
return !Settings::GetDebugKnobAt(2);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -308,13 +324,13 @@ bool UseOptimizedPath() {
|
|||||||
```cpp
|
```cpp
|
||||||
void ExperimentalFeature() {
|
void ExperimentalFeature() {
|
||||||
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
|
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
|
||||||
|
|
||||||
if (!Settings::getDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
|
if (!Settings::GetDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
|
||||||
// Fallback to stable implementation
|
// Fallback to stable implementation
|
||||||
StableImplementation();
|
StableImplementation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Experimental implementation
|
// Experimental implementation
|
||||||
ExperimentalImplementation();
|
ExperimentalImplementation();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,3 +77,41 @@ Use this guide to get starting using the Eden emulator.
|
|||||||
8. Double-Click the main window to add the folder containing your games.
|
8. Double-Click the main window to add the folder containing your games.
|
||||||
9. Go to *Emulation > Configure > Input* and set up your controller. Click **OK** to close the dialog window.
|
9. Go to *Emulation > Configure > Input* and set up your controller. Click **OK** to close the dialog window.
|
||||||
10. Double-Click a game to run it.
|
10. Double-Click a game to run it.
|
||||||
|
|
||||||
|
## macOS
|
||||||
|
|
||||||
|
Current macOS support is still experimental and very reliant on MoltenVK developments, plans have shifted to properly provide support for KosmicKrisp and similar new GPU endeavours, but macOS users still are bound to MoltenVK itself.
|
||||||
|
|
||||||
|
Users of macOS may wish to use [Asahi Linux](https://wiki.gentoo.org/wiki/Project:Asahi/Guide) for the rising KosmicKrisp support.
|
||||||
|
|
||||||
|
As of writing, neither macOS nor Asahi has support for NCE; additionally Asahi has extraneous paging bugs with fastmem.
|
||||||
|
|
||||||
|
### Allowing Eden to Run on MacOS
|
||||||
|
|
||||||
|
Use this guide when you need to allow Eden to run on a Mac system, but are being blocked by Apple Security policy.
|
||||||
|
|
||||||
|
**Click [Here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for a version of this guide with images & visual elements.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
##### Pre-Requisites
|
||||||
|
|
||||||
|
- Permissions to modify settings in MacOS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Why am I Seeing This?
|
||||||
|
|
||||||
|
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isn't on the list of trusted ones, it will stop the program from executing and display the message above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Steps
|
||||||
|
|
||||||
|
1. Open the *System Settings* panel.
|
||||||
|
2. Navigate to *Privacy & Security*.
|
||||||
|
3. Scroll down and observe the following message under the **Security** settings.
|
||||||
|
4. Select **Open Anyway** to tell your Mac that you trust the application.
|
||||||
|
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
|
||||||
|
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
|
||||||
|
7. Eden will now open and any subsequent launches of the program will not prompt this.
|
||||||
|
|||||||
+3
-1
@@ -10,13 +10,15 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
|||||||
|
|
||||||
- **[The Basics](Basics.md)**
|
- **[The Basics](Basics.md)**
|
||||||
- **[Quickstart](./QuickStart.md)**
|
- **[Quickstart](./QuickStart.md)**
|
||||||
|
- **[Windows](./QuickStart.md#windows)**
|
||||||
|
- **[Steamdeck](./QuickStart.md#steamdeck)**
|
||||||
|
- **[macOS](./QuickStart.md#macos)**
|
||||||
- **[Settings](./Settings.md)**
|
- **[Settings](./Settings.md)**
|
||||||
- **[Controllers](./Controllers.md)**
|
- **[Controllers](./Controllers.md)**
|
||||||
- **[Controller profiles](./Controllers.md#configuring-controller-profiles)**
|
- **[Controller profiles](./Controllers.md#configuring-controller-profiles)**
|
||||||
- **[Audio](Audio.md)**
|
- **[Audio](Audio.md)**
|
||||||
- **[Graphics](Graphics.md)**
|
- **[Graphics](Graphics.md)**
|
||||||
- **[Installing Mods](./Mods.md)**
|
- **[Installing Mods](./Mods.md)**
|
||||||
- **[Run On macOS](./RunOnMacOS.md)**
|
|
||||||
- **[Data, Savefiles and Storage](Storage.md)**
|
- **[Data, Savefiles and Storage](Storage.md)**
|
||||||
- **[Orphaned Profiles](Orphaned.md)**
|
- **[Orphaned Profiles](Orphaned.md)**
|
||||||
- **[Troubleshooting](./Troubleshoot.md)**
|
- **[Troubleshooting](./Troubleshoot.md)**
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
# User Handbook - Run on macOS
|
|
||||||
|
|
||||||
Current macOS support is still experimental and very reliant on MoltenVK developments, plans have shifted to properly provide support for KosmicKrisp and similar new GPU endeavours, but macOS users still are bound to MoltenVK itself.
|
|
||||||
|
|
||||||
Users of macOS may wish to use [Asahi Linux](https://wiki.gentoo.org/wiki/Project:Asahi/Guide) for the rising KosmicKrisp support.
|
|
||||||
|
|
||||||
As of writing, neither macOS nor Asahi has support for NCE; additionally Asahi has extraneous paging bugs with fastmem.
|
|
||||||
|
|
||||||
## Allowing Eden to Run on MacOS
|
|
||||||
|
|
||||||
Use this guide when you need to allow Eden to run on a Mac system, but are being blocked by Apple Security policy.
|
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for a version of this guide with images & visual elements.**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Pre-Requisites
|
|
||||||
|
|
||||||
- Permissions to modify settings in MacOS
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Why am I Seeing This?
|
|
||||||
|
|
||||||
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isn't on the list of trusted ones, it will stop the program from executing and display the message above.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Steps
|
|
||||||
|
|
||||||
1. Open the *System Settings* panel.
|
|
||||||
2. Navigate to *Privacy & Security*.
|
|
||||||
3. Scroll down and observe the following message under the **Security** settings.
|
|
||||||
4. Select **Open Anyway** to tell your Mac that you trust the application.
|
|
||||||
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
|
|
||||||
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
|
|
||||||
7. Eden will now open and any subsequent launches of the program will not prompt this.
|
|
||||||
@@ -220,7 +220,7 @@ object NativeLibrary {
|
|||||||
|
|
||||||
external fun refreshThreadPolicies()
|
external fun refreshThreadPolicies()
|
||||||
|
|
||||||
external fun getDebugKnobAt(index: Int): Boolean
|
external fun GetDebugKnobAt(index: Int): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current speed limit to the configured turbo speed.
|
* Set the current speed limit to the configured turbo speed.
|
||||||
@@ -539,6 +539,40 @@ object NativeLibrary {
|
|||||||
*/
|
*/
|
||||||
external fun installKeys(path: String, ext: String): Int
|
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
|
* Checks the PatchManager for any addons that are available
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -559,6 +559,15 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
|||||||
private fun enableFullscreenImmersive() {
|
private fun enableFullscreenImmersive() {
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
window.decorView.systemUiVisibility =
|
||||||
|
View.SYSTEM_UI_FLAG_FULLSCREEN or
|
||||||
|
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||||
|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||||
|
|
||||||
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||||
controller.hide(WindowInsetsCompat.Type.systemBars())
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
controller.systemBarsBehavior =
|
controller.systemBarsBehavior =
|
||||||
|
|||||||
+4
@@ -37,6 +37,10 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
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"),
|
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
||||||
PICTURE_IN_PICTURE("picture_in_picture"),
|
PICTURE_IN_PICTURE("picture_in_picture"),
|
||||||
USE_CUSTOM_RTC("custom_rtc_enabled"),
|
USE_CUSTOM_RTC("custom_rtc_enabled"),
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
|||||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
||||||
RENDERER_ACCURACY("gpu_accuracy"),
|
RENDERER_ACCURACY("gpu_accuracy"),
|
||||||
RENDERER_RESOLUTION("resolution_setup"),
|
RENDERER_RESOLUTION("resolution_setup"),
|
||||||
|
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
|
||||||
|
RENDERER_FRAME_GEN_TARGET_RATE("frame_gen_target_rate"),
|
||||||
|
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
|
||||||
|
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
|
||||||
RENDERER_VSYNC("use_vsync"),
|
RENDERER_VSYNC("use_vsync"),
|
||||||
RENDERER_SCALING_FILTER("scaling_filter"),
|
RENDERER_SCALING_FILTER("scaling_filter"),
|
||||||
RENDERER_ANTI_ALIASING("anti_aliasing"),
|
RENDERER_ANTI_ALIASING("anti_aliasing"),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ object Settings {
|
|||||||
SECTION_ROOT(R.string.advanced_settings),
|
SECTION_ROOT(R.string.advanced_settings),
|
||||||
SECTION_SYSTEM(R.string.preferences_system),
|
SECTION_SYSTEM(R.string.preferences_system),
|
||||||
SECTION_RENDERER(R.string.preferences_graphics),
|
SECTION_RENDERER(R.string.preferences_graphics),
|
||||||
|
SECTION_FRAME_GEN(R.string.frame_gen),
|
||||||
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
||||||
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
|
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
|
||||||
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
|
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
|
||||||
@@ -34,8 +35,8 @@ object Settings {
|
|||||||
fun getPlayerString(player: Int): String =
|
fun getPlayerString(player: Int): String =
|
||||||
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
||||||
|
|
||||||
fun getDebugKnobAt(index: Int): Boolean {
|
fun GetDebugKnobAt(index: Int): Boolean {
|
||||||
return org.yuzu.yuzu_emu.NativeLibrary.getDebugKnobAt(index)
|
return org.yuzu.yuzu_emu.NativeLibrary.GetDebugKnobAt(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||||
|
|||||||
+2
-3
@@ -11,8 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
|
|||||||
enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
||||||
RENDERER_SPEED_LIMIT("speed_limit"),
|
RENDERER_SPEED_LIMIT("speed_limit"),
|
||||||
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
|
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
|
||||||
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"),
|
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit")
|
||||||
DEBUG_KNOBS("debug_knobs")
|
|
||||||
;
|
;
|
||||||
|
|
||||||
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
|
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
|
||||||
@@ -29,4 +28,4 @@ enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
|||||||
override fun getValueAsString(needsGlobal: Boolean): String = getShort(needsGlobal).toString()
|
override fun getValueAsString(needsGlobal: Boolean): String = getShort(needsGlobal).toString()
|
||||||
|
|
||||||
override fun reset() = NativeConfig.setShort(key, defaultValue)
|
override fun reset() = NativeConfig.setShort(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.features.settings.model
|
||||||
|
|
||||||
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
|
|
||||||
|
enum class UShortSetting(override val key: String) : AbstractIntSetting {
|
||||||
|
DEBUG_KNOBS("debug_knobs")
|
||||||
|
;
|
||||||
|
|
||||||
|
override fun getInt(needsGlobal: Boolean): Int =
|
||||||
|
NativeConfig.getUnsignedShort(key, needsGlobal)
|
||||||
|
|
||||||
|
override fun setInt(value: Int) {
|
||||||
|
if (NativeConfig.isPerGameConfigLoaded()) {
|
||||||
|
global = false
|
||||||
|
}
|
||||||
|
NativeConfig.setUnsignedShort(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultValue: Int by lazy { NativeConfig.getDefaultToString(key).toInt() }
|
||||||
|
|
||||||
|
override fun getValueAsString(needsGlobal: Boolean): String = getInt(needsGlobal).toString()
|
||||||
|
|
||||||
|
override fun reset() = NativeConfig.setUnsignedShort(key, defaultValue)
|
||||||
|
}
|
||||||
+106
-1
@@ -20,7 +20,9 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
|||||||
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
|
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.ShortSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
|
||||||
import org.yuzu.yuzu_emu.network.NetDataValidators
|
import org.yuzu.yuzu_emu.network.NetDataValidators
|
||||||
|
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,6 +67,19 @@ abstract class SettingsItem(
|
|||||||
return NativeLibrary.isFirmwareAvailable()
|
return NativeLibrary.isFirmwareAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (setting.key in frameGenKeys &&
|
||||||
|
!(LosslessScalingHelper.isInstalled() && LosslessScalingHelper.isSupportedByGpu())
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// A frame rate target moves the multiplier on its own
|
||||||
|
if (setting.key == IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key &&
|
||||||
|
frameGenTargetRate != 0
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Can't edit settings that aren't saveable in per-game config even if they are switchable
|
// Can't edit settings that aren't saveable in per-game config even if they are switchable
|
||||||
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
|
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
|
||||||
return false
|
return false
|
||||||
@@ -88,7 +103,31 @@ abstract class SettingsItem(
|
|||||||
val clearable: Boolean
|
val clearable: Boolean
|
||||||
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
|
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
|
||||||
|
|
||||||
|
private val frameGenTargetRate: Int
|
||||||
|
get() {
|
||||||
|
val key = IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
|
||||||
|
val needsGlobal = if (NativeLibrary.isRunning() &&
|
||||||
|
!NativeConfig.isPerGameConfigLoaded()
|
||||||
|
) {
|
||||||
|
!NativeConfig.usingGlobal(key)
|
||||||
|
} else {
|
||||||
|
NativeConfig.usingGlobal(key)
|
||||||
|
}
|
||||||
|
return IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(needsGlobal)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val frameGenKeys = setOf(
|
||||||
|
BooleanSetting.RENDERER_FRAME_GEN.key,
|
||||||
|
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
|
||||||
|
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.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_HEADER = 0
|
||||||
const val TYPE_SWITCH = 1
|
const val TYPE_SWITCH = 1
|
||||||
const val TYPE_SINGLE_CHOICE = 2
|
const val TYPE_SINGLE_CHOICE = 2
|
||||||
@@ -586,6 +625,7 @@ abstract class SettingsItem(
|
|||||||
IntSetting.FSR_SHARPENING_SLIDER,
|
IntSetting.FSR_SHARPENING_SLIDER,
|
||||||
titleId = R.string.fsr_sharpness,
|
titleId = R.string.fsr_sharpness,
|
||||||
descriptionId = R.string.fsr_sharpness_description,
|
descriptionId = R.string.fsr_sharpness_description,
|
||||||
|
max = 200,
|
||||||
units = "%"
|
units = "%"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -607,6 +647,71 @@ abstract class SettingsItem(
|
|||||||
valuesId = R.array.rendererAntiAliasingValues
|
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_TARGET_RATE,
|
||||||
|
titleId = R.string.frame_gen_target_rate,
|
||||||
|
descriptionId = R.string.frame_gen_target_rate_description,
|
||||||
|
choicesId = R.array.frameGenTargetRateNames,
|
||||||
|
valuesId = R.array.frameGenTargetRateValues
|
||||||
|
)
|
||||||
|
)
|
||||||
|
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(
|
put(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.RENDERER_SCREEN_LAYOUT,
|
IntSetting.RENDERER_SCREEN_LAYOUT,
|
||||||
@@ -930,7 +1035,7 @@ abstract class SettingsItem(
|
|||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
SpinBoxSetting(
|
SpinBoxSetting(
|
||||||
ShortSetting.DEBUG_KNOBS,
|
UShortSetting.DEBUG_KNOBS,
|
||||||
titleId = R.string.debug_knobs,
|
titleId = R.string.debug_knobs,
|
||||||
descriptionId = R.string.debug_knobs_description,
|
descriptionId = R.string.debug_knobs_description,
|
||||||
valueHint = R.string.debug_knobs_hint,
|
valueHint = R.string.debug_knobs_hint,
|
||||||
|
|||||||
+3
-1
@@ -382,7 +382,9 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
|
|||||||
}
|
}
|
||||||
scSetting.setSelectedValue(value)
|
scSetting.setSelectedValue(value)
|
||||||
|
|
||||||
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key) {
|
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key ||
|
||||||
|
scSetting.setting.key == IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
|
||||||
|
) {
|
||||||
settingsViewModel.setShouldReloadSettingsList(true)
|
settingsViewModel.setShouldReloadSettingsList(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-4
@@ -25,8 +25,10 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
|
|||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
|
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
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.StringSetting
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
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.NativeConfig
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||||
@@ -76,6 +78,46 @@ class SettingsFragmentPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addFrameGenSettings(sl: ArrayList<SettingsItem>) {
|
||||||
|
sl.apply {
|
||||||
|
if (!LosslessScalingHelper.isSupportedByGpu()) {
|
||||||
|
add(
|
||||||
|
RunnableSetting(
|
||||||
|
titleId = R.string.frame_gen_unsupported,
|
||||||
|
descriptionId = R.string.frame_gen_unsupported_description,
|
||||||
|
isRunnable = false
|
||||||
|
) {}
|
||||||
|
)
|
||||||
|
} else if (!LosslessScalingHelper.isInstalled()) {
|
||||||
|
add(
|
||||||
|
RunnableSetting(
|
||||||
|
titleId = R.string.lossless_scaling_missing,
|
||||||
|
descriptionId = R.string.lossless_scaling_missing_description,
|
||||||
|
isRunnable = false
|
||||||
|
) {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
add(BooleanSetting.RENDERER_FRAME_GEN.key)
|
||||||
|
add(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
||||||
|
if (IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(
|
||||||
|
getNeedsGlobalForKey(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
||||||
|
) == 0
|
||||||
|
) {
|
||||||
|
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 {
|
private fun isSharpnessScalingFilterSelected(): Boolean {
|
||||||
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
|
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||||
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
|
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
|
||||||
@@ -120,6 +162,7 @@ class SettingsFragmentPresenter(
|
|||||||
MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
||||||
MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
||||||
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||||
|
MenuTag.SECTION_FRAME_GEN -> addFrameGenSettings(sl)
|
||||||
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
||||||
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
||||||
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
||||||
@@ -270,8 +313,6 @@ class SettingsFragmentPresenter(
|
|||||||
// TODO(crueter): sub-submenus?
|
// TODO(crueter): sub-submenus?
|
||||||
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
||||||
sl.apply {
|
sl.apply {
|
||||||
// add(IntSetting.RENDERER_NVDEC_EMULATION.key)
|
|
||||||
|
|
||||||
add(IntSetting.RENDERER_RESOLUTION.key)
|
add(IntSetting.RENDERER_RESOLUTION.key)
|
||||||
add(IntSetting.RENDERER_VSYNC.key)
|
add(IntSetting.RENDERER_VSYNC.key)
|
||||||
add(IntSetting.RENDERER_SCALING_FILTER.key)
|
add(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||||
@@ -288,6 +329,7 @@ class SettingsFragmentPresenter(
|
|||||||
add(IntSetting.MAX_ANISOTROPY.key)
|
add(IntSetting.MAX_ANISOTROPY.key)
|
||||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||||
|
add(IntSetting.RENDERER_NVDEC_EMULATION.key)
|
||||||
|
|
||||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||||
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
||||||
@@ -302,7 +344,6 @@ class SettingsFragmentPresenter(
|
|||||||
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
||||||
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
||||||
add(BooleanSetting.EMULATE_BGR565.key)
|
add(BooleanSetting.EMULATE_BGR565.key)
|
||||||
add(BooleanSetting.RESCALE_HACK.key)
|
|
||||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||||
add(IntSetting.ANDROID_PIPELINE_WORKERS.key)
|
add(IntSetting.ANDROID_PIPELINE_WORKERS.key)
|
||||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
|
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
|
||||||
@@ -1286,7 +1327,7 @@ class SettingsFragmentPresenter(
|
|||||||
|
|
||||||
add(HeaderSetting(R.string.general))
|
add(HeaderSetting(R.string.general))
|
||||||
|
|
||||||
add(ShortSetting.DEBUG_KNOBS.key)
|
add(UShortSetting.DEBUG_KNOBS.key)
|
||||||
add(StringSetting.PROGRAM_ARGS.key)
|
add(StringSetting.PROGRAM_ARGS.key)
|
||||||
|
|
||||||
if (!NativeConfig.isPerGameConfigLoaded()) {
|
if (!NativeConfig.isPerGameConfigLoaded()) {
|
||||||
@@ -1296,6 +1337,7 @@ class SettingsFragmentPresenter(
|
|||||||
add(BooleanSetting.DUMP_GUEST_SHADERS.key)
|
add(BooleanSetting.DUMP_GUEST_SHADERS.key)
|
||||||
add(BooleanSetting.GPU_LOG_SHADER_DUMPS.key)
|
add(BooleanSetting.GPU_LOG_SHADER_DUMPS.key)
|
||||||
add(BooleanSetting.DUMP_MACROS.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_MEMORY_TRACKING.key)
|
||||||
add(BooleanSetting.GPU_LOG_DRIVER_DEBUG.key)
|
add(BooleanSetting.GPU_LOG_DRIVER_DEBUG.key)
|
||||||
add(IntSetting.GPU_LOG_RING_BUFFER_SIZE.key)
|
add(IntSetting.GPU_LOG_RING_BUFFER_SIZE.key)
|
||||||
|
|||||||
+2
@@ -29,6 +29,7 @@ enum class SettingsSubscreen {
|
|||||||
DRIVER_MANAGER,
|
DRIVER_MANAGER,
|
||||||
DRIVER_FETCHER,
|
DRIVER_FETCHER,
|
||||||
FREEDRENO_SETTINGS,
|
FREEDRENO_SETTINGS,
|
||||||
|
LOSSLESS_MANAGER,
|
||||||
APPLET_LAUNCHER,
|
APPLET_LAUNCHER,
|
||||||
INSTALLABLE,
|
INSTALLABLE,
|
||||||
GAME_FOLDERS,
|
GAME_FOLDERS,
|
||||||
@@ -126,6 +127,7 @@ class SettingsSubscreenActivity : AppCompatActivity() {
|
|||||||
SettingsSubscreen.DRIVER_MANAGER -> R.id.driverManagerFragment
|
SettingsSubscreen.DRIVER_MANAGER -> R.id.driverManagerFragment
|
||||||
SettingsSubscreen.DRIVER_FETCHER -> R.id.driverFetcherFragment
|
SettingsSubscreen.DRIVER_FETCHER -> R.id.driverFetcherFragment
|
||||||
SettingsSubscreen.FREEDRENO_SETTINGS -> R.id.freedrenoSettingsFragment
|
SettingsSubscreen.FREEDRENO_SETTINGS -> R.id.freedrenoSettingsFragment
|
||||||
|
SettingsSubscreen.LOSSLESS_MANAGER -> R.id.losslessManagerFragment
|
||||||
SettingsSubscreen.APPLET_LAUNCHER -> R.id.appletLauncherFragment
|
SettingsSubscreen.APPLET_LAUNCHER -> R.id.appletLauncherFragment
|
||||||
SettingsSubscreen.INSTALLABLE -> R.id.installableFragment
|
SettingsSubscreen.INSTALLABLE -> R.id.installableFragment
|
||||||
SettingsSubscreen.GAME_FOLDERS -> R.id.gameFoldersFragment
|
SettingsSubscreen.GAME_FOLDERS -> R.id.gameFoldersFragment
|
||||||
|
|||||||
@@ -1182,7 +1182,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
container,
|
container,
|
||||||
IntSetting.FSR_SHARPENING_SLIDER,
|
IntSetting.FSR_SHARPENING_SLIDER,
|
||||||
minValue = 0,
|
minValue = 0,
|
||||||
maxValue = 100,
|
maxValue = 200,
|
||||||
units = "%"
|
units = "%"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,6 +369,21 @@ class GamePropertiesFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
SubmenuProperty(
|
||||||
|
R.string.frame_gen,
|
||||||
|
R.string.frame_gen_per_game_description,
|
||||||
|
R.drawable.ic_duck,
|
||||||
|
action = {
|
||||||
|
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||||
|
args.game,
|
||||||
|
Settings.MenuTag.SECTION_FRAME_GEN
|
||||||
|
)
|
||||||
|
binding.root.findNavController().navigate(action)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if (GpuDriverHelper.isAdrenoGpu()) {
|
if (GpuDriverHelper.isAdrenoGpu()) {
|
||||||
add(
|
add(
|
||||||
SubmenuProperty(
|
SubmenuProperty(
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import org.yuzu.yuzu_emu.ui.main.MainActivity
|
|||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import org.yuzu.yuzu_emu.utils.Log
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
|
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
|
|
||||||
class HomeSettingsFragment : Fragment() {
|
class HomeSettingsFragment : Fragment() {
|
||||||
@@ -170,6 +171,24 @@ class HomeSettingsFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
HomeSetting(
|
||||||
|
R.string.lossless_scaling,
|
||||||
|
R.string.lossless_scaling_description,
|
||||||
|
R.drawable.ic_duck,
|
||||||
|
{
|
||||||
|
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
|
||||||
|
SettingsSubscreen.LOSSLESS_MANAGER,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
binding.root.findNavController().navigate(action)
|
||||||
|
},
|
||||||
|
{ true },
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
LosslessScalingHelper.statusText
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
HomeSetting(
|
HomeSetting(
|
||||||
R.string.multiplayer,
|
R.string.multiplayer,
|
||||||
@@ -337,6 +356,7 @@ class HomeSettingsFragment : Fragment() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
driverViewModel.updateDriverNameForGame(null)
|
driverViewModel.updateDriverNameForGame(null)
|
||||||
|
LosslessScalingHelper.refreshStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
|
||||||
|
import org.yuzu.yuzu_emu.databinding.FragmentLosslessManagerBinding
|
||||||
|
import org.yuzu.yuzu_emu.features.fetcher.SpacingItemDecoration
|
||||||
|
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||||
|
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||||
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
|
import org.yuzu.yuzu_emu.utils.collect
|
||||||
|
|
||||||
|
class LosslessManagerFragment : Fragment() {
|
||||||
|
private var _binding: FragmentLosslessManagerBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = FragmentLosslessManagerBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.toolbarLossless.setNavigationOnClickListener {
|
||||||
|
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.losslessOptionsList.apply {
|
||||||
|
layoutManager =
|
||||||
|
GridLayoutManager(requireContext(), resources.getInteger(R.integer.grid_columns))
|
||||||
|
addItemDecoration(
|
||||||
|
SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.spacing_small))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LosslessScalingHelper.statusText.collect(viewLifecycleOwner) { refreshOptions() }
|
||||||
|
|
||||||
|
setInsets()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshOptions() {
|
||||||
|
binding.losslessOptionsList.adapter = HomeSettingAdapter(
|
||||||
|
requireActivity() as AppCompatActivity,
|
||||||
|
viewLifecycleOwner,
|
||||||
|
buildOptions()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildOptions(): List<HomeSetting> {
|
||||||
|
val installed = LosslessScalingHelper.isInstalled()
|
||||||
|
return listOf(
|
||||||
|
HomeSetting(
|
||||||
|
if (installed) R.string.lossless_scaling_replace else R.string.lossless_scaling_install,
|
||||||
|
if (installed) {
|
||||||
|
R.string.lossless_scaling_replace_description
|
||||||
|
} else {
|
||||||
|
R.string.lossless_scaling_install_description
|
||||||
|
},
|
||||||
|
R.drawable.ic_install,
|
||||||
|
{ dllPickerLauncher.launch(arrayOf("*/*")) },
|
||||||
|
{ !NativeLibrary.isRunning() },
|
||||||
|
R.string.lossless_scaling_locked,
|
||||||
|
R.string.lossless_scaling_locked_description,
|
||||||
|
LosslessScalingHelper.statusText
|
||||||
|
),
|
||||||
|
HomeSetting(
|
||||||
|
R.string.lossless_scaling_remove,
|
||||||
|
R.string.lossless_scaling_remove_description,
|
||||||
|
R.drawable.ic_delete,
|
||||||
|
{ confirmRemoval() },
|
||||||
|
{ installed && !NativeLibrary.isRunning() },
|
||||||
|
if (installed) {
|
||||||
|
R.string.lossless_scaling_locked
|
||||||
|
} else {
|
||||||
|
R.string.lossless_scaling_remove_unavailable
|
||||||
|
},
|
||||||
|
if (installed) {
|
||||||
|
R.string.lossless_scaling_locked_description
|
||||||
|
} else {
|
||||||
|
R.string.lossless_scaling_remove_unavailable_description
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun confirmRemoval() {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
requireActivity(),
|
||||||
|
titleId = R.string.lossless_scaling_remove,
|
||||||
|
descriptionId = R.string.lossless_scaling_remove_confirmation,
|
||||||
|
positiveButtonTitleId = R.string.lossless_scaling_remove,
|
||||||
|
positiveAction = { LosslessScalingHelper.remove() },
|
||||||
|
showNegativeButton = true,
|
||||||
|
negativeAction = {}
|
||||||
|
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val dllPickerLauncher =
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setInsets() =
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
|
||||||
|
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||||
|
|
||||||
|
binding.appbarLossless.updateMargins(
|
||||||
|
left = barInsets.left + cutoutInsets.left,
|
||||||
|
right = barInsets.right + cutoutInsets.right
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.scrollViewLossless.updatePadding(bottom = barInsets.bottom)
|
||||||
|
|
||||||
|
binding.losslessOptionsList.updatePadding(
|
||||||
|
left = barInsets.left + cutoutInsets.left,
|
||||||
|
right = barInsets.right + cutoutInsets.right
|
||||||
|
)
|
||||||
|
|
||||||
|
windowInsets
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.fragments
|
package org.yuzu.yuzu_emu.fragments
|
||||||
@@ -42,6 +42,7 @@ import org.yuzu.yuzu_emu.model.SetupPage
|
|||||||
import org.yuzu.yuzu_emu.model.PageState
|
import org.yuzu.yuzu_emu.model.PageState
|
||||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
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.NativeConfig
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||||
@@ -202,6 +203,24 @@ class SetupFragment : Fragment() {
|
|||||||
R.string.install_firmware_warning_help,
|
R.string.install_firmware_warning_help,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
PageButton(
|
||||||
|
R.drawable.ic_duck,
|
||||||
|
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(
|
add(
|
||||||
PageButton(
|
PageButton(
|
||||||
R.drawable.ic_controller,
|
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 =
|
val getGamesDirectory =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
|||||||
+13
-1
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.fragments
|
package org.yuzu.yuzu_emu.fragments
|
||||||
@@ -72,6 +72,18 @@ class SystemInfoDialogFragment : DialogFragment() {
|
|||||||
|
|
||||||
val vulkanDriver = NativeLibrary.getVulkanDriverVersion()
|
val vulkanDriver = NativeLibrary.getVulkanDriverVersion()
|
||||||
appendLine("${getString(R.string.vulkan_driver_version)}: $vulkanDriver")
|
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) {
|
} catch (e: Exception) {
|
||||||
appendLine("${getString(R.string.error_getting_emulator_info)}: ${e.message}")
|
appendLine("${getString(R.string.error_getting_emulator_info)}: ${e.message}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@@ -59,6 +60,10 @@ class GamesFragment : Fragment() {
|
|||||||
|
|
||||||
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
|
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
|
||||||
private var fallbackBottomInset: Int = 0
|
private var fallbackBottomInset: Int = 0
|
||||||
|
private var pendingPostReloadListSettle = false
|
||||||
|
private var pendingPostReloadListSettleGeneration = 0
|
||||||
|
private var gameListSubmitGeneration = 0
|
||||||
|
private var committedGameListSubmitGeneration = 0
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SEARCH_TEXT = "SearchText"
|
private const val SEARCH_TEXT = "SearchText"
|
||||||
@@ -168,10 +173,9 @@ class GamesFragment : Fragment() {
|
|||||||
|
|
||||||
gamesViewModel.shouldScrollAfterReload.collect(viewLifecycleOwner) { shouldScroll ->
|
gamesViewModel.shouldScrollAfterReload.collect(viewLifecycleOwner) { shouldScroll ->
|
||||||
if (shouldScroll) {
|
if (shouldScroll) {
|
||||||
binding.gridGames.post {
|
pendingPostReloadListSettle = true
|
||||||
(binding.gridGames as? CarouselRecyclerView)?.pendingScrollAfterReload = true
|
pendingPostReloadListSettleGeneration = gameListSubmitGeneration
|
||||||
gameAdapter.notifyDataSetChanged()
|
schedulePostReloadListSettle()
|
||||||
}
|
|
||||||
gamesViewModel.setShouldScrollAfterReload(false)
|
gamesViewModel.setShouldScrollAfterReload(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,11 +277,42 @@ class GamesFragment : Fragment() {
|
|||||||
lastSearchText = currentSearchText
|
lastSearchText = currentSearchText
|
||||||
lastFilter = currentFilter
|
lastFilter = currentFilter
|
||||||
} else {
|
} else {
|
||||||
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(games)
|
submitGameList(games)
|
||||||
gamesViewModel.setFilteredGames(games)
|
gamesViewModel.setFilteredGames(games)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun submitGameList(games: List<Game>) {
|
||||||
|
val adapter = (binding.gridGames as? RecyclerView)?.adapter as? GameAdapter
|
||||||
|
if (adapter == null) {
|
||||||
|
schedulePostReloadListSettle()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val submitGeneration = ++gameListSubmitGeneration
|
||||||
|
adapter.submitList(games) {
|
||||||
|
if (committedGameListSubmitGeneration < submitGeneration) {
|
||||||
|
committedGameListSubmitGeneration = submitGeneration
|
||||||
|
}
|
||||||
|
schedulePostReloadListSettle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun schedulePostReloadListSettle() {
|
||||||
|
if (!pendingPostReloadListSettle || _binding == null) return
|
||||||
|
|
||||||
|
binding.gridGames.doOnPreDraw {
|
||||||
|
if (!pendingPostReloadListSettle || _binding == null) return@doOnPreDraw
|
||||||
|
if (committedGameListSubmitGeneration < pendingPostReloadListSettleGeneration) {
|
||||||
|
schedulePostReloadListSettle()
|
||||||
|
return@doOnPreDraw
|
||||||
|
}
|
||||||
|
pendingPostReloadListSettle = false
|
||||||
|
|
||||||
|
(binding.gridGames as? CarouselRecyclerView)?.refreshView()
|
||||||
|
}
|
||||||
|
}
|
||||||
private fun setupTopView() {
|
private fun setupTopView() {
|
||||||
binding.searchText.doOnTextChanged() { text: CharSequence?, _: Int, _: Int, _: Int ->
|
binding.searchText.doOnTextChanged() { text: CharSequence?, _: Int, _: Int, _: Int ->
|
||||||
if (text.toString().isNotEmpty()) {
|
if (text.toString().isNotEmpty()) {
|
||||||
@@ -414,9 +449,7 @@ class GamesFragment : Fragment() {
|
|||||||
|
|
||||||
val searchTerm = binding.searchText.text.toString().lowercase(Locale.getDefault())
|
val searchTerm = binding.searchText.text.toString().lowercase(Locale.getDefault())
|
||||||
if (searchTerm.isEmpty()) {
|
if (searchTerm.isEmpty()) {
|
||||||
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(
|
submitGameList(filteredList)
|
||||||
filteredList
|
|
||||||
)
|
|
||||||
gamesViewModel.setFilteredGames(filteredList)
|
gamesViewModel.setFilteredGames(filteredList)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -432,7 +465,7 @@ class GamesFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}.sortedByDescending { it.score }.map { it.item }
|
}.sortedByDescending { it.score }.map { it.item }
|
||||||
|
|
||||||
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(sortedList)
|
submitGameList(sortedList)
|
||||||
gamesViewModel.setFilteredGames(sortedList)
|
gamesViewModel.setFilteredGames(sortedList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ object GameHelper {
|
|||||||
|
|
||||||
fun getGames(): List<Game> {
|
fun getGames(): List<Game> {
|
||||||
val games = mutableListOf<Game>()
|
val games = mutableListOf<Game>()
|
||||||
|
val gamesByProgramId = mutableMapOf<String, Game>()
|
||||||
val context = YuzuApplication.appContext
|
val context = YuzuApplication.appContext
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ object GameHelper {
|
|||||||
|
|
||||||
addGamesRecursive(
|
addGamesRecursive(
|
||||||
games,
|
games,
|
||||||
|
gamesByProgramId,
|
||||||
FileUtil.listFiles(gameDirUri),
|
FileUtil.listFiles(gameDirUri),
|
||||||
scanDepth,
|
scanDepth,
|
||||||
mountedContainerUris
|
mountedContainerUris
|
||||||
@@ -136,6 +138,7 @@ object GameHelper {
|
|||||||
|
|
||||||
private fun addGamesRecursive(
|
private fun addGamesRecursive(
|
||||||
games: MutableList<Game>,
|
games: MutableList<Game>,
|
||||||
|
gamesByProgramId: MutableMap<String, Game>,
|
||||||
files: Array<MinimalDocumentFile>,
|
files: Array<MinimalDocumentFile>,
|
||||||
depth: Int,
|
depth: Int,
|
||||||
mountedContainerUris: MutableSet<String>
|
mountedContainerUris: MutableSet<String>
|
||||||
@@ -148,6 +151,7 @@ object GameHelper {
|
|||||||
if (it.isDirectory) {
|
if (it.isDirectory) {
|
||||||
addGamesRecursive(
|
addGamesRecursive(
|
||||||
games,
|
games,
|
||||||
|
gamesByProgramId,
|
||||||
FileUtil.listFiles(it.uri),
|
FileUtil.listFiles(it.uri),
|
||||||
depth - 1,
|
depth - 1,
|
||||||
mountedContainerUris
|
mountedContainerUris
|
||||||
@@ -156,8 +160,9 @@ object GameHelper {
|
|||||||
val extension = FileUtil.getExtension(it.uri).lowercase()
|
val extension = FileUtil.getExtension(it.uri).lowercase()
|
||||||
val filePath = it.uri.toString()
|
val filePath = it.uri.toString()
|
||||||
|
|
||||||
if (externalContentExtensions.contains(extension) &&
|
val mountedContainer = externalContentExtensions.contains(extension) &&
|
||||||
mountedContainerUris.add(filePath)) {
|
mountedContainerUris.add(filePath)
|
||||||
|
if (mountedContainer) {
|
||||||
NativeLibrary.addGameFolderFileToFilesystemProvider(filePath)
|
NativeLibrary.addGameFolderFileToFilesystemProvider(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +170,20 @@ object GameHelper {
|
|||||||
val game = getGame(it.uri, true, false)
|
val game = getGame(it.uri, true, false)
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
games.add(game)
|
games.add(game)
|
||||||
|
if (game.programId != "0") {
|
||||||
|
gamesByProgramId[game.programId] = game
|
||||||
|
}
|
||||||
|
} else if (mountedContainer) {
|
||||||
|
GameMetadata.getProgramId(filePath).toLongOrNull()?.let { programId ->
|
||||||
|
gamesByProgramId[(programId and 0x800L.inv()).toString()]
|
||||||
|
}?.let { existingGame ->
|
||||||
|
NativeLibrary.getPatchesForFile(existingGame.path, existingGame.programId)
|
||||||
|
existingGame.version = GameMetadata.getVersion(
|
||||||
|
existingGame.path,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
GameIconUtils.refreshGameIcon(existingGame)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -24,6 +27,15 @@ import coil.request.Options
|
|||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.model.Game
|
import org.yuzu.yuzu_emu.model.Game
|
||||||
|
import java.util.Collections
|
||||||
|
import java.util.WeakHashMap
|
||||||
|
|
||||||
|
private val gameIconHashes = Collections.synchronizedMap(mutableMapOf<String, Int>())
|
||||||
|
private val gameIconTargets = Collections.synchronizedMap(WeakHashMap<ImageView, GameIconTarget>())
|
||||||
|
|
||||||
|
private fun Game.iconCacheKey(): String = "$path|$version"
|
||||||
|
|
||||||
|
private data class GameIconTarget(val game: Game, var iconHash: Int? = null)
|
||||||
|
|
||||||
class GameIconFetcher(
|
class GameIconFetcher(
|
||||||
private val game: Game,
|
private val game: Game,
|
||||||
@@ -31,14 +43,15 @@ class GameIconFetcher(
|
|||||||
) : Fetcher {
|
) : Fetcher {
|
||||||
override suspend fun fetch(): FetchResult {
|
override suspend fun fetch(): FetchResult {
|
||||||
return DrawableResult(
|
return DrawableResult(
|
||||||
drawable = decodeGameIcon(game.path)!!.toDrawable(options.context.resources),
|
drawable = decodeGameIcon(game)!!.toDrawable(options.context.resources),
|
||||||
isSampled = false,
|
isSampled = false,
|
||||||
dataSource = DataSource.DISK
|
dataSource = DataSource.DISK
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decodeGameIcon(uri: String): Bitmap? {
|
private fun decodeGameIcon(game: Game): Bitmap? {
|
||||||
val data = GameMetadata.getIcon(uri)
|
val data = GameMetadata.getIcon(game.path)
|
||||||
|
gameIconHashes[game.iconCacheKey()] = data.contentHashCode()
|
||||||
return BitmapFactory.decodeByteArray(
|
return BitmapFactory.decodeByteArray(
|
||||||
data,
|
data,
|
||||||
0,
|
0,
|
||||||
@@ -54,7 +67,7 @@ class GameIconFetcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class GameIconKeyer : Keyer<Game> {
|
class GameIconKeyer : Keyer<Game> {
|
||||||
override fun key(data: Game, options: Options): String = data.path
|
override fun key(data: Game, options: Options): String = data.iconCacheKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
object GameIconUtils {
|
object GameIconUtils {
|
||||||
@@ -71,14 +84,58 @@ object GameIconUtils {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun loadGameIcon(game: Game, imageView: ImageView) {
|
fun loadGameIcon(game: Game, imageView: ImageView) {
|
||||||
|
gameIconTargets[imageView] = GameIconTarget(game)
|
||||||
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
||||||
.data(game)
|
.data(game)
|
||||||
.target(imageView)
|
.target(imageView)
|
||||||
.error(R.drawable.default_icon)
|
.error(R.drawable.default_icon)
|
||||||
|
.listener(
|
||||||
|
onSuccess = { _, _ ->
|
||||||
|
val target = gameIconTargets[imageView]
|
||||||
|
if (target?.game?.iconCacheKey() == game.iconCacheKey()) {
|
||||||
|
gameIconHashes[game.iconCacheKey()]?.let {
|
||||||
|
target.iconHash = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError = { _, _ ->
|
||||||
|
gameIconTargets[imageView]?.iconHash = null
|
||||||
|
}
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
imageLoader.enqueue(request)
|
imageLoader.enqueue(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun refreshGameIcon(game: Game) {
|
||||||
|
val targets = synchronized(gameIconTargets) {
|
||||||
|
gameIconTargets
|
||||||
|
.filterValues { it.game.path == game.path && it.game.programId == game.programId }
|
||||||
|
.keys
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
if (targets.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val iconHash = GameMetadata.getIcon(game.path).contentHashCode()
|
||||||
|
val targetsToRefresh = targets.filter { gameIconTargets[it]?.iconHash != iconHash }
|
||||||
|
if (targetsToRefresh.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imageLoader.memoryCache?.remove(MemoryCache.Key(game.iconCacheKey()))
|
||||||
|
targetsToRefresh.forEach { imageView ->
|
||||||
|
imageView.post {
|
||||||
|
val target = gameIconTargets[imageView] ?: return@post
|
||||||
|
if (target.game.path == game.path && target.game.programId == game.programId) {
|
||||||
|
if (target.iconHash != iconHash) {
|
||||||
|
loadGameIcon(game, imageView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
|
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
|
||||||
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
||||||
.data(game)
|
.data(game)
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,6 +80,12 @@ object NativeConfig {
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
external fun setShort(key: String, value: Short)
|
external fun setShort(key: String, value: Short)
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
external fun getUnsignedShort(key: String, needsGlobal: Boolean): Int
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
external fun setUnsignedShort(key: String, value: Int)
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
external fun getInt(key: String, needsGlobal: Boolean): Int
|
external fun getInt(key: String, needsGlobal: Boolean): Int
|
||||||
|
|
||||||
|
|||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.ui
|
package org.yuzu.yuzu_emu.ui
|
||||||
@@ -11,6 +11,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import androidx.recyclerview.widget.PagerSnapHelper
|
import androidx.recyclerview.widget.PagerSnapHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.adapters.GameAdapter
|
import org.yuzu.yuzu_emu.adapters.GameAdapter
|
||||||
import androidx.core.view.doOnNextLayout
|
import androidx.core.view.doOnNextLayout
|
||||||
@@ -34,6 +36,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
private var overlapDecoration: OverlappingDecoration? = null
|
private var overlapDecoration: OverlappingDecoration? = null
|
||||||
private var pagerSnapHelper: PagerSnapHelper? = null
|
private var pagerSnapHelper: PagerSnapHelper? = null
|
||||||
private var scalingScrollListener: OnScrollListener? = null
|
private var scalingScrollListener: OnScrollListener? = null
|
||||||
|
private var savedItemAnimator: RecyclerView.ItemAnimator? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val CAROUSEL_CARD_SIZE_FACTOR = "CarouselCardSizeMultiplier"
|
private const val CAROUSEL_CARD_SIZE_FACTOR = "CarouselCardSizeMultiplier"
|
||||||
@@ -42,8 +45,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
private const val CAROUSEL_OVERLAP_FACTOR = "CarouselOverlapFactor"
|
private const val CAROUSEL_OVERLAP_FACTOR = "CarouselOverlapFactor"
|
||||||
private const val CAROUSEL_MAX_FLING_COUNT = "CarouselMaxFlingCount"
|
private const val CAROUSEL_MAX_FLING_COUNT = "CarouselMaxFlingCount"
|
||||||
private const val CAROUSEL_FLING_MULTIPLIER = "CarouselFlingMultiplier"
|
private const val CAROUSEL_FLING_MULTIPLIER = "CarouselFlingMultiplier"
|
||||||
private const val CAROUSEL_CARDS_SCALING_SHAPE = "CarouselCardsScalingShape"
|
private const val CAROUSEL_ARC_ANGLE_STEP_DEGREES = 15.0
|
||||||
private const val CAROUSEL_CARDS_ALPHA_SHAPE = "CarouselCardsAlphaShape"
|
private const val CAROUSEL_ARC_MAX_ANGLE_DEGREES = 165.0
|
||||||
|
private const val CAROUSEL_ARC_DEPTH_MAX_ANGLE_DEGREES = 85.0
|
||||||
|
private const val CAROUSEL_ARC_DEPTH_STRETCH = 5.0f
|
||||||
|
private const val CAROUSEL_ARC_X_DEPTH_FACTOR = 0.55f
|
||||||
|
private const val CAROUSEL_ARC_FADE_OUT_START_DEGREES = 60.0
|
||||||
|
private const val CAROUSEL_ARC_FADE_OUT_END_DEGREES = 95.0
|
||||||
const val CAROUSEL_LAST_SCROLL_POSITION = "CarouselLastScrollPosition"
|
const val CAROUSEL_LAST_SCROLL_POSITION = "CarouselLastScrollPosition"
|
||||||
const val CAROUSEL_VIEW_TYPE_PORTRAIT = "GamesViewTypePortrait"
|
const val CAROUSEL_VIEW_TYPE_PORTRAIT = "GamesViewTypePortrait"
|
||||||
const val CAROUSEL_VIEW_TYPE_LANDSCAPE = "GamesViewTypeLandscape"
|
const val CAROUSEL_VIEW_TYPE_LANDSCAPE = "GamesViewTypeLandscape"
|
||||||
@@ -160,46 +168,52 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shapingFunction(x: Float, option: Int = 0): Float {
|
|
||||||
return when (option) {
|
|
||||||
0 -> 1f // Off
|
|
||||||
1 -> 1f - x // linear descending
|
|
||||||
2 -> (1f - x) * (1f - x) // Ease out
|
|
||||||
3 -> if (x < 0.05f) 1f else (1f - x) * 0.8f
|
|
||||||
4 -> kotlin.math.cos(x * Math.PI).toFloat() // Cosine
|
|
||||||
5 -> kotlin.math.cos((1.5f * x).coerceIn(0f, 1f) * Math.PI).toFloat() // Cosine 1.5x trimmed
|
|
||||||
else -> 1f // Default to Off
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateChildScaleAndAlphaForPosition(child: View) {
|
fun updateChildScaleAndAlphaForPosition(child: View) {
|
||||||
val cardSize = (adapter as? GameAdapter ?: return).cardSize
|
val cardSize = (adapter as? GameAdapter ?: return).cardSize
|
||||||
val position = getChildViewHolder(child).bindingAdapterPosition
|
val position = getChildViewHolder(child).bindingAdapterPosition
|
||||||
if (position == RecyclerView.NO_POSITION || cardSize <= 0) {
|
if (position == RecyclerView.NO_POSITION || cardSize <= 0) {
|
||||||
return // No valid position or card size
|
return // No valid position or card size
|
||||||
}
|
}
|
||||||
child.layoutParams.width = cardSize
|
val layoutParams = child.layoutParams
|
||||||
child.layoutParams.height = cardSize
|
if (layoutParams.width != cardSize || layoutParams.height != cardSize) {
|
||||||
|
child.layoutParams = layoutParams.apply {
|
||||||
|
width = cardSize
|
||||||
|
height = cardSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val signedDistance = getChildDistanceToCenter(child)
|
||||||
|
val itemStep = (cardSize - overlapPx).toFloat().coerceAtLeast(1f)
|
||||||
|
val angleStep = Math.toRadians(CAROUSEL_ARC_ANGLE_STEP_DEGREES).toFloat()
|
||||||
|
val maxAngle = Math.toRadians(CAROUSEL_ARC_MAX_ANGLE_DEGREES).toFloat()
|
||||||
|
val depthMaxAngle = Math.toRadians(CAROUSEL_ARC_DEPTH_MAX_ANGLE_DEGREES).toFloat()
|
||||||
|
val fadeOutStartAngle = Math.toRadians(CAROUSEL_ARC_FADE_OUT_START_DEGREES).toFloat()
|
||||||
|
val fadeOutEndAngle = Math.toRadians(CAROUSEL_ARC_FADE_OUT_END_DEGREES).toFloat()
|
||||||
|
val angle = (signedDistance / itemStep * angleStep).coerceIn(-maxAngle, maxAngle)
|
||||||
|
val arcRadius = itemStep / angleStep
|
||||||
|
val arcX = sin(angle) * arcRadius
|
||||||
|
val absoluteAngle = abs(angle)
|
||||||
|
val rawDepthInput = ((1f - cos(absoluteAngle)) / (1f - cos(depthMaxAngle)))
|
||||||
|
.coerceIn(0f, 1f)
|
||||||
|
val easedDepthTail = Math.pow(
|
||||||
|
(1f - rawDepthInput).toDouble(),
|
||||||
|
CAROUSEL_ARC_DEPTH_STRETCH.toDouble()
|
||||||
|
).toFloat()
|
||||||
|
val depthInput = (1f - easedDepthTail).coerceIn(0f, 1f)
|
||||||
|
val projectedArcX = arcX * (1f - rawDepthInput * CAROUSEL_ARC_X_DEPTH_FACTOR)
|
||||||
|
|
||||||
|
child.animate().cancel()
|
||||||
|
child.translationX = projectedArcX - signedDistance
|
||||||
|
|
||||||
val center = getRecyclerViewCenter()
|
|
||||||
val distance = abs(getChildDistanceToCenter(child))
|
|
||||||
val internalBorderScale = resources.getFraction(R.fraction.carousel_bordercards_scale, 1, 1)
|
val internalBorderScale = resources.getFraction(R.fraction.carousel_bordercards_scale, 1, 1)
|
||||||
val borderScale = preferences.getFloat(CAROUSEL_BORDERCARDS_SCALE, internalBorderScale).coerceIn(
|
val borderScale = preferences.getFloat(CAROUSEL_BORDERCARDS_SCALE, internalBorderScale).coerceIn(
|
||||||
0f,
|
0f,
|
||||||
1f
|
1f
|
||||||
)
|
)
|
||||||
|
|
||||||
val shapeInput = (distance / center).coerceIn(0f, 1f)
|
val shapedScaling = 1f - depthInput
|
||||||
val internalShapeSetting = resources.getInteger(R.integer.carousel_cards_scaling_shape)
|
|
||||||
val scalingShapeSetting = preferences.getInt(
|
|
||||||
CAROUSEL_CARDS_SCALING_SHAPE,
|
|
||||||
internalShapeSetting
|
|
||||||
)
|
|
||||||
val shapedScaling = shapingFunction(shapeInput, scalingShapeSetting)
|
|
||||||
val scale = (borderScale + (1f - borderScale) * shapedScaling).coerceIn(0f, 1f)
|
val scale = (borderScale + (1f - borderScale) * shapedScaling).coerceIn(0f, 1f)
|
||||||
|
|
||||||
val maxDistance = width / 2f
|
|
||||||
val alphaInput = (distance / maxDistance).coerceIn(0f, 1f)
|
|
||||||
val internalBordersAlpha = resources.getFraction(
|
val internalBordersAlpha = resources.getFraction(
|
||||||
R.fraction.carousel_bordercards_alpha,
|
R.fraction.carousel_bordercards_alpha,
|
||||||
1,
|
1,
|
||||||
@@ -209,15 +223,12 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
0f,
|
0f,
|
||||||
1f
|
1f
|
||||||
)
|
)
|
||||||
val internalAlphaShapeSetting = resources.getInteger(R.integer.carousel_cards_alpha_shape)
|
val shapedAlpha = cos(depthInput * Math.PI).toFloat()
|
||||||
val alphaShapeSetting = preferences.getInt(
|
val baseAlpha = (borderAlpha + (1f - borderAlpha) * shapedAlpha).coerceIn(0f, 1f)
|
||||||
CAROUSEL_CARDS_ALPHA_SHAPE,
|
val rearPresence = (1f - (absoluteAngle - fadeOutStartAngle) /
|
||||||
internalAlphaShapeSetting
|
(fadeOutEndAngle - fadeOutStartAngle)).coerceIn(0f, 1f)
|
||||||
)
|
val alpha = (baseAlpha * rearPresence).coerceIn(0f, 1f)
|
||||||
val shapedAlpha = shapingFunction(alphaInput, alphaShapeSetting)
|
|
||||||
val alpha = (borderAlpha + (1f - borderAlpha) * shapedAlpha).coerceIn(0f, 1f)
|
|
||||||
|
|
||||||
child.animate().cancel()
|
|
||||||
child.alpha = alpha
|
child.alpha = alpha
|
||||||
child.scaleX = scale
|
child.scaleX = scale
|
||||||
child.scaleY = scale
|
child.scaleY = scale
|
||||||
@@ -273,7 +284,9 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
0f,
|
0f,
|
||||||
1f
|
1f
|
||||||
)
|
)
|
||||||
return (userFactor * (height - bottomInset)).toInt()
|
val scaledHeight = height * userFactor
|
||||||
|
val availableHeight = height - bottomInset
|
||||||
|
return minOf(scaledHeight.toInt(), availableHeight.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupCarousel(enabled: Boolean) {
|
fun setupCarousel(enabled: Boolean) {
|
||||||
@@ -282,6 +295,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
if (gameAdapter.cardSize == 0) return
|
if (gameAdapter.cardSize == 0) return
|
||||||
if (bottomInset < 0) return
|
if (bottomInset < 0) return
|
||||||
|
|
||||||
|
itemAnimator?.let {
|
||||||
|
if (savedItemAnimator == null) {
|
||||||
|
savedItemAnimator = it
|
||||||
|
}
|
||||||
|
itemAnimator = null
|
||||||
|
}
|
||||||
|
|
||||||
useCustomDrawingOrder = true
|
useCustomDrawingOrder = true
|
||||||
val cardSize = gameAdapter.cardSize
|
val cardSize = gameAdapter.cardSize
|
||||||
|
|
||||||
@@ -336,6 +356,12 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
// Detach PagerSnapHelper
|
// Detach PagerSnapHelper
|
||||||
pagerSnapHelper?.attachToRecyclerView(null)
|
pagerSnapHelper?.attachToRecyclerView(null)
|
||||||
pagerSnapHelper = null
|
pagerSnapHelper = null
|
||||||
|
savedItemAnimator?.let {
|
||||||
|
if (itemAnimator == null) {
|
||||||
|
itemAnimator = it
|
||||||
|
}
|
||||||
|
savedItemAnimator = null
|
||||||
|
}
|
||||||
useCustomDrawingOrder = false
|
useCustomDrawingOrder = false
|
||||||
// Reset padding and fling
|
// Reset padding and fling
|
||||||
setPadding(0, 0, 0, 0)
|
setPadding(0, 0, 0, 0)
|
||||||
@@ -344,6 +370,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
|
|||||||
// Reset scaling
|
// Reset scaling
|
||||||
for (i in 0 until childCount) {
|
for (i in 0 until childCount) {
|
||||||
val child = getChildAt(i)
|
val child = getChildAt(i)
|
||||||
|
child?.translationX = 0f
|
||||||
child?.scaleX = 1f
|
child?.scaleX = 1f
|
||||||
child?.scaleY = 1f
|
child?.scaleY = 1f
|
||||||
child?.alpha = 1f
|
child?.alpha = 1f
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ void AndroidConfig::SaveAllValues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AndroidConfig::ReadAndroidValues() {
|
void AndroidConfig::ReadAndroidValues() {
|
||||||
|
ReadAndroidUIValues();
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadAndroidUIValues();
|
|
||||||
ReadUIValues();
|
ReadUIValues();
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||||
Settings::values.ext_content_from_game_dirs = ReadBooleanSetting(
|
Settings::values.ext_content_from_game_dirs = ReadBooleanSetting(
|
||||||
@@ -223,8 +223,8 @@ void AndroidConfig::ReadAndroidControlValues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AndroidConfig::SaveAndroidValues() {
|
void AndroidConfig::SaveAndroidValues() {
|
||||||
|
SaveAndroidUIValues();
|
||||||
if (global) {
|
if (global) {
|
||||||
SaveAndroidUIValues();
|
|
||||||
SaveUIValues();
|
SaveUIValues();
|
||||||
SaveOverlayValues();
|
SaveOverlayValues();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ namespace AndroidSettings {
|
|||||||
&show_performance_overlay};
|
&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::Category::Android,
|
||||||
Settings::Specialization::Default,
|
Settings::Specialization::Default,
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -124,9 +124,18 @@ float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
|||||||
return QuantizeFrameRateHint(verified_rate);
|
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 {
|
float EmuWindow_Android::GetFrameRateHint() const {
|
||||||
const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f);
|
const float presented_multiplier = GetPresentedFrameMultiplier();
|
||||||
const float frame_time_verified_hint = GetFrameTimeVerifiedHint();
|
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) {
|
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);
|
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;
|
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()) {
|
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||||
return NominalFrameRate;
|
return QuantizeFrameRateHint(nominal_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u16 speed_limit = Settings::SpeedLimit();
|
const u16 speed_limit = Settings::SpeedLimit();
|
||||||
@@ -161,7 +170,7 @@ float EmuWindow_Android::GetFrameRateHint() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float speed_limited_rate =
|
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);
|
return QuantizeFrameRateHint(speed_limited_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ private:
|
|||||||
void UpdateObservedFrameRate();
|
void UpdateObservedFrameRate();
|
||||||
[[nodiscard]] float GetFrameRateHint() const;
|
[[nodiscard]] float GetFrameRateHint() const;
|
||||||
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
|
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
|
||||||
|
[[nodiscard]] static float GetPresentedFrameMultiplier();
|
||||||
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
||||||
|
|
||||||
float m_window_width{};
|
float m_window_width{};
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ extern "C" {
|
|||||||
#include "common/android/android_common.h"
|
#include "common/android/android_common.h"
|
||||||
#include "common/android/id_cache.h"
|
#include "common/android/id_cache.h"
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
|
#include "common/fs/fs_util.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
@@ -75,6 +76,7 @@ extern "C" {
|
|||||||
#include "core/frontend/applets/software_keyboard.h"
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "common/android/applets/web_browser.h"
|
#include "common/android/applets/web_browser.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
@@ -90,6 +92,7 @@ extern "C" {
|
|||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
#include "input_common/drivers/virtual_amiibo.h"
|
#include "input_common/drivers/virtual_amiibo.h"
|
||||||
#include "jni/native.h"
|
#include "jni/native.h"
|
||||||
|
#include "video_core/frame_gen/lossless_dll.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
#include "video_core/capture.h"
|
#include "video_core/capture.h"
|
||||||
@@ -309,11 +312,23 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
ConfigureFilesystemProvider(filepath);
|
ConfigureFilesystemProvider(filepath);
|
||||||
|
|
||||||
// Load the ROM.
|
// Load the ROM.
|
||||||
|
const u64 previous_program_id =
|
||||||
|
program_index != 0 && m_next_program_id.load() >
|
||||||
|
static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)
|
||||||
|
? m_next_program_id.load()
|
||||||
|
: 0;
|
||||||
|
|
||||||
Service::AM::FrontendAppletParameters params{
|
Service::AM::FrontendAppletParameters params{
|
||||||
|
.program_id = previous_program_id,
|
||||||
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||||
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
||||||
: Service::AM::LaunchType::ApplicationInitiated,
|
: Service::AM::LaunchType::ApplicationInitiated,
|
||||||
.program_index = static_cast<s32>(program_index),
|
.program_index = static_cast<s32>(program_index),
|
||||||
|
.previous_program_index =
|
||||||
|
previous_program_id != 0
|
||||||
|
? static_cast<s32>(previous_program_id -
|
||||||
|
FileSys::GetBaseTitleID(previous_program_id))
|
||||||
|
: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||||
@@ -326,8 +341,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
m_system.GetCpuManager().OnGpuReady();
|
m_system.GetCpuManager().OnGpuReady();
|
||||||
m_system.RegisterExitCallback([&] { HaltEmulation(); });
|
m_system.RegisterExitCallback([&] { HaltEmulation(); });
|
||||||
|
|
||||||
|
m_system.RegisterApplicationChangedCallback(
|
||||||
|
[&](u64 changed_program_id) { RequestDiskShaderCacheReload(changed_program_id); });
|
||||||
|
|
||||||
// Register an ExecuteProgram callback such that Core can execute a sub-program
|
// Register an ExecuteProgram callback such that Core can execute a sub-program
|
||||||
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
|
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
|
||||||
|
m_next_program_id = m_system.GetApplicationProcessProgramID();
|
||||||
m_next_program_index = program_index_;
|
m_next_program_index = program_index_;
|
||||||
EmulationSession::GetInstance().HaltEmulation();
|
EmulationSession::GetInstance().HaltEmulation();
|
||||||
});
|
});
|
||||||
@@ -405,20 +424,58 @@ void EmulationSession::RunEmulation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
std::optional<u64> reload_title;
|
||||||
{
|
{
|
||||||
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
[[maybe_unused]] std::unique_lock lock(m_mutex);
|
||||||
if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
|
if (m_cv.wait_for(lock, std::chrono::milliseconds(800), [&]() {
|
||||||
[&]() { return !m_is_running; })) {
|
return !m_is_running || m_pending_shader_cache_title.has_value();
|
||||||
// Emulation halted.
|
})) {
|
||||||
break;
|
if (!m_is_running) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reload_title = std::exchange(m_pending_shader_cache_title, std::nullopt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reload_title.has_value())
|
||||||
|
ReloadDiskShaderCache(*reload_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset current applet ID.
|
// Reset current applet ID.
|
||||||
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
|
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulationSession::RequestDiskShaderCacheReload(u64 program_id) {
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(m_mutex);
|
||||||
|
m_pending_shader_cache_title = program_id;
|
||||||
|
}
|
||||||
|
m_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulationSession::ReloadDiskShaderCache(u64 program_id) {
|
||||||
|
if (!Settings::values.use_disk_shader_cache.GetValue())
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG_INFO(Frontend, "Reloading disk shader cache for {:016X}", program_id);
|
||||||
|
|
||||||
|
const bool was_paused = m_is_paused;
|
||||||
|
|
||||||
|
m_system.Pause();
|
||||||
|
m_system.GPU().WaitForIdle();
|
||||||
|
m_system.GPU().ObtainContext();
|
||||||
|
|
||||||
|
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||||
|
m_system.Renderer().ReadRasterizer()->LoadDiskResources(program_id, std::stop_token{},
|
||||||
|
LoadDiskCacheProgress);
|
||||||
|
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
|
||||||
|
|
||||||
|
m_system.GPU().ReleaseContext();
|
||||||
|
|
||||||
|
if (!was_paused)
|
||||||
|
m_system.Run();
|
||||||
|
}
|
||||||
|
|
||||||
Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
|
Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
|
||||||
return m_software_keyboard;
|
return m_software_keyboard;
|
||||||
}
|
}
|
||||||
@@ -998,7 +1055,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
|
|||||||
FILE* f = std::fopen(CPUINFO_PATH, "r");
|
FILE* f = std::fopen(CPUINFO_PATH, "r");
|
||||||
if (!f) return Common::Android::ToJString(env, result);
|
if (!f) return Common::Android::ToJString(env, result);
|
||||||
|
|
||||||
char buf[512];
|
char buf[4096];
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
std::set<std::string> feature_set;
|
std::set<std::string> feature_set;
|
||||||
@@ -1029,7 +1086,13 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
|
|||||||
bool has_dotprod = feature_set.count("asimddp") || feature_set.count("dotprod");
|
bool has_dotprod = feature_set.count("asimddp") || feature_set.count("dotprod");
|
||||||
bool has_i8mm = feature_set.count("i8mm");
|
bool has_i8mm = feature_set.count("i8mm");
|
||||||
bool has_bf16 = feature_set.count("bf16");
|
bool has_bf16 = feature_set.count("bf16");
|
||||||
|
bool has_fp16 = feature_set.count("fphp") || feature_set.count("asimdhp");
|
||||||
bool has_atomics = feature_set.count("atomics") || feature_set.count("lse");
|
bool has_atomics = feature_set.count("atomics") || feature_set.count("lse");
|
||||||
|
bool has_lse2 = feature_set.count("uscat");
|
||||||
|
bool has_rcpc = feature_set.count("lrcpc");
|
||||||
|
bool has_rcpc2 = feature_set.count("ilrcpc");
|
||||||
|
bool has_flagm = feature_set.count("flagm");
|
||||||
|
bool has_flagm2 = feature_set.count("flagm2");
|
||||||
|
|
||||||
std::string features;
|
std::string features;
|
||||||
if (has_neon || has_fp) {
|
if (has_neon || has_fp) {
|
||||||
@@ -1037,6 +1100,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
|
|||||||
if (has_dotprod) features += "+DP";
|
if (has_dotprod) features += "+DP";
|
||||||
if (has_i8mm) features += "+I8MM";
|
if (has_i8mm) features += "+I8MM";
|
||||||
if (has_bf16) features += "+BF16";
|
if (has_bf16) features += "+BF16";
|
||||||
|
if (has_fp16) features += "+FP16";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_sve) {
|
if (has_sve) {
|
||||||
@@ -1053,6 +1117,19 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
|
|||||||
if (has_atomics) {
|
if (has_atomics) {
|
||||||
if (!features.empty()) features += " | ";
|
if (!features.empty()) features += " | ";
|
||||||
features += "LSE";
|
features += "LSE";
|
||||||
|
if (has_lse2) features += "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_rcpc) {
|
||||||
|
if (!features.empty()) features += " | ";
|
||||||
|
features += "RCpc";
|
||||||
|
if (has_rcpc2) features += "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_flagm) {
|
||||||
|
if (!features.empty()) features += " | ";
|
||||||
|
features += "FlagM";
|
||||||
|
if (has_flagm2) features += "2";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!features.empty()) {
|
if (!features.empty()) {
|
||||||
@@ -1090,6 +1167,34 @@ VkPhysicalDeviceProperties GetVulkanDeviceProperties() {
|
|||||||
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
|
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
|
||||||
return physical_device.GetProperties();
|
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
|
} // namespace
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanDriverVersion(JNIEnv* env, jobject jobj) {
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanDriverVersion(JNIEnv* env, jobject jobj) {
|
||||||
@@ -1165,6 +1270,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) {
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuModel(JNIEnv* env, jobject jobj) {
|
||||||
const auto props = GetVulkanDeviceProperties();
|
const auto props = GetVulkanDeviceProperties();
|
||||||
if (props.deviceID == 0) {
|
if (props.deviceID == 0) {
|
||||||
@@ -1187,8 +1300,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jo
|
|||||||
Common::RefreshThreadPolicies();
|
Common::RefreshThreadPolicies();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
|
||||||
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
|
return static_cast<jboolean>(Settings::GetDebugKnobAt(static_cast<u8>(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
||||||
@@ -1390,6 +1503,39 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz
|
|||||||
return static_cast<int>(FirmwareManager::InstallKeys(path, ext));
|
return static_cast<int>(FirmwareManager::InstallKeys(path, ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getLosslessDllPath(JNIEnv* env, jclass clazz) {
|
||||||
|
#ifdef HAS_LSFG
|
||||||
|
const auto path = VideoCore::FrameGen::GetLosslessDllPath();
|
||||||
|
return Common::Android::ToJString(env, Common::FS::PathToUTF8String(path));
|
||||||
|
#else
|
||||||
|
return Common::Android::ToJString(env, "");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_validateLosslessDll(JNIEnv* env, jclass clazz) {
|
||||||
|
#ifdef HAS_LSFG
|
||||||
|
return static_cast<jint>(VideoCore::FrameGen::GetInstalledLosslessStatus());
|
||||||
|
#else
|
||||||
|
return static_cast<jint>(VideoCore::FrameGen::LosslessStatus::NotInstalled);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_prepareLosslessDll(JNIEnv* env, jclass clazz) {
|
||||||
|
#ifdef HAS_LSFG
|
||||||
|
return static_cast<jint>(VideoCore::FrameGen::BuildShaderCache());
|
||||||
|
#else
|
||||||
|
return static_cast<jint>(VideoCore::FrameGen::LosslessStatus::NotInstalled);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_removeLosslessDll(JNIEnv* env, jclass clazz) {
|
||||||
|
#ifdef HAS_LSFG
|
||||||
|
return static_cast<jboolean>(VideoCore::FrameGen::RemoveInstalledLosslessDll());
|
||||||
|
#else
|
||||||
|
return static_cast<jboolean>(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
|
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
|
||||||
jstring jpath,
|
jstring jpath,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
#include "common/android/applets/software_keyboard.h"
|
#include "common/android/applets/software_keyboard.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
@@ -44,6 +46,7 @@ public:
|
|||||||
void HaltEmulation();
|
void HaltEmulation();
|
||||||
void RunEmulation();
|
void RunEmulation();
|
||||||
void ShutdownEmulation();
|
void ShutdownEmulation();
|
||||||
|
void RequestDiskShaderCacheReload(u64 program_id);
|
||||||
|
|
||||||
const Core::PerfStatsResults& PerfStats();
|
const Core::PerfStatsResults& PerfStats();
|
||||||
int ShadersBuilding();
|
int ShadersBuilding();
|
||||||
@@ -65,6 +68,7 @@ private:
|
|||||||
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
||||||
static void OnEmulationStopped(Core::SystemResultStatus result);
|
static void OnEmulationStopped(Core::SystemResultStatus result);
|
||||||
static void ChangeProgram(std::size_t program_index);
|
static void ChangeProgram(std::size_t program_index);
|
||||||
|
void ReloadDiskShaderCache(u64 program_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Window management
|
// Window management
|
||||||
@@ -83,6 +87,7 @@ private:
|
|||||||
Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
|
Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
|
||||||
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
|
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
|
||||||
int m_applet_id{1};
|
int m_applet_id{1};
|
||||||
|
std::optional<u64> m_pending_shader_cache_title;
|
||||||
|
|
||||||
// GPU driver parameters
|
// GPU driver parameters
|
||||||
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
|
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
|
||||||
@@ -93,4 +98,5 @@ private:
|
|||||||
|
|
||||||
// Program index for next boot
|
// Program index for next boot
|
||||||
std::atomic<s32> m_next_program_index = -1;
|
std::atomic<s32> m_next_program_index = -1;
|
||||||
|
std::atomic<u64> m_next_program_id = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -130,6 +130,25 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject ob
|
|||||||
setting->SetValue(value);
|
setting->SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getUnsignedShort(JNIEnv* env, jobject obj,
|
||||||
|
jstring jkey,
|
||||||
|
jboolean needGlobal) {
|
||||||
|
auto setting = getSetting<u16>(env, jkey);
|
||||||
|
if (setting == nullptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return static_cast<jint>(setting->GetValue(static_cast<bool>(needGlobal)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setUnsignedShort(JNIEnv* env, jobject obj,
|
||||||
|
jstring jkey, jint value) {
|
||||||
|
auto setting = getSetting<u16>(env, jkey);
|
||||||
|
if (setting == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setting->SetValue(static_cast<u16>(value));
|
||||||
|
}
|
||||||
|
|
||||||
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
|
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
|
||||||
jboolean needGlobal) {
|
jboolean needGlobal) {
|
||||||
auto setting = getSetting<int>(env, jkey);
|
auto setting = getSetting<int>(env, jkey);
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true" android:color="?attr/colorControlHighlight" />
|
||||||
|
<item android:state_focused="true" android:color="@android:color/transparent" />
|
||||||
|
<item android:state_selected="true" android:color="@android:color/transparent" />
|
||||||
|
<item android:state_hovered="true" android:color="@android:color/transparent" />
|
||||||
|
<item android:color="@android:color/transparent" />
|
||||||
|
</selector>
|
||||||
@@ -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>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
android:clipChildren="true"
|
android:clipChildren="true"
|
||||||
android:layout_margin="0dp"
|
android:layout_margin="0dp"
|
||||||
app:cardBackgroundColor="@color/eden_card_background"
|
app:cardBackgroundColor="@color/eden_card_background"
|
||||||
|
app:rippleColor="@color/game_card_ripple"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="@color/eden_border">
|
app:strokeColor="@color/eden_border">
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardPreventCornerOverlap="true"
|
app:cardPreventCornerOverlap="true"
|
||||||
android:clipChildren="true"
|
android:clipChildren="true"
|
||||||
|
app:rippleColor="@color/game_card_ripple"
|
||||||
android:layout_margin="4dp">
|
android:layout_margin="4dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:transitionName="card_game"
|
android:transitionName="card_game"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
|
app:rippleColor="@color/game_card_ripple"
|
||||||
android:foreground="@color/eden_border_gradient_start">
|
android:foreground="@color/eden_border_gradient_start">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:transitionName="card_game_compact"
|
android:transitionName="card_game_compact"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
|
app:rippleColor="@color/game_card_ripple"
|
||||||
android:foreground="@color/eden_border_gradient_start">
|
android:foreground="@color/eden_border_gradient_start">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="0dp"
|
||||||
app:cardBackgroundColor="@android:color/transparent"
|
app:cardBackgroundColor="@android:color/transparent"
|
||||||
|
app:rippleColor="@color/game_card_ripple"
|
||||||
app:strokeWidth="0dp">
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appbar_lossless"
|
||||||
|
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar_lossless"
|
||||||
|
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
app:title="@string/lossless_scaling" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/scroll_view_lossless"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:defaultFocusHighlightEnabled="false"
|
||||||
|
android:fadeScrollbars="false"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/appbar_lossless">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/lossless_options_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false" />
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -47,6 +47,12 @@
|
|||||||
android:defaultValue="@null" />
|
android:defaultValue="@null" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/losslessManagerFragment"
|
||||||
|
android:name="org.yuzu.yuzu_emu.fragments.LosslessManagerFragment"
|
||||||
|
android:label="@string/lossless_scaling"
|
||||||
|
tools:layout="@layout/fragment_lossless_manager" />
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/appletLauncherFragment"
|
android:id="@+id/appletLauncherFragment"
|
||||||
android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment"
|
android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment"
|
||||||
|
|||||||
@@ -291,6 +291,22 @@
|
|||||||
<string name="gpu_driver_fetcher">أداة جلب برامج تشغيل وحدة المعالجة الرسومية</string>
|
<string name="gpu_driver_fetcher">أداة جلب برامج تشغيل وحدة المعالجة الرسومية</string>
|
||||||
<string name="gpu_driver_manager">إدارة برامج تشغيل وحدة معالجة الرسومات</string>
|
<string name="gpu_driver_manager">إدارة برامج تشغيل وحدة معالجة الرسومات</string>
|
||||||
<string name="install_gpu_driver_description">تثبيت برامج تشغيل بديلة لأداء أو دقة أفضل</string>
|
<string name="install_gpu_driver_description">تثبيت برامج تشغيل بديلة لأداء أو دقة أفضل</string>
|
||||||
|
<string name="frame_gen">توليد الإطار</string>
|
||||||
|
<string name="frame_gen_per_game_description">تكوين إعدادات إنشاء الإطارات لهذه اللعبة</string>
|
||||||
|
<string name="frame_gen_description">قم بإدراج الإطارات المُستكملة بين الإطارات المُعالجة باستخدام تقنية التحجيم بدون فقدان الجودة. يُفرض هذا الخيار عرض الإطارات وفقًا لترتيب FIFO عند تفعيله.</string>
|
||||||
|
<string name="frame_gen_multiplier">مضاعف الإطارات</string>
|
||||||
|
<string name="frame_gen_multiplier_description">عدد الإطارات المطلوب عرضها لكل إطار مُعالَج. تتطلب القيم الأعلى وقت معالجة رسوميات أكبر. طلب عدد إطارات يفوق قدرة الشاشة على عرضه سيؤدي إلى إبطاء المحاكاة.</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_target_rate">معدل الإطارات المستهدف</string>
|
||||||
|
<string name="frame_gen_target_rate_off">استخدم مضاعفًا ثابتًا</string>
|
||||||
|
<string name="frame_gen_target_rate_60">60 إطارًا في الثانية</string>
|
||||||
|
<string name="frame_gen_target_rate_90">90 إطارًا في الثانية</string>
|
||||||
|
<string name="frame_gen_target_rate_120">120 إطارًا في الثانية</string>
|
||||||
|
<string name="frame_gen_target_rate_144">144 إطارًا في الثانية</string>
|
||||||
|
<string name="frame_gen_target_rate_165">165 إطارًا في الثانية</string>
|
||||||
|
<string name="frame_gen_queue_target">هدف قائمة انتظار الإطارات</string>
|
||||||
<string name="advanced_settings">الإعدادات المتقدمة</string>
|
<string name="advanced_settings">الإعدادات المتقدمة</string>
|
||||||
<string name="settings_description">ضبط إعدادات المحاكي</string>
|
<string name="settings_description">ضبط إعدادات المحاكي</string>
|
||||||
<string name="search_recently_played">تم تشغيلها مؤخرًا</string>
|
<string name="search_recently_played">تم تشغيلها مؤخرًا</string>
|
||||||
@@ -1091,7 +1107,6 @@
|
|||||||
<string name="theme_mode_light">فاتح</string>
|
<string name="theme_mode_light">فاتح</string>
|
||||||
<string name="theme_mode_dark">داكن</string>
|
<string name="theme_mode_dark">داكن</string>
|
||||||
|
|
||||||
<string name="multiplier_none">لا شيء</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
||||||
|
|||||||
@@ -991,7 +991,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="theme_mode_light">Hell</string>
|
<string name="theme_mode_light">Hell</string>
|
||||||
<string name="theme_mode_dark">Dunkel</string>
|
<string name="theme_mode_dark">Dunkel</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Keine</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
||||||
|
|||||||
@@ -291,6 +291,23 @@
|
|||||||
<string name="gpu_driver_fetcher">Obtenedor de controladores de la GPU</string>
|
<string name="gpu_driver_fetcher">Obtenedor de controladores de la GPU</string>
|
||||||
<string name="gpu_driver_manager">Gestor de controladores de la GPU</string>
|
<string name="gpu_driver_manager">Gestor de controladores de la GPU</string>
|
||||||
<string name="install_gpu_driver_description">Instale los controladores alternativos para obtener un posible mejor rendimiento o precisión</string>
|
<string name="install_gpu_driver_description">Instale los controladores alternativos para obtener un posible mejor rendimiento o precisión</string>
|
||||||
|
<string name="frame_gen">Generación de fotograma</string>
|
||||||
|
<string name="frame_gen_multiplier">Multiplicador de fotograma</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_target_rate_60">60 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_90">90 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_120">120 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_144">144 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_165">165 FPS</string>
|
||||||
|
<string name="frame_gen_queue_target_1">Equilibrado (1 fotograma)</string>
|
||||||
|
<string name="frame_generation_support">Generación de fotograma</string>
|
||||||
|
<string name="frame_generation_supported">Soportado</string>
|
||||||
|
<string name="lossless_scaling">Escalado sin pérdidas</string>
|
||||||
|
<string name="lossless_scaling_installed">Instalado</string>
|
||||||
|
<string name="lossless_scaling_not_installed">No instalado</string>
|
||||||
|
<string name="lossless_scaling_missing">Lossless.dll no instalado</string>
|
||||||
<string name="advanced_settings">Ajustes avanzados</string>
|
<string name="advanced_settings">Ajustes avanzados</string>
|
||||||
<string name="settings_description">Configurar los ajustes del emulador</string>
|
<string name="settings_description">Configurar los ajustes del emulador</string>
|
||||||
<string name="search_recently_played">Jugado recientemente</string>
|
<string name="search_recently_played">Jugado recientemente</string>
|
||||||
@@ -1075,7 +1092,6 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Oscuro</string>
|
<string name="theme_mode_dark">Oscuro</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Nada</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Fondos oscuros</string>
|
<string name="use_black_backgrounds">Fondos oscuros</string>
|
||||||
|
|||||||
@@ -808,9 +808,6 @@
|
|||||||
<string name="multiplier_x4">x4</string>
|
<string name="multiplier_x4">x4</string>
|
||||||
<string name="multiplier_x8">x8</string>
|
<string name="multiplier_x8">x8</string>
|
||||||
<string name="multiplier_x16">x16</string>
|
<string name="multiplier_x16">x16</string>
|
||||||
<string name="multiplier_x32">x32</string>
|
|
||||||
<string name="multiplier_x64">x64</string>
|
|
||||||
<string name="multiplier_none">None</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">پسزمینه مشکی</string>
|
<string name="use_black_backgrounds">پسزمینه مشکی</string>
|
||||||
|
|||||||
@@ -1004,7 +1004,6 @@
|
|||||||
<string name="theme_mode_light">Lumineux</string>
|
<string name="theme_mode_light">Lumineux</string>
|
||||||
<string name="theme_mode_dark">Sombre</string>
|
<string name="theme_mode_dark">Sombre</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Aucun</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
||||||
|
|||||||
@@ -935,7 +935,6 @@
|
|||||||
<string name="theme_mode_light">Jasny</string>
|
<string name="theme_mode_light">Jasny</string>
|
||||||
<string name="theme_mode_dark">Ciemny</string>
|
<string name="theme_mode_dark">Ciemny</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Brak</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Czarne tła</string>
|
<string name="use_black_backgrounds">Czarne tła</string>
|
||||||
|
|||||||
@@ -891,7 +891,6 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Escuro</string>
|
<string name="theme_mode_dark">Escuro</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Nenhum</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
||||||
|
|||||||
@@ -1071,7 +1071,6 @@
|
|||||||
<string name="theme_mode_light">Светлая</string>
|
<string name="theme_mode_light">Светлая</string>
|
||||||
<string name="theme_mode_dark">Темная</string>
|
<string name="theme_mode_dark">Темная</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Отключено</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чёрный фон</string>
|
<string name="use_black_backgrounds">Чёрный фон</string>
|
||||||
|
|||||||
@@ -1053,7 +1053,6 @@
|
|||||||
<string name="theme_mode_light">Світла</string>
|
<string name="theme_mode_light">Світла</string>
|
||||||
<string name="theme_mode_dark">Темна</string>
|
<string name="theme_mode_dark">Темна</string>
|
||||||
|
|
||||||
<string name="multiplier_none">Жодного</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чорний фон</string>
|
<string name="use_black_backgrounds">Чорний фон</string>
|
||||||
|
|||||||
@@ -1081,7 +1081,6 @@
|
|||||||
<string name="theme_mode_light">浅色</string>
|
<string name="theme_mode_light">浅色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
<string name="multiplier_none">无</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">使用黑色背景</string>
|
<string name="use_black_backgrounds">使用黑色背景</string>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
<string name="use_sync_core">同步核心速度</string>
|
<string name="use_sync_core">同步核心速度</string>
|
||||||
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
|
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
|
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
|
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速客體程式的記憶體存取。啟用後,客體記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
|
||||||
<string name="debug_knobs">偵錯開關</string>
|
<string name="debug_knobs">偵錯開關</string>
|
||||||
<string name="debug_knobs_description">僅限開發用途</string>
|
<string name="debug_knobs_description">僅限開發用途</string>
|
||||||
<string name="debug_knobs_hint">0到65535</string>
|
<string name="debug_knobs_hint">0到65535</string>
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
|
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
|
||||||
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
|
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
|
||||||
<string name="multiplayer_port_error">埠號需為1-65535</string>
|
<string name="multiplayer_port_error">埠號需為1-65535</string>
|
||||||
<string name="cancel">略過</string>
|
<string name="cancel">取消</string>
|
||||||
<string name="ok">確定</string>
|
<string name="ok">確定</string>
|
||||||
<string name="refresh">重新整理</string>
|
<string name="refresh">重新整理</string>
|
||||||
<string name="room_list">房間列表</string>
|
<string name="room_list">房間列表</string>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<string name="notification_no_directory_link">無法開啟 Eden 目錄</string>
|
<string name="notification_no_directory_link">無法開啟 Eden 目錄</string>
|
||||||
<string name="notification_no_directory_link_description">請使用檔案管理員的側邊面板手動定位到使用者資料夾</string>
|
<string name="notification_no_directory_link_description">請使用檔案管理員的側邊面板手動定位到使用者資料夾</string>
|
||||||
<string name="manage_save_data">管理儲存資料</string>
|
<string name="manage_save_data">管理儲存資料</string>
|
||||||
<string name="manage_save_data_description">導入/導出遊戲的儲存資料\n\n壓縮檔中首個子資料夾名稱必須為遊戲 ID</string>
|
<string name="manage_save_data_description">導入/導出遊戲的儲存資料\n壓縮檔必須為.zip格式\n壓縮檔中首個子資料夾名稱必須為遊戲 ID</string>
|
||||||
<string name="import_save_warning">導入儲存資料</string>
|
<string name="import_save_warning">導入儲存資料</string>
|
||||||
<string name="import_save_warning_description">這將會以提供的檔案覆寫現有的該遊戲儲存資料,您確定要繼續嗎?</string>
|
<string name="import_save_warning_description">這將會以提供的檔案覆寫現有的該遊戲儲存資料,您確定要繼續嗎?</string>
|
||||||
<string name="save_files_importing">正在導入儲存資料…</string>
|
<string name="save_files_importing">正在導入儲存資料…</string>
|
||||||
@@ -433,6 +433,9 @@
|
|||||||
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
|
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
|
||||||
<string name="set_custom_rtc">設定自訂 RTC</string>
|
<string name="set_custom_rtc">設定自訂 RTC</string>
|
||||||
|
|
||||||
|
<!-- CPU -->
|
||||||
|
<string name="fast_cpu_time">CPU 時脈</string>
|
||||||
|
<string name="fast_cpu_time_description">提高模擬 CPU 回報的時脈,可以減少某些 FPS 限制。較弱的 CPU 可能會出現效能下降的情況,部分遊戲可能會出現異常</string>
|
||||||
<string name="custom_cpu_ticks">自訂CPU時脈</string>
|
<string name="custom_cpu_ticks">自訂CPU時脈</string>
|
||||||
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
|
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
|
||||||
<string name="cpu_ticks">時脈</string>
|
<string name="cpu_ticks">時脈</string>
|
||||||
@@ -479,16 +482,56 @@
|
|||||||
<string name="renderer_force_max_clock">強制使用最大時脈 (僅限Adreno)</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_asynchronous_gpu_emulation">GPU 非同步模擬</string>
|
<string name="renderer_asynchronous_gpu_emulation">GPU 非同步模擬</string>
|
||||||
<string name="renderer_asynchronous_gpu_emulation_description">此修改可透過使用 GPU 非同步模擬來提升性能,不過可能會導致圖形問題且會提高在進行時序相關操作時崩潰的機率</string>
|
<string name="renderer_asynchronous_gpu_emulation_description">此修改可透過使用 GPU 非同步模擬來提升性能,不過可能會導致圖形問題且會提高在進行時序相關操作時當機的機率</string>
|
||||||
|
<string name="renderer_async_presentation">非同步呈現</string>
|
||||||
|
<string name="renderer_async_presentation_description">此修改可以透過將渲染移至單獨的 CPU 執行緒來提升性能,但可能會導致圖形問題</string>
|
||||||
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
|
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
|
||||||
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
|
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
|
||||||
|
<string name="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="use_optimized_vertex_buffers">最佳化頂點緩衝區</string>
|
||||||
|
<string name="use_optimized_vertex_buffers_description">啟用最佳化的頂點緩衝區綁定。需要安裝 Mesa 26.0+ Turnip drivers/Qualcomm drivers。使用舊版 Turnip drivers 會導致當機 (25.3版和更低的版本)</string>
|
||||||
|
|
||||||
|
<string name="hacks">修改</string>
|
||||||
|
|
||||||
|
<string name="fast_gpu_time">GPU 時脈</string>
|
||||||
|
<string name="fast_gpu_time_description">讓遊戲誤以為 GPU 工作能更快完成,避免遊戲為了配合 Switch 的時脈而降低解析度與渲染距離</string>
|
||||||
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
|
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些CPU端快取的失效處理,減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或崩潰。</string>
|
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些CPU端快取的失效處理,減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或當機。</string>
|
||||||
|
<string name="fix_bloom_effects">修正光暈特效</string>
|
||||||
|
<string name="fix_bloom_effects_description">在 薩爾達傳說:織夢島 和 薩爾達傳說:智慧的再現 中 減少光暈模糊的問題並移除 橫衝直撞:狂飆樂園重製版 中的光暈效果 (Adreno A6XX - A7XX/ Turnip)。警告:可能會在其它遊戲中導致圖形異常</string>
|
||||||
|
<string name="emulate_bgr565">模擬 BGR565</string>
|
||||||
|
<string name="emulate_bgr565_description">修正遊戲中出現的顏色反轉、圖形異常或陰影異常</string>
|
||||||
|
<string name="rescale_hack">啟用舊版重新縮放處理</string>
|
||||||
|
<string name="rescale_hack_description">透過快速重新縮放處理來啟用遊戲重新縮放設定階段的舊版處理方式</string>
|
||||||
<string name="renderer_asynchronous_shaders">使用非同步著色器</string>
|
<string name="renderer_asynchronous_shaders">使用非同步著色器</string>
|
||||||
<string name="renderer_asynchronous_shaders_description">非同步編譯著色器。這可能會減少卡頓,但也可能導致圖形錯誤。</string>
|
<string name="renderer_asynchronous_shaders_description">使用非同步編譯著色器。這可能會減少卡頓,但也可能導致圖形錯誤。</string>
|
||||||
|
<string name="gpu_unswizzle_settings">GPU Unswizzle 設定</string>
|
||||||
|
<string name="gpu_unswizzle_settings_description">設定基於 GPU 的 Unswizzling 參數或完全停用此功能。調整此設定以在性能與紋理載入品質中取得平衡</string>
|
||||||
|
<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_stream_size">GPU Unswizzle 流大小</string>
|
||||||
|
<string name="gpu_unswizzle_stream_size_description">設定每個影格處理大型紋理 Unswizzling 的資料上限。數值越高載入紋理的速度越快,但會增加畫面延遲;數值較低則能降低 GPU 負載,不過有可能導致至紋理載入不完全甚至突然出現</string>
|
||||||
|
<string name="gpu_unswizzle_chunk_size">GPU Unswizzle 塊大小</string>
|
||||||
|
<string name="gpu_unswizzle_chunk_size_description">設定 3D 紋理每批次處理的深度切片數量。增加此數值可提升規格較佳 GPU 的處理效率,但在較低規格的硬體上可能導致卡頓或驅動程式逾時</string>
|
||||||
|
<string name="gpu_unswizzle_default_button">預設</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="extensions">擴充功能</string>
|
||||||
|
|
||||||
<string name="dyna_state">擴展動態狀態</string>
|
<string name="dyna_state">擴展動態狀態</string>
|
||||||
<string name="disabled">已停用</string>
|
<string name="dyna_state_description">控制擴展動態狀態中可使用的功能數量。較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數。</string>
|
||||||
|
<string name="disabled">停用</string>
|
||||||
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
||||||
|
<string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string>
|
||||||
|
<string name="sample_shading_fraction">取樣著色</string>
|
||||||
|
<string name="sample_shading_fraction_description">讓片段著色器在多重取樣片段中針對每個取樣執行,而不是每個片段只執行一次。可提升圖形品質但會降低部分效能</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="display">顯示</string>
|
<string name="display">顯示</string>
|
||||||
|
|
||||||
<string name="renderer_screen_layout">方向</string>
|
<string name="renderer_screen_layout">方向</string>
|
||||||
@@ -497,32 +540,55 @@
|
|||||||
<string name="picture_in_picture">子母畫面</string>
|
<string name="picture_in_picture">子母畫面</string>
|
||||||
<string name="picture_in_picture_description">位於背景時最小化視窗</string>
|
<string name="picture_in_picture_description">位於背景時最小化視窗</string>
|
||||||
|
|
||||||
<string name="warning_resolution">解析度縮放到2倍或更高可能會導致問題,並可能顯著降低設備速度。</string>
|
<string name="warning_resolution">解析度縮放到2倍或更高可能會導致問題,並可能顯著降低設備速度</string>
|
||||||
|
|
||||||
<!-- Debug settings strings -->
|
<!-- Debug settings strings -->
|
||||||
<string name="cpu">CPU</string>
|
<string name="cpu">CPU</string>
|
||||||
|
<string name="clocks">時脈</string>
|
||||||
<string name="use_auto_stub">使用自動存根</string>
|
<string name="use_auto_stub">使用自動存根</string>
|
||||||
<string name="use_auto_stub_description">自動補上缺少的服務和功能。可提高相容性但可能導致崩潰和穩定性問題。</string>
|
<string name="use_auto_stub_description">自動補上缺少的服務和功能。可提高相容性但可能導致當機和穩定性問題。</string>
|
||||||
|
|
||||||
<string name="gpu">GPU</string>
|
<string name="gpu">GPU</string>
|
||||||
<string name="renderer_api">API</string>
|
<string name="renderer_api">API</string>
|
||||||
<string name="renderer_debug">圖形偵錯</string>
|
<string name="renderer_debug">圖形偵錯</string>
|
||||||
<string name="renderer_debug_description">將圖形 API 設為慢速偵錯模式。</string>
|
<string name="renderer_debug_description">將圖形 API 設為慢速偵錯模式</string>
|
||||||
|
<string name="patch_old_qcom_drivers">BCn 區塊壓縮紋理修補</string>
|
||||||
|
<string name="patch_old_qcom_drivers_description">覆寫 Adreno GPU 的 BCn 紋理格式自動偵測。通常會根據 Android 版本自動偵測(會在API 28 以上自動啟用)</string>
|
||||||
<string name="fastmem">Fastmem</string>
|
<string name="fastmem">Fastmem</string>
|
||||||
|
|
||||||
<string name="log">日誌記錄</string>
|
<string name="log">日誌</string>
|
||||||
<string name="flush_by_line">按行寫入偵錯日誌</string>
|
<string name="flush_by_line">按行寫入偵錯日誌</string>
|
||||||
<string name="flush_by_line_description">在每行寫入時重新整理偵錯日誌,讓程式在崩潰或當機時更容易偵錯。</string>
|
<string name="flush_by_line_description">在每行寫入時重新整理偵錯日誌,讓程式在當機或閃退時更容易偵錯。</string>
|
||||||
|
|
||||||
|
<!-- GPU Logging strings -->
|
||||||
|
<string name="gpu_logging_header">GPU 日誌</string>
|
||||||
|
<string name="gpu_log_level">記錄層級</string>
|
||||||
|
<string name="gpu_log_level_description">GPU 日誌的詳細層級 (越高日誌越詳細,不過會更容易過熱)</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) 儲存至 Eden 資料夾裡的 dump 資料夾中。可使用 spirv-dis/spirv-cross/spirv-val 進行檢查</string>
|
||||||
|
<string name="dump_guest_shaders">傾印客體(Maxwell)著色器</string>
|
||||||
|
<string name="dump_guest_shaders_description">將 Maxwell 客體著色器位元組碼檔案 (.ash) 儲存至 Eden 資料夾裡的 dump 資料夾中。可使用 nvdisasm 進行檢查</string>
|
||||||
|
<string name="dump_macros">傾印 Maxwell 巨集</string>
|
||||||
|
<string name="dump_macros_description">將 Maxwell 巨集程式檔案 (.macro) 儲存至 Eden 資料夾裡的 dump 資料夾中。可使用 envydis 進行檢查</string>
|
||||||
|
<string name="gpu_log_memory_tracking">追蹤 GPU 記憶體</string>
|
||||||
|
<string name="gpu_log_memory_tracking_description">監控 GPU 記憶體的分配和釋放</string>
|
||||||
|
<string name="gpu_log_driver_debug">驅動程式偵錯資料</string>
|
||||||
|
<string name="gpu_log_driver_debug_description">擷取驅動程式的特定偵錯資料(例如 Turnip breadcrumbs)</string>
|
||||||
|
<string name="gpu_log_ring_buffer_size">環形緩衝區大小</string>
|
||||||
|
<string name="gpu_log_ring_buffer_size_description">追蹤的近期 Vulkan 呼叫數量(預設為 512 )</string>
|
||||||
|
<string name="gpu_log_ring_buffer_size_hint">64 至 4096 個項目</string>
|
||||||
|
|
||||||
<string name="general">一般</string>
|
<string name="general">一般</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">輸出引擎</string>
|
<string name="audio_output_engine">輸出引擎</string>
|
||||||
<string name="audio_volume">音量</string>
|
<string name="audio_volume">音量</string>
|
||||||
<string name="audio_volume_description">指定音訊輸出音量。</string>
|
<string name="audio_volume_description">指定音訊輸出音量</string>
|
||||||
|
|
||||||
<!-- Input strings -->
|
<!-- Input strings -->
|
||||||
<string name="buttons">按键</string>
|
<string name="buttons">按鍵</string>
|
||||||
<string name="button_plus">+</string>
|
<string name="button_plus">+</string>
|
||||||
<string name="button_minus">-</string>
|
<string name="button_minus">-</string>
|
||||||
<string name="button_home">HOME</string>
|
<string name="button_home">HOME</string>
|
||||||
@@ -591,19 +657,20 @@
|
|||||||
<string name="button_map_description">按下一個按鈕或肩部按鍵/移動搖桿</string>
|
<string name="button_map_description">按下一個按鈕或肩部按鍵/移動搖桿</string>
|
||||||
<string name="map_dpad_direction">將方向鍵配對到 %1$s</string>
|
<string name="map_dpad_direction">將方向鍵配對到 %1$s</string>
|
||||||
<string name="map_control">配對到 %1$s</string>
|
<string name="map_control">配對到 %1$s</string>
|
||||||
<string name="failed_to_load_profile">匯入設定檔失敗</string>
|
<string name="failed_to_load_profile">導入設定檔失敗</string>
|
||||||
<string name="failed_to_save_profile">儲存設定檔失敗</string>
|
<string name="failed_to_save_profile">儲存設定檔失敗</string>
|
||||||
<string name="reset_mapping">重設控制器配對</string>
|
<string name="reset_mapping">重設控制器配對</string>
|
||||||
<string name="reset_mapping_description">您確定要將此控制器的所有配對重設為預設值?此動作無法復原</string>
|
<string name="reset_mapping_description">您確定要將此控制器的所有配對重設為預設值?此動作無法復原</string>
|
||||||
|
|
||||||
<!-- Miscellaneous -->
|
<!-- Miscellaneous -->
|
||||||
<string name="slider_default">預設</string>
|
<string name="slider_default">預設</string>
|
||||||
|
<string name="default_string">預設</string>
|
||||||
<string name="loading">正在載入…</string>
|
<string name="loading">正在載入…</string>
|
||||||
<string name="shutting_down">正在關閉…</string>
|
<string name="shutting_down">正在關閉…</string>
|
||||||
<string name="reset_setting_confirmation">要將此設定重設回預設值嗎?</string>
|
<string name="reset_setting_confirmation">要將此設定重設回預設值嗎?</string>
|
||||||
<string name="reset_to_default">重設為預設值</string>
|
<string name="reset_to_default">重設為預設值</string>
|
||||||
<string name="reset_to_default_description">重設所有進階設定</string>
|
<string name="reset_to_default_description">重設所有進階設定</string>
|
||||||
<string name="reset_all_settings">重設所有設定?</string>
|
<string name="reset_all_settings">確定要重設所有設定嗎?</string>
|
||||||
<string name="reset_all_settings_description">所有進階設定將被重設,此動作無法復原</string>
|
<string name="reset_all_settings_description">所有進階設定將被重設,此動作無法復原</string>
|
||||||
<string name="settings_reset">設定已重設</string>
|
<string name="settings_reset">設定已重設</string>
|
||||||
<string name="close">關閉</string>
|
<string name="close">關閉</string>
|
||||||
@@ -623,8 +690,8 @@
|
|||||||
<string name="import_success">已成功導入</string>
|
<string name="import_success">已成功導入</string>
|
||||||
<string name="export_success">已成功導出</string>
|
<string name="export_success">已成功導出</string>
|
||||||
<string name="start">開始</string>
|
<string name="start">開始</string>
|
||||||
<string name="global">全域</string>
|
<string name="global">全域設定</string>
|
||||||
<string name="custom">自定義</string>
|
<string name="custom">個別遊戲設定</string>
|
||||||
<string name="import_complete">導入完成</string>
|
<string name="import_complete">導入完成</string>
|
||||||
<string name="use_global_setting">使用全域設定</string>
|
<string name="use_global_setting">使用全域設定</string>
|
||||||
<string name="operation_completed_successfully">操作已成功完成</string>
|
<string name="operation_completed_successfully">操作已成功完成</string>
|
||||||
@@ -636,6 +703,7 @@
|
|||||||
<string name="select_gpu_driver_default">預設</string>
|
<string name="select_gpu_driver_default">預設</string>
|
||||||
<string name="select_gpu_driver_error">選擇的驅動程式無效</string>
|
<string name="select_gpu_driver_error">選擇的驅動程式無效</string>
|
||||||
<string name="driver_already_installed">驅動程式已安裝</string>
|
<string name="driver_already_installed">驅動程式已安裝</string>
|
||||||
|
<string name="installed_label">%1$s(已安裝)</string>
|
||||||
<string name="system_gpu_driver">系統 GPU 驅動程式</string>
|
<string name="system_gpu_driver">系統 GPU 驅動程式</string>
|
||||||
<string name="installing_driver">正在安裝驅動程式…</string>
|
<string name="installing_driver">正在安裝驅動程式…</string>
|
||||||
|
|
||||||
@@ -665,6 +733,9 @@
|
|||||||
<string name="preferences_system_description">底座模式、區域及語言</string>
|
<string name="preferences_system_description">底座模式、區域及語言</string>
|
||||||
<string name="preferences_graphics">圖形</string>
|
<string name="preferences_graphics">圖形</string>
|
||||||
<string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string>
|
<string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string>
|
||||||
|
<string name="quick_settings">快捷設定</string>
|
||||||
|
<string name="enable_quick_settings">啟用快捷設定</string>
|
||||||
|
<string name="enable_quick_settings_description">允許透過滑動和選單按鈕存取快捷設定選單</string>
|
||||||
<string name="preferences_audio">音訊</string>
|
<string name="preferences_audio">音訊</string>
|
||||||
<string name="preferences_audio_description">輸出引擎及音量</string>
|
<string name="preferences_audio_description">輸出引擎及音量</string>
|
||||||
<string name="preferences_controls">控制</string>
|
<string name="preferences_controls">控制</string>
|
||||||
@@ -672,12 +743,26 @@
|
|||||||
<string name="preferences_player">玩家 %d</string>
|
<string name="preferences_player">玩家 %d</string>
|
||||||
<string name="preferences_debug">偵錯</string>
|
<string name="preferences_debug">偵錯</string>
|
||||||
<string name="preferences_debug_description">CPU/GPU 偵錯、圖形 API 及 fastmem</string>
|
<string name="preferences_debug_description">CPU/GPU 偵錯、圖形 API 及 fastmem</string>
|
||||||
|
<string name="preferences_custom_paths">自訂路徑</string>
|
||||||
|
<string name="preferences_custom_paths_description">自訂檔案的存放路徑</string>
|
||||||
|
|
||||||
|
<!-- Custom Paths settings -->
|
||||||
|
<string name="custom_save_directory">遊戲儲存資料路徑</string>
|
||||||
|
<string name="custom_save_directory_description">設定遊戲儲存資料的自訂路徑</string>
|
||||||
|
<string name="reset_to_nand">重設為預設值</string>
|
||||||
|
<string name="migrate_save_data">遷移儲存資料</string>
|
||||||
|
<string name="migrate_save_data_question">您要將現有的儲存資料移至新位置嗎?</string>
|
||||||
|
<string name="save_migration_complete">成功遷移儲存資料</string>
|
||||||
|
<string name="save_migration_failed">儲存資料遷移失敗</string>
|
||||||
|
<string name="save_directory_set">存檔目錄設定完成</string>
|
||||||
|
<string name="skip_migration">跳過</string>
|
||||||
|
|
||||||
<!-- Game properties -->
|
<!-- Game properties -->
|
||||||
<string name="info">資訊</string>
|
<string name="info">資訊</string>
|
||||||
<string name="info_description">程式 ID、開發人員及版本資訊</string>
|
<string name="info_description">程式 ID、開發人員及版本資訊</string>
|
||||||
<string name="per_game_settings">個別遊戲設定</string>
|
<string name="per_game_settings">個別遊戲設定</string>
|
||||||
<string name="per_game_settings_description">編輯此遊戲的特定設定</string>
|
<string name="per_game_settings_description">編輯此遊戲的特定設定</string>
|
||||||
<string name="launch_options">啟動組態</string>
|
<string name="launch_options">啟動設定</string>
|
||||||
<string name="path">路徑</string>
|
<string name="path">路徑</string>
|
||||||
<string name="program_id">程式 ID</string>
|
<string name="program_id">程式 ID</string>
|
||||||
<string name="developer">開發商</string>
|
<string name="developer">開發商</string>
|
||||||
@@ -783,7 +868,7 @@
|
|||||||
<string name="driver_missing_title">需要GPU驅動程式</string>
|
<string name="driver_missing_title">需要GPU驅動程式</string>
|
||||||
<string name="driver_missing_message">這個遊戲的設定需要 \"%s\"驅動程式,而它並沒有安裝在您的裝置上\n\n要下載並安裝此驅動程式嗎?</string>
|
<string name="driver_missing_message">這個遊戲的設定需要 \"%s\"驅動程式,而它並沒有安裝在您的裝置上\n\n要下載並安裝此驅動程式嗎?</string>
|
||||||
<string name="driver_download_cancelled">驅動程式下載已取消。沒有所需的驅動程式無法啟動遊戲。</string>
|
<string name="driver_download_cancelled">驅動程式下載已取消。沒有所需的驅動程式無法啟動遊戲。</string>
|
||||||
<string name="download">下載</string>
|
<string name="download">遷移</string>
|
||||||
|
|
||||||
<!-- Emulation Menu -->
|
<!-- Emulation Menu -->
|
||||||
<string name="emulation_exit">結束模擬</string>
|
<string name="emulation_exit">結束模擬</string>
|
||||||
@@ -826,11 +911,11 @@
|
|||||||
<string name="abort_button">中止</string>
|
<string name="abort_button">中止</string>
|
||||||
<string name="continue_button">繼續</string>
|
<string name="continue_button">繼續</string>
|
||||||
<string name="system_archive_not_found">找不到系統存檔</string>
|
<string name="system_archive_not_found">找不到系統存檔</string>
|
||||||
<string name="system_archive_not_found_message">缺少%s,請轉儲您的系統存檔\n繼續模擬可能會導致崩潰</string>
|
<string name="system_archive_not_found_message">缺少%s,請轉儲您的系統存檔\n繼續模擬可能會導致當機</string>
|
||||||
<string name="system_archive_general">系統存檔</string>
|
<string name="system_archive_general">系統存檔</string>
|
||||||
<string name="save_load_error">儲存/載入時發生錯誤</string>
|
<string name="save_load_error">儲存/載入時發生錯誤</string>
|
||||||
<string name="fatal_error">嚴重錯誤</string>
|
<string name="fatal_error">嚴重錯誤</string>
|
||||||
<string name="fatal_error_message">發生嚴重錯誤。請查看日誌以取得詳細資料\n繼續模擬可能會導致崩潰</string>
|
<string name="fatal_error_message">發生嚴重錯誤。請查看日誌以取得詳細資料\n繼續模擬可能會導致當機</string>
|
||||||
<string name="device_memory_inadequate">裝置記憶體大小:%1$s\n推薦記憶體大小:%2$s</string>
|
<string name="device_memory_inadequate">裝置記憶體大小:%1$s\n推薦記憶體大小:%2$s</string>
|
||||||
<string name="memory_formatted">%1$s%2$s</string>
|
<string name="memory_formatted">%1$s%2$s</string>
|
||||||
<string name="no_game_present">目前沒有可啟動的遊戲!</string>
|
<string name="no_game_present">目前沒有可啟動的遊戲!</string>
|
||||||
@@ -921,7 +1006,6 @@
|
|||||||
<string name="theme_mode_light">淺色</string>
|
<string name="theme_mode_light">淺色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
<string name="multiplier_none">無</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">黑色背景</string>
|
<string name="use_black_backgrounds">黑色背景</string>
|
||||||
|
|||||||
@@ -111,43 +111,38 @@
|
|||||||
<item>1</item>
|
<item>1</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<!-- VRAM USAGE MODE CHOICES -->
|
|
||||||
<string-array name="vramUsageMethodNames">
|
<string-array name="vramUsageMethodNames">
|
||||||
<item>@string/vram_usage_conservative</item>
|
<item>@string/vram_usage_conservative</item>
|
||||||
<item>@string/vram_usage_aggressive</item>
|
<item>@string/vram_usage_aggressive</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- VRAM USAGE MODE VALUES -->
|
|
||||||
<integer-array name="vramUsageMethodValues">
|
<integer-array name="vramUsageMethodValues">
|
||||||
<item>0</item> <!-- Conservative -->
|
<item>0</item>
|
||||||
<item>1</item> <!-- Aggressive -->
|
<item>1</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<!-- ASTC Decoding Method Choices -->
|
|
||||||
<string-array name="astcDecodingMethodNames">
|
<string-array name="astcDecodingMethodNames">
|
||||||
<item>@string/accelerate_astc_cpu</item>
|
<item>@string/accelerate_astc_cpu</item>
|
||||||
<item>@string/accelerate_astc_gpu</item>
|
<item>@string/accelerate_astc_gpu</item>
|
||||||
<item>@string/accelerate_astc_async</item>
|
<item>@string/accelerate_astc_async</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- ASTC Decoding Method Values -->
|
|
||||||
<integer-array name="astcDecodingMethodValues">
|
<integer-array name="astcDecodingMethodValues">
|
||||||
<item>0</item> <!-- CPU -->
|
<item>0</item>
|
||||||
<item>1</item> <!-- GPU -->
|
<item>1</item>
|
||||||
<item>2</item> <!-- CPU Asynchronously -->
|
<item>2</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
<!-- NVDEC Emulation Choices -->
|
|
||||||
<string-array name="rendererNvdecNames">
|
<string-array name="rendererNvdecNames">
|
||||||
<item>@string/nvdec_emulation_none</item> <!-- Off -->
|
<item>@string/nvdec_emulation_none</item>
|
||||||
<item>@string/nvdec_emulation_cpu</item> <!-- Cpu -->
|
<item>@string/nvdec_emulation_cpu</item>
|
||||||
<item>@string/nvdec_emulation_gpu</item> <!-- Gpu -->
|
<item>@string/nvdec_emulation_gpu</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- NVDEC Emulation Values -->
|
|
||||||
<integer-array name="rendererNvdecValues">
|
<integer-array name="rendererNvdecValues">
|
||||||
<item>3</item> <!-- Off value -->
|
<item>0</item>
|
||||||
<item>1</item> <!-- CPU value -->
|
<item>1</item>
|
||||||
<item>2</item> <!-- GPU value -->
|
<item>2</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<string-array name="rendererResolutionNames">
|
<string-array name="rendererResolutionNames">
|
||||||
@@ -162,6 +157,48 @@
|
|||||||
<item>@string/resolution_four</item>
|
<item>@string/resolution_four</item>
|
||||||
</string-array>
|
</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="frameGenTargetRateNames">
|
||||||
|
<item>@string/frame_gen_target_rate_off</item>
|
||||||
|
<item>@string/frame_gen_target_rate_60</item>
|
||||||
|
<item>@string/frame_gen_target_rate_90</item>
|
||||||
|
<item>@string/frame_gen_target_rate_120</item>
|
||||||
|
<item>@string/frame_gen_target_rate_144</item>
|
||||||
|
<item>@string/frame_gen_target_rate_165</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<integer-array name="frameGenTargetRateValues">
|
||||||
|
<item>0</item>
|
||||||
|
<item>60</item>
|
||||||
|
<item>90</item>
|
||||||
|
<item>120</item>
|
||||||
|
<item>144</item>
|
||||||
|
<item>165</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">
|
<string-array name="rendererVSyncNames">
|
||||||
<item>@string/renderer_vsync_immediate</item>
|
<item>@string/renderer_vsync_immediate</item>
|
||||||
<item>@string/renderer_vsync_mailbox</item>
|
<item>@string/renderer_vsync_mailbox</item>
|
||||||
@@ -471,9 +508,6 @@
|
|||||||
<item>@string/multiplier_x4</item>
|
<item>@string/multiplier_x4</item>
|
||||||
<item>@string/multiplier_x8</item>
|
<item>@string/multiplier_x8</item>
|
||||||
<item>@string/multiplier_x16</item>
|
<item>@string/multiplier_x16</item>
|
||||||
<item>@string/multiplier_x32</item>
|
|
||||||
<item>@string/multiplier_x64</item>
|
|
||||||
<item>@string/multiplier_none</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
<integer-array name="anisoValues">
|
<integer-array name="anisoValues">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
@@ -482,9 +516,6 @@
|
|||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
<item>5</item>
|
<item>5</item>
|
||||||
<item>6</item>
|
|
||||||
<item>7</item>
|
|
||||||
<item>8</item>
|
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<string-array name="verticalAlignmentEntries">
|
<string-array name="verticalAlignmentEntries">
|
||||||
@@ -638,6 +669,16 @@
|
|||||||
<item>@string/error_keys_failed_init</item>
|
<item>@string/error_keys_failed_init</item>
|
||||||
</string-array>
|
</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 -->
|
<!-- GPU Logging Arrays -->
|
||||||
<string-array name="gpuLogLevelEntries">
|
<string-array name="gpuLogLevelEntries">
|
||||||
<item>Off</item>
|
<item>Off</item>
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
<integer name="game_columns_grid">2</integer>
|
<integer name="game_columns_grid">2</integer>
|
||||||
<integer name="carousel_max_fling_count">4</integer>
|
<integer name="carousel_max_fling_count">4</integer>
|
||||||
<integer name="carousel_focus_search_repeat_threshold_ms">100</integer>
|
<integer name="carousel_focus_search_repeat_threshold_ms">100</integer>
|
||||||
<integer name="carousel_cards_scaling_shape">1</integer>
|
|
||||||
<integer name="carousel_cards_alpha_shape">4</integer>
|
|
||||||
|
|
||||||
<!-- Default SWITCH landscape layout -->
|
<!-- Default SWITCH landscape layout -->
|
||||||
<integer name="BUTTON_A_X">760</integer>
|
<integer name="BUTTON_A_X">760</integer>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC Emulation</string>
|
<string name="nvdec_emulation">NVDEC Emulation</string>
|
||||||
<string name="nvdec_emulation_description">Select how video decoding (NVDEC) is handled during cutscenes and intros.</string>
|
<string name="nvdec_emulation_description">Change to CPU if a crash occurs on cinematics.</string>
|
||||||
<string name="nvdec_emulation_cpu" translatable="false">CPU</string>
|
<string name="nvdec_emulation_cpu" translatable="false">CPU</string>
|
||||||
<string name="nvdec_emulation_gpu" translatable="false">GPU</string>
|
<string name="nvdec_emulation_gpu" translatable="false">GPU</string>
|
||||||
<string name="nvdec_emulation_none">None</string>
|
<string name="nvdec_emulation_none">None</string>
|
||||||
@@ -298,6 +298,67 @@
|
|||||||
<string name="gpu_driver_fetcher">GPU driver fetcher</string>
|
<string name="gpu_driver_fetcher">GPU driver fetcher</string>
|
||||||
<string name="gpu_driver_manager">GPU driver manager</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="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_per_game_description">Configure frame generation for this game</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_target_rate">Target frame rate</string>
|
||||||
|
<string name="frame_gen_target_rate_description">Pick the rate your display can actually show. The multiplier then rises or falls on its own to hold it, and rolls back any step that makes the game itself run slower.</string>
|
||||||
|
<string name="frame_gen_target_rate_off">Use a fixed multiplier</string>
|
||||||
|
<string name="frame_gen_target_rate_60">60 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_90">90 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_120">120 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_144">144 FPS</string>
|
||||||
|
<string name="frame_gen_target_rate_165">165 FPS</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">Lowest latency (Unbuffered)</string>
|
||||||
|
<string name="frame_gen_queue_target_1">Balanced (1 frame)</string>
|
||||||
|
<string name="frame_gen_queue_target_2">Smoothest (2 frames)</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. 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_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_missing">Lossless.dll not installed</string>
|
||||||
|
<string name="lossless_scaling_missing_description">Install it from Settings › Lossless Scaling to use frame generation.</string>
|
||||||
|
<string name="lossless_scaling_locked">Close the game first</string>
|
||||||
|
<string name="lossless_scaling_locked_description">Lossless.dll cannot be changed while a game is running.</string>
|
||||||
|
<string name="lossless_scaling_remove_unavailable">Nothing to remove</string>
|
||||||
|
<string name="lossless_scaling_remove_unavailable_description">Lossless.dll is not installed yet.</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="advanced_settings">Advanced settings</string>
|
||||||
<string name="settings_description">Configure emulator settings</string>
|
<string name="settings_description">Configure emulator settings</string>
|
||||||
<string name="search_recently_played">Recently played</string>
|
<string name="search_recently_played">Recently played</string>
|
||||||
@@ -1185,9 +1246,6 @@
|
|||||||
<string name="multiplier_x4" translatable="false">x4</string>
|
<string name="multiplier_x4" translatable="false">x4</string>
|
||||||
<string name="multiplier_x8" translatable="false">x8</string>
|
<string name="multiplier_x8" translatable="false">x8</string>
|
||||||
<string name="multiplier_x16" translatable="false">x16</string>
|
<string name="multiplier_x16" translatable="false">x16</string>
|
||||||
<string name="multiplier_x32" translatable="false">x32</string>
|
|
||||||
<string name="multiplier_x64" translatable="false">x64</string>
|
|
||||||
<string name="multiplier_none">None</string>
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Black backgrounds</string>
|
<string name="use_black_backgrounds">Black backgrounds</string>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -7,13 +10,12 @@
|
|||||||
namespace AudioCore::ADSP::OpusDecoder {
|
namespace AudioCore::ADSP::OpusDecoder {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool IsValidChannelCount(u32 channel_count) {
|
constexpr u32 OpusStreamCountMax = 255;
|
||||||
return channel_count == 1 || channel_count == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) {
|
bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) {
|
||||||
return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 &&
|
return total_stream_count > 0 && total_stream_count <= OpusStreamCountMax &&
|
||||||
stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count);
|
static_cast<s32>(stereo_stream_count) >= 0 &&
|
||||||
|
stereo_stream_count <= total_stream_count;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -105,7 +108,7 @@ Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 chan
|
|||||||
shared_memory.host_send_data[4] = total_stream_count;
|
shared_memory.host_send_data[4] = total_stream_count;
|
||||||
shared_memory.host_send_data[5] = stereo_stream_count;
|
shared_memory.host_send_data[5] = stereo_stream_count;
|
||||||
|
|
||||||
ASSERT(channel_count <= MaxChannels);
|
ASSERT(channel_count <= shared_memory.channel_mapping.size());
|
||||||
std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8));
|
std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8));
|
||||||
|
|
||||||
opus_decoder.Send(ADSP::Direction::DSP,
|
opus_decoder.Send(ADSP::Direction::DSP,
|
||||||
|
|||||||
@@ -19,6 +19,23 @@
|
|||||||
namespace AudioCore::Sink {
|
namespace AudioCore::Sink {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
[[nodiscard]] bool InitializeAudio() {
|
||||||
|
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||||
|
// See https://github.com/PCSX2/pcsx2/pull/12312
|
||||||
|
// "SDL and cubeb backends previously resulted in different names for the output which
|
||||||
|
// caused them be identified as different applications by the OS."
|
||||||
|
//
|
||||||
|
// Keep in sync with cubeb_sink.cpp name.
|
||||||
|
SDL_SetHint("SDL_AUDIO_DEVICE_APP_NAME", "yuzu Latency Getter");
|
||||||
|
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
|
||||||
|
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_AudioDeviceID FindAudioDeviceByName(const std::string& device_name, bool capture) {
|
SDL_AudioDeviceID FindAudioDeviceByName(const std::string& device_name, bool capture) {
|
||||||
int device_count = 0;
|
int device_count = 0;
|
||||||
SDL_AudioDeviceID* devices = capture ? SDL_GetAudioRecordingDevices(&device_count)
|
SDL_AudioDeviceID* devices = capture ? SDL_GetAudioRecordingDevices(&device_count)
|
||||||
@@ -204,20 +221,14 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SDLSink::SDLSink(std::string_view target_device_name) {
|
SDLSink::SDLSink(std::string_view target_device_name) {
|
||||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
if (InitializeAudio()) {
|
||||||
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
|
if (target_device_name != auto_device_name && !target_device_name.empty()) {
|
||||||
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
|
output_device = target_device_name;
|
||||||
return;
|
} else {
|
||||||
|
output_device.clear();
|
||||||
}
|
}
|
||||||
|
device_channels = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_device_name != auto_device_name && !target_device_name.empty()) {
|
|
||||||
output_device = target_device_name;
|
|
||||||
} else {
|
|
||||||
output_device.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
device_channels = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLSink::~SDLSink() = default;
|
SDLSink::~SDLSink() = default;
|
||||||
@@ -265,15 +276,10 @@ void SDLSink::SetSystemVolume(f32 volume) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ListSDLSinkDevices(bool capture) {
|
std::vector<std::string> ListSDLSinkDevices(bool capture) {
|
||||||
|
if (!InitializeAudio())
|
||||||
|
return {}; //no devices
|
||||||
|
|
||||||
std::vector<std::string> device_list;
|
std::vector<std::string> device_list;
|
||||||
|
|
||||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
|
||||||
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
|
|
||||||
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_count = 0;
|
int device_count = 0;
|
||||||
SDL_AudioDeviceID* devices =
|
SDL_AudioDeviceID* devices =
|
||||||
capture ? SDL_GetAudioRecordingDevices(&device_count)
|
capture ? SDL_GetAudioRecordingDevices(&device_count)
|
||||||
@@ -304,13 +310,8 @@ bool IsSDLSuitable() {
|
|||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
// Check SDL can init
|
// Check SDL can init
|
||||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
if (!InitializeAudio()!
|
||||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
return false;
|
||||||
LOG_ERROR(Audio_Sink, "SDL failed to init, it is not suitable. Error: {}",
|
|
||||||
SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can set any latency frequency we want with SDL, so no need to check that.
|
// We can set any latency frequency we want with SDL, so no need to check that.
|
||||||
|
|
||||||
|
|||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#define KEYS_DIR "keys"
|
#define KEYS_DIR "keys"
|
||||||
#define LOAD_DIR "load"
|
#define LOAD_DIR "load"
|
||||||
#define LOG_DIR "log"
|
#define LOG_DIR "log"
|
||||||
|
#define LOSSLESS_DIR "lossless"
|
||||||
#define NAND_DIR "nand"
|
#define NAND_DIR "nand"
|
||||||
#define PLAY_TIME_DIR "play_time"
|
#define PLAY_TIME_DIR "play_time"
|
||||||
#define SCREENSHOTS_DIR "screenshots"
|
#define SCREENSHOTS_DIR "screenshots"
|
||||||
@@ -37,3 +38,5 @@
|
|||||||
|
|
||||||
// yuzu-specific files
|
// yuzu-specific files
|
||||||
#define LOG_FILE "eden_log.txt"
|
#define LOG_FILE "eden_log.txt"
|
||||||
|
#define LOSSLESS_DLL_FILE "Lossless.dll"
|
||||||
|
#define LOSSLESS_CACHE_FILE "lsfg_spirv.cache"
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ public:
|
|||||||
GenerateEdenPath(EdenPath::KeysDir, eden_path / KEYS_DIR);
|
GenerateEdenPath(EdenPath::KeysDir, eden_path / KEYS_DIR);
|
||||||
GenerateEdenPath(EdenPath::LoadDir, eden_path / LOAD_DIR);
|
GenerateEdenPath(EdenPath::LoadDir, eden_path / LOAD_DIR);
|
||||||
GenerateEdenPath(EdenPath::LogDir, eden_path / LOG_DIR);
|
GenerateEdenPath(EdenPath::LogDir, eden_path / LOG_DIR);
|
||||||
|
GenerateEdenPath(EdenPath::LosslessDir, eden_path / LOSSLESS_DIR);
|
||||||
GenerateEdenPath(EdenPath::NANDDir, eden_path / NAND_DIR);
|
GenerateEdenPath(EdenPath::NANDDir, eden_path / NAND_DIR);
|
||||||
GenerateEdenPath(EdenPath::PlayTimeDir, eden_path / PLAY_TIME_DIR);
|
GenerateEdenPath(EdenPath::PlayTimeDir, eden_path / PLAY_TIME_DIR);
|
||||||
GenerateEdenPath(EdenPath::SaveDir, eden_path / NAND_DIR);
|
GenerateEdenPath(EdenPath::SaveDir, eden_path / NAND_DIR);
|
||||||
|
|||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
@@ -23,6 +23,7 @@ enum class EdenPath {
|
|||||||
KeysDir, // Where key files are stored.
|
KeysDir, // Where key files are stored.
|
||||||
LoadDir, // Where cheat/mod files are stored.
|
LoadDir, // Where cheat/mod files are stored.
|
||||||
LogDir, // Where log files are stored.
|
LogDir, // Where log files are stored.
|
||||||
|
LosslessDir, // Where the user-supplied Lossless Scaling library is stored.
|
||||||
NANDDir, // Where the emulated NAND is stored.
|
NANDDir, // Where the emulated NAND is stored.
|
||||||
PlayTimeDir, // Where play time data is stored.
|
PlayTimeDir, // Where play time data is stored.
|
||||||
SaveDir, // Where save data is stored.
|
SaveDir, // Where save data is stored.
|
||||||
|
|||||||
+56
-45
@@ -39,6 +39,19 @@
|
|||||||
|
|
||||||
namespace Common::Log {
|
namespace Common::Log {
|
||||||
|
|
||||||
|
/// @brief A log entry. Log entries are store in a structured format to permit more varied output
|
||||||
|
/// formatting on different frontends, as well as facilitating filtering and aggregation.
|
||||||
|
struct Entry {
|
||||||
|
char const* message = nullptr;
|
||||||
|
size_t message_len = 0;
|
||||||
|
std::chrono::microseconds timestamp;
|
||||||
|
Class log_class{};
|
||||||
|
Level log_level{};
|
||||||
|
const char* filename = nullptr;
|
||||||
|
const char* function = nullptr;
|
||||||
|
uint32_t line_num = 0;
|
||||||
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief Returns the name of the passed log class as a C-string. Subclasses are separated by periods
|
/// @brief Returns the name of the passed log class as a C-string. Subclasses are separated by periods
|
||||||
@@ -70,8 +83,6 @@ const char* GetLevelName(Level log_level) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some IDEs prefer <file>:<line> instead, so let's just do that :)
|
// Some IDEs prefer <file>:<line> instead, so let's just do that :)
|
||||||
std::string FormatLogMessage(const Entry& entry) noexcept {
|
std::string FormatLogMessage(const Entry& entry) noexcept {
|
||||||
if (!entry.filename) return "";
|
if (!entry.filename) return "";
|
||||||
@@ -79,10 +90,9 @@ std::string FormatLogMessage(const Entry& entry) noexcept {
|
|||||||
auto const time_fractional = uint32_t(entry.timestamp.count() % 1000000);
|
auto const time_fractional = uint32_t(entry.timestamp.count() % 1000000);
|
||||||
auto const class_name = GetLogClassName(entry.log_class);
|
auto const class_name = GetLogClassName(entry.log_class);
|
||||||
auto const level_name = GetLevelName(entry.log_level);
|
auto const level_name = GetLevelName(entry.log_level);
|
||||||
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}", time_seconds, time_fractional, class_name, level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}\n", time_seconds, time_fractional, class_name, level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
template <typename It>
|
template <typename It>
|
||||||
Level GetLevelByName(const It begin, const It end) {
|
Level GetLevelByName(const It begin, const It end) {
|
||||||
for (u32 i = 0; i < u32(Level::Count); ++i) {
|
for (u32 i = 0; i < u32(Level::Count); ++i) {
|
||||||
@@ -127,25 +137,6 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
instance.SetClassLevel(log_class, level);
|
instance.SetClassLevel(log_class, level);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
|
||||||
|
|
||||||
void Filter::ParseFilterString(std::string_view filter_view) {
|
|
||||||
auto clause_begin = filter_view.cbegin();
|
|
||||||
while (clause_begin != filter_view.cend()) {
|
|
||||||
auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
|
|
||||||
// If clause isn't empty
|
|
||||||
if (clause_end != clause_begin) {
|
|
||||||
ParseFilterRule(*this, clause_begin, clause_end);
|
|
||||||
}
|
|
||||||
if (clause_end != filter_view.cend()) {
|
|
||||||
// Skip over the whitespace
|
|
||||||
++clause_end;
|
|
||||||
}
|
|
||||||
clause_begin = clause_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string
|
/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string
|
||||||
/// do not be fooled this isn't generating new strings on .rodata :)
|
/// do not be fooled this isn't generating new strings on .rodata :)
|
||||||
@@ -208,7 +199,7 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
}());
|
}());
|
||||||
SetConsoleTextAttribute(console_handle, color);
|
SetConsoleTextAttribute(console_handle, color);
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
@@ -220,22 +211,24 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
~ColorConsoleBackend() noexcept override {}
|
~ColorConsoleBackend() noexcept override {}
|
||||||
void Write(const Entry& entry) noexcept override {
|
void Write(const Entry& entry) noexcept override {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
#define ESC "\x1b"
|
|
||||||
auto const color_str = [&entry]() -> const char* {
|
auto const color_str = [&entry]() -> const char* {
|
||||||
switch (entry.log_level) {
|
switch (entry.log_level) {
|
||||||
#define CCB_MAKE_COLOR_FMT(X) ESC X CCB_PRINTF_FMT ESC "[0m\n"
|
case Level::Debug: return "[0;36m"; // Cyan
|
||||||
case Level::Debug: return CCB_MAKE_COLOR_FMT("[0;36m"); // Cyan
|
case Level::Info: return "[0;37m"; // Bright gray
|
||||||
case Level::Info: return CCB_MAKE_COLOR_FMT("[0;37m"); // Bright gray
|
case Level::Warning: return "[1;33m"; // Bright yellow
|
||||||
case Level::Warning: return CCB_MAKE_COLOR_FMT("[1;33m"); // Bright yellow
|
case Level::Error: return "[1;31m"; // Bright red
|
||||||
case Level::Error: return CCB_MAKE_COLOR_FMT("[1;31m"); // Bright red
|
case Level::Critical: return "[1;35m"; // Bright magenta
|
||||||
case Level::Critical: return CCB_MAKE_COLOR_FMT("[1;35m"); // Bright magenta
|
default: return "[1;30m"; // Grey
|
||||||
default: return CCB_MAKE_COLOR_FMT("[1;30m"); // Grey
|
|
||||||
#undef CCB_MAKE_COLOR_FMT
|
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
std::fprintf(stdout, color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
// more restrictive, because take for example this simple prelude:
|
||||||
#undef ESC
|
// [ 50.872256] Config <Info> common/settings.cpp:142:LogSettings:
|
||||||
|
char buffer[256];
|
||||||
|
auto result = fmt::format_to_n(buffer, sizeof(buffer) - 1, "\x1b{}[{:4d}.{:06d}] {} <{}> {}:{}:{}: ", color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||||
|
std::fwrite(buffer, 1, (std::min)(sizeof(buffer) - 1, result.size), stdout);
|
||||||
|
std::fwrite(entry.message, 1, entry.message_len, stdout);
|
||||||
|
std::fwrite("\x1b[0m\n", 1, sizeof("\x1b[0m\n"), stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
@@ -246,7 +239,7 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
#ifndef __OPENORBIS__
|
#ifndef __OPENORBIS__
|
||||||
/// @brief Backend that writes to a file passed into the constructor
|
/// @brief Backend that writes to a file passed into the constructor
|
||||||
struct FileBackend final : public Backend {
|
struct FileBackend final : public Backend {
|
||||||
explicit FileBackend(const std::filesystem::path& filename) noexcept {
|
explicit FileBackend(const std::filesystem::path filename) noexcept {
|
||||||
auto old_filename = filename;
|
auto old_filename = filename;
|
||||||
old_filename += ".old.txt";
|
old_filename += ".old.txt";
|
||||||
// Existence checks are done within the functions themselves.
|
// Existence checks are done within the functions themselves.
|
||||||
@@ -261,7 +254,7 @@ struct FileBackend final : public Backend {
|
|||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto message = FormatLogMessage(entry).append(1, '\n');
|
auto message = FormatLogMessage(entry);
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
if (Settings::values.censor_username.GetValue()) {
|
if (Settings::values.censor_username.GetValue()) {
|
||||||
// This must be a static otherwise it would get checked on EVERY
|
// This must be a static otherwise it would get checked on EVERY
|
||||||
@@ -269,8 +262,7 @@ struct FileBackend final : public Backend {
|
|||||||
static std::string username = []() -> std::string {
|
static std::string username = []() -> std::string {
|
||||||
// in order of precedence
|
// in order of precedence
|
||||||
// LOGNAME usually works on UNIX, USERNAME on Windows
|
// LOGNAME usually works on UNIX, USERNAME on Windows
|
||||||
// Some UNIX systems suck and don't use LOGNAME so we also
|
// Some UNIX systems suck and don't use LOGNAME so we also need USER :(
|
||||||
// need USER :(
|
|
||||||
for (auto const var : { "LOGNAME", "USERNAME", "USER", })
|
for (auto const var : { "LOGNAME", "USERNAME", "USER", })
|
||||||
if (auto const s = ::getenv(var); s != nullptr)
|
if (auto const s = ::getenv(var); s != nullptr)
|
||||||
return std::string{s};
|
return std::string{s};
|
||||||
@@ -280,7 +272,7 @@ struct FileBackend final : public Backend {
|
|||||||
boost::replace_all(message, username, "user");
|
boost::replace_all(message, username, "user");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bytes_written += file->WriteString(message);
|
bytes_written += file->WriteSpan(std::span<const char>{message.begin(), message.end()});
|
||||||
|
|
||||||
// Option to log each line rather than 4k buffers
|
// Option to log each line rather than 4k buffers
|
||||||
if (Settings::values.log_flush_line.GetValue())
|
if (Settings::values.log_flush_line.GetValue())
|
||||||
@@ -308,14 +300,13 @@ private:
|
|||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/// @brief Backend that writes to Visual Studio's output window
|
/// @brief Backend that writes to Visual Studio's output window
|
||||||
struct DebuggerBackend final : public Backend {
|
struct DebuggerBackend final : public Backend {
|
||||||
explicit DebuggerBackend() noexcept = default;
|
explicit DebuggerBackend() noexcept = default;
|
||||||
~DebuggerBackend() noexcept override = default;
|
~DebuggerBackend() noexcept override = default;
|
||||||
void Write(const Entry& entry) noexcept override {
|
void Write(const Entry& entry) noexcept override {
|
||||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry)).c_str());
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
};
|
};
|
||||||
@@ -338,7 +329,7 @@ struct LogcatBackend : public Backend {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
};
|
};
|
||||||
@@ -377,7 +368,23 @@ struct Impl {
|
|||||||
#endif
|
#endif
|
||||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||||
};
|
};
|
||||||
} // namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
void Filter::ParseFilterString(std::string_view filter_view) {
|
||||||
|
auto clause_begin = filter_view.cbegin();
|
||||||
|
while (clause_begin < filter_view.cend()) {
|
||||||
|
auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
|
||||||
|
// If clause isn't empty
|
||||||
|
if (clause_end != clause_begin) {
|
||||||
|
ParseFilterRule(*this, clause_begin, clause_end);
|
||||||
|
}
|
||||||
|
if (clause_end != filter_view.cend()) {
|
||||||
|
// Skip over the whitespace
|
||||||
|
++clause_end;
|
||||||
|
}
|
||||||
|
clause_begin = clause_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Constructor shall NOT depend upon Settings() or whatever
|
// Constructor shall NOT depend upon Settings() or whatever
|
||||||
// it's ran at global static ctor() time... so BE CAREFUL MFER!
|
// it's ran at global static ctor() time... so BE CAREFUL MFER!
|
||||||
@@ -419,9 +426,13 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) {
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) {
|
||||||
if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) {
|
if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) {
|
||||||
auto const flush = ::Settings::values.log_flush_line.GetValue();
|
auto const flush = ::Settings::values.log_flush_line.GetValue();
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
auto result = fmt::vformat_to_n(buffer, sizeof(buffer) - 1, format, args);
|
||||||
|
buffer[(std::min)(result.size, sizeof(buffer) - 1)] = '\0';
|
||||||
logging_instance->ForEachBackend([=](Backend& backend) {
|
logging_instance->ForEachBackend([=](Backend& backend) {
|
||||||
backend.Write(Entry{
|
backend.Write(Entry{
|
||||||
.message = fmt::vformat(format, args),
|
.message = buffer,
|
||||||
|
.message_len = (std::min)(result.size, sizeof(buffer) - 1),
|
||||||
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
|
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
|
||||||
.log_class = log_class,
|
.log_class = log_class,
|
||||||
.log_level = log_level,
|
.log_level = log_level,
|
||||||
|
|||||||
@@ -140,25 +140,4 @@ void Stop();
|
|||||||
void SetGlobalFilter(const Filter& filter);
|
void SetGlobalFilter(const Filter& filter);
|
||||||
void SetColorConsoleBackendEnabled(bool enabled);
|
void SetColorConsoleBackendEnabled(bool enabled);
|
||||||
|
|
||||||
/// @brief A log entry. Log entries are store in a structured format to permit more varied output
|
|
||||||
/// formatting on different frontends, as well as facilitating filtering and aggregation.
|
|
||||||
struct Entry {
|
|
||||||
std::string message;
|
|
||||||
std::chrono::microseconds timestamp;
|
|
||||||
Class log_class{};
|
|
||||||
Level log_level{};
|
|
||||||
const char* filename = nullptr;
|
|
||||||
const char* function = nullptr;
|
|
||||||
unsigned int line_num = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Formats a log entry into the provided text buffer.
|
|
||||||
std::string FormatLogMessage(const Entry& entry) noexcept;
|
|
||||||
|
|
||||||
/// Prints the same message as `PrintMessage`, but colored according to the severity level.
|
|
||||||
void PrintColoredMessage(const Entry& entry) noexcept;
|
|
||||||
|
|
||||||
/// Formats and prints a log entry to the android logcat.
|
|
||||||
void PrintMessageToLogcat(const Entry& entry) noexcept;
|
|
||||||
|
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ std::optional<std::string> MakeRequest(const std::string& url, const std::string
|
|||||||
response.status);
|
response.status);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!response.headers.contains("content-type")) {
|
if (!response.has_header("content-type")) {
|
||||||
LOG_ERROR(Common, "GET to {}{} returned no content", url, path);
|
LOG_ERROR(Common, "GET to {}{} returned no content", url, path);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-5
@@ -132,11 +132,9 @@ void LogSettings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG_INFO(Config, "Eden Configuration:");
|
||||||
std::string settings_str{};
|
|
||||||
for (auto const& e : settings_list)
|
for (auto const& e : settings_list)
|
||||||
settings_str += e;
|
LOG_INFO(Config, "{}", e);
|
||||||
LOG_INFO(Config, "Eden Configuration:\n{}", settings_str);
|
|
||||||
#define LOG_PATH(NAME) \
|
#define LOG_PATH(NAME) \
|
||||||
LOG_INFO(Config, #NAME ": {}", Common::FS::PathToUTF8String(Common::FS::GetEdenPath(Common::FS::EdenPath::NAME)))
|
LOG_INFO(Config, #NAME ": {}", Common::FS::PathToUTF8String(Common::FS::GetEdenPath(Common::FS::EdenPath::NAME)))
|
||||||
LOG_PATH(CacheDir);
|
LOG_PATH(CacheDir);
|
||||||
@@ -148,7 +146,7 @@ void LogSettings() {
|
|||||||
#undef LOG_PATH
|
#undef LOG_PATH
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getDebugKnobAt(u8 i) {
|
bool GetDebugKnobAt(u8 i) {
|
||||||
return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0;
|
return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,6 +378,28 @@ void UpdateRescalingInfo() {
|
|||||||
TranslateResolutionInfo(setup, info);
|
TranslateResolutionInfo(setup, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 FrameGenMultiplier() {
|
||||||
|
return std::clamp(values.frame_gen_multiplier.GetValue(), MIN_FRAME_GEN_MULTIPLIER,
|
||||||
|
MAX_FRAME_GEN_MULTIPLIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FrameGenGenerations() {
|
||||||
|
if (!values.frame_gen.GetValue()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return FrameGenMultiplier() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FrameGenMaxGenerations() {
|
||||||
|
if (!values.frame_gen.GetValue()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (values.frame_gen_target_rate.GetValue() != 0) {
|
||||||
|
return MAX_FRAME_GEN_MULTIPLIER - 1;
|
||||||
|
}
|
||||||
|
return FrameGenMultiplier() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void RestoreGlobalState(bool is_powered_on) {
|
void RestoreGlobalState(bool is_powered_on) {
|
||||||
// If a game is running, DO NOT restore the global settings state
|
// If a game is running, DO NOT restore the global settings state
|
||||||
if (is_powered_on) {
|
if (is_powered_on) {
|
||||||
|
|||||||
+78
-10
@@ -352,7 +352,7 @@ struct Values {
|
|||||||
true};
|
true};
|
||||||
|
|
||||||
SwitchableSetting<ScalingFilter> scaling_filter{linkage,
|
SwitchableSetting<ScalingFilter> scaling_filter{linkage,
|
||||||
ScalingFilter::Bilinear,
|
ScalingFilter::NearestNeighbor,
|
||||||
"scaling_filter",
|
"scaling_filter",
|
||||||
Category::Renderer,
|
Category::Renderer,
|
||||||
Specialization::Default,
|
Specialization::Default,
|
||||||
@@ -388,6 +388,69 @@ struct Values {
|
|||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
|
|
||||||
|
SwitchableSetting<bool> frame_gen{linkage, false, "frame_gen", Category::Renderer,
|
||||||
|
Specialization::Default, true, false};
|
||||||
|
|
||||||
|
SwitchableSetting<u32, true> frame_gen_multiplier{linkage,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
"frame_gen_multiplier",
|
||||||
|
Category::Renderer,
|
||||||
|
Specialization::Countable,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<u32, true> frame_gen_target_rate{linkage,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
240,
|
||||||
|
"frame_gen_target_rate",
|
||||||
|
Category::Renderer,
|
||||||
|
Specialization::Countable,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<bool> frame_gen_flow_scale_auto{linkage,
|
||||||
|
true,
|
||||||
|
"frame_gen_flow_scale_auto",
|
||||||
|
Category::Renderer,
|
||||||
|
Specialization::Default,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<u32, true> frame_gen_flow_scale{linkage,
|
||||||
|
75,
|
||||||
|
25,
|
||||||
|
100,
|
||||||
|
"frame_gen_flow_scale",
|
||||||
|
Category::Renderer,
|
||||||
|
Specialization::Countable |
|
||||||
|
Specialization::Percentage,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<u32, true> frame_gen_queue_target{linkage,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
"frame_gen_queue_target",
|
||||||
|
Category::Renderer,
|
||||||
|
Specialization::Countable,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<bool> frame_gen_fp16{linkage, true, "frame_gen_fp16", Category::Renderer,
|
||||||
|
Specialization::Default, true, false, &frame_gen};
|
||||||
|
|
||||||
|
SwitchableSetting<bool> frame_gen_dump_flow{linkage, false, "frame_gen_dump_flow",
|
||||||
|
Category::Renderer};
|
||||||
|
|
||||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{linkage,
|
SwitchableSetting<bool> use_asynchronous_gpu_emulation{linkage,
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
false,
|
false,
|
||||||
@@ -569,13 +632,8 @@ struct Values {
|
|||||||
SwitchableSetting<bool> emulate_bgr565{linkage, false, "emulate_bgr565",
|
SwitchableSetting<bool> emulate_bgr565{linkage, false, "emulate_bgr565",
|
||||||
Category::RendererHacks};
|
Category::RendererHacks};
|
||||||
|
|
||||||
SwitchableSetting<bool> rescale_hack{linkage,
|
SwitchableSetting<bool> rescale_hack{linkage, false, "rescale_hack",
|
||||||
#ifdef __ANDROID__
|
Category::RendererHacks};
|
||||||
true,
|
|
||||||
#else
|
|
||||||
false,
|
|
||||||
#endif
|
|
||||||
"rescale_hack", Category::RendererHacks};
|
|
||||||
SwitchableSetting<bool> enable_gpu_buffer_readback{linkage,
|
SwitchableSetting<bool> enable_gpu_buffer_readback{linkage,
|
||||||
false,
|
false,
|
||||||
"enable_gpu_buffer_readback",
|
"enable_gpu_buffer_readback",
|
||||||
@@ -846,7 +904,7 @@ struct Values {
|
|||||||
0,
|
0,
|
||||||
65535,
|
65535,
|
||||||
"debug_knobs",
|
"debug_knobs",
|
||||||
Category::Debugging,
|
Category::System,
|
||||||
Specialization::Countable,
|
Specialization::Countable,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
@@ -875,11 +933,21 @@ struct Values {
|
|||||||
|
|
||||||
// Per-game overrides
|
// Per-game overrides
|
||||||
bool use_squashed_iterated_blend;
|
bool use_squashed_iterated_blend;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Values values;
|
extern Values values;
|
||||||
|
|
||||||
bool getDebugKnobAt(u8 i);
|
constexpr u32 MIN_FRAME_GEN_MULTIPLIER = 2;
|
||||||
|
constexpr u32 MAX_FRAME_GEN_MULTIPLIER = 4;
|
||||||
|
|
||||||
|
[[nodiscard]] u32 FrameGenMultiplier();
|
||||||
|
|
||||||
|
[[nodiscard]] size_t FrameGenGenerations();
|
||||||
|
|
||||||
|
[[nodiscard]] size_t FrameGenMaxGenerations();
|
||||||
|
|
||||||
|
bool GetDebugKnobAt(u8 i);
|
||||||
|
|
||||||
void UpdateGPUAccuracy();
|
void UpdateGPUAccuracy();
|
||||||
bool IsGPULevelHigh();
|
bool IsGPULevelHigh();
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt
|
|||||||
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
||||||
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
||||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
|
||||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
||||||
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_90, Target_120);
|
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_90, Target_120);
|
||||||
|
|||||||
@@ -7,6 +7,4 @@
|
|||||||
#define STB_IMAGE_IMPLEMENTATION 1
|
#define STB_IMAGE_IMPLEMENTATION 1
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION 1
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION 1
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION 1
|
#define STB_IMAGE_WRITE_IMPLEMENTATION 1
|
||||||
#define STBI_ONLY_JPEG 1
|
|
||||||
|
|
||||||
#include "common/stb.h"
|
#include "common/stb.h"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define STBI_ONLY_JPEG 1
|
#define STBI_ONLY_JPEG 1
|
||||||
|
#define STBI_WRITE_NO_STDIO 1
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
#include <stb_image_resize.h>
|
#include <stb_image_resize.h>
|
||||||
#include <stb_image_write.h>
|
#include <stb_image_write.h>
|
||||||
|
|||||||
+6
-10
@@ -388,14 +388,6 @@ add_library(core STATIC
|
|||||||
hle/result.h
|
hle/result.h
|
||||||
hle/service/acc/acc.cpp
|
hle/service/acc/acc.cpp
|
||||||
hle/service/acc/acc.h
|
hle/service/acc/acc.h
|
||||||
hle/service/acc/acc_aa.cpp
|
|
||||||
hle/service/acc/acc_aa.h
|
|
||||||
hle/service/acc/acc_su.cpp
|
|
||||||
hle/service/acc/acc_su.h
|
|
||||||
hle/service/acc/acc_u0.cpp
|
|
||||||
hle/service/acc/acc_u0.h
|
|
||||||
hle/service/acc/acc_u1.cpp
|
|
||||||
hle/service/acc/acc_u1.h
|
|
||||||
hle/service/acc/async_context.cpp
|
hle/service/acc/async_context.cpp
|
||||||
hle/service/acc/async_context.h
|
hle/service/acc/async_context.h
|
||||||
hle/service/acc/errors.h
|
hle/service/acc/errors.h
|
||||||
@@ -768,8 +760,8 @@ add_library(core STATIC
|
|||||||
hle/service/mii/types/ver3_store_data.h
|
hle/service/mii/types/ver3_store_data.h
|
||||||
hle/service/mm/mm_u.cpp
|
hle/service/mm/mm_u.cpp
|
||||||
hle/service/mm/mm_u.h
|
hle/service/mm/mm_u.h
|
||||||
hle/service/mnpp/mnpp_app.cpp
|
hle/service/mnpp/mnpp.cpp
|
||||||
hle/service/mnpp/mnpp_app.h
|
hle/service/mnpp/mnpp.h
|
||||||
hle/service/ncm/ncm.cpp
|
hle/service/ncm/ncm.cpp
|
||||||
hle/service/ncm/ncm.h
|
hle/service/ncm/ncm.h
|
||||||
hle/service/nfc/common/amiibo_crypto.cpp
|
hle/service/nfc/common/amiibo_crypto.cpp
|
||||||
@@ -1089,6 +1081,8 @@ add_library(core STATIC
|
|||||||
hle/service/ssl/ssl.h
|
hle/service/ssl/ssl.h
|
||||||
hle/service/ssl/ssl_backend.h
|
hle/service/ssl/ssl_backend.h
|
||||||
hle/service/ssl/ssl_types.h
|
hle/service/ssl/ssl_types.h
|
||||||
|
hle/service/tma/tma.cpp
|
||||||
|
hle/service/tma/tma.h
|
||||||
hle/service/usb/usb.cpp
|
hle/service/usb/usb.cpp
|
||||||
hle/service/usb/usb.h
|
hle/service/usb/usb.h
|
||||||
hle/service/vi/application_display_service.cpp
|
hle/service/vi/application_display_service.cpp
|
||||||
@@ -1125,6 +1119,8 @@ add_library(core STATIC
|
|||||||
hle/service/gpio/gpio.h
|
hle/service/gpio/gpio.h
|
||||||
hle/service/i2c/i2c.cpp
|
hle/service/i2c/i2c.cpp
|
||||||
hle/service/i2c/i2c.h
|
hle/service/i2c/i2c.h
|
||||||
|
hle/service/wlan/wlan.cpp
|
||||||
|
hle/service/wlan/wlan.h
|
||||||
internal_network/emu_net_state.cpp
|
internal_network/emu_net_state.cpp
|
||||||
internal_network/emu_net_state.h
|
internal_network/emu_net_state.h
|
||||||
internal_network/network.cpp
|
internal_network/network.cpp
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) {
|
|||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
|
||||||
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
|
||||||
break;
|
break;
|
||||||
// Paranoia mode for debugging optimizations
|
// Paranoia mode for debugging optimizations
|
||||||
case Settings::CpuAccuracy::Paranoid:
|
case Settings::CpuAccuracy::Paranoid:
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s
|
|||||||
config.unsafe_optimizations = true;
|
config.unsafe_optimizations = true;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.fastmem_address_space_bits = 64;
|
config.fastmem_address_space_bits = 64;
|
||||||
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
|
||||||
break;
|
break;
|
||||||
// Paranoia mode for debugging optimizations
|
// Paranoia mode for debugging optimizations
|
||||||
case Settings::CpuAccuracy::Paranoid:
|
case Settings::CpuAccuracy::Paranoid:
|
||||||
|
|||||||
+43
-2
@@ -295,6 +295,10 @@ struct System::Impl {
|
|||||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) {
|
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) {
|
||||||
InitializeKernel(system);
|
InitializeKernel(system);
|
||||||
|
|
||||||
|
if (params.applet_type == Service::AM::AppletType::Application) {
|
||||||
|
current_application_filepath = filepath;
|
||||||
|
}
|
||||||
|
|
||||||
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
||||||
|
|
||||||
// Create the application process
|
// Create the application process
|
||||||
@@ -330,7 +334,7 @@ struct System::Impl {
|
|||||||
LaunchTimestampCache::SaveLaunchTimestamp(params.program_id);
|
LaunchTimestampCache::SaveLaunchTimestamp(params.program_id);
|
||||||
|
|
||||||
// Make the process created be the application
|
// Make the process created be the application
|
||||||
kernel.MakeApplicationProcess(process->GetHandle());
|
kernel.SetApplicationProcess(process->GetHandle());
|
||||||
|
|
||||||
// Set up the rest of the system.
|
// Set up the rest of the system.
|
||||||
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
|
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
|
||||||
@@ -467,6 +471,7 @@ struct System::Impl {
|
|||||||
Core::SpeedLimiter speed_limiter;
|
Core::SpeedLimiter speed_limiter;
|
||||||
ExecuteProgramCallback execute_program_callback;
|
ExecuteProgramCallback execute_program_callback;
|
||||||
ExitCallback exit_callback;
|
ExitCallback exit_callback;
|
||||||
|
ApplicationChangedCallback application_changed_callback;
|
||||||
|
|
||||||
std::optional<Service::Services> services;
|
std::optional<Service::Services> services;
|
||||||
std::optional<Core::Debugger> debugger;
|
std::optional<Core::Debugger> debugger;
|
||||||
@@ -488,6 +493,8 @@ struct System::Impl {
|
|||||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
||||||
std::array<u8, 0x20> build_id{};
|
std::array<u8, 0x20> build_id{};
|
||||||
|
|
||||||
|
std::string current_application_filepath;
|
||||||
|
|
||||||
/// Service manager
|
/// Service manager
|
||||||
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
||||||
/// ContentProviderUnion instance
|
/// ContentProviderUnion instance
|
||||||
@@ -727,7 +734,25 @@ const Core::SpeedLimiter& System::SpeedLimiter() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 System::GetApplicationProcessProgramID() const {
|
u64 System::GetApplicationProcessProgramID() const {
|
||||||
return impl->kernel.ApplicationProcess()->GetProgramId();
|
const auto* const process = impl->kernel.ApplicationProcess();
|
||||||
|
return process != nullptr ? process->GetProgramId() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 System::GetProgramIdForProcessId(u64 process_id) const {
|
||||||
|
auto process = impl->kernel.GetProcessByProcessId(process_id);
|
||||||
|
return process.IsNull() ? 0 : process->GetProgramId();
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 System::ResolveCallerProgramId(u64 process_id) const {
|
||||||
|
if (const auto program_id = this->GetProgramIdForProcessId(process_id); program_id != 0) {
|
||||||
|
return program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto fallback = this->GetApplicationProcessProgramID();
|
||||||
|
LOG_WARNING(Core,
|
||||||
|
"Could not resolve caller process_id={}, falling back to application {:016X}",
|
||||||
|
process_id, fallback);
|
||||||
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader::ResultStatus System::GetGameName(std::string& out) const {
|
Loader::ResultStatus System::GetGameName(std::string& out) const {
|
||||||
@@ -910,6 +935,10 @@ void System::ExecuteProgram(std::size_t program_index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& System::GetCurrentApplicationFilePath() const {
|
||||||
|
return impl->current_application_filepath;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Gets a reference to the user channel stack.
|
/// @brief Gets a reference to the user channel stack.
|
||||||
/// It is used to transfer data between programs.
|
/// It is used to transfer data between programs.
|
||||||
std::vector<std::vector<u8>>& System::GetUserChannel() {
|
std::vector<std::vector<u8>>& System::GetUserChannel() {
|
||||||
@@ -961,6 +990,18 @@ void System::Exit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::RegisterApplicationChangedCallback(ApplicationChangedCallback&& callback) {
|
||||||
|
impl->application_changed_callback = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::NotifyApplicationChanged(u64 program_id) {
|
||||||
|
//LOG_DEBUG(Core, "Running application changed to {:016X}", program_id);
|
||||||
|
|
||||||
|
if (impl->application_changed_callback) {
|
||||||
|
impl->application_changed_callback(program_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void System::ApplySettings() {
|
void System::ApplySettings() {
|
||||||
impl->RefreshTime(*this);
|
impl->RefreshTime(*this);
|
||||||
|
|
||||||
|
|||||||
@@ -322,6 +322,10 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] u64 GetApplicationProcessProgramID() const;
|
[[nodiscard]] u64 GetApplicationProcessProgramID() const;
|
||||||
|
|
||||||
|
[[nodiscard]] u64 GetProgramIdForProcessId(u64 process_id) const;
|
||||||
|
|
||||||
|
[[nodiscard]] u64 ResolveCallerProgramId(u64 process_id) const;
|
||||||
|
|
||||||
/// Gets the name of the current game
|
/// Gets the name of the current game
|
||||||
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
|
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
|
||||||
|
|
||||||
@@ -422,6 +426,7 @@ public:
|
|||||||
void PushGeneralChannelData(std::vector<u8>&& data);
|
void PushGeneralChannelData(std::vector<u8>&& data);
|
||||||
bool TryPopGeneralChannel(std::vector<u8>& out_data);
|
bool TryPopGeneralChannel(std::vector<u8>& out_data);
|
||||||
[[nodiscard]] Service::Event& GetGeneralChannelEvent();
|
[[nodiscard]] Service::Event& GetGeneralChannelEvent();
|
||||||
|
[[nodiscard]] const std::string& GetCurrentApplicationFilePath() const;
|
||||||
|
|
||||||
/// Type used for the frontend to designate a callback for System to exit the application.
|
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||||
using ExitCallback = std::function<void()>;
|
using ExitCallback = std::function<void()>;
|
||||||
@@ -435,6 +440,10 @@ public:
|
|||||||
/// Instructs the frontend to exit the application.
|
/// Instructs the frontend to exit the application.
|
||||||
void Exit();
|
void Exit();
|
||||||
|
|
||||||
|
using ApplicationChangedCallback = std::function<void(u64 program_id)>;
|
||||||
|
void RegisterApplicationChangedCallback(ApplicationChangedCallback&& callback);
|
||||||
|
void NotifyApplicationChanged(u64 program_id);
|
||||||
|
|
||||||
/// Applies any changes to settings to this core instance.
|
/// Applies any changes to settings to this core instance.
|
||||||
void ApplySettings();
|
void ApplySettings();
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ static u8 MasterKeyIdForKeyGeneration(u8 key_generation) {
|
|||||||
return std::max<u8>(key_generation, 1) - 1;
|
return std::max<u8>(key_generation, 1) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NCA::NCA(VirtualFile file_, const NCA* base_nca)
|
NCA::NCA(VirtualFile file_, const NCA* base_nca, bool allow_missing_base)
|
||||||
: file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
: file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
status = Loader::ResultStatus::ErrorNullFile;
|
status = Loader::ResultStatus::ErrorNullFile;
|
||||||
@@ -110,7 +110,7 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_update && base_nca == nullptr) {
|
if (is_update && base_nca == nullptr && !allow_missing_base) {
|
||||||
status = Loader::ResultStatus::ErrorMissingBKTRBaseRomFS;
|
status = Loader::ResultStatus::ErrorMissingBKTRBaseRomFS;
|
||||||
} else {
|
} else {
|
||||||
status = Loader::ResultStatus::Success;
|
status = Loader::ResultStatus::Success;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ inline bool IsDirectoryLogoPartition(const VirtualDir& pfs) {
|
|||||||
// After construction, use GetStatus to determine if the file is valid and ready to be used.
|
// After construction, use GetStatus to determine if the file is valid and ready to be used.
|
||||||
class NCA : public ReadOnlyVfsDirectory {
|
class NCA : public ReadOnlyVfsDirectory {
|
||||||
public:
|
public:
|
||||||
explicit NCA(VirtualFile file, const NCA* base_nca = nullptr);
|
explicit NCA(VirtualFile file, const NCA* base_nca = nullptr, bool allow_missing_base = false);
|
||||||
~NCA() override;
|
~NCA() override;
|
||||||
|
|
||||||
Loader::ResultStatus GetStatus() const;
|
Loader::ResultStatus GetStatus() const;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/fssystem/fssystem_indirect_storage.h"
|
#include "core/file_sys/fssystem/fssystem_indirect_storage.h"
|
||||||
|
|
||||||
@@ -99,6 +100,18 @@ Result IndirectStorage::GetEntryList(Entry* out_entries, s32* out_entry_count, s
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IndirectStorage::ReportMissingOriginal(s64 offset, s64 size) {
|
||||||
|
if (m_reported_missing_original) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_reported_missing_original = true;
|
||||||
|
|
||||||
|
LOG_ERROR(Common_Filesystem,
|
||||||
|
"Patch storage requests {:#x} bytes at {:#x} from a base storage that is not "
|
||||||
|
"present; this data will read as garbage",
|
||||||
|
size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const {
|
size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const {
|
||||||
// Validate pre-conditions.
|
// Validate pre-conditions.
|
||||||
ASSERT(this->IsInitialized());
|
ASSERT(this->IsInitialized());
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ public:
|
|||||||
void SetStorage(s32 idx, VirtualFile storage) {
|
void SetStorage(s32 idx, VirtualFile storage) {
|
||||||
ASSERT(0 <= idx && idx < StorageCount);
|
ASSERT(0 <= idx && idx < StorageCount);
|
||||||
m_data_storage[idx] = storage;
|
m_data_storage[idx] = storage;
|
||||||
|
if (idx == 0) {
|
||||||
|
m_original_missing = storage == nullptr || storage->GetSize() == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -130,6 +133,9 @@ protected:
|
|||||||
|
|
||||||
template <bool ContinuousCheck, bool RangeCheck, typename F>
|
template <bool ContinuousCheck, bool RangeCheck, typename F>
|
||||||
Result OperatePerEntry(s64 offset, s64 size, F func);
|
Result OperatePerEntry(s64 offset, s64 size, F func);
|
||||||
|
// Launching another game makes the original storage inaccessable.
|
||||||
|
// This is a helper for multi-nca games.
|
||||||
|
void ReportMissingOriginal(s64 offset, s64 size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ContinuousReadingEntry {
|
struct ContinuousReadingEntry {
|
||||||
@@ -154,6 +160,8 @@ private:
|
|||||||
private:
|
private:
|
||||||
mutable BucketTree m_table;
|
mutable BucketTree m_table;
|
||||||
std::array<VirtualFile, StorageCount> m_data_storage;
|
std::array<VirtualFile, StorageCount> m_data_storage;
|
||||||
|
bool m_original_missing{false};
|
||||||
|
bool m_reported_missing_original{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool ContinuousCheck, bool RangeCheck, typename F>
|
template <bool ContinuousCheck, bool RangeCheck, typename F>
|
||||||
@@ -272,6 +280,10 @@ Result IndirectStorage::OperatePerEntry(s64 offset, s64 size, F func) {
|
|||||||
if (needs_operate) {
|
if (needs_operate) {
|
||||||
const auto cur_entry_phys_offset = cur_entry.GetPhysicalOffset();
|
const auto cur_entry_phys_offset = cur_entry.GetPhysicalOffset();
|
||||||
|
|
||||||
|
if (cur_entry.storage_index == 0 && m_original_missing) {
|
||||||
|
this->ReportMissingOriginal(cur_offset, cur_size);
|
||||||
|
}
|
||||||
|
|
||||||
if constexpr (RangeCheck) {
|
if constexpr (RangeCheck) {
|
||||||
// Get the current data storage's size.
|
// Get the current data storage's size.
|
||||||
s64 cur_data_storage_size = m_data_storage[cur_entry.storage_index]->GetSize();
|
s64 cur_data_storage_size = m_data_storage[cur_entry.storage_index]->GetSize();
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ struct ContentRecord {
|
|||||||
std::array<u8, 0x10> nca_id;
|
std::array<u8, 0x10> nca_id;
|
||||||
std::array<u8, 0x6> size;
|
std::array<u8, 0x6> size;
|
||||||
ContentRecordType type;
|
ContentRecordType type;
|
||||||
INSERT_PADDING_BYTES(1);
|
u8 id_offset;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ContentRecord) == 0x38, "ContentRecord has incorrect size.");
|
static_assert(sizeof(ContentRecord) == 0x38, "ContentRecord has incorrect size.");
|
||||||
|
|
||||||
constexpr ContentRecord EMPTY_META_CONTENT_RECORD{{}, {}, {}, ContentRecordType::Meta, {}};
|
constexpr ContentRecord EMPTY_META_CONTENT_RECORD{{}, {}, {}, ContentRecordType::Meta, 0};
|
||||||
|
|
||||||
struct MetaRecord {
|
struct MetaRecord {
|
||||||
u64_le title_id;
|
u64_le title_id;
|
||||||
|
|||||||
@@ -567,20 +567,45 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<NcaID> CheckMapForContentRecord(const ankerl::unordered_dense::map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
|
static std::optional<NcaID> CheckMapForContentRecord(const ankerl::unordered_dense::map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
|
||||||
const auto cmnt_iter = map.find(title_id);
|
auto cmnt_iter = map.find(title_id);
|
||||||
|
u8 id_offset = 0;
|
||||||
|
|
||||||
if (cmnt_iter == map.cend()) {
|
if (cmnt_iter == map.cend()) {
|
||||||
return std::nullopt;
|
const auto program_index = title_id & AOC_TITLE_ID_MASK;
|
||||||
|
if (program_index == 0) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmnt_iter = map.find(title_id & ~AOC_TITLE_ID_MASK);
|
||||||
|
if (cmnt_iter == map.cend()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
id_offset = static_cast<u8>(program_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& cnmt = cmnt_iter->second;
|
const auto& cnmt = cmnt_iter->second;
|
||||||
const auto& content_records = cnmt.GetContentRecords();
|
const auto& content_records = cnmt.GetContentRecords();
|
||||||
const auto iter = std::find_if(content_records.cbegin(), content_records.cend(),
|
const auto iter = std::find_if(content_records.cbegin(), content_records.cend(),
|
||||||
[type](const ContentRecord& rec) { return rec.type == type; });
|
[type, id_offset](const ContentRecord& rec) {
|
||||||
if (iter == content_records.cend()) {
|
return rec.type == type && rec.id_offset == id_offset;
|
||||||
|
});
|
||||||
|
if (iter != content_records.cend()) {
|
||||||
|
return std::make_optional(iter->nca_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id_offset != 0) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_optional(iter->nca_id);
|
const auto fallback_iter =
|
||||||
|
std::find_if(content_records.cbegin(), content_records.cend(),
|
||||||
|
[type](const ContentRecord& rec) { return rec.type == type; });
|
||||||
|
if (fallback_iter == content_records.cend()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_optional(fallback_iter->nca_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
|
std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
#include "core/file_sys/partition_filesystem.h"
|
#include "core/file_sys/partition_filesystem.h"
|
||||||
@@ -65,10 +66,12 @@ u64 NSP::GetProgramTitleID() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto program_id = expected_program_id;
|
auto program_id = expected_program_id;
|
||||||
if (program_id == 0) {
|
if (program_id == 0 && !program_status.empty()) {
|
||||||
if (!program_status.empty()) {
|
program_id = std::min_element(program_status.cbegin(), program_status.cend(),
|
||||||
program_id = program_status.begin()->first;
|
[](const auto& lhs, const auto& rhs) {
|
||||||
}
|
return lhs.first < rhs.first;
|
||||||
|
})
|
||||||
|
->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_id = program_id + program_index;
|
program_id = program_id + program_index;
|
||||||
@@ -273,8 +276,7 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
|
|||||||
// If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and
|
// If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and
|
||||||
// 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular
|
// 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular
|
||||||
// update NCA.
|
// update NCA.
|
||||||
if ((next_nca->GetTitleId() & 0x7FF) != 0 &&
|
if ((next_nca->GetTitleId() & AOC_TITLE_ID_MASK) != 0) {
|
||||||
(next_nca->GetTitleId() & 0x800) == 0) {
|
|
||||||
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] =
|
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] =
|
||||||
std::move(next_nca);
|
std::move(next_nca);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -349,9 +349,18 @@ struct KernelCore::Impl {
|
|||||||
object_name_global_data.emplace(kernel);
|
object_name_global_data.emplace(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeApplicationProcess(KernelCore& kernel, KProcess* process) {
|
void SetApplicationProcess(KernelCore& kernel, KProcess* process) {
|
||||||
|
if (application_process == process)
|
||||||
|
return;
|
||||||
|
|
||||||
|
KProcess* const previous = application_process;
|
||||||
application_process = process;
|
application_process = process;
|
||||||
application_process->Open(kernel);
|
|
||||||
|
if (application_process != nullptr)
|
||||||
|
application_process->Open(kernel);
|
||||||
|
|
||||||
|
if (previous != nullptr)
|
||||||
|
previous->Close(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the host thread ID for the caller.
|
/// Sets the host thread ID for the caller.
|
||||||
@@ -879,8 +888,8 @@ void KernelCore::RemoveProcess(KProcess* process) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::MakeApplicationProcess(KProcess* process) {
|
void KernelCore::SetApplicationProcess(KProcess* process) {
|
||||||
impl->MakeApplicationProcess(*this, process);
|
impl->SetApplicationProcess(*this, process);
|
||||||
}
|
}
|
||||||
|
|
||||||
KProcess* KernelCore::ApplicationProcess() {
|
KProcess* KernelCore::ApplicationProcess() {
|
||||||
@@ -891,6 +900,14 @@ const KProcess* KernelCore::ApplicationProcess() const {
|
|||||||
return impl->application_process;
|
return impl->application_process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KScopedAutoObject<KProcess> KernelCore::GetProcessByProcessId(u64 process_id) {
|
||||||
|
std::scoped_lock lk{impl->process_list_lock};
|
||||||
|
for (auto* const process : impl->process_list)
|
||||||
|
if (process != nullptr && process->GetProcessId() == process_id)
|
||||||
|
return {*this, process};
|
||||||
|
return {*this, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
|
std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
|
||||||
std::list<KScopedAutoObject<KProcess>> processes;
|
std::list<KScopedAutoObject<KProcess>> processes;
|
||||||
std::scoped_lock lk{impl->process_list_lock};
|
std::scoped_lock lk{impl->process_list_lock};
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ public:
|
|||||||
void AppendNewProcess(KProcess* process);
|
void AppendNewProcess(KProcess* process);
|
||||||
void RemoveProcess(KProcess* process);
|
void RemoveProcess(KProcess* process);
|
||||||
|
|
||||||
/// Makes the given process the new application process.
|
/// Makes the given process the current application process.
|
||||||
void MakeApplicationProcess(KProcess* process);
|
void SetApplicationProcess(KProcess* process);
|
||||||
|
|
||||||
/// Retrieves a pointer to the application process.
|
/// Retrieves a pointer to the application process.
|
||||||
KProcess* ApplicationProcess();
|
KProcess* ApplicationProcess();
|
||||||
@@ -133,6 +133,9 @@ public:
|
|||||||
/// Retrieves a const pointer to the application process.
|
/// Retrieves a const pointer to the application process.
|
||||||
const KProcess* ApplicationProcess() const;
|
const KProcess* ApplicationProcess() const;
|
||||||
|
|
||||||
|
/// Retrieves the process with the given process ID, or a null object.
|
||||||
|
KScopedAutoObject<KProcess> GetProcessByProcessId(u64 process_id);
|
||||||
|
|
||||||
/// Retrieves the list of processes.
|
/// Retrieves the list of processes.
|
||||||
std::list<KScopedAutoObject<KProcess>> GetProcessList();
|
std::list<KScopedAutoObject<KProcess>> GetProcessList();
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,6 @@
|
|||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/hle/service/acc/acc.h"
|
#include "core/hle/service/acc/acc.h"
|
||||||
#include "core/hle/service/acc/acc_aa.h"
|
|
||||||
#include "core/hle/service/acc/acc_su.h"
|
|
||||||
#include "core/hle/service/acc/acc_u0.h"
|
|
||||||
#include "core/hle/service/acc/acc_u1.h"
|
|
||||||
#include "core/hle/service/acc/async_context.h"
|
#include "core/hle/service/acc/async_context.h"
|
||||||
#include "core/hle/service/acc/errors.h"
|
#include "core/hle/service/acc/errors.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
@@ -1244,19 +1240,416 @@ Module::Interface::Interface(std::shared_ptr<Module> module_,
|
|||||||
|
|
||||||
Module::Interface::~Interface() = default;
|
Module::Interface::~Interface() = default;
|
||||||
|
|
||||||
|
class ACC_AA final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
explicit ACC_AA(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:aa") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "EnsureCacheAsync"},
|
||||||
|
{1, nullptr, "LoadCache"},
|
||||||
|
{2, nullptr, "GetDeviceAccountId"},
|
||||||
|
{50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
||||||
|
{51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
~ACC_AA() override = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_SU final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
explicit ACC_SU(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:su") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ACC_SU::GetUserCount, "GetUserCount"},
|
||||||
|
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
|
||||||
|
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
|
||||||
|
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
|
||||||
|
{4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||||
|
{5, &ACC_SU::GetProfile, "GetProfile"},
|
||||||
|
{6, nullptr, "GetProfileDigest"},
|
||||||
|
{50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||||
|
{51, &ACC_SU::TrySelectUserWithoutInteractionDeprecated, "TrySelectUserWithoutInteractionDeprecated"},
|
||||||
|
{52, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, // 19.0.0+
|
||||||
|
{60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
|
||||||
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
|
{102, &ACC_SU::GetBaasAccountManagerForSystemService, "GetBaasAccountManagerForSystemService"},
|
||||||
|
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
|
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
|
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
{106, nullptr, "GetProfileSyncNotifier"},
|
||||||
|
{110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"},
|
||||||
|
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||||
|
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||||
|
{120, nullptr, "ListOpenUsersInApplication"},
|
||||||
|
{130, nullptr, "ActivateOpenContextRetention"},
|
||||||
|
{140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"},
|
||||||
|
{150, nullptr, "AuthenticateApplicationAsync"},
|
||||||
|
{151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
||||||
|
{152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
||||||
|
{190, nullptr, "GetUserLastOpenedApplication"},
|
||||||
|
{191, nullptr, "ActivateOpenContextHolder"},
|
||||||
|
{200, &ACC_SU::BeginUserRegistration, "BeginUserRegistration"},
|
||||||
|
{201, &ACC_SU::CompleteUserRegistration, "CompleteUserRegistration"},
|
||||||
|
{202, nullptr, "CancelUserRegistration"},
|
||||||
|
{203, &ACC_SU::DeleteUser, "DeleteUser"},
|
||||||
|
{204, &ACC_SU::SetUserPosition, "SetUserPosition"},
|
||||||
|
{205, &ACC_SU::GetProfileEditor, "GetProfileEditor"},
|
||||||
|
{206, nullptr, "CompleteUserRegistrationForcibly"},
|
||||||
|
{210, nullptr, "CreateFloatingRegistrationRequest"},
|
||||||
|
{211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"},
|
||||||
|
{212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"},
|
||||||
|
{230, nullptr, "AuthenticateServiceAsync"},
|
||||||
|
{250, &ACC_SU::GetBaasAccountAdministrator, "GetBaasAccountAdministrator"},
|
||||||
|
{290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
|
||||||
|
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
|
||||||
|
{299, nullptr, "SuspendBackgroundDaemon"},
|
||||||
|
{400, nullptr, "SetPinCode"}, // 18.0.0+
|
||||||
|
{401, &ACC_SU::GetPinCodeLength, "GetPinCodeLength"}, // 18.0.0+
|
||||||
|
{402, nullptr, "GetPinCode"}, // 18.0.0+
|
||||||
|
{403, nullptr, "GetPinCodeParity"},
|
||||||
|
{404, nullptr, "VerifyPinCode"},
|
||||||
|
{405, nullptr, "IsPinCodeVerificationForbidden"},
|
||||||
|
{410, nullptr, "GetPinCodeErrorCount"}, // 18.0.0+
|
||||||
|
{411, nullptr, "ResetPinCodeErrorCount"}, // 18.0.0+
|
||||||
|
{412, nullptr, "IncrementPinCodeErrorCount"}, // 18.0.0+
|
||||||
|
{900, nullptr, "SetUserUnqualifiedForDebug"},
|
||||||
|
{901, nullptr, "UnsetUserUnqualifiedForDebug"},
|
||||||
|
{902, nullptr, "ListUsersUnqualifiedForDebug"},
|
||||||
|
{910, nullptr, "RefreshFirmwareSettingsForDebug"},
|
||||||
|
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||||
|
{998, nullptr, "DebugSetUserStateClose"},
|
||||||
|
{999, nullptr, "DebugSetUserStateOpen"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
~ACC_SU() override = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_U0 final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:u0") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ACC_U0::GetUserCount, "GetUserCount"},
|
||||||
|
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
|
||||||
|
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
|
||||||
|
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
|
||||||
|
{4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||||
|
{5, &ACC_U0::GetProfile, "GetProfile"},
|
||||||
|
{6, nullptr, "GetProfileDigest"}, // 3.0.0+
|
||||||
|
{50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||||
|
{51, &ACC_U0::TrySelectUserWithoutInteractionDeprecated, "TrySelectUserWithoutInteractionDeprecated"},
|
||||||
|
{52, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||||
|
{60, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
|
||||||
|
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
|
||||||
|
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
|
||||||
|
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
|
||||||
|
{102, nullptr, "AuthenticateApplicationAsync"},
|
||||||
|
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
|
||||||
|
{110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
|
||||||
|
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{120, nullptr, "CreateGuestLoginRequest"},
|
||||||
|
{130, nullptr, "LoadOpenContext"}, // 5.0.0+
|
||||||
|
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
|
||||||
|
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
|
||||||
|
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
||||||
|
{150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, // 6.0.0+
|
||||||
|
{160, &ACC_U0::InitializeApplicationInfoV2, "InitializeApplicationInfoV2"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
~ACC_U0() override = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_U1 final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
ACC_U1(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:u1") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ACC_U1::GetUserCount, "GetUserCount"},
|
||||||
|
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
|
||||||
|
{2, &ACC_U1::ListAllUsers, "ListAllUsers"},
|
||||||
|
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
|
||||||
|
{4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||||
|
{5, &ACC_U1::GetProfile, "GetProfile"},
|
||||||
|
{6, nullptr, "GetProfileDigest"},
|
||||||
|
{50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||||
|
{51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||||
|
{60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
|
||||||
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
|
{102, &ACC_U1::GetBaasAccountManagerForSystemService, "GetBaasAccountManagerForSystemService"},
|
||||||
|
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
|
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
|
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
{106, nullptr, "GetProfileSyncNotifier"},
|
||||||
|
{110, &ACC_U1::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
|
||||||
|
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||||
|
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||||
|
{120, nullptr, "ListOpenUsersInApplication"},
|
||||||
|
{130, nullptr, "ActivateOpenContextRetention"},
|
||||||
|
{140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"},
|
||||||
|
{150, nullptr, "AuthenticateApplicationAsync"},
|
||||||
|
{151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
||||||
|
{152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
||||||
|
{190, nullptr, "GetUserLastOpenedApplication"},
|
||||||
|
{191, nullptr, "ActivateOpenContextHolder"},
|
||||||
|
{401, &ACC_U1::GetPinCodeLength, "GetPinCodeLength"}, // 18.0.0+
|
||||||
|
{402, nullptr, "GetPinCode"}, // 18.0.0+
|
||||||
|
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||||
|
{998, nullptr, "DebugSetUserStateClose"},
|
||||||
|
{999, nullptr, "DebugSetUserStateOpen"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
~ACC_U1() override = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DAUTH_0 final : public ServiceFramework<DAUTH_0> {
|
||||||
|
public:
|
||||||
|
explicit DAUTH_0(Core::System& system_) : ServiceFramework{system_, "dauth:0"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "EnsureAuthenticationTokenCacheAsync"},
|
||||||
|
{1, nullptr, "LoadAuthenticationTokenCache"},
|
||||||
|
{2, nullptr, "InvalidateAuthenticationTokenCache"},
|
||||||
|
{3, nullptr, "IsDeviceAuthenticationTokenCacheAvailable"},
|
||||||
|
{10, nullptr, "EnsureEdgeTokenCacheAsync"},
|
||||||
|
{11, nullptr, "LoadEdgeTokenCache"},
|
||||||
|
{12, nullptr, "InvalidateEdgeTokenCache"},
|
||||||
|
{13, nullptr, "IsEdgeTokenCacheAvailable"},
|
||||||
|
{20, nullptr, "EnsureApplicationAuthenticationCacheAsync"},
|
||||||
|
{21, nullptr, "LoadApplicationAuthenticationTokenCache"},
|
||||||
|
{22, nullptr, "LoadApplicationNetworkServiceClientConfigCache"},
|
||||||
|
{23, nullptr, "IsApplicationAuthenticationCacheAvailable"},
|
||||||
|
{24, nullptr, "InvalidateApplicationAuthenticationCache"},
|
||||||
|
{30, nullptr, "EnsureGameCardAuthenticationCacheAsync"},
|
||||||
|
{31, nullptr, "LoadGameCardAuthenticationTokenCache"},
|
||||||
|
{32, nullptr, "IsGameCardAuthenticationCacheAvailable"},
|
||||||
|
{33, nullptr, "InvalidateGameCardAuthenticationCache"},
|
||||||
|
{1000, nullptr, "GetInactiveElicenseUsedEvent"},
|
||||||
|
{9000, nullptr, "ImportVirtualClientCertificate"},
|
||||||
|
{9010, nullptr, "DeleteVirtualClientCertificate"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_E final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
explicit ACC_E(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:e") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{ 0, nullptr, "GetUserCount"},
|
||||||
|
{ 1, nullptr, "GetUserExistence"},
|
||||||
|
{ 2, nullptr, "ListAllUsers"},
|
||||||
|
{ 3, nullptr, "ListOpenUsers"},
|
||||||
|
{ 4, nullptr, "GetLastOpenedUser"},
|
||||||
|
{ 5, nullptr, "GetProfile"},
|
||||||
|
{ 6, nullptr, "GetProfileDigest"},
|
||||||
|
{ 50, nullptr, "IsUserRegistrationRequestPermitted"},
|
||||||
|
{ 51, nullptr, "TrySelectUserWithoutInteractionDeprecated"},
|
||||||
|
{ 52, nullptr, "TrySelectUserWithoutInteraction"},
|
||||||
|
{ 99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
|
{ 100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
{ 101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
|
{ 102, nullptr, "GetBaasAccountManagerForSystemService"},
|
||||||
|
{ 103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
|
{ 104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
|
{ 105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
{ 106, nullptr, "GetProfileSyncNotifier"},
|
||||||
|
{ 110, nullptr, "StoreSaveDataThumbnail"},
|
||||||
|
{ 111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{ 112, nullptr, "LoadSaveDataThumbnail"},
|
||||||
|
{ 113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||||
|
{ 120, nullptr, "ListOpenUsersInApplication"},
|
||||||
|
{ 130, nullptr, "ActivateOpenContextRetention"},
|
||||||
|
{ 140, nullptr, "ListQualifiedUsers"},
|
||||||
|
{ 151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
||||||
|
{ 152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
||||||
|
{ 170, nullptr, "GetNasOp2MembershipStateChangeNotifier"},
|
||||||
|
{ 191, nullptr, "UpdateNotificationReceiverInfo"},
|
||||||
|
{ 200, nullptr, "BeginUserRegistration"},
|
||||||
|
{ 201, nullptr, "CompleteUserRegistration"},
|
||||||
|
{ 202, nullptr, "CancelUserRegistration"},
|
||||||
|
{ 203, nullptr, "DeleteUser"},
|
||||||
|
{ 204, nullptr, "SetUserPosition"},
|
||||||
|
{ 205, nullptr, "GetProfileEditor"},
|
||||||
|
{ 206, nullptr, "CompleteUserRegistrationForcibly"},
|
||||||
|
{ 210, nullptr, "CreateFloatingRegistrationRequest"},
|
||||||
|
{ 211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"},
|
||||||
|
{ 212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"},
|
||||||
|
{ 213, nullptr, "CreateProcedureToCreateUserWithNintendoAccount"},
|
||||||
|
{ 214, nullptr, "ResumeProcedureToCreateUserWithNintendoAccount"},
|
||||||
|
{ 215, nullptr, "ResumeProcedureToCreateUserWithNintendoAccountAfterApplyResponse"},
|
||||||
|
{ 230, nullptr, "AuthenticateServiceAsync"},
|
||||||
|
{ 250, nullptr, "GetBaasAccountAdministrator"},
|
||||||
|
{ 251, nullptr, "SynchronizeNetworkServiceAccountsSnapshotAsync"},
|
||||||
|
{ 290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
|
||||||
|
{ 291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
|
||||||
|
{ 292, nullptr, "ProxyProcedureForDeviceMigrationAuthenticatingOperatingUser"},
|
||||||
|
{ 293, nullptr, "ProxyProcedureForDeviceMigrationDownload"},
|
||||||
|
{ 299, nullptr, "SuspendBackgroundDaemon"},
|
||||||
|
{ 350, nullptr, "CreateDeviceMigrationUserExportRequest"},
|
||||||
|
{ 351, nullptr, "UploadNasCredential"},
|
||||||
|
{ 352, nullptr, "CreateDeviceMigrationUserImportRequest"},
|
||||||
|
{ 353, nullptr, "DeleteUserMigrationSaveData"},
|
||||||
|
{ 400, nullptr, "SetPinCode"},
|
||||||
|
{ 401, nullptr, "GetPinCodeLength"},
|
||||||
|
{ 402, nullptr, "GetPinCode"},
|
||||||
|
{ 403, nullptr, "GetPinCodeParity"},
|
||||||
|
{ 404, nullptr, "VerifyPinCode"},
|
||||||
|
{ 405, nullptr, "IsPinCodeVerificationForbidden"},
|
||||||
|
{ 410, nullptr, "GetPinCodeErrorCount"},
|
||||||
|
{ 411, nullptr, "ResetPinCodeErrorCount"},
|
||||||
|
{ 412, nullptr, "IncrementPinCodeErrorCount"},
|
||||||
|
{ 413, nullptr, "SetPinCodeErrorCount"},
|
||||||
|
{ 420, nullptr, "SetStartPenaltyTime"},
|
||||||
|
{ 421, nullptr, "GetStartPenaltyTime"},
|
||||||
|
{ 900, nullptr, "SetUserUnqualifiedForDebug"},
|
||||||
|
{ 901, nullptr, "UnsetUserUnqualifiedForDebug"},
|
||||||
|
{ 902, nullptr, "ListUsersUnqualifiedForDebug"},
|
||||||
|
{ 910, nullptr, "RefreshFirmwareSettingsForDebug"},
|
||||||
|
{ 997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||||
|
{ 998, nullptr, "DebugSetUserStateClose"},
|
||||||
|
{ 999, nullptr, "DebugSetUserStateOpen"},
|
||||||
|
{ 1000, nullptr, "CreateIAccountEntityServiceForApplication"},
|
||||||
|
{ 1100, nullptr, "CreateIUserStateManager"},
|
||||||
|
{ 10050, nullptr, "IsUserRegistrationRequestPermittedForAccountPolicy"},
|
||||||
|
{ 10105, nullptr, "CheckNetworkServiceAvailabilityAsyncForAccountPolicy"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_E_U1 final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
explicit ACC_E_U1(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:e:u1") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "GetUserCount"},
|
||||||
|
{1, nullptr, "GetUserExistence"},
|
||||||
|
{2, nullptr, "ListAllUsers"},
|
||||||
|
{3, nullptr, "ListOpenUsers"},
|
||||||
|
{4, nullptr, "GetLastOpenedUser"},
|
||||||
|
{5, nullptr, "GetProfile"},
|
||||||
|
{6, nullptr, "GetProfileDigest"},
|
||||||
|
{50, nullptr, "IsUserRegistrationRequestPermitted"},
|
||||||
|
{51, nullptr, "TrySelectUserWithoutInteractionDeprecated"},
|
||||||
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
|
{102, nullptr, "GetBaasAccountManagerForSystemService"},
|
||||||
|
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
|
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
|
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
{106, nullptr, "GetProfileSyncNotifier"},
|
||||||
|
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||||
|
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||||
|
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||||
|
{120, nullptr, "ListOpenUsersInApplication"},
|
||||||
|
{130, nullptr, "ActivateOpenContextRetention"},
|
||||||
|
{140, nullptr, "ListQualifiedUsers"},
|
||||||
|
{151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
||||||
|
{152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
||||||
|
{170, nullptr, "GetNasOp2MembershipStateChangeNotifier"},
|
||||||
|
{191, nullptr, "UpdateNotificationReceiverInfo"},
|
||||||
|
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||||
|
{998, nullptr, "DebugSetUserStateClose"},
|
||||||
|
{999, nullptr, "DebugSetUserStateOpen"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ACC_E_U2 final : public Module::Interface {
|
||||||
|
public:
|
||||||
|
explicit ACC_E_U2(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_)
|
||||||
|
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:e:u2") {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "GetUserCount"},
|
||||||
|
{1, nullptr, "GetUserExistence"},
|
||||||
|
{2, nullptr, "ListAllUsers"},
|
||||||
|
{3, nullptr, "ListOpenUsers"},
|
||||||
|
{4, nullptr, "GetLastOpenedUser"},
|
||||||
|
{5, nullptr, "GetProfile"},
|
||||||
|
{6, nullptr, "GetProfileDigest"},
|
||||||
|
{50, nullptr, "#IsUserRegistrationRequestPermitted"},
|
||||||
|
{51, nullptr, "TrySelectUserWithoutInteractionDeprecated"},
|
||||||
|
{52, nullptr, "TrySelectUserWithoutInteraction"},
|
||||||
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
|
{102, nullptr, "GetBaasAccountManagerForSystemService"},
|
||||||
|
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
|
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
|
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
{106, nullptr, "GetProfileSyncNotifier"},
|
||||||
|
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||||
|
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||||
|
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||||
|
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||||
|
{120, nullptr, "ListOpenUsersInApplication"},
|
||||||
|
{130, nullptr, "ActivateOpenContextRetention"},
|
||||||
|
{140, nullptr, "ListQualifiedUsers"},
|
||||||
|
{151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
||||||
|
{152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
||||||
|
{170, nullptr, "GetNasOp2MembershipStateChangeNotifier"},
|
||||||
|
{191, nullptr, "UpdateNotificationReceiverInfo"},
|
||||||
|
{205, nullptr, "GetProfileEditor"},
|
||||||
|
{401, nullptr, "GetPinCodeLength"},
|
||||||
|
{402, nullptr, "GetPinCode"},
|
||||||
|
{403, nullptr, "GetPinCodeParity"},
|
||||||
|
{404, nullptr, "VerifyPinCode"},
|
||||||
|
{405, nullptr, "IsPinCodeVerificationForbidden"},
|
||||||
|
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||||
|
{998, nullptr, "DebugSetUserStateClose"},
|
||||||
|
{999, nullptr, "DebugSetUserStateOpen"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
auto module = std::make_shared<Module>();
|
auto module = std::make_shared<Module>();
|
||||||
auto profile_manager = std::make_shared<ProfileManager>();
|
auto profile_manager = std::make_shared<ProfileManager>();
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService("acc:aa",
|
server_manager->RegisterNamedService("acc:aa", std::make_shared<ACC_AA>(module, profile_manager, system));
|
||||||
std::make_shared<ACC_AA>(module, profile_manager, system));
|
server_manager->RegisterNamedService("acc:su", std::make_shared<ACC_SU>(module, profile_manager, system));
|
||||||
server_manager->RegisterNamedService("acc:su",
|
server_manager->RegisterNamedService("acc:u0", std::make_shared<ACC_U0>(module, profile_manager, system));
|
||||||
std::make_shared<ACC_SU>(module, profile_manager, system));
|
server_manager->RegisterNamedService("acc:u1", std::make_shared<ACC_U1>(module, profile_manager, system));
|
||||||
server_manager->RegisterNamedService("acc:u0",
|
|
||||||
std::make_shared<ACC_U0>(module, profile_manager, system));
|
server_manager->RegisterNamedService("acc:e", std::make_shared<ACC_E>(module, profile_manager, system));
|
||||||
server_manager->RegisterNamedService("acc:u1",
|
server_manager->RegisterNamedService("acc:e:u1", std::make_shared<ACC_E_U1>(module, profile_manager, system));
|
||||||
std::make_shared<ACC_U1>(module, profile_manager, system));
|
server_manager->RegisterNamedService("acc:e:u2", std::make_shared<ACC_E_U2>(module, profile_manager, system));
|
||||||
|
|
||||||
|
server_manager->RegisterNamedService("dauth:0", std::make_shared<DAUTH_0>(system));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc_aa.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
ACC_AA::ACC_AA(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_,
|
|
||||||
Core::System& system_)
|
|
||||||
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:aa") {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, nullptr, "EnsureCacheAsync"},
|
|
||||||
{1, nullptr, "LoadCache"},
|
|
||||||
{2, nullptr, "GetDeviceAccountId"},
|
|
||||||
{50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
|
||||||
{51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACC_AA::~ACC_AA() = default;
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
class ACC_AA final : public Module::Interface {
|
|
||||||
public:
|
|
||||||
explicit ACC_AA(std::shared_ptr<Module> module_,
|
|
||||||
std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_);
|
|
||||||
~ACC_AA() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc_su.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
ACC_SU::ACC_SU(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_,
|
|
||||||
Core::System& system_)
|
|
||||||
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:su") {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ACC_SU::GetUserCount, "GetUserCount"},
|
|
||||||
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
|
|
||||||
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
|
|
||||||
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
|
|
||||||
{4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"},
|
|
||||||
{5, &ACC_SU::GetProfile, "GetProfile"},
|
|
||||||
{6, nullptr, "GetProfileDigest"},
|
|
||||||
{50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
|
||||||
{51, &ACC_SU::TrySelectUserWithoutInteractionDeprecated, "TrySelectUserWithoutInteractionDeprecated"},
|
|
||||||
{52, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, // 19.0.0+
|
|
||||||
{60, &ACC_SU::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
|
|
||||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
|
||||||
{100, nullptr, "GetUserRegistrationNotifier"},
|
|
||||||
{101, nullptr, "GetUserStateChangeNotifier"},
|
|
||||||
{102, &ACC_SU::GetBaasAccountManagerForSystemService, "GetBaasAccountManagerForSystemService"},
|
|
||||||
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
|
||||||
{104, nullptr, "GetProfileUpdateNotifier"},
|
|
||||||
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
|
||||||
{106, nullptr, "GetProfileSyncNotifier"},
|
|
||||||
{110, &ACC_SU::StoreSaveDataThumbnailSystem, "StoreSaveDataThumbnail"},
|
|
||||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
|
||||||
{112, nullptr, "LoadSaveDataThumbnail"},
|
|
||||||
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
|
||||||
{120, nullptr, "ListOpenUsersInApplication"},
|
|
||||||
{130, nullptr, "ActivateOpenContextRetention"},
|
|
||||||
{140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"},
|
|
||||||
{150, nullptr, "AuthenticateApplicationAsync"},
|
|
||||||
{151, nullptr, "EnsureSignedDeviceIdentifierCacheForNintendoAccountAsync"},
|
|
||||||
{152, nullptr, "LoadSignedDeviceIdentifierCacheForNintendoAccount"},
|
|
||||||
{190, nullptr, "GetUserLastOpenedApplication"},
|
|
||||||
{191, nullptr, "ActivateOpenContextHolder"},
|
|
||||||
{200, &ACC_SU::BeginUserRegistration, "BeginUserRegistration"},
|
|
||||||
{201, &ACC_SU::CompleteUserRegistration, "CompleteUserRegistration"},
|
|
||||||
{202, nullptr, "CancelUserRegistration"},
|
|
||||||
{203, &ACC_SU::DeleteUser, "DeleteUser"},
|
|
||||||
{204, &ACC_SU::SetUserPosition, "SetUserPosition"},
|
|
||||||
{205, &ACC_SU::GetProfileEditor, "GetProfileEditor"},
|
|
||||||
{206, nullptr, "CompleteUserRegistrationForcibly"},
|
|
||||||
{210, nullptr, "CreateFloatingRegistrationRequest"},
|
|
||||||
{211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"},
|
|
||||||
{212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"},
|
|
||||||
{230, nullptr, "AuthenticateServiceAsync"},
|
|
||||||
{250, &ACC_SU::GetBaasAccountAdministrator, "GetBaasAccountAdministrator"},
|
|
||||||
{290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
|
|
||||||
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
|
|
||||||
{299, nullptr, "SuspendBackgroundDaemon"},
|
|
||||||
{400, nullptr, "SetPinCode"}, // 18.0.0+
|
|
||||||
{401, &ACC_SU::GetPinCodeLength, "GetPinCodeLength"}, // 18.0.0+
|
|
||||||
{402, nullptr, "GetPinCode"}, // 18.0.0+
|
|
||||||
{410, nullptr, "GetPinCodeErrorCount"}, // 18.0.0+
|
|
||||||
{411, nullptr, "ResetPinCodeErrorCount"}, // 18.0.0+
|
|
||||||
{412, nullptr, "IncrementPinCodeErrorCount"}, // 18.0.0+
|
|
||||||
{900, nullptr, "SetUserUnqualifiedForDebug"},
|
|
||||||
{901, nullptr, "UnsetUserUnqualifiedForDebug"},
|
|
||||||
{902, nullptr, "ListUsersUnqualifiedForDebug"},
|
|
||||||
{910, nullptr, "RefreshFirmwareSettingsForDebug"},
|
|
||||||
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
|
||||||
{998, nullptr, "DebugSetUserStateClose"},
|
|
||||||
{999, nullptr, "DebugSetUserStateOpen"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACC_SU::~ACC_SU() = default;
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
class ACC_SU final : public Module::Interface {
|
|
||||||
public:
|
|
||||||
explicit ACC_SU(std::shared_ptr<Module> module_,
|
|
||||||
std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_);
|
|
||||||
~ACC_SU() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc_u0.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> profile_manager_,
|
|
||||||
Core::System& system_)
|
|
||||||
: Interface(std::move(module_), std::move(profile_manager_), system_, "acc:u0") {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ACC_U0::GetUserCount, "GetUserCount"},
|
|
||||||
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
|
|
||||||
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
|
|
||||||
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
|
|
||||||
{4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"},
|
|
||||||
{5, &ACC_U0::GetProfile, "GetProfile"},
|
|
||||||
{6, nullptr, "GetProfileDigest"}, // 3.0.0+
|
|
||||||
{50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
|
||||||
{51, &ACC_U0::TrySelectUserWithoutInteractionDeprecated, "TrySelectUserWithoutInteractionDeprecated"},
|
|
||||||
{52, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
|
||||||
{60, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
|
|
||||||
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
|
|
||||||
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
|
|
||||||
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
|
|
||||||
{102, nullptr, "AuthenticateApplicationAsync"},
|
|
||||||
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
|
|
||||||
{110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
|
|
||||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
|
||||||
{120, nullptr, "CreateGuestLoginRequest"},
|
|
||||||
{130, nullptr, "LoadOpenContext"}, // 5.0.0+
|
|
||||||
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
|
|
||||||
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
|
|
||||||
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
|
||||||
{150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, // 6.0.0+
|
|
||||||
{160, &ACC_U0::InitializeApplicationInfoV2, "InitializeApplicationInfoV2"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACC_U0::~ACC_U0() = default;
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/acc/acc.h"
|
|
||||||
|
|
||||||
namespace Service::Account {
|
|
||||||
|
|
||||||
class ACC_U0 final : public Module::Interface {
|
|
||||||
public:
|
|
||||||
explicit ACC_U0(std::shared_ptr<Module> module_,
|
|
||||||
std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_);
|
|
||||||
~ACC_U0() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Account
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user