Compare commits
3 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ab4ab16a7 | ||
|
|
4767fe993b | ||
|
|
9440d5eb8d |
@@ -2,5 +2,5 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
[codespell]
|
||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
|
||||
ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink
|
||||
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES
|
||||
ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink
|
||||
|
||||
@@ -129,11 +129,6 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@@ -165,3 +160,24 @@ jobs:
|
||||
with:
|
||||
name: android
|
||||
path: artifacts/
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ android ]
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: Create release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
release_name: ${{ github.ref_name }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload artifacts
|
||||
uses: alexellis/upload-assets@0.4.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
asset_paths: '["./**/*.tar.*","./**/*.AppImage","./**/*.7z","./**/*.zip","./**/*.apk","./**/*.aab"]'
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -26,8 +26,6 @@ CMakeSettings.json
|
||||
# OSX global filetypes
|
||||
# Created by Finder or Spotlight in directories for various OS functionality (indexing, etc)
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.Spotlight-V100
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -49,6 +49,6 @@
|
||||
[submodule "cpp-jwt"]
|
||||
path = externals/cpp-jwt
|
||||
url = https://github.com/arun11299/cpp-jwt.git
|
||||
[submodule "libadrenotools"]
|
||||
[submodule "externals/libadrenotools"]
|
||||
path = externals/libadrenotools
|
||||
url = https://github.com/bylaws/libadrenotools
|
||||
|
||||
@@ -255,7 +255,7 @@ endif()
|
||||
# boost asio's concept usage doesn't play nicely with some compilers yet.
|
||||
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
|
||||
if (MSVC)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++20>)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++latest>)
|
||||
|
||||
# boost still makes use of deprecated result_of.
|
||||
add_definitions(-D_HAS_DEPRECATED_RESULT_OF)
|
||||
|
||||
@@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
<h4 align="center"><b>yuzu</b> is the world's most popular, open-source, Nintendo Switch emulator — started by the creators of <a href="https://citra-emu.org" target="_blank">Citra</a>.
|
||||
<br>
|
||||
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.
|
||||
It is written in C++ with portability in mind, and we actively maintain builds for Windows and Linux.
|
||||
</h4>
|
||||
|
||||
<p align="center">
|
||||
|
||||
6
externals/CMakeLists.txt
vendored
6
externals/CMakeLists.txt
vendored
@@ -63,9 +63,8 @@ if (YUZU_USE_EXTERNAL_SDL2)
|
||||
# Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers
|
||||
# Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095)
|
||||
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
|
||||
# CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809)
|
||||
set(SDL_UNUSED_SUBSYSTEMS
|
||||
File Filesystem
|
||||
CPUinfo File Filesystem
|
||||
Locale Power Render)
|
||||
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
|
||||
string(TOUPPER ${_SUB} _OPT)
|
||||
@@ -140,9 +139,6 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
add_subdirectory(Vulkan-Headers)
|
||||
endif()
|
||||
|
||||
# TZDB (Time Zone Database)
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
if (NOT TARGET LLVM::Demangle)
|
||||
add_library(demangle demangle/ItaniumDemangle.cpp)
|
||||
target_include_directories(demangle PUBLIC ./demangle)
|
||||
|
||||
65
externals/nx_tzdb/CMakeLists.txt
vendored
65
externals/nx_tzdb/CMakeLists.txt
vendored
@@ -1,65 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(NX_TZDB_VERSION "220816")
|
||||
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
||||
|
||||
set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
|
||||
set(NX_TZDB_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
|
||||
|
||||
set(NX_TZDB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
if (NOT EXISTS ${NX_TZDB_ARCHIVE})
|
||||
file(DOWNLOAD ${NX_TZDB_DOWNLOAD_URL} ${NX_TZDB_ARCHIVE})
|
||||
file(ARCHIVE_EXTRACT
|
||||
INPUT
|
||||
${NX_TZDB_ARCHIVE}
|
||||
DESTINATION
|
||||
${NX_TZDB_DIR})
|
||||
endif()
|
||||
|
||||
add_library(nx_tzdb INTERFACE)
|
||||
target_include_directories(nx_tzdb
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
INTERFACE ${NX_TZDB_INCLUDE_DIR})
|
||||
|
||||
function(CreateHeader ZONE_PATH HEADER_NAME)
|
||||
set(HEADER_PATH "${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/NxTzdbCreateHeader.cmake
|
||||
${ZONE_PATH}
|
||||
${HEADER_NAME}
|
||||
${NX_TZDB_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS
|
||||
tzdb_template.h.in
|
||||
NxTzdbCreateHeader.cmake)
|
||||
|
||||
target_sources(nx_tzdb PRIVATE ${HEADER_PATH})
|
||||
endfunction()
|
||||
|
||||
CreateHeader(${NX_TZDB_DIR} base)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo zoneinfo)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Africa africa)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/America america)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/America/Argentina america_argentina)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/America/Indiana america_indiana)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/America/Kentucky america_kentucky)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/America/North_Dakota america_north_dakota)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Antartica antartica)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Arctic arctic)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Asia asia)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Atlantic atlantic)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Australia australia)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Brazil brazil)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Canada canada)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Chile chile)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Etc etc)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Europe europe)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Indian indian)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Mexico mexico)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/Pacific pacific)
|
||||
CreateHeader(${NX_TZDB_DIR}/zoneinfo/US us)
|
||||
8
externals/nx_tzdb/ListFilesInDirectory.cmake
vendored
8
externals/nx_tzdb/ListFilesInDirectory.cmake
vendored
@@ -1,8 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# CMake does not have a way to list the files in a specific directory,
|
||||
# so we need this script to do that for us in a platform-agnostic fashion
|
||||
|
||||
file(GLOB FILE_LIST LIST_DIRECTORIES false RELATIVE ${CMAKE_SOURCE_DIR} "*")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${FILE_LIST};")
|
||||
46
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
46
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
@@ -1,46 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(ZONE_PATH ${CMAKE_ARGV3})
|
||||
set(HEADER_NAME ${CMAKE_ARGV4})
|
||||
set(NX_TZDB_INCLUDE_DIR ${CMAKE_ARGV5})
|
||||
set(NX_TZDB_SOURCE_DIR ${CMAKE_ARGV6})
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -P ${NX_TZDB_SOURCE_DIR}/ListFilesInDirectory.cmake
|
||||
WORKING_DIRECTORY ${ZONE_PATH}
|
||||
OUTPUT_VARIABLE FILE_LIST)
|
||||
|
||||
set(DIRECTORY_NAME ${HEADER_NAME})
|
||||
|
||||
set(FILE_DATA "")
|
||||
foreach(ZONE_FILE ${FILE_LIST})
|
||||
if ("${ZONE_FILE}" STREQUAL "\n")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
string(APPEND FILE_DATA "{\"${ZONE_FILE}\",\n{")
|
||||
|
||||
file(READ ${ZONE_PATH}/${ZONE_FILE} ZONE_DATA HEX)
|
||||
string(LENGTH "${ZONE_DATA}" ZONE_DATA_LEN)
|
||||
foreach(I RANGE 0 ${ZONE_DATA_LEN} 2)
|
||||
math(EXPR BREAK_LINE "(${I} + 2) % 38")
|
||||
|
||||
string(SUBSTRING "${ZONE_DATA}" "${I}" "2" HEX_DATA)
|
||||
if ("${HEX_DATA}" STREQUAL "")
|
||||
break()
|
||||
endif()
|
||||
|
||||
string(APPEND FILE_DATA "0x${HEX_DATA},")
|
||||
if ("${BREAK_LINE}" STREQUAL "0")
|
||||
string(APPEND FILE_DATA "\n")
|
||||
else()
|
||||
string(APPEND FILE_DATA " ")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
string(APPEND FILE_DATA "}},\n")
|
||||
endforeach()
|
||||
|
||||
file(READ ${NX_TZDB_SOURCE_DIR}/tzdb_template.h.in NX_TZDB_TEMPLATE_H_IN)
|
||||
file(CONFIGURE OUTPUT ${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h CONTENT "${NX_TZDB_TEMPLATE_H_IN}")
|
||||
27
externals/nx_tzdb/include/nx_tzdb.h
vendored
27
externals/nx_tzdb/include/nx_tzdb.h
vendored
@@ -1,27 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nx_tzdb/africa.h"
|
||||
#include "nx_tzdb/america.h"
|
||||
#include "nx_tzdb/america_argentina.h"
|
||||
#include "nx_tzdb/america_indiana.h"
|
||||
#include "nx_tzdb/america_kentucky.h"
|
||||
#include "nx_tzdb/america_north_dakota.h"
|
||||
#include "nx_tzdb/antartica.h"
|
||||
#include "nx_tzdb/arctic.h"
|
||||
#include "nx_tzdb/asia.h"
|
||||
#include "nx_tzdb/atlantic.h"
|
||||
#include "nx_tzdb/australia.h"
|
||||
#include "nx_tzdb/base.h"
|
||||
#include "nx_tzdb/brazil.h"
|
||||
#include "nx_tzdb/canada.h"
|
||||
#include "nx_tzdb/chile.h"
|
||||
#include "nx_tzdb/etc.h"
|
||||
#include "nx_tzdb/europe.h"
|
||||
#include "nx_tzdb/indian.h"
|
||||
#include "nx_tzdb/mexico.h"
|
||||
#include "nx_tzdb/pacific.h"
|
||||
#include "nx_tzdb/us.h"
|
||||
#include "nx_tzdb/zoneinfo.h"
|
||||
18
externals/nx_tzdb/tzdb_template.h.in
vendored
18
externals/nx_tzdb/tzdb_template.h.in
vendored
@@ -1,18 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace NxTzdb {
|
||||
|
||||
// clang-format off
|
||||
const static std::map<const char*, const std::vector<uint8_t>> @DIRECTORY_NAME@ =
|
||||
{
|
||||
@FILE_DATA@};
|
||||
// clang-format on
|
||||
|
||||
} // namespace NxTzdb
|
||||
2
externals/vcpkg
vendored
2
externals/vcpkg
vendored
Submodule externals/vcpkg updated: a487471068...656fcc6ab2
@@ -43,7 +43,7 @@ if (MSVC)
|
||||
/Zo
|
||||
/permissive-
|
||||
/EHsc
|
||||
/std:c++20
|
||||
/std:c++latest
|
||||
/utf-8
|
||||
/volatile:iso
|
||||
/Zc:externConstexpr
|
||||
@@ -51,10 +51,8 @@ if (MSVC)
|
||||
/Zc:throwingNew
|
||||
/GT
|
||||
|
||||
# Modules
|
||||
/experimental:module- # Disable module support explicitly due to conflicts with precompiled headers
|
||||
|
||||
# External headers diagnostics
|
||||
/experimental:external # Enables the external headers options. This option isn't required in Visual Studio 2019 version 16.10 and later
|
||||
/external:anglebrackets # Treats all headers included by #include <header>, where the header file is enclosed in angle brackets (< >), as external headers
|
||||
/external:W0 # Sets the default warning level to 0 for external headers, effectively turning off warnings for external headers
|
||||
|
||||
|
||||
@@ -2,17 +2,12 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import kotlin.collections.setOf
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("kotlin-parcelize")
|
||||
kotlin("plugin.serialization") version "1.8.21"
|
||||
id("androidx.navigation.safeargs.kotlin")
|
||||
id("org.jlleitschuh.gradle.ktlint") version "11.4.0"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,6 +42,16 @@ android {
|
||||
jniLibs.useLegacyPackaging = true
|
||||
}
|
||||
|
||||
lint {
|
||||
// This is important as it will run lint but not abort on error
|
||||
// Lint has some overly obnoxious "errors" that should really be warnings
|
||||
abortOnError = false
|
||||
|
||||
//Uncomment disable lines for test builds...
|
||||
//disable 'MissingTranslation'bin
|
||||
//disable 'ExtraTranslation'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO If this is ever modified, change application_id in strings.xml
|
||||
applicationId = "org.yuzu.yuzu_emu"
|
||||
@@ -54,20 +59,6 @@ android {
|
||||
targetSdk = 33
|
||||
versionName = getGitVersion()
|
||||
|
||||
// If you want to use autoVersion for the versionCode, create a property in local.properties
|
||||
// named "autoVersioned" and set it to "true"
|
||||
val properties = Properties()
|
||||
val versionProperty = try {
|
||||
properties.load(project.rootProject.file("local.properties").inputStream())
|
||||
properties.getProperty("autoVersioned") ?: ""
|
||||
} catch (e: Exception) { "" }
|
||||
|
||||
versionCode = if (versionProperty == "true") {
|
||||
autoVersion
|
||||
} else {
|
||||
1
|
||||
}
|
||||
|
||||
ndk {
|
||||
@SuppressLint("ChromeOsAbiSupport")
|
||||
abiFilters += listOf("arm64-v8a")
|
||||
@@ -82,7 +73,16 @@ android {
|
||||
|
||||
// Signed by release key, allowing for upload to Play Store.
|
||||
release {
|
||||
resValue("string", "app_name_suffixed", "yuzu")
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isMinifyEnabled = true
|
||||
isDebuggable = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
|
||||
register("relWithVersionCode") {
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isMinifyEnabled = true
|
||||
isDebuggable = false
|
||||
@@ -95,7 +95,6 @@ android {
|
||||
// builds a release build that doesn't need signing
|
||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||
register("relWithDebInfo") {
|
||||
resValue("string", "app_name_suffixed", "yuzu Debug Release")
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isMinifyEnabled = true
|
||||
isDebuggable = true
|
||||
@@ -103,19 +102,16 @@ android {
|
||||
getDefaultProguardFile("proguard-android.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
versionNameSuffix = "-relWithDebInfo"
|
||||
applicationIdSuffix = ".relWithDebInfo"
|
||||
versionNameSuffix = "-debug"
|
||||
isJniDebuggable = true
|
||||
}
|
||||
|
||||
// Signed by debug key disallowing distribution on Play Store.
|
||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||
debug {
|
||||
resValue("string", "app_name_suffixed", "yuzu Debug")
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
versionNameSuffix = "-debug"
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,41 +156,24 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.getByPath("preBuild").dependsOn("ktlintCheck")
|
||||
|
||||
ktlint {
|
||||
version.set("0.47.0")
|
||||
android.set(true)
|
||||
ignoreFailures.set(false)
|
||||
disabledRules.set(
|
||||
setOf(
|
||||
"no-wildcard-imports",
|
||||
"package-name"
|
||||
)
|
||||
)
|
||||
reporters {
|
||||
reporter(ReporterType.CHECKSTYLE)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.core:core-ktx:1.10.1")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("androidx.recyclerview:recyclerview:1.3.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation("androidx.fragment:fragment-ktx:1.6.0")
|
||||
implementation("androidx.fragment:fragment-ktx:1.5.7")
|
||||
implementation("androidx.documentfile:documentfile:1.0.1")
|
||||
implementation("com.google.android.material:material:1.9.0")
|
||||
implementation("androidx.preference:preference:1.2.0")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||
implementation("io.coil-kt:coil:2.2.2")
|
||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||
implementation("androidx.window:window:1.1.0")
|
||||
implementation("androidx.window:window:1.0.0")
|
||||
implementation("org.ini4j:ini4j:0.5.4")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
|
||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||
}
|
||||
|
||||
@@ -6,10 +6,17 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
|
||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.vulkan.version" android:version="0x401000" android:required="true" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false"/>
|
||||
<uses-feature
|
||||
android:name="android.hardware.gamepad"
|
||||
android:required="false"/>
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.vulkan.version"
|
||||
android:version="0x401000"
|
||||
android:required="true" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
@@ -18,14 +25,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
<application
|
||||
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
||||
android:label="@string/app_name_suffixed"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:allowBackup="true"
|
||||
android:hasFragileUserData="true"
|
||||
android:supportsRtl="true"
|
||||
android:isGame="true"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
android:banner="@drawable/tv_banner"
|
||||
android:banner="@drawable/ic_launcher"
|
||||
android:extractNativeLibs="true"
|
||||
android:fullBackupContent="@xml/data_extraction_rules"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
||||
@@ -38,10 +44,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
<!-- This intentfilter marks this Activity as the one that gets launched from Home screen. -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
@@ -53,8 +58,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<activity
|
||||
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
|
||||
android:theme="@style/Theme.Yuzu.Main"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="userLandscape"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
@@ -14,18 +14,16 @@ import android.widget.TextView
|
||||
import androidx.annotation.Keep
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.lang.ref.WeakReference
|
||||
import org.yuzu.yuzu_emu.YuzuApplication.Companion.appContext
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.exists
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.getFileSize
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.isDirectory
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.openContentUri
|
||||
import org.yuzu.yuzu_emu.utils.Log.error
|
||||
import org.yuzu.yuzu_emu.utils.Log.verbose
|
||||
import org.yuzu.yuzu_emu.utils.Log.warning
|
||||
import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* Class which contains methods that interact
|
||||
@@ -76,9 +74,7 @@ object NativeLibrary {
|
||||
fun openContentUri(path: String?, openmode: String?): Int {
|
||||
return if (isNativePath(path!!)) {
|
||||
YuzuApplication.documentsTree!!.openContentUri(path, openmode)
|
||||
} else {
|
||||
openContentUri(appContext, path, openmode)
|
||||
}
|
||||
} else openContentUri(appContext, path, openmode)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@@ -86,29 +82,7 @@ object NativeLibrary {
|
||||
fun getSize(path: String?): Long {
|
||||
return if (isNativePath(path!!)) {
|
||||
YuzuApplication.documentsTree!!.getFileSize(path)
|
||||
} else {
|
||||
getFileSize(appContext, path)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun exists(path: String?): Boolean {
|
||||
return if (isNativePath(path!!)) {
|
||||
YuzuApplication.documentsTree!!.exists(path)
|
||||
} else {
|
||||
exists(appContext, path)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun isDirectory(path: String?): Boolean {
|
||||
return if (isNativePath(path!!)) {
|
||||
YuzuApplication.documentsTree!!.isDirectory(path)
|
||||
} else {
|
||||
isDirectory(appContext, path)
|
||||
}
|
||||
} else getFileSize(appContext, path)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,12 +223,8 @@ object NativeLibrary {
|
||||
|
||||
external fun getCompany(filename: String): String
|
||||
|
||||
external fun isHomebrew(filename: String): Boolean
|
||||
|
||||
external fun setAppDirectory(directory: String)
|
||||
|
||||
external fun installFileToNand(filename: String): Int
|
||||
|
||||
external fun initializeGpuDriver(
|
||||
hookLibDir: String?,
|
||||
customDriverDir: String?,
|
||||
@@ -308,11 +278,6 @@ object NativeLibrary {
|
||||
*/
|
||||
external fun isRunning(): Boolean
|
||||
|
||||
/**
|
||||
* Returns true if emulation is paused.
|
||||
*/
|
||||
external fun isPaused(): Boolean
|
||||
|
||||
/**
|
||||
* Returns the performance stats for the current game
|
||||
*/
|
||||
@@ -462,9 +427,7 @@ object NativeLibrary {
|
||||
Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
|
||||
emulationActivity.finish()
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> emulationActivity.finish() }
|
||||
.setOnDismissListener { emulationActivity.finish() }
|
||||
emulationActivity.runOnUiThread {
|
||||
val alert = builder.create()
|
||||
@@ -542,15 +505,4 @@ object NativeLibrary {
|
||||
const val RELEASED = 0
|
||||
const val PRESSED = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Result from installFileToNand
|
||||
*/
|
||||
object InstallFileToNandResult {
|
||||
const val Success = 0
|
||||
const val SuccessFileOverwritten = 1
|
||||
const val Error = 2
|
||||
const val ErrorBaseGame = 3
|
||||
const val ErrorFilenameExtension = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import android.app.Application
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.DocumentsTree
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import java.io.File
|
||||
|
||||
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
|
||||
fun Context.getPublicFilesDir() : File = getExternalFilesDir(null) ?: filesDir
|
||||
|
||||
class YuzuApplication : Application() {
|
||||
private fun createNotificationChannels() {
|
||||
@@ -21,9 +21,7 @@ class YuzuApplication : Application() {
|
||||
getString(R.string.emulation_notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
emulationChannel.description = getString(
|
||||
R.string.emulation_notification_channel_description
|
||||
)
|
||||
emulationChannel.description = getString(R.string.emulation_notification_channel_description)
|
||||
emulationChannel.setSound(null, null)
|
||||
emulationChannel.vibrationPattern = null
|
||||
|
||||
@@ -50,7 +48,7 @@ class YuzuApplication : Application() {
|
||||
GpuDriverHelper.initializeDriverParameters(applicationContext)
|
||||
NativeLibrary.logDeviceInfo()
|
||||
|
||||
createNotificationChannels()
|
||||
createNotificationChannels();
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -4,55 +4,48 @@
|
||||
package org.yuzu.yuzu_emu.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.app.PictureInPictureParams
|
||||
import android.app.RemoteAction
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Icon
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Rational
|
||||
import android.view.InputDevice
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import kotlin.math.roundToInt
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.window.layout.WindowInfoTracker
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
|
||||
import org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
|
||||
import org.yuzu.yuzu_emu.utils.ForegroundService
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.NfcReader
|
||||
import org.yuzu.yuzu_emu.utils.SerializableHelper.parcelable
|
||||
import org.yuzu.yuzu_emu.utils.ThemeHelper
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
private lateinit var binding: ActivityEmulationBinding
|
||||
|
||||
private var controllerMappingHelper: ControllerMappingHelper? = null
|
||||
|
||||
var isActivityRecreated = false
|
||||
private var emulationFragment: EmulationFragment? = null
|
||||
private lateinit var nfcReader: NfcReader
|
||||
private lateinit var inputHandler: InputHandler
|
||||
|
||||
@@ -61,10 +54,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
private var motionTimestamp: Long = 0
|
||||
private var flipMotionOrientation: Boolean = false
|
||||
|
||||
private val actionPause = "ACTION_EMULATOR_PAUSE"
|
||||
private val actionPlay = "ACTION_EMULATOR_PLAY"
|
||||
|
||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
private lateinit var game: Game
|
||||
|
||||
override fun onDestroy() {
|
||||
stopForegroundService(this)
|
||||
@@ -74,34 +64,48 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
ThemeHelper.setTheme(this)
|
||||
|
||||
settingsViewModel.settings.loadSettings()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
||||
val navController = navHostFragment.navController
|
||||
navController
|
||||
.setGraph(R.navigation.emulation_navigation, intent.extras)
|
||||
|
||||
isActivityRecreated = savedInstanceState != null
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// Get params we were passed
|
||||
game = intent.parcelable(EXTRA_SELECTED_GAME)!!
|
||||
isActivityRecreated = false
|
||||
} else {
|
||||
isActivityRecreated = true
|
||||
restoreState(savedInstanceState)
|
||||
}
|
||||
controllerMappingHelper = ControllerMappingHelper()
|
||||
|
||||
// Set these options now so that the SurfaceView the game renders into is the right size.
|
||||
enableFullscreenImmersive()
|
||||
|
||||
setContentView(R.layout.activity_emulation)
|
||||
window.decorView.setBackgroundColor(getColor(android.R.color.black))
|
||||
|
||||
// Find or create the EmulationFragment
|
||||
emulationFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.frame_emulation_fragment) as EmulationFragment?
|
||||
if (emulationFragment == null) {
|
||||
emulationFragment = EmulationFragment.newInstance(game)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.frame_emulation_fragment, emulationFragment!!)
|
||||
.commit()
|
||||
}
|
||||
title = game.title
|
||||
|
||||
nfcReader = NfcReader(this)
|
||||
nfcReader.initialize()
|
||||
|
||||
inputHandler = InputHandler()
|
||||
inputHandler.initialize()
|
||||
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
WindowInfoTracker.getOrCreate(this@EmulationActivity)
|
||||
.windowLayoutInfo(this@EmulationActivity)
|
||||
.collect { emulationFragment?.updateCurrentLayout(this@EmulationActivity, it) }
|
||||
}
|
||||
}
|
||||
|
||||
// Start a foreground service to prevent the app from getting killed in the background
|
||||
val startIntent = Intent(this, ForegroundService::class.java)
|
||||
startForegroundService(startIntent)
|
||||
@@ -135,7 +139,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
nfcReader.startScanning()
|
||||
startMotionSensorListener()
|
||||
|
||||
buildPictureInPictureParams()
|
||||
NativeLibrary.notifyOrientationChange(
|
||||
EmulationMenuSettings.LayoutOption_MobileLandscape,
|
||||
Surface.ROTATION_90
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
@@ -144,22 +151,17 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
stopMotionSensorListener()
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
if (BooleanSetting.PICTURE_IN_PICTURE.boolean && !isInPictureInPictureMode) {
|
||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
nfcReader.onNewIntent(intent)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putParcelable(EXTRA_SELECTED_GAME, game)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
|
||||
@@ -246,6 +248,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor, i: Int) {}
|
||||
|
||||
private fun restoreState(savedInstanceState: Bundle) {
|
||||
game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!!
|
||||
}
|
||||
|
||||
private fun enableFullscreenImmersive() {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
@@ -256,100 +262,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private fun PictureInPictureParams.Builder.getPictureInPictureAspectBuilder():
|
||||
PictureInPictureParams.Builder {
|
||||
val aspectRatio = when (IntSetting.RENDERER_ASPECT_RATIO.int) {
|
||||
0 -> Rational(16, 9)
|
||||
1 -> Rational(4, 3)
|
||||
2 -> Rational(21, 9)
|
||||
3 -> Rational(16, 10)
|
||||
else -> null // Best fit
|
||||
}
|
||||
return this.apply { aspectRatio?.let { setAspectRatio(it) } }
|
||||
}
|
||||
|
||||
private fun PictureInPictureParams.Builder.getPictureInPictureActionsBuilder():
|
||||
PictureInPictureParams.Builder {
|
||||
val pictureInPictureActions: MutableList<RemoteAction> = mutableListOf()
|
||||
val pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
|
||||
if (NativeLibrary.isPaused()) {
|
||||
val playIcon = Icon.createWithResource(this@EmulationActivity, R.drawable.ic_pip_play)
|
||||
val playPendingIntent = PendingIntent.getBroadcast(
|
||||
this@EmulationActivity,
|
||||
R.drawable.ic_pip_play,
|
||||
Intent(actionPlay),
|
||||
pendingFlags
|
||||
)
|
||||
val playRemoteAction = RemoteAction(
|
||||
playIcon,
|
||||
getString(R.string.play),
|
||||
getString(R.string.play),
|
||||
playPendingIntent
|
||||
)
|
||||
pictureInPictureActions.add(playRemoteAction)
|
||||
} else {
|
||||
val pauseIcon = Icon.createWithResource(this@EmulationActivity, R.drawable.ic_pip_pause)
|
||||
val pausePendingIntent = PendingIntent.getBroadcast(
|
||||
this@EmulationActivity,
|
||||
R.drawable.ic_pip_pause,
|
||||
Intent(actionPause),
|
||||
pendingFlags
|
||||
)
|
||||
val pauseRemoteAction = RemoteAction(
|
||||
pauseIcon,
|
||||
getString(R.string.pause),
|
||||
getString(R.string.pause),
|
||||
pausePendingIntent
|
||||
)
|
||||
pictureInPictureActions.add(pauseRemoteAction)
|
||||
}
|
||||
|
||||
return this.apply { setActions(pictureInPictureActions) }
|
||||
}
|
||||
|
||||
fun buildPictureInPictureParams() {
|
||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
pictureInPictureParamsBuilder.setAutoEnterEnabled(
|
||||
BooleanSetting.PICTURE_IN_PICTURE.boolean
|
||||
)
|
||||
}
|
||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
|
||||
private var pictureInPictureReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent) {
|
||||
if (intent.action == actionPlay) {
|
||||
if (NativeLibrary.isPaused()) NativeLibrary.unPauseEmulation()
|
||||
} else if (intent.action == actionPause) {
|
||||
if (!NativeLibrary.isPaused()) NativeLibrary.pauseEmulation()
|
||||
}
|
||||
buildPictureInPictureParams()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPictureInPictureModeChanged(
|
||||
isInPictureInPictureMode: Boolean,
|
||||
newConfig: Configuration
|
||||
) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
if (isInPictureInPictureMode) {
|
||||
IntentFilter().apply {
|
||||
addAction(actionPause)
|
||||
addAction(actionPlay)
|
||||
}.also {
|
||||
registerReceiver(pictureInPictureReceiver, it)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
unregisterReceiver(pictureInPictureReceiver)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startMotionSensorListener() {
|
||||
val sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
val gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
|
||||
|
||||
@@ -16,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
@@ -24,13 +23,13 @@ import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import kotlinx.coroutines.launch
|
||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder
|
||||
import org.yuzu.yuzu_emu.databinding.CardGameBinding
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder
|
||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||
|
||||
class GameAdapter(private val activity: AppCompatActivity) :
|
||||
@@ -59,10 +58,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
override fun onClick(view: View) {
|
||||
val holder = view.tag as GameViewHolder
|
||||
|
||||
val gameExists = DocumentFile.fromSingleUri(
|
||||
YuzuApplication.appContext,
|
||||
Uri.parse(holder.game.path)
|
||||
)?.exists() == true
|
||||
val gameExists = DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(holder.game.path))?.exists() == true
|
||||
if (!gameExists) {
|
||||
Toast.makeText(
|
||||
YuzuApplication.appContext,
|
||||
@@ -82,8 +78,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
)
|
||||
.apply()
|
||||
|
||||
val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game)
|
||||
view.findNavController().navigate(action)
|
||||
EmulationActivity.launch(activity, holder.game)
|
||||
}
|
||||
|
||||
inner class GameViewHolder(val binding: CardGameBinding) :
|
||||
|
||||
@@ -58,12 +58,11 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
|
||||
)
|
||||
|
||||
when (option.titleId) {
|
||||
R.string.get_early_access ->
|
||||
binding.optionLayout.background =
|
||||
ContextCompat.getDrawable(
|
||||
binding.optionCard.context,
|
||||
R.drawable.premium_background
|
||||
)
|
||||
R.string.get_early_access -> binding.optionLayout.background =
|
||||
ContextCompat.getDrawable(
|
||||
binding.optionCard.context,
|
||||
R.drawable.premium_background
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.fragments.LicenseBottomSheetDialogFragment
|
||||
import org.yuzu.yuzu_emu.model.License
|
||||
|
||||
class LicenseAdapter(private val activity: AppCompatActivity, var licenses: List<License>) :
|
||||
RecyclerView.Adapter<LicenseAdapter.LicenseViewHolder>(),
|
||||
View.OnClickListener {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LicenseViewHolder {
|
||||
val binding =
|
||||
ListItemSettingBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
binding.root.setOnClickListener(this)
|
||||
return LicenseViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = licenses.size
|
||||
|
||||
override fun onBindViewHolder(holder: LicenseViewHolder, position: Int) {
|
||||
holder.bind(licenses[position])
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val license = (view.tag as LicenseViewHolder).license
|
||||
LicenseBottomSheetDialogFragment.newInstance(license)
|
||||
.show(activity.supportFragmentManager, LicenseBottomSheetDialogFragment.TAG)
|
||||
}
|
||||
|
||||
inner class LicenseViewHolder(val binding: ListItemSettingBinding) : ViewHolder(binding.root) {
|
||||
lateinit var license: License
|
||||
|
||||
init {
|
||||
itemView.tag = this
|
||||
}
|
||||
|
||||
fun bind(license: License) {
|
||||
this.license = license
|
||||
|
||||
val context = YuzuApplication.appContext
|
||||
binding.textSettingName.text = context.getString(license.titleId)
|
||||
binding.textSettingDescription.text = context.getString(license.descriptionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,10 @@ import android.view.WindowInsets
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.annotation.Keep
|
||||
import androidx.core.view.ViewCompat
|
||||
import java.io.Serializable
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.applets.keyboard.ui.KeyboardDialogFragment
|
||||
import java.io.Serializable
|
||||
|
||||
@Keep
|
||||
object SoftwareKeyboard {
|
||||
@@ -40,22 +40,19 @@ object SoftwareKeyboard {
|
||||
// There isn't a good way to know that the IMM is dismissed, so poll every 500ms to submit inline keyboard result.
|
||||
val handler = Handler(Looper.myLooper()!!)
|
||||
val delayMs = 500
|
||||
handler.postDelayed(
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
val insets = ViewCompat.getRootWindowInsets(overlayView)
|
||||
val isKeyboardVisible = insets!!.isVisible(WindowInsets.Type.ime())
|
||||
if (isKeyboardVisible) {
|
||||
handler.postDelayed(this, delayMs.toLong())
|
||||
return
|
||||
}
|
||||
|
||||
// No longer visible, submit the result.
|
||||
NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
|
||||
handler.postDelayed(object : Runnable {
|
||||
override fun run() {
|
||||
val insets = ViewCompat.getRootWindowInsets(overlayView)
|
||||
val isKeyboardVisible = insets!!.isVisible(WindowInsets.Type.ime())
|
||||
if (isKeyboardVisible) {
|
||||
handler.postDelayed(this, delayMs.toLong())
|
||||
return
|
||||
}
|
||||
},
|
||||
delayMs.toLong()
|
||||
)
|
||||
|
||||
// No longer visible, submit the result.
|
||||
NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
|
||||
}
|
||||
}, delayMs.toLong())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -63,7 +63,7 @@ class KeyboardDialogFragment : DialogFragment() {
|
||||
val headerText =
|
||||
config.header_text!!.ifEmpty { resources.getString(R.string.software_keyboard) }
|
||||
val okText =
|
||||
config.ok_text!!.ifEmpty { resources.getString(R.string.submit) }
|
||||
config.ok_text!!.ifEmpty { resources.getString(android.R.string.ok) }
|
||||
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(headerText)
|
||||
|
||||
@@ -20,10 +20,7 @@ object DiskShaderCacheProgress {
|
||||
emulationActivity.getString(R.string.loading),
|
||||
emulationActivity.getString(R.string.preparing_shaders)
|
||||
)
|
||||
fragment.show(
|
||||
emulationActivity.supportFragmentManager,
|
||||
ShaderProgressDialogFragment.TAG
|
||||
)
|
||||
fragment.show(emulationActivity.supportFragmentManager, ShaderProgressDialogFragment.TAG)
|
||||
}
|
||||
synchronized(finishLock) { finishLock.wait() }
|
||||
}
|
||||
|
||||
@@ -62,9 +62,7 @@ class ShaderProgressDialogFragment : DialogFragment() {
|
||||
shaderProgressViewModel.message.observe(viewLifecycleOwner) { msg ->
|
||||
alertDialog.setMessage(msg)
|
||||
}
|
||||
synchronized(DiskShaderCacheProgress.finishLock) {
|
||||
DiskShaderCacheProgress.finishLock.notifyAll()
|
||||
}
|
||||
synchronized(DiskShaderCacheProgress.finishLock) { DiskShaderCacheProgress.finishLock.notifyAll() }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
||||
@@ -13,11 +13,11 @@ import android.os.ParcelFileDescriptor
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.DocumentsProvider
|
||||
import android.webkit.MimeTypeMap
|
||||
import java.io.*
|
||||
import org.yuzu.yuzu_emu.BuildConfig
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.getPublicFilesDir
|
||||
import java.io.*
|
||||
|
||||
class DocumentProvider : DocumentsProvider() {
|
||||
private val baseDirectory: File
|
||||
@@ -44,7 +44,7 @@ class DocumentProvider : DocumentsProvider() {
|
||||
DocumentsContract.Document.COLUMN_SIZE
|
||||
)
|
||||
|
||||
const val AUTHORITY: String = BuildConfig.APPLICATION_ID + ".user"
|
||||
const val AUTHORITY : String = BuildConfig.APPLICATION_ID + ".user"
|
||||
const val ROOT_ID: String = "root"
|
||||
}
|
||||
|
||||
@@ -58,11 +58,7 @@ class DocumentProvider : DocumentsProvider() {
|
||||
private fun getFile(documentId: String): File {
|
||||
if (documentId.startsWith(ROOT_ID)) {
|
||||
val file = baseDirectory.resolve(documentId.drop(ROOT_ID.length + 1))
|
||||
if (!file.exists()) {
|
||||
throw FileNotFoundException(
|
||||
"${file.absolutePath} ($documentId) not found"
|
||||
)
|
||||
}
|
||||
if (!file.exists()) throw FileNotFoundException("${file.absolutePath} ($documentId) not found")
|
||||
return file
|
||||
} else {
|
||||
throw FileNotFoundException("'$documentId' is not in any known root")
|
||||
@@ -84,8 +80,7 @@ class DocumentProvider : DocumentsProvider() {
|
||||
add(DocumentsContract.Root.COLUMN_SUMMARY, null)
|
||||
add(
|
||||
DocumentsContract.Root.COLUMN_FLAGS,
|
||||
DocumentsContract.Root.FLAG_SUPPORTS_CREATE or
|
||||
DocumentsContract.Root.FLAG_SUPPORTS_IS_CHILD
|
||||
DocumentsContract.Root.FLAG_SUPPORTS_CREATE or DocumentsContract.Root.FLAG_SUPPORTS_IS_CHILD
|
||||
)
|
||||
add(DocumentsContract.Root.COLUMN_TITLE, context!!.getString(R.string.app_name))
|
||||
add(DocumentsContract.Root.COLUMN_DOCUMENT_ID, getDocumentId(baseDirectory))
|
||||
@@ -132,13 +127,11 @@ class DocumentProvider : DocumentsProvider() {
|
||||
|
||||
try {
|
||||
if (DocumentsContract.Document.MIME_TYPE_DIR == mimeType) {
|
||||
if (!newFile.mkdir()) {
|
||||
if (!newFile.mkdir())
|
||||
throw IOException("Failed to create directory")
|
||||
}
|
||||
} else {
|
||||
if (!newFile.createNewFile()) {
|
||||
if (!newFile.createNewFile())
|
||||
throw IOException("Failed to create file")
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw FileNotFoundException("Couldn't create document '${newFile.path}': ${e.message}")
|
||||
@@ -149,9 +142,8 @@ class DocumentProvider : DocumentsProvider() {
|
||||
|
||||
override fun deleteDocument(documentId: String?) {
|
||||
val file = getFile(documentId!!)
|
||||
if (!file.delete()) {
|
||||
if (!file.delete())
|
||||
throw FileNotFoundException("Couldn't delete document with ID '$documentId'")
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeDocument(documentId: String, parentDocumentId: String?) {
|
||||
@@ -159,55 +151,38 @@ class DocumentProvider : DocumentsProvider() {
|
||||
val file = getFile(documentId)
|
||||
|
||||
if (parent == file || file.parentFile == null || file.parentFile!! == parent) {
|
||||
if (!file.delete()) {
|
||||
if (!file.delete())
|
||||
throw FileNotFoundException("Couldn't delete document with ID '$documentId'")
|
||||
}
|
||||
} else {
|
||||
throw FileNotFoundException("Couldn't delete document with ID '$documentId'")
|
||||
}
|
||||
}
|
||||
|
||||
override fun renameDocument(documentId: String?, displayName: String?): String {
|
||||
if (displayName == null) {
|
||||
throw FileNotFoundException(
|
||||
"Couldn't rename document '$documentId' as the new name is null"
|
||||
)
|
||||
}
|
||||
if (displayName == null)
|
||||
throw FileNotFoundException("Couldn't rename document '$documentId' as the new name is null")
|
||||
|
||||
val sourceFile = getFile(documentId!!)
|
||||
val sourceParentFile = sourceFile.parentFile
|
||||
?: throw FileNotFoundException(
|
||||
"Couldn't rename document '$documentId' as it has no parent"
|
||||
)
|
||||
?: throw FileNotFoundException("Couldn't rename document '$documentId' as it has no parent")
|
||||
val destFile = sourceParentFile.resolve(displayName)
|
||||
|
||||
try {
|
||||
if (!sourceFile.renameTo(destFile)) {
|
||||
throw FileNotFoundException(
|
||||
"Couldn't rename document from '${sourceFile.name}' to '${destFile.name}'"
|
||||
)
|
||||
}
|
||||
if (!sourceFile.renameTo(destFile))
|
||||
throw FileNotFoundException("Couldn't rename document from '${sourceFile.name}' to '${destFile.name}'")
|
||||
} catch (e: Exception) {
|
||||
throw FileNotFoundException(
|
||||
"Couldn't rename document from '${sourceFile.name}' to '${destFile.name}': " +
|
||||
"${e.message}"
|
||||
)
|
||||
throw FileNotFoundException("Couldn't rename document from '${sourceFile.name}' to '${destFile.name}': ${e.message}")
|
||||
}
|
||||
|
||||
return getDocumentId(destFile)
|
||||
}
|
||||
|
||||
private fun copyDocument(
|
||||
sourceDocumentId: String,
|
||||
sourceParentDocumentId: String,
|
||||
sourceDocumentId: String, sourceParentDocumentId: String,
|
||||
targetParentDocumentId: String?
|
||||
): String {
|
||||
if (!isChildDocument(sourceParentDocumentId, sourceDocumentId)) {
|
||||
throw FileNotFoundException(
|
||||
"Couldn't copy document '$sourceDocumentId' as its parent is not " +
|
||||
"'$sourceParentDocumentId'"
|
||||
)
|
||||
}
|
||||
if (!isChildDocument(sourceParentDocumentId, sourceDocumentId))
|
||||
throw FileNotFoundException("Couldn't copy document '$sourceDocumentId' as its parent is not '$sourceParentDocumentId'")
|
||||
|
||||
return copyDocument(sourceDocumentId, targetParentDocumentId)
|
||||
}
|
||||
@@ -218,13 +193,8 @@ class DocumentProvider : DocumentsProvider() {
|
||||
val newFile = parent.resolveWithoutConflict(oldFile.name)
|
||||
|
||||
try {
|
||||
if (!(
|
||||
newFile.createNewFile() && newFile.setWritable(true) &&
|
||||
newFile.setReadable(true)
|
||||
)
|
||||
) {
|
||||
if (!(newFile.createNewFile() && newFile.setWritable(true) && newFile.setReadable(true)))
|
||||
throw IOException("Couldn't create new file")
|
||||
}
|
||||
|
||||
FileInputStream(oldFile).use { inStream ->
|
||||
FileOutputStream(newFile).use { outStream ->
|
||||
@@ -239,14 +209,12 @@ class DocumentProvider : DocumentsProvider() {
|
||||
}
|
||||
|
||||
override fun moveDocument(
|
||||
sourceDocumentId: String,
|
||||
sourceParentDocumentId: String?,
|
||||
sourceDocumentId: String, sourceParentDocumentId: String?,
|
||||
targetParentDocumentId: String?
|
||||
): String {
|
||||
try {
|
||||
val newDocumentId = copyDocument(
|
||||
sourceDocumentId,
|
||||
sourceParentDocumentId!!,
|
||||
sourceDocumentId, sourceParentDocumentId!!,
|
||||
targetParentDocumentId
|
||||
)
|
||||
removeDocument(sourceDocumentId, sourceParentDocumentId)
|
||||
@@ -277,30 +245,24 @@ class DocumentProvider : DocumentsProvider() {
|
||||
add(DocumentsContract.Document.COLUMN_DOCUMENT_ID, localDocumentId)
|
||||
add(
|
||||
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
|
||||
if (localFile == baseDirectory) {
|
||||
context!!.getString(R.string.app_name)
|
||||
} else {
|
||||
localFile.name
|
||||
}
|
||||
if (localFile == baseDirectory) context!!.getString(R.string.app_name) else localFile.name
|
||||
)
|
||||
add(DocumentsContract.Document.COLUMN_SIZE, localFile.length())
|
||||
add(DocumentsContract.Document.COLUMN_MIME_TYPE, getTypeForFile(localFile))
|
||||
add(DocumentsContract.Document.COLUMN_LAST_MODIFIED, localFile.lastModified())
|
||||
add(DocumentsContract.Document.COLUMN_FLAGS, flags)
|
||||
if (localFile == baseDirectory) {
|
||||
if (localFile == baseDirectory)
|
||||
add(DocumentsContract.Root.COLUMN_ICON, R.drawable.ic_yuzu)
|
||||
}
|
||||
}
|
||||
|
||||
return cursor
|
||||
}
|
||||
|
||||
private fun getTypeForFile(file: File): Any {
|
||||
return if (file.isDirectory) {
|
||||
return if (file.isDirectory)
|
||||
DocumentsContract.Document.MIME_TYPE_DIR
|
||||
} else {
|
||||
else
|
||||
getTypeForName(file.name)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTypeForName(name: String): Any {
|
||||
@@ -308,9 +270,8 @@ class DocumentProvider : DocumentsProvider() {
|
||||
if (lastDot >= 0) {
|
||||
val extension = name.substring(lastDot + 1)
|
||||
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||
if (mime != null) {
|
||||
if (mime != null)
|
||||
return mime
|
||||
}
|
||||
}
|
||||
return "application/octect-stream"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ enum class BooleanSetting(
|
||||
override val section: String,
|
||||
override val defaultValue: Boolean
|
||||
) : AbstractBooleanSetting {
|
||||
PICTURE_IN_PICTURE("picture_in_picture", Settings.SECTION_GENERAL, true),
|
||||
USE_CUSTOM_RTC("custom_rtc_enabled", Settings.SECTION_SYSTEM, false);
|
||||
|
||||
override var boolean: Boolean = defaultValue
|
||||
@@ -28,7 +27,6 @@ enum class BooleanSetting(
|
||||
|
||||
companion object {
|
||||
private val NOT_RUNTIME_EDITABLE = listOf(
|
||||
PICTURE_IN_PICTURE,
|
||||
USE_CUSTOM_RTC
|
||||
)
|
||||
|
||||
|
||||
@@ -26,18 +26,13 @@ enum class IntSetting(
|
||||
RENDERER_FORCE_MAX_CLOCK(
|
||||
"force_max_clock",
|
||||
Settings.SECTION_RENDERER,
|
||||
0
|
||||
1
|
||||
),
|
||||
RENDERER_ASYNCHRONOUS_SHADERS(
|
||||
"use_asynchronous_shaders",
|
||||
Settings.SECTION_RENDERER,
|
||||
0
|
||||
),
|
||||
RENDERER_REACTIVE_FLUSHING(
|
||||
"use_reactive_flushing",
|
||||
Settings.SECTION_RENDERER,
|
||||
0
|
||||
),
|
||||
RENDERER_DEBUG(
|
||||
"debug",
|
||||
Settings.SECTION_RENDERER,
|
||||
@@ -93,11 +88,6 @@ enum class IntSetting(
|
||||
Settings.SECTION_RENDERER,
|
||||
0
|
||||
),
|
||||
RENDERER_SCREEN_LAYOUT(
|
||||
"screen_layout",
|
||||
Settings.SECTION_RENDERER,
|
||||
Settings.LayoutOption_MobileLandscape
|
||||
),
|
||||
RENDERER_ASPECT_RATIO(
|
||||
"aspect_ratio",
|
||||
Settings.SECTION_RENDERER,
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
package org.yuzu.yuzu_emu.features.settings.model
|
||||
|
||||
import android.text.TextUtils
|
||||
import java.util.*
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivityView
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import java.util.*
|
||||
|
||||
class Settings {
|
||||
private var gameId: String? = null
|
||||
@@ -39,7 +39,7 @@ class Settings {
|
||||
val isEmpty: Boolean
|
||||
get() = sections.isEmpty()
|
||||
|
||||
fun loadSettings(view: SettingsActivityView? = null) {
|
||||
fun loadSettings(view: SettingsActivityView) {
|
||||
sections = SettingsSectionMap()
|
||||
loadYuzuSettings(view)
|
||||
if (!TextUtils.isEmpty(gameId)) {
|
||||
@@ -48,13 +48,13 @@ class Settings {
|
||||
isLoaded = true
|
||||
}
|
||||
|
||||
private fun loadYuzuSettings(view: SettingsActivityView?) {
|
||||
private fun loadYuzuSettings(view: SettingsActivityView) {
|
||||
for ((fileName) in configFileSectionsMap) {
|
||||
sections.putAll(SettingsFile.readFile(fileName, view))
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCustomGameSettings(gameId: String, view: SettingsActivityView?) {
|
||||
private fun loadCustomGameSettings(gameId: String, view: SettingsActivityView) {
|
||||
// Custom game settings
|
||||
mergeSections(SettingsFile.readCustomGameSettings(gameId, view))
|
||||
}
|
||||
@@ -108,7 +108,6 @@ class Settings {
|
||||
const val SECTION_AUDIO = "Audio"
|
||||
const val SECTION_CPU = "Cpu"
|
||||
const val SECTION_THEME = "Theme"
|
||||
const val SECTION_DEBUG = "Debug"
|
||||
|
||||
const val PREF_OVERLAY_INIT = "OverlayInit"
|
||||
const val PREF_CONTROL_SCALE = "controlScale"
|
||||
@@ -133,6 +132,7 @@ class Settings {
|
||||
const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
|
||||
const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
|
||||
const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"
|
||||
const val PREF_MENU_SETTINGS_SCREEN_LAYOUT = "EmulationMenuSettings_ScreenLayout"
|
||||
const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
|
||||
const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"
|
||||
|
||||
@@ -143,10 +143,6 @@ class Settings {
|
||||
|
||||
private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap()
|
||||
|
||||
const val LayoutOption_Unspecified = 0
|
||||
const val LayoutOption_MobilePortrait = 4
|
||||
const val LayoutOption_MobileLandscape = 5
|
||||
|
||||
init {
|
||||
configFileSectionsMap[SettingsFile.FILE_NAME_CONFIG] =
|
||||
listOf(
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
|
||||
class SingleChoiceSetting(
|
||||
setting: AbstractIntSetting?,
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import kotlin.math.roundToInt
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractFloatSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.FloatSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class SliderSetting(
|
||||
setting: AbstractSetting?,
|
||||
@@ -17,7 +19,7 @@ class SliderSetting(
|
||||
val max: Int,
|
||||
val units: String,
|
||||
val key: String? = null,
|
||||
val defaultValue: Int? = null
|
||||
val defaultValue: Int? = null,
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_SLIDER
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
|
||||
class StringSingleChoiceSetting(
|
||||
val key: String? = null,
|
||||
@@ -21,9 +22,7 @@ class StringSingleChoiceSetting(
|
||||
if (valuesId == null) return null
|
||||
return if (index >= 0 && index < valuesId.size) {
|
||||
valuesId[index]
|
||||
} else {
|
||||
""
|
||||
}
|
||||
} else ""
|
||||
}
|
||||
|
||||
val selectedValue: String
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
|
||||
|
||||
class SubmenuSetting(
|
||||
setting: AbstractSetting?,
|
||||
titleId: Int,
|
||||
descriptionId: Int,
|
||||
val menuKey: String
|
||||
) : SettingsItem(null, titleId, descriptionId) {
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_SUBMENU
|
||||
}
|
||||
|
||||
@@ -8,18 +8,17 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.view.updatePadding
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import java.io.IOException
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
@@ -30,6 +29,7 @@ import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.utils.*
|
||||
import java.io.IOException
|
||||
|
||||
class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
private val presenter = SettingsActivityPresenter(this)
|
||||
@@ -59,9 +59,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
setSupportActionBar(binding.toolbarSettings)
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
if (InsetsHelper.getSystemGestureType(applicationContext) !=
|
||||
InsetsHelper.GESTURE_NAVIGATION
|
||||
) {
|
||||
if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION) {
|
||||
binding.navigationBarShade.setBackgroundColor(
|
||||
ThemeHelper.getColorWithOpacity(
|
||||
MaterialColors.getColor(
|
||||
@@ -77,8 +75,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() = navigateBack()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
setInsets()
|
||||
}
|
||||
@@ -151,13 +148,11 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
private fun areSystemAnimationsEnabled(): Boolean {
|
||||
val duration = android.provider.Settings.Global.getFloat(
|
||||
contentResolver,
|
||||
android.provider.Settings.Global.ANIMATOR_DURATION_SCALE,
|
||||
1f
|
||||
android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, 1f
|
||||
)
|
||||
val transition = android.provider.Settings.Global.getFloat(
|
||||
contentResolver,
|
||||
android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE,
|
||||
1f
|
||||
android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE, 1f
|
||||
)
|
||||
return duration != 0f && transition != 0f
|
||||
}
|
||||
@@ -212,9 +207,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.frameContent
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.frameContent) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
view.updatePadding(
|
||||
@@ -246,17 +239,5 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
settings.putExtra(ARG_GAME_ID, gameId)
|
||||
context.startActivity(settings)
|
||||
}
|
||||
|
||||
fun launch(
|
||||
context: Context,
|
||||
launcher: ActivityResultLauncher<Intent>,
|
||||
menuTag: String?,
|
||||
gameId: String?
|
||||
) {
|
||||
val settings = Intent(context, SettingsActivity::class.java)
|
||||
settings.putExtra(ARG_MENU_TAG, menuTag)
|
||||
settings.putExtra(ARG_GAME_ID, gameId)
|
||||
launcher.launch(settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ package org.yuzu.yuzu_emu.features.settings.ui
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import java.io.File
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import java.io.File
|
||||
|
||||
class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
|
||||
val settings: Settings get() = activityView.settings
|
||||
@@ -46,15 +46,9 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
|
||||
|
||||
private fun prepareDirectoriesIfNeeded() {
|
||||
val configFile =
|
||||
File(
|
||||
"${DirectoryInitialization.userDirectory}/config/" +
|
||||
"${SettingsFile.FILE_NAME_CONFIG}.ini"
|
||||
)
|
||||
File(DirectoryInitialization.userDirectory + "/config/" + SettingsFile.FILE_NAME_CONFIG + ".ini")
|
||||
if (!configFile.exists()) {
|
||||
Log.error(
|
||||
"${DirectoryInitialization.userDirectory}/config/" +
|
||||
"${SettingsFile.FILE_NAME_CONFIG}.ini"
|
||||
)
|
||||
Log.error(DirectoryInitialization.userDirectory + "/config/" + SettingsFile.FILE_NAME_CONFIG + ".ini")
|
||||
Log.error("yuzu config file could not be found!")
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
@@ -50,10 +50,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
settingsAdapter = SettingsAdapter(this, requireActivity())
|
||||
val dividerDecoration = MaterialDividerItemDecoration(
|
||||
requireContext(),
|
||||
LinearLayoutManager.VERTICAL
|
||||
)
|
||||
val dividerDecoration = MaterialDividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
|
||||
dividerDecoration.isLastItemDecorated = false
|
||||
binding.listSettings.apply {
|
||||
adapter = settingsAdapter
|
||||
@@ -102,9 +99,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.listSettings
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.listSettings) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
view.updatePadding(bottom = insets.bottom)
|
||||
windowInsets
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
|
||||
@@ -67,7 +68,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
Settings.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||
Settings.SECTION_AUDIO -> addAudioSettings(sl)
|
||||
Settings.SECTION_THEME -> addThemeSettings(sl)
|
||||
Settings.SECTION_DEBUG -> addDebugSettings(sl)
|
||||
else -> {
|
||||
fragmentView.showToastMessage("Unimplemented menu", false)
|
||||
return
|
||||
@@ -78,10 +78,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
}
|
||||
|
||||
private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
|
||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.advanced_settings))
|
||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_advanced_settings))
|
||||
sl.apply {
|
||||
add(
|
||||
SubmenuSetting(
|
||||
null,
|
||||
R.string.preferences_general,
|
||||
0,
|
||||
Settings.SECTION_GENERAL
|
||||
@@ -89,6 +90,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
null,
|
||||
R.string.preferences_system,
|
||||
0,
|
||||
Settings.SECTION_SYSTEM
|
||||
@@ -96,6 +98,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
null,
|
||||
R.string.preferences_graphics,
|
||||
0,
|
||||
Settings.SECTION_RENDERER
|
||||
@@ -103,18 +106,12 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
null,
|
||||
R.string.preferences_audio,
|
||||
0,
|
||||
Settings.SECTION_AUDIO
|
||||
)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
R.string.preferences_debug,
|
||||
0,
|
||||
Settings.SECTION_DEBUG
|
||||
)
|
||||
)
|
||||
add(
|
||||
RunnableSetting(
|
||||
R.string.reset_to_default,
|
||||
@@ -165,15 +162,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
IntSetting.CPU_ACCURACY.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.PICTURE_IN_PICTURE,
|
||||
R.string.picture_in_picture,
|
||||
R.string.picture_in_picture_description,
|
||||
BooleanSetting.PICTURE_IN_PICTURE.key,
|
||||
BooleanSetting.PICTURE_IN_PICTURE.defaultValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +223,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics))
|
||||
sl.apply {
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_BACKEND,
|
||||
R.string.renderer_api,
|
||||
0,
|
||||
R.array.rendererApiNames,
|
||||
R.array.rendererApiValues,
|
||||
IntSetting.RENDERER_BACKEND.key,
|
||||
IntSetting.RENDERER_BACKEND.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_ACCURACY,
|
||||
@@ -290,17 +289,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
IntSetting.RENDERER_ANTI_ALIASING.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_SCREEN_LAYOUT,
|
||||
R.string.renderer_screen_layout,
|
||||
0,
|
||||
R.array.rendererScreenLayoutNames,
|
||||
R.array.rendererScreenLayoutValues,
|
||||
IntSetting.RENDERER_SCREEN_LAYOUT.key,
|
||||
IntSetting.RENDERER_SCREEN_LAYOUT.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_ASPECT_RATIO,
|
||||
@@ -341,11 +329,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
add(
|
||||
SwitchSetting(
|
||||
IntSetting.RENDERER_REACTIVE_FLUSHING,
|
||||
R.string.renderer_reactive_flushing,
|
||||
R.string.renderer_reactive_flushing_description,
|
||||
IntSetting.RENDERER_REACTIVE_FLUSHING.key,
|
||||
IntSetting.RENDERER_REACTIVE_FLUSHING.defaultValue
|
||||
IntSetting.RENDERER_DEBUG,
|
||||
R.string.renderer_debug,
|
||||
R.string.renderer_debug_description,
|
||||
IntSetting.RENDERER_DEBUG.key,
|
||||
IntSetting.RENDERER_DEBUG.defaultValue
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -463,30 +451,4 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDebugSettings(sl: ArrayList<SettingsItem>) {
|
||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug))
|
||||
sl.apply {
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_BACKEND,
|
||||
R.string.renderer_api,
|
||||
0,
|
||||
R.array.rendererApiNames,
|
||||
R.array.rendererApiValues,
|
||||
IntSetting.RENDERER_BACKEND.key,
|
||||
IntSetting.RENDERER_BACKEND.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SwitchSetting(
|
||||
IntSetting.RENDERER_DEBUG,
|
||||
R.string.renderer_debug,
|
||||
R.string.renderer_debug_description,
|
||||
IntSetting.RENDERER_DEBUG.key,
|
||||
IntSetting.RENDERER_DEBUG.defaultValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||
SettingViewHolder(binding.root, adapter) {
|
||||
|
||||
@@ -6,8 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
import android.view.View
|
||||
import android.widget.CompoundButton
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) :
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.utils
|
||||
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import org.ini4j.Wini
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
@@ -15,6 +13,8 @@ import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivityView
|
||||
import org.yuzu.yuzu_emu.utils.BiMap
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Contains static methods for interacting with .ini files in which settings are stored.
|
||||
@@ -37,7 +37,7 @@ object SettingsFile {
|
||||
private fun readFile(
|
||||
ini: File?,
|
||||
isCustomGame: Boolean,
|
||||
view: SettingsActivityView? = null
|
||||
view: SettingsActivityView?
|
||||
): HashMap<String, SettingSection?> {
|
||||
val sections: HashMap<String, SettingSection?> = SettingsSectionMap()
|
||||
var reader: BufferedReader? = null
|
||||
@@ -74,13 +74,10 @@ object SettingsFile {
|
||||
return sections
|
||||
}
|
||||
|
||||
fun readFile(fileName: String, view: SettingsActivityView?): HashMap<String, SettingSection?> {
|
||||
fun readFile(fileName: String, view: SettingsActivityView): HashMap<String, SettingSection?> {
|
||||
return readFile(getSettingsFile(fileName), false, view)
|
||||
}
|
||||
|
||||
fun readFile(fileName: String): HashMap<String, SettingSection?> =
|
||||
readFile(getSettingsFile(fileName), false)
|
||||
|
||||
/**
|
||||
* Reads a given .ini file from disk and returns it as a HashMap of SettingSections, themselves
|
||||
* effectively a HashMap of key/value settings. If unsuccessful, outputs an error telling why it
|
||||
@@ -91,7 +88,7 @@ object SettingsFile {
|
||||
*/
|
||||
fun readCustomGameSettings(
|
||||
gameId: String,
|
||||
view: SettingsActivityView?
|
||||
view: SettingsActivityView
|
||||
): HashMap<String, SettingSection?> {
|
||||
return readFile(getCustomGameSettingsFile(gameId), true, view)
|
||||
}
|
||||
@@ -137,12 +134,9 @@ object SettingsFile {
|
||||
for (settingKey in sortedKeySet) {
|
||||
val setting = settings[settingKey]
|
||||
NativeLibrary.setUserSetting(
|
||||
gameId,
|
||||
mapSectionNameFromIni(
|
||||
gameId, mapSectionNameFromIni(
|
||||
section.name
|
||||
),
|
||||
setting!!.key,
|
||||
setting.valueAsString
|
||||
), setting!!.key, setting.valueAsString
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -151,17 +145,13 @@ object SettingsFile {
|
||||
private fun mapSectionNameFromIni(generalSectionName: String): String? {
|
||||
return if (sectionsMap.getForward(generalSectionName) != null) {
|
||||
sectionsMap.getForward(generalSectionName)
|
||||
} else {
|
||||
generalSectionName
|
||||
}
|
||||
} else generalSectionName
|
||||
}
|
||||
|
||||
private fun mapSectionNameToIni(generalSectionName: String): String {
|
||||
return if (sectionsMap.getBackward(generalSectionName) != null) {
|
||||
sectionsMap.getBackward(generalSectionName).toString()
|
||||
} else {
|
||||
generalSectionName
|
||||
}
|
||||
} else generalSectionName
|
||||
}
|
||||
|
||||
fun getSettingsFile(fileName: String): File {
|
||||
|
||||
@@ -15,12 +15,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import org.yuzu.yuzu_emu.BuildConfig
|
||||
import org.yuzu.yuzu_emu.R
|
||||
@@ -37,7 +38,6 @@ class AboutFragment : Fragment() {
|
||||
super.onCreate(savedInstanceState)
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@@ -54,7 +54,7 @@ class AboutFragment : Fragment() {
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = false)
|
||||
|
||||
binding.toolbarAbout.setNavigationOnClickListener {
|
||||
binding.root.findNavController().popBackStack()
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()?.popBackStack()
|
||||
}
|
||||
|
||||
binding.imageLogo.setOnLongClickListener {
|
||||
@@ -66,15 +66,7 @@ class AboutFragment : Fragment() {
|
||||
true
|
||||
}
|
||||
|
||||
binding.buttonContributors.setOnClickListener {
|
||||
openLink(
|
||||
getString(R.string.contributors_link)
|
||||
)
|
||||
}
|
||||
binding.buttonLicenses.setOnClickListener {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment)
|
||||
}
|
||||
binding.buttonContributors.setOnClickListener { openLink(getString(R.string.contributors_link)) }
|
||||
|
||||
binding.textBuildHash.text = BuildConfig.GIT_HASH
|
||||
binding.buttonBuildHash.setOnClickListener {
|
||||
@@ -105,9 +97,7 @@ class AboutFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
|
||||
@@ -49,11 +49,7 @@ class EarlyAccessFragment : Fragment() {
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()?.popBackStack()
|
||||
}
|
||||
|
||||
binding.getEarlyAccessButton.setOnClickListener {
|
||||
openLink(
|
||||
getString(R.string.play_store_link)
|
||||
)
|
||||
}
|
||||
binding.getEarlyAccessButton.setOnClickListener { openLink(getString(R.string.play_store_link)) }
|
||||
|
||||
setInsets()
|
||||
}
|
||||
@@ -64,9 +60,7 @@ class EarlyAccessFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
|
||||
@@ -7,51 +7,44 @@ import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Rational
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import androidx.window.layout.WindowInfoTracker
|
||||
import androidx.window.layout.WindowLayoutInfo
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.slider.Slider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.overlay.InputOverlay
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.utils.*
|
||||
import org.yuzu.yuzu_emu.utils.SerializableHelper.parcelable
|
||||
|
||||
class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
private lateinit var preferences: SharedPreferences
|
||||
@@ -62,43 +55,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
private var _binding: FragmentEmulationBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
val args by navArgs<EmulationFragmentArgs>()
|
||||
|
||||
private var isInFoldableLayout = false
|
||||
|
||||
private lateinit var onReturnFromSettings: ActivityResultLauncher<Intent>
|
||||
private lateinit var game: Game
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
if (context is EmulationActivity) {
|
||||
emulationActivity = context
|
||||
NativeLibrary.setEmulationActivity(context)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
WindowInfoTracker.getOrCreate(context)
|
||||
.windowLayoutInfo(context)
|
||||
.collect { updateFoldableLayout(context, it) }
|
||||
}
|
||||
}
|
||||
|
||||
onReturnFromSettings = context.activityResultRegistry.register(
|
||||
"SettingsResult",
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
binding.surfaceEmulation.setAspectRatio(
|
||||
when (IntSetting.RENDERER_ASPECT_RATIO.int) {
|
||||
0 -> Rational(16, 9)
|
||||
1 -> Rational(4, 3)
|
||||
2 -> Rational(21, 9)
|
||||
3 -> Rational(16, 10)
|
||||
4 -> null // Stretch
|
||||
else -> Rational(16, 9)
|
||||
}
|
||||
)
|
||||
emulationActivity?.buildPictureInPictureParams()
|
||||
updateScreenLayout()
|
||||
}
|
||||
} else {
|
||||
throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
|
||||
}
|
||||
@@ -113,7 +76,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
// So this fragment doesn't restart on configuration changes; i.e. rotation.
|
||||
retainInstance = true
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
emulationState = EmulationState(args.game.path)
|
||||
game = requireArguments().parcelable(EmulationActivity.EXTRA_SELECTED_GAME)!!
|
||||
emulationState = EmulationState(game.path)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +101,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
updateShowFpsOverlay()
|
||||
|
||||
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
|
||||
args.game.title
|
||||
game.title
|
||||
binding.inGameMenu.setNavigationItemSelectedListener {
|
||||
when (it.itemId) {
|
||||
R.id.menu_pause_emulation -> {
|
||||
@@ -162,12 +126,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
R.id.menu_settings -> {
|
||||
SettingsActivity.launch(
|
||||
requireContext(),
|
||||
onReturnFromSettings,
|
||||
SettingsFile.FILE_NAME_CONFIG,
|
||||
""
|
||||
)
|
||||
SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
|
||||
true
|
||||
}
|
||||
|
||||
@@ -192,48 +151,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
requireActivity(),
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (binding.drawerLayout.isOpen) {
|
||||
binding.drawerLayout.close()
|
||||
} else {
|
||||
binding.drawerLayout.open()
|
||||
}
|
||||
if (binding.drawerLayout.isOpen) binding.drawerLayout.close() else binding.drawerLayout.open()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
WindowInfoTracker.getOrCreate(requireContext())
|
||||
.windowLayoutInfo(requireActivity())
|
||||
.collect { updateFoldableLayout(requireActivity() as EmulationActivity, it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
if (emulationActivity?.isInPictureInPictureMode == true) {
|
||||
if (binding.drawerLayout.isOpen) {
|
||||
binding.drawerLayout.close()
|
||||
}
|
||||
if (EmulationMenuSettings.showOverlay) {
|
||||
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = false }
|
||||
}
|
||||
} else {
|
||||
if (EmulationMenuSettings.showOverlay) {
|
||||
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = true }
|
||||
}
|
||||
if (!isInFoldableLayout) {
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.PORTRAIT
|
||||
} else {
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.LANDSCAPE
|
||||
}
|
||||
}
|
||||
if (!binding.surfaceInputOverlay.isInEditMode) {
|
||||
refreshInputOverlay()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -241,20 +161,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
if (!DirectoryInitialization.areDirectoriesReady) {
|
||||
DirectoryInitialization.start(requireContext())
|
||||
}
|
||||
|
||||
binding.surfaceEmulation.setAspectRatio(
|
||||
when (IntSetting.RENDERER_ASPECT_RATIO.int) {
|
||||
0 -> Rational(16, 9)
|
||||
1 -> Rational(4, 3)
|
||||
2 -> Rational(21, 9)
|
||||
3 -> Rational(16, 10)
|
||||
4 -> null // Stretch
|
||||
else -> Rational(16, 9)
|
||||
}
|
||||
)
|
||||
|
||||
updateScreenLayout()
|
||||
|
||||
emulationState.run(emulationActivity!!.isActivityRecreated)
|
||||
}
|
||||
|
||||
@@ -275,6 +181,37 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
super.onDetach()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
|
||||
val emulatorLayout = when (newConfig.orientation) {
|
||||
Configuration.ORIENTATION_LANDSCAPE -> { EmulationMenuSettings.LayoutOption_MobileLandscape }
|
||||
Configuration.ORIENTATION_PORTRAIT -> { EmulationMenuSettings.LayoutOption_MobilePortrait }
|
||||
else -> { EmulationMenuSettings.LayoutOption_MobileLandscape }
|
||||
}
|
||||
|
||||
emulationActivity?.let {
|
||||
var rotation = it.getSystemService<DisplayManager>()!!
|
||||
.getDisplay(Display.DEFAULT_DISPLAY).rotation
|
||||
if (newConfig.orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||
rotation = when (rotation) {
|
||||
Surface.ROTATION_0 -> Surface.ROTATION_90
|
||||
Surface.ROTATION_90 -> Surface.ROTATION_0
|
||||
Surface.ROTATION_180 -> Surface.ROTATION_270
|
||||
Surface.ROTATION_270 -> Surface.ROTATION_180
|
||||
else -> { rotation }
|
||||
}
|
||||
}
|
||||
if (it.isInPictureInPictureMode) {
|
||||
NativeLibrary.notifyOrientationChange(
|
||||
EmulationMenuSettings.LayoutOption_MobileLandscape, rotation
|
||||
)
|
||||
} else {
|
||||
NativeLibrary.notifyOrientationChange(emulatorLayout, rotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshInputOverlay() {
|
||||
binding.surfaceInputOverlay.refreshControls()
|
||||
}
|
||||
@@ -317,54 +254,46 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
private fun updateScreenLayout() {
|
||||
emulationActivity?.let {
|
||||
it.requestedOrientation = when (IntSetting.RENDERER_SCREEN_LAYOUT.int) {
|
||||
Settings.LayoutOption_MobileLandscape ->
|
||||
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||
Settings.LayoutOption_MobilePortrait ->
|
||||
ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
Settings.LayoutOption_Unspecified -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
else -> ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||
when (EmulationMenuSettings.screenLayout) {
|
||||
EmulationMenuSettings.LayoutOption_MobileLandscape -> {
|
||||
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||
}
|
||||
EmulationMenuSettings.LayoutOption_MobilePortrait -> {
|
||||
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
}
|
||||
EmulationMenuSettings.LayoutOption_Default -> {
|
||||
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
}
|
||||
else -> { it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE }
|
||||
}
|
||||
}
|
||||
onConfigurationChanged(resources.configuration)
|
||||
}
|
||||
|
||||
private fun updateFoldableLayout(
|
||||
emulationActivity: EmulationActivity,
|
||||
newLayoutInfo: WindowLayoutInfo
|
||||
) {
|
||||
val isFolding =
|
||||
(newLayoutInfo.displayFeatures.find { it is FoldingFeature } as? FoldingFeature)?.let {
|
||||
if (it.isSeparating) {
|
||||
emulationActivity.requestedOrientation =
|
||||
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) {
|
||||
// Restrict emulation and overlays to the top of the screen
|
||||
binding.emulationContainer.layoutParams.height = it.bounds.top
|
||||
binding.overlayContainer.layoutParams.height = it.bounds.top
|
||||
// Restrict input and menu drawer to the bottom of the screen
|
||||
binding.inputContainer.layoutParams.height = it.bounds.bottom
|
||||
binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
||||
private val Number.toPx get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
|
||||
|
||||
isInFoldableLayout = true
|
||||
binding.surfaceInputOverlay.orientation = InputOverlay.FOLDABLE
|
||||
refreshInputOverlay()
|
||||
}
|
||||
fun updateCurrentLayout(emulationActivity: EmulationActivity, newLayoutInfo: WindowLayoutInfo) {
|
||||
val isFolding = (newLayoutInfo.displayFeatures.find { it is FoldingFeature } as? FoldingFeature)?.let {
|
||||
if (it.isSeparating) {
|
||||
emulationActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) {
|
||||
binding.surfaceEmulation.layoutParams.height = it.bounds.top
|
||||
binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
||||
binding.overlayContainer.layoutParams.height = it.bounds.bottom - 48.toPx
|
||||
binding.overlayContainer.updatePadding(0, 0, 0, 24.toPx)
|
||||
}
|
||||
it.isSeparating
|
||||
} ?: false
|
||||
}
|
||||
it.isSeparating
|
||||
} ?: false
|
||||
if (!isFolding) {
|
||||
binding.emulationContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
binding.inputContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
binding.surfaceEmulation.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
binding.inGameMenu.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
isInFoldableLayout = false
|
||||
binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
binding.overlayContainer.updatePadding(0, 0, 0, 0)
|
||||
updateScreenLayout()
|
||||
}
|
||||
binding.emulationContainer.requestLayout()
|
||||
binding.inputContainer.requestLayout()
|
||||
binding.overlayContainer.requestLayout()
|
||||
binding.surfaceInputOverlay.requestLayout()
|
||||
binding.inGameMenu.requestLayout()
|
||||
binding.overlayContainer.requestLayout()
|
||||
}
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||
@@ -389,6 +318,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
popup.menu.apply {
|
||||
findItem(R.id.menu_toggle_fps).isChecked = EmulationMenuSettings.showFps
|
||||
findItem(R.id.menu_screen_layout).subMenu?.let { subMenu ->
|
||||
when (EmulationMenuSettings.screenLayout) {
|
||||
EmulationMenuSettings.LayoutOption_MobileLandscape -> {
|
||||
subMenu.findItem(R.id.menu_screen_layout_landscape).isChecked = true
|
||||
}
|
||||
EmulationMenuSettings.LayoutOption_MobilePortrait -> {
|
||||
subMenu.findItem(R.id.menu_screen_layout_portrait).isChecked = true
|
||||
}
|
||||
EmulationMenuSettings.LayoutOption_Default -> {
|
||||
subMenu.findItem(R.id.menu_screen_layout_auto).isChecked = true
|
||||
}
|
||||
else -> { subMenu.findItem(R.id.menu_screen_layout_landscape).isChecked = true }
|
||||
}
|
||||
}
|
||||
findItem(R.id.menu_rel_stick_center).isChecked = EmulationMenuSettings.joystickRelCenter
|
||||
findItem(R.id.menu_dpad_slide).isChecked = EmulationMenuSettings.dpadSlide
|
||||
findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay
|
||||
@@ -404,6 +347,29 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
true
|
||||
}
|
||||
|
||||
R.id.menu_screen_layout_landscape -> {
|
||||
EmulationMenuSettings.screenLayout = EmulationMenuSettings.LayoutOption_MobileLandscape
|
||||
updateScreenLayout()
|
||||
false
|
||||
}
|
||||
|
||||
R.id.menu_screen_layout_portrait -> {
|
||||
EmulationMenuSettings.screenLayout = EmulationMenuSettings.LayoutOption_MobilePortrait
|
||||
updateScreenLayout()
|
||||
false
|
||||
}
|
||||
|
||||
R.id.menu_screen_layout_auto -> {
|
||||
EmulationMenuSettings.screenLayout = EmulationMenuSettings.LayoutOption_Default
|
||||
updateScreenLayout()
|
||||
false
|
||||
}
|
||||
|
||||
R.id.menu_screen_layout -> {
|
||||
it.subMenu?.setGroupCheckable(R.id.menu_screen_layout_group, true, true)
|
||||
true
|
||||
}
|
||||
|
||||
R.id.menu_edit_overlay -> {
|
||||
binding.drawerLayout.close()
|
||||
binding.surfaceInputOverlay.requestFocus()
|
||||
@@ -437,7 +403,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
refreshInputOverlay()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setNeutralButton(R.string.emulation_toggle_all) { _, _ -> }
|
||||
.show()
|
||||
|
||||
@@ -494,19 +459,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
popup.show()
|
||||
}
|
||||
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
private fun startConfiguringControls() {
|
||||
// Lock the current orientation to prevent editing inconsistencies
|
||||
if (IntSetting.RENDERER_SCREEN_LAYOUT.int == Settings.LayoutOption_Unspecified) {
|
||||
emulationActivity?.let {
|
||||
it.requestedOrientation =
|
||||
if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
} else {
|
||||
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.doneControlConfig.visibility = View.VISIBLE
|
||||
binding.surfaceInputOverlay.setIsInEditMode(true)
|
||||
}
|
||||
@@ -514,12 +467,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
private fun stopConfiguringControls() {
|
||||
binding.doneControlConfig.visibility = View.GONE
|
||||
binding.surfaceInputOverlay.setIsInEditMode(false)
|
||||
// Unlock the orientation if it was locked for editing
|
||||
if (IntSetting.RENDERER_SCREEN_LAYOUT.int == Settings.LayoutOption_Unspecified) {
|
||||
emulationActivity?.let {
|
||||
it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@@ -529,22 +476,18 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
inputScaleSlider.apply {
|
||||
valueTo = 150F
|
||||
value = preferences.getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat()
|
||||
addOnChangeListener(
|
||||
Slider.OnChangeListener { _, value, _ ->
|
||||
inputScaleValue.text = "${value.toInt()}%"
|
||||
setControlScale(value.toInt())
|
||||
}
|
||||
)
|
||||
addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
inputScaleValue.text = "${value.toInt()}%"
|
||||
setControlScale(value.toInt())
|
||||
})
|
||||
}
|
||||
inputOpacitySlider.apply {
|
||||
valueTo = 100F
|
||||
value = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100).toFloat()
|
||||
addOnChangeListener(
|
||||
Slider.OnChangeListener { _, value, _ ->
|
||||
inputOpacityValue.text = "${value.toInt()}%"
|
||||
setControlOpacity(value.toInt())
|
||||
}
|
||||
)
|
||||
addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
inputOpacityValue.text = "${value.toInt()}%"
|
||||
setControlOpacity(value.toInt())
|
||||
})
|
||||
}
|
||||
inputScaleValue.text = "${inputScaleSlider.value.toInt()}%"
|
||||
inputOpacityValue.text = "${inputOpacitySlider.value.toInt()}%"
|
||||
@@ -576,9 +519,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.inGameMenu
|
||||
) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.inGameMenu) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
val cutInsets: Insets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
var left = 0
|
||||
var right = 0
|
||||
@@ -698,12 +639,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
state = State.PAUSED
|
||||
}
|
||||
|
||||
State.PAUSED -> Log.warning(
|
||||
"[EmulationFragment] Surface cleared while emulation paused."
|
||||
)
|
||||
else -> Log.warning(
|
||||
"[EmulationFragment] Surface cleared while emulation stopped."
|
||||
)
|
||||
State.PAUSED -> Log.warning("[EmulationFragment] Surface cleared while emulation paused.")
|
||||
else -> Log.warning("[EmulationFragment] Surface cleared while emulation stopped.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,5 +675,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
companion object {
|
||||
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
|
||||
fun newInstance(game: Game): EmulationFragment {
|
||||
val args = Bundle()
|
||||
args.putParcelable(EmulationActivity.EXTRA_SELECTED_GAME, game)
|
||||
val fragment = EmulationFragment()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
@@ -40,7 +40,6 @@ import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
|
||||
class HomeSettingsFragment : Fragment() {
|
||||
@@ -94,43 +93,21 @@ class HomeSettingsFragment : Fragment() {
|
||||
R.string.install_amiibo_keys_description,
|
||||
R.drawable.ic_nfc
|
||||
) { mainActivity.getAmiiboKey.launch(arrayOf("*/*")) },
|
||||
HomeSetting(
|
||||
R.string.install_game_content,
|
||||
R.string.install_game_content_description,
|
||||
R.drawable.ic_system_update_alt
|
||||
) { mainActivity.installGameUpdate.launch(arrayOf("*/*")) },
|
||||
HomeSetting(
|
||||
R.string.select_games_folder,
|
||||
R.string.select_games_folder_description,
|
||||
R.drawable.ic_add
|
||||
) {
|
||||
mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
|
||||
},
|
||||
) { mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) },
|
||||
HomeSetting(
|
||||
R.string.manage_save_data,
|
||||
R.string.import_export_saves_description,
|
||||
R.drawable.ic_save
|
||||
) {
|
||||
ImportExportSavesFragment().show(
|
||||
parentFragmentManager,
|
||||
ImportExportSavesFragment.TAG
|
||||
)
|
||||
},
|
||||
) { ImportExportSavesFragment().show(parentFragmentManager, ImportExportSavesFragment.TAG) },
|
||||
HomeSetting(
|
||||
R.string.install_prod_keys,
|
||||
R.string.install_prod_keys_description,
|
||||
R.drawable.ic_unlock
|
||||
) { mainActivity.getProdKey.launch(arrayOf("*/*")) },
|
||||
HomeSetting(
|
||||
R.string.install_firmware,
|
||||
R.string.install_firmware_description,
|
||||
R.drawable.ic_firmware
|
||||
) { mainActivity.getFirmware.launch(arrayOf("application/zip")) },
|
||||
HomeSetting(
|
||||
R.string.share_log,
|
||||
R.string.share_log_description,
|
||||
R.drawable.ic_log
|
||||
) { shareLog() },
|
||||
HomeSetting(
|
||||
R.string.about,
|
||||
R.string.about_description,
|
||||
@@ -227,11 +204,7 @@ class HomeSettingsFragment : Fragment() {
|
||||
val intent = Intent(action)
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
intent.data = DocumentsContract.buildRootUri(authority, DocumentProvider.ROOT_ID)
|
||||
intent.addFlags(
|
||||
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
)
|
||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
return intent
|
||||
}
|
||||
|
||||
@@ -289,33 +262,8 @@ class HomeSettingsFragment : Fragment() {
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun shareLog() {
|
||||
val file = DocumentFile.fromSingleUri(
|
||||
mainActivity,
|
||||
DocumentsContract.buildDocumentUri(
|
||||
DocumentProvider.AUTHORITY,
|
||||
"${DocumentProvider.ROOT_ID}/log/yuzu_log.txt"
|
||||
)
|
||||
)!!
|
||||
if (file.exists()) {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
.setDataAndType(file.uri, FileUtil.TEXT_PLAIN)
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
.putExtra(Intent.EXTRA_STREAM, file.uri)
|
||||
startActivity(Intent.createChooser(intent, getText(R.string.share_log)))
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getText(R.string.share_log_missing),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
val spacingNavigation = resources.getDimensionPixelSize(R.dimen.spacing_navigation)
|
||||
|
||||
@@ -15,14 +15,6 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FilenameFilter
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -31,7 +23,18 @@ import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.DocumentProvider
|
||||
import org.yuzu.yuzu_emu.getPublicFilesDir
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FilenameFilter
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
class ImportExportSavesFragment : DialogFragment() {
|
||||
private val context = YuzuApplication.appContext
|
||||
@@ -98,7 +101,7 @@ class ImportExportSavesFragment : DialogFragment() {
|
||||
val outputZipFile = File(
|
||||
tempFolder,
|
||||
"yuzu saves - ${
|
||||
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
||||
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
||||
}.zip"
|
||||
)
|
||||
outputZipFile.createNewFile()
|
||||
@@ -106,14 +109,12 @@ class ImportExportSavesFragment : DialogFragment() {
|
||||
saveFolder.walkTopDown().forEach { file ->
|
||||
val zipFileName =
|
||||
file.absolutePath.removePrefix(savesFolderRoot).removePrefix("/")
|
||||
if (zipFileName == "") {
|
||||
if (zipFileName == "")
|
||||
return@forEach
|
||||
}
|
||||
val entry = ZipEntry("$zipFileName${(if (file.isDirectory) "/" else "")}")
|
||||
zos.putNextEntry(entry)
|
||||
if (file.isFile) {
|
||||
if (file.isFile)
|
||||
file.inputStream().use { fis -> fis.copyTo(zos) }
|
||||
}
|
||||
}
|
||||
}
|
||||
lastZipCreated = outputZipFile
|
||||
@@ -123,6 +124,33 @@ class ImportExportSavesFragment : DialogFragment() {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the save files located in the given zip file and copies them to the saves folder.
|
||||
* @exception IOException if the file was being created outside of the target directory
|
||||
*/
|
||||
private fun unzip(zipStream: InputStream, destDir: File): Boolean {
|
||||
val zis = ZipInputStream(BufferedInputStream(zipStream))
|
||||
var entry: ZipEntry? = zis.nextEntry
|
||||
while (entry != null) {
|
||||
val entryName = entry.name
|
||||
val entryFile = File(destDir, entryName)
|
||||
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) {
|
||||
zis.close()
|
||||
throw IOException("Entry is outside of the target dir: " + entryFile.name)
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
entryFile.mkdirs()
|
||||
} else {
|
||||
entryFile.parentFile?.mkdirs()
|
||||
entryFile.createNewFile()
|
||||
entryFile.outputStream().use { fos -> zis.copyTo(fos) }
|
||||
}
|
||||
entry = zis.nextEntry
|
||||
}
|
||||
zis.close()
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the save file located in the given folder path by creating a zip file and sharing it via intent.
|
||||
*/
|
||||
@@ -139,8 +167,7 @@ class ImportExportSavesFragment : DialogFragment() {
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
val file = DocumentFile.fromSingleUri(
|
||||
context,
|
||||
DocumentsContract.buildDocumentUri(
|
||||
context, DocumentsContract.buildDocumentUri(
|
||||
DocumentProvider.AUTHORITY,
|
||||
"${DocumentProvider.ROOT_ID}/temp/${lastZipFile.name}"
|
||||
)
|
||||
@@ -177,7 +204,7 @@ class ImportExportSavesFragment : DialogFragment() {
|
||||
|
||||
try {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
FileUtil.unzip(inputZip, cacheSaveDir)
|
||||
unzip(inputZip, cacheSaveDir)
|
||||
cacheSaveDir.list(filterTitleId)?.forEach { savePath ->
|
||||
File(savesFolder, savePath).deleteRecursively()
|
||||
File(cacheSaveDir, savePath).copyRecursively(File(savesFolder, savePath), true)
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
|
||||
import org.yuzu.yuzu_emu.model.TaskViewModel
|
||||
|
||||
class IndeterminateProgressDialogFragment : DialogFragment() {
|
||||
private val taskViewModel: TaskViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val titleId = requireArguments().getInt(TITLE)
|
||||
|
||||
val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
|
||||
progressBinding.progressBar.isIndeterminate = true
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(titleId)
|
||||
.setView(progressBinding.root)
|
||||
.create()
|
||||
dialog.setCanceledOnTouchOutside(false)
|
||||
|
||||
taskViewModel.isComplete.observe(this) { complete ->
|
||||
if (complete) {
|
||||
dialog.dismiss()
|
||||
when (val result = taskViewModel.result.value) {
|
||||
is String -> Toast.makeText(requireContext(), result, Toast.LENGTH_LONG).show()
|
||||
is MessageDialogFragment -> result.show(
|
||||
parentFragmentManager,
|
||||
MessageDialogFragment.TAG
|
||||
)
|
||||
}
|
||||
taskViewModel.clear()
|
||||
}
|
||||
}
|
||||
|
||||
if (taskViewModel.isRunning.value == false) {
|
||||
taskViewModel.runTask()
|
||||
}
|
||||
return dialog
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "IndeterminateProgressDialogFragment"
|
||||
|
||||
private const val TITLE = "Title"
|
||||
|
||||
fun newInstance(
|
||||
activity: AppCompatActivity,
|
||||
titleId: Int,
|
||||
task: () -> Any
|
||||
): IndeterminateProgressDialogFragment {
|
||||
val dialog = IndeterminateProgressDialogFragment()
|
||||
val args = Bundle()
|
||||
ViewModelProvider(activity)[TaskViewModel::class.java].task = task
|
||||
args.putInt(TITLE, titleId)
|
||||
dialog.arguments = args
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.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 com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.yuzu.yuzu_emu.databinding.DialogLicenseBinding
|
||||
import org.yuzu.yuzu_emu.model.License
|
||||
import org.yuzu.yuzu_emu.utils.SerializableHelper.parcelable
|
||||
|
||||
class LicenseBottomSheetDialogFragment : BottomSheetDialogFragment() {
|
||||
private var _binding: DialogLicenseBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = DialogLicenseBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
BottomSheetBehavior.from<View>(view.parent as View).state =
|
||||
BottomSheetBehavior.STATE_HALF_EXPANDED
|
||||
|
||||
val license = requireArguments().parcelable<License>(LICENSE)!!
|
||||
|
||||
binding.apply {
|
||||
textTitle.setText(license.titleId)
|
||||
textLink.setText(license.linkId)
|
||||
textCopyright.setText(license.copyrightId)
|
||||
textLicense.setText(license.licenseId)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "LicenseBottomSheetDialogFragment"
|
||||
|
||||
const val LICENSE = "License"
|
||||
|
||||
fun newInstance(
|
||||
license: License
|
||||
): LicenseBottomSheetDialogFragment {
|
||||
val dialog = LicenseBottomSheetDialogFragment()
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(LICENSE, license)
|
||||
dialog.arguments = bundle
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.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 android.view.ViewGroup.MarginLayoutParams
|
||||
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.fragment.app.activityViewModels
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.adapters.LicenseAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentLicensesBinding
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.model.License
|
||||
|
||||
class LicensesFragment : Fragment() {
|
||||
private var _binding: FragmentLicensesBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val homeViewModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentLicensesBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
homeViewModel.setNavigationVisibility(visible = false, animated = true)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = false)
|
||||
|
||||
binding.toolbarLicenses.setNavigationOnClickListener {
|
||||
binding.root.findNavController().popBackStack()
|
||||
}
|
||||
|
||||
val licenses = listOf(
|
||||
License(
|
||||
R.string.license_fidelityfx_fsr,
|
||||
R.string.license_fidelityfx_fsr_description,
|
||||
R.string.license_fidelityfx_fsr_link,
|
||||
R.string.license_fidelityfx_fsr_copyright,
|
||||
R.string.license_fidelityfx_fsr_text
|
||||
),
|
||||
License(
|
||||
R.string.license_cubeb,
|
||||
R.string.license_cubeb_description,
|
||||
R.string.license_cubeb_link,
|
||||
R.string.license_cubeb_copyright,
|
||||
R.string.license_cubeb_text
|
||||
),
|
||||
License(
|
||||
R.string.license_dynarmic,
|
||||
R.string.license_dynarmic_description,
|
||||
R.string.license_dynarmic_link,
|
||||
R.string.license_dynarmic_copyright,
|
||||
R.string.license_dynarmic_text
|
||||
),
|
||||
License(
|
||||
R.string.license_ffmpeg,
|
||||
R.string.license_ffmpeg_description,
|
||||
R.string.license_ffmpeg_link,
|
||||
R.string.license_ffmpeg_copyright,
|
||||
R.string.license_ffmpeg_text
|
||||
),
|
||||
License(
|
||||
R.string.license_opus,
|
||||
R.string.license_opus_description,
|
||||
R.string.license_opus_link,
|
||||
R.string.license_opus_copyright,
|
||||
R.string.license_opus_text
|
||||
),
|
||||
License(
|
||||
R.string.license_sirit,
|
||||
R.string.license_sirit_description,
|
||||
R.string.license_sirit_link,
|
||||
R.string.license_sirit_copyright,
|
||||
R.string.license_sirit_text
|
||||
),
|
||||
License(
|
||||
R.string.license_adreno_tools,
|
||||
R.string.license_adreno_tools_description,
|
||||
R.string.license_adreno_tools_link,
|
||||
R.string.license_adreno_tools_copyright,
|
||||
R.string.license_adreno_tools_text
|
||||
)
|
||||
)
|
||||
|
||||
binding.listLicenses.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = LicenseAdapter(requireActivity() as AppCompatActivity, licenses)
|
||||
}
|
||||
|
||||
setInsets()
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
val leftInsets = barInsets.left + cutoutInsets.left
|
||||
val rightInsets = barInsets.right + cutoutInsets.right
|
||||
|
||||
val mlpAppBar = binding.appbarLicenses.layoutParams as MarginLayoutParams
|
||||
mlpAppBar.leftMargin = leftInsets
|
||||
mlpAppBar.rightMargin = rightInsets
|
||||
binding.appbarLicenses.layoutParams = mlpAppBar
|
||||
|
||||
val mlpScrollAbout = binding.listLicenses.layoutParams as MarginLayoutParams
|
||||
mlpScrollAbout.leftMargin = leftInsets
|
||||
mlpScrollAbout.rightMargin = rightInsets
|
||||
binding.listLicenses.layoutParams = mlpScrollAbout
|
||||
|
||||
binding.listLicenses.updatePadding(bottom = barInsets.bottom)
|
||||
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import androidx.fragment.app.activityViewModels
|
||||
import androidx.preference.PreferenceManager
|
||||
import info.debatty.java.stringsimilarity.Jaccard
|
||||
import info.debatty.java.stringsimilarity.JaroWinkler
|
||||
import java.util.Locale
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.adapters.GameAdapter
|
||||
@@ -30,6 +29,8 @@ import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import java.util.Locale
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
private var _binding: FragmentSearchBinding? = null
|
||||
@@ -126,18 +127,24 @@ class SearchFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
R.id.chip_homebrew -> baseList.filter { it.isHomebrew }
|
||||
R.id.chip_homebrew -> {
|
||||
baseList.filter {
|
||||
Log.error("Guh - ${it.path}")
|
||||
FileUtil.hasExtension(it.path, "nro")
|
||||
|| FileUtil.hasExtension(it.path, "nso")
|
||||
}
|
||||
}
|
||||
|
||||
R.id.chip_retail -> baseList.filter {
|
||||
FileUtil.hasExtension(it.path, "xci") ||
|
||||
FileUtil.hasExtension(it.path, "nsp")
|
||||
FileUtil.hasExtension(it.path, "xci")
|
||||
|| FileUtil.hasExtension(it.path, "nsp")
|
||||
}
|
||||
|
||||
else -> baseList
|
||||
}
|
||||
|
||||
if (binding.searchText.text.toString().isEmpty() &&
|
||||
binding.chipGroup.checkedChipId != View.NO_ID
|
||||
if (binding.searchText.text.toString().isEmpty()
|
||||
&& binding.chipGroup.checkedChipId != View.NO_ID
|
||||
) {
|
||||
gamesViewModel.setSearchedGames(filteredList)
|
||||
return
|
||||
@@ -172,16 +179,14 @@ class SearchFragment : Fragment() {
|
||||
private fun focusSearch() {
|
||||
if (_binding != null) {
|
||||
binding.searchText.requestFocus()
|
||||
val imm = requireActivity()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
|
||||
val imm =
|
||||
requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
|
||||
imm?.showSoftInput(binding.searchText, InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
val extraListSpacing = resources.getDimensionPixelSize(R.dimen.spacing_med)
|
||||
|
||||
@@ -25,7 +25,6 @@ import androidx.navigation.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import java.io.File
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.adapters.SetupAdapter
|
||||
@@ -36,6 +35,7 @@ import org.yuzu.yuzu_emu.model.SetupPage
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||
import java.io.File
|
||||
|
||||
class SetupFragment : Fragment() {
|
||||
private var _binding: FragmentSetupBinding? = null
|
||||
@@ -82,8 +82,7 @@ class SetupFragment : Fragment() {
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
requireActivity().window.navigationBarColor =
|
||||
ContextCompat.getColor(requireContext(), android.R.color.transparent)
|
||||
@@ -149,20 +148,14 @@ class SetupFragment : Fragment() {
|
||||
R.drawable.ic_add,
|
||||
true,
|
||||
R.string.add_games,
|
||||
{
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
},
|
||||
{ mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) },
|
||||
true,
|
||||
R.string.add_games_warning,
|
||||
R.string.add_games_warning_description,
|
||||
R.string.add_games_warning_help,
|
||||
{
|
||||
val preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(
|
||||
YuzuApplication.appContext
|
||||
)
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()
|
||||
}
|
||||
)
|
||||
@@ -267,9 +260,7 @@ class SetupFragment : Fragment() {
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private val permissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
if (!it &&
|
||||
!shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)
|
||||
) {
|
||||
if (!it && !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
PermissionDeniedDialogFragment().show(
|
||||
childFragmentManager,
|
||||
PermissionDeniedDialogFragment.TAG
|
||||
@@ -324,9 +315,7 @@ class SetupFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
view.setPadding(
|
||||
|
||||
@@ -44,9 +44,7 @@ class AutofitGridLayoutManager(
|
||||
override fun onLayoutChildren(recycler: Recycler, state: RecyclerView.State) {
|
||||
val width = width
|
||||
val height = height
|
||||
if (columnWidth > 0 && width > 0 && height > 0 &&
|
||||
(isColumnWidthChanged || lastWidth != width || lastHeight != height)
|
||||
) {
|
||||
if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
|
||||
val totalSpace: Int = if (orientation == VERTICAL) {
|
||||
width - paddingRight - paddingLeft
|
||||
} else {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
package org.yuzu.yuzu_emu.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import java.util.HashSet
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.HashSet
|
||||
|
||||
@Parcelize
|
||||
@Serializable
|
||||
@@ -16,29 +16,21 @@ class Game(
|
||||
val regions: String,
|
||||
val path: String,
|
||||
val gameId: String,
|
||||
val company: String,
|
||||
val isHomebrew: Boolean
|
||||
val company: String
|
||||
) : Parcelable {
|
||||
val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime"
|
||||
val keyLastPlayedTime get() = "${gameId}_LastPlayed"
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Game) {
|
||||
if (other !is Game)
|
||||
return false
|
||||
}
|
||||
|
||||
return hashCode() == other.hashCode()
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = title.hashCode()
|
||||
result = 31 * result + description.hashCode()
|
||||
result = 31 * result + regions.hashCode()
|
||||
result = 31 * result + path.hashCode()
|
||||
result = 31 * result + gameId.hashCode()
|
||||
result = 31 * result + company.hashCode()
|
||||
result = 31 * result + isHomebrew.hashCode()
|
||||
return result
|
||||
return title == other.title
|
||||
&& description == other.description
|
||||
&& regions == other.regions
|
||||
&& path == other.path
|
||||
&& gameId == other.gameId
|
||||
&& company == other.company
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -10,19 +10,16 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.preference.PreferenceManager
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.MissingFieldException
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||
import java.util.Locale
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
class GamesViewModel : ViewModel() {
|
||||
private val _games = MutableLiveData<List<Game>>(emptyList())
|
||||
val games: LiveData<List<Game>> get() = _games
|
||||
@@ -52,13 +49,7 @@ class GamesViewModel : ViewModel() {
|
||||
if (storedGames!!.isNotEmpty()) {
|
||||
val deserializedGames = mutableSetOf<Game>()
|
||||
storedGames.forEach {
|
||||
val game: Game
|
||||
try {
|
||||
game = Json.decodeFromString(it)
|
||||
} catch (e: MissingFieldException) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val game: Game = Json.decodeFromString(it)
|
||||
val gameExists =
|
||||
DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(game.path))
|
||||
?.exists()
|
||||
@@ -99,9 +90,8 @@ class GamesViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
fun reloadGames(directoryChanged: Boolean) {
|
||||
if (isReloading.value == true) {
|
||||
if (isReloading.value == true)
|
||||
return
|
||||
}
|
||||
_isReloading.postValue(true)
|
||||
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class License(
|
||||
val titleId: Int,
|
||||
val descriptionId: Int,
|
||||
val linkId: Int,
|
||||
val copyrightId: Int,
|
||||
val licenseId: Int
|
||||
) : Parcelable
|
||||
@@ -1,47 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.model
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class TaskViewModel : ViewModel() {
|
||||
private val _result = MutableLiveData<Any>()
|
||||
val result: LiveData<Any> = _result
|
||||
|
||||
private val _isComplete = MutableLiveData<Boolean>()
|
||||
val isComplete: LiveData<Boolean> = _isComplete
|
||||
|
||||
private val _isRunning = MutableLiveData<Boolean>()
|
||||
val isRunning: LiveData<Boolean> = _isRunning
|
||||
|
||||
lateinit var task: () -> Any
|
||||
|
||||
init {
|
||||
clear()
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
_result.value = Any()
|
||||
_isComplete.value = false
|
||||
_isRunning.value = false
|
||||
}
|
||||
|
||||
fun runTask() {
|
||||
if (_isRunning.value == true) {
|
||||
return
|
||||
}
|
||||
_isRunning.value = true
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val res = task()
|
||||
_result.postValue(res)
|
||||
_isComplete.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package org.yuzu.yuzu_emu.overlay
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Point
|
||||
@@ -23,8 +24,6 @@ import android.view.WindowInsets
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.NativeLibrary.ButtonType
|
||||
import org.yuzu.yuzu_emu.NativeLibrary.StickType
|
||||
@@ -32,13 +31,14 @@ import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Draws the interactive input overlay on top of the
|
||||
* [SurfaceView] that is rendering emulation.
|
||||
*/
|
||||
class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
SurfaceView(context, attrs),
|
||||
class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context, attrs),
|
||||
OnTouchListener {
|
||||
private val overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
|
||||
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
|
||||
@@ -51,14 +51,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
private lateinit var windowInsets: WindowInsets
|
||||
|
||||
var orientation = LANDSCAPE
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
|
||||
windowInsets = rootWindowInsets
|
||||
|
||||
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||
if (!preferences.getBoolean(Settings.PREF_OVERLAY_INIT, false)) {
|
||||
defaultOverlay()
|
||||
}
|
||||
|
||||
@@ -95,11 +93,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
var shouldUpdateView = false
|
||||
val playerIndex =
|
||||
if (NativeLibrary.isHandheldOnly()) {
|
||||
NativeLibrary.ConsoleDevice
|
||||
} else {
|
||||
NativeLibrary.Player1Device
|
||||
}
|
||||
if (NativeLibrary.isHandheldOnly()) NativeLibrary.ConsoleDevice else NativeLibrary.Player1Device
|
||||
|
||||
for (button in overlayButtons) {
|
||||
if (!button.updateStatus(event)) {
|
||||
@@ -162,9 +156,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
shouldUpdateView = true
|
||||
}
|
||||
|
||||
if (shouldUpdateView) {
|
||||
if (shouldUpdateView)
|
||||
invalidate()
|
||||
}
|
||||
|
||||
if (!preferences.getBoolean(Settings.PREF_TOUCH_ENABLED, true)) {
|
||||
return true
|
||||
@@ -240,6 +233,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
val fingerPositionX = event.getX(pointerIndex).toInt()
|
||||
val fingerPositionY = event.getY(pointerIndex).toInt()
|
||||
|
||||
// TODO: Provide support for portrait layout
|
||||
//val orientation =
|
||||
// if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
|
||||
|
||||
for (button in overlayButtons) {
|
||||
// Determine the button state to apply based on the MotionEvent action flag.
|
||||
when (event.action and MotionEvent.ACTION_MASK) {
|
||||
@@ -248,9 +245,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
// If no button is being moved now, remember the currently touched button to move.
|
||||
if (buttonBeingConfigured == null &&
|
||||
button.bounds.contains(
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
) {
|
||||
buttonBeingConfigured = button
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
@@ -269,7 +266,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
buttonBeingConfigured!!.buttonId,
|
||||
buttonBeingConfigured!!.bounds.centerX(),
|
||||
buttonBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
""
|
||||
)
|
||||
buttonBeingConfigured = null
|
||||
}
|
||||
@@ -302,7 +299,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
dpadBeingConfigured!!.upId,
|
||||
dpadBeingConfigured!!.bounds.centerX(),
|
||||
dpadBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
""
|
||||
)
|
||||
dpadBeingConfigured = null
|
||||
}
|
||||
@@ -314,9 +311,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
MotionEvent.ACTION_DOWN,
|
||||
MotionEvent.ACTION_POINTER_DOWN -> if (joystickBeingConfigured == null &&
|
||||
joystick.bounds.contains(
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
) {
|
||||
joystickBeingConfigured = joystick
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
@@ -333,7 +330,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
joystickBeingConfigured!!.buttonId,
|
||||
joystickBeingConfigured!!.bounds.centerX(),
|
||||
joystickBeingConfigured!!.bounds.centerY(),
|
||||
orientation
|
||||
""
|
||||
)
|
||||
joystickBeingConfigured = null
|
||||
}
|
||||
@@ -536,6 +533,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
overlayButtons.clear()
|
||||
overlayDpads.clear()
|
||||
overlayJoysticks.clear()
|
||||
val orientation =
|
||||
if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
|
||||
|
||||
// Add all the enabled overlay items back to the HashSet.
|
||||
if (EmulationMenuSettings.showOverlay) {
|
||||
@@ -549,8 +548,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
val min = windowSize.first
|
||||
val max = windowSize.second
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||
.putFloat("$sharedPrefsId-X$orientation", (x - min.x).toFloat() / max.x)
|
||||
.putFloat("$sharedPrefsId-Y$orientation", (y - min.y).toFloat() / max.y)
|
||||
.putFloat("$sharedPrefsId$orientation-X", (x - min.x).toFloat() / max.x)
|
||||
.putFloat("$sharedPrefsId$orientation-Y", (y - min.y).toFloat() / max.y)
|
||||
.apply()
|
||||
}
|
||||
|
||||
@@ -559,250 +558,145 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
}
|
||||
|
||||
private fun defaultOverlay() {
|
||||
if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) {
|
||||
defaultOverlayByLayout(orientation)
|
||||
if (!preferences.getBoolean(Settings.PREF_OVERLAY_INIT, false)) {
|
||||
defaultOverlayLandscape()
|
||||
}
|
||||
|
||||
resetButtonPlacement()
|
||||
preferences.edit()
|
||||
.putBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", true)
|
||||
.putBoolean(Settings.PREF_OVERLAY_INIT, true)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun resetButtonPlacement() {
|
||||
defaultOverlayByLayout(orientation)
|
||||
defaultOverlayLandscape()
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
private val landscapeResources = arrayOf(
|
||||
R.integer.SWITCH_BUTTON_A_X,
|
||||
R.integer.SWITCH_BUTTON_A_Y,
|
||||
R.integer.SWITCH_BUTTON_B_X,
|
||||
R.integer.SWITCH_BUTTON_B_Y,
|
||||
R.integer.SWITCH_BUTTON_X_X,
|
||||
R.integer.SWITCH_BUTTON_X_Y,
|
||||
R.integer.SWITCH_BUTTON_Y_X,
|
||||
R.integer.SWITCH_BUTTON_Y_Y,
|
||||
R.integer.SWITCH_TRIGGER_ZL_X,
|
||||
R.integer.SWITCH_TRIGGER_ZL_Y,
|
||||
R.integer.SWITCH_TRIGGER_ZR_X,
|
||||
R.integer.SWITCH_TRIGGER_ZR_Y,
|
||||
R.integer.SWITCH_BUTTON_DPAD_X,
|
||||
R.integer.SWITCH_BUTTON_DPAD_Y,
|
||||
R.integer.SWITCH_TRIGGER_L_X,
|
||||
R.integer.SWITCH_TRIGGER_L_Y,
|
||||
R.integer.SWITCH_TRIGGER_R_X,
|
||||
R.integer.SWITCH_TRIGGER_R_Y,
|
||||
R.integer.SWITCH_BUTTON_PLUS_X,
|
||||
R.integer.SWITCH_BUTTON_PLUS_Y,
|
||||
R.integer.SWITCH_BUTTON_MINUS_X,
|
||||
R.integer.SWITCH_BUTTON_MINUS_Y,
|
||||
R.integer.SWITCH_BUTTON_HOME_X,
|
||||
R.integer.SWITCH_BUTTON_HOME_Y,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_X,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_Y,
|
||||
R.integer.SWITCH_STICK_R_X,
|
||||
R.integer.SWITCH_STICK_R_Y,
|
||||
R.integer.SWITCH_STICK_L_X,
|
||||
R.integer.SWITCH_STICK_L_Y
|
||||
)
|
||||
|
||||
private val portraitResources = arrayOf(
|
||||
R.integer.SWITCH_BUTTON_A_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_A_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_B_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_B_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_X_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_X_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_Y_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_Y_Y_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_ZL_X_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_ZL_Y_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_ZR_X_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_ZR_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_DPAD_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_DPAD_Y_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_L_X_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_L_Y_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_R_X_PORTRAIT,
|
||||
R.integer.SWITCH_TRIGGER_R_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_PLUS_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_PLUS_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_MINUS_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_MINUS_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_HOME_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_HOME_Y_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_X_PORTRAIT,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_Y_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_R_X_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_R_Y_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_L_X_PORTRAIT,
|
||||
R.integer.SWITCH_STICK_L_Y_PORTRAIT
|
||||
)
|
||||
|
||||
private val foldableResources = arrayOf(
|
||||
R.integer.SWITCH_BUTTON_A_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_A_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_B_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_B_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_X_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_X_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_Y_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_Y_Y_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_ZL_X_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_ZL_Y_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_ZR_X_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_ZR_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_DPAD_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_DPAD_Y_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_L_X_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_L_Y_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_R_X_FOLDABLE,
|
||||
R.integer.SWITCH_TRIGGER_R_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_PLUS_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_PLUS_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_MINUS_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_MINUS_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_HOME_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_HOME_Y_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_X_FOLDABLE,
|
||||
R.integer.SWITCH_BUTTON_CAPTURE_Y_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_R_X_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_R_Y_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_L_X_FOLDABLE,
|
||||
R.integer.SWITCH_STICK_L_Y_FOLDABLE
|
||||
)
|
||||
|
||||
private fun getResourceValue(orientation: String, position: Int): Float {
|
||||
return when (orientation) {
|
||||
PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000
|
||||
FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000
|
||||
else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultOverlayByLayout(orientation: String) {
|
||||
private fun defaultOverlayLandscape() {
|
||||
// Each value represents the position of the button in relation to the screen size without insets.
|
||||
preferences.edit()
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_A.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 0)
|
||||
ButtonType.BUTTON_A.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_A_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_A.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 1)
|
||||
ButtonType.BUTTON_A.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_A_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_B.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 2)
|
||||
ButtonType.BUTTON_B.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_B_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_B.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 3)
|
||||
ButtonType.BUTTON_B.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_B_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_X.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 4)
|
||||
ButtonType.BUTTON_X.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_X_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_X.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 5)
|
||||
ButtonType.BUTTON_X.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_X_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_Y.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 6)
|
||||
ButtonType.BUTTON_Y.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_Y_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_Y.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 7)
|
||||
ButtonType.BUTTON_Y.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_Y_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZL.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 8)
|
||||
ButtonType.TRIGGER_ZL.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZL.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 9)
|
||||
ButtonType.TRIGGER_ZL.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZR.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 10)
|
||||
ButtonType.TRIGGER_ZR.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_ZR.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 11)
|
||||
ButtonType.TRIGGER_ZR.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.DPAD_UP.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 12)
|
||||
ButtonType.DPAD_UP.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.DPAD_UP.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 13)
|
||||
ButtonType.DPAD_UP.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_L.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 14)
|
||||
ButtonType.TRIGGER_L.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_L_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_L.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 15)
|
||||
ButtonType.TRIGGER_L.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_L_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_R.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 16)
|
||||
ButtonType.TRIGGER_R.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_R_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.TRIGGER_R.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 17)
|
||||
ButtonType.TRIGGER_R.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_TRIGGER_R_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_PLUS.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 18)
|
||||
ButtonType.BUTTON_PLUS.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_PLUS.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 19)
|
||||
ButtonType.BUTTON_PLUS.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_MINUS.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 20)
|
||||
ButtonType.BUTTON_MINUS.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_MINUS.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 21)
|
||||
ButtonType.BUTTON_MINUS.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_HOME.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 22)
|
||||
ButtonType.BUTTON_HOME.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_HOME_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_HOME.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 23)
|
||||
ButtonType.BUTTON_HOME.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_HOME_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 24)
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_X)
|
||||
.toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 25)
|
||||
ButtonType.BUTTON_CAPTURE.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_Y)
|
||||
.toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_R.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 26)
|
||||
ButtonType.STICK_R.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_STICK_R_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_R.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 27)
|
||||
ButtonType.STICK_R.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_STICK_R_Y).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_L.toString() + "-X$orientation",
|
||||
getResourceValue(orientation, 28)
|
||||
ButtonType.STICK_L.toString() + "-X",
|
||||
resources.getInteger(R.integer.SWITCH_STICK_L_X).toFloat() / 1000
|
||||
)
|
||||
.putFloat(
|
||||
ButtonType.STICK_L.toString() + "-Y$orientation",
|
||||
getResourceValue(orientation, 29)
|
||||
ButtonType.STICK_L.toString() + "-Y",
|
||||
resources.getInteger(R.integer.SWITCH_STICK_L_Y).toFloat() / 1000
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
@@ -815,17 +709,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
private val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
const val LANDSCAPE = ""
|
||||
const val PORTRAIT = "_Portrait"
|
||||
const val FOLDABLE = "_Foldable"
|
||||
|
||||
/**
|
||||
* Resizes a [Bitmap] by a given scale factor
|
||||
*
|
||||
* @param context Context for getting the vector drawable
|
||||
* @param drawableId The ID of the drawable to scale.
|
||||
* @param scale The scale factor for the bitmap.
|
||||
* @return The scaled [Bitmap]
|
||||
* @return The scaled [Bitmap]
|
||||
*/
|
||||
private fun getBitmap(context: Context, drawableId: Int, scale: Float): Bitmap {
|
||||
val vectorDrawable = ContextCompat.getDrawable(context, drawableId) as VectorDrawable
|
||||
@@ -859,13 +749,14 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
* Gets the safe screen size for drawing the overlay
|
||||
*
|
||||
* @param context Context for getting the window metrics
|
||||
* @return A pair of points, the first being the top left corner of the safe area,
|
||||
* @return A pair of points, the first being the top left corner of the safe area,
|
||||
* the second being the bottom right corner of the safe area
|
||||
*/
|
||||
private fun getSafeScreenSize(context: Context): Pair<Point, Point> {
|
||||
// Get screen size
|
||||
val windowMetrics = WindowMetricsCalculator.getOrCreate()
|
||||
.computeCurrentWindowMetrics(context as Activity)
|
||||
val windowMetrics =
|
||||
WindowMetricsCalculator.getOrCreate()
|
||||
.computeCurrentWindowMetrics(context as Activity)
|
||||
var maxY = windowMetrics.bounds.height().toFloat()
|
||||
var maxX = windowMetrics.bounds.width().toFloat()
|
||||
var minY = 0
|
||||
@@ -874,26 +765,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
// If we have API access, calculate the safe area to draw the overlay
|
||||
var cutoutLeft = 0
|
||||
var cutoutBottom = 0
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout
|
||||
if (insets != null) {
|
||||
if (insets.boundingRectTop.bottom != 0 &&
|
||||
insets.boundingRectTop.bottom > maxY / 2
|
||||
) {
|
||||
maxY = insets.boundingRectTop.bottom.toFloat()
|
||||
}
|
||||
if (insets.boundingRectRight.left != 0 &&
|
||||
insets.boundingRectRight.left > maxX / 2
|
||||
) {
|
||||
maxX = insets.boundingRectRight.left.toFloat()
|
||||
}
|
||||
val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout
|
||||
if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2)
|
||||
insets.boundingRectTop.bottom.toFloat() else maxY
|
||||
if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2)
|
||||
insets.boundingRectRight.left.toFloat() else maxX
|
||||
|
||||
minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left
|
||||
minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom
|
||||
minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left
|
||||
minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom
|
||||
|
||||
cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left
|
||||
cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom
|
||||
}
|
||||
cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left
|
||||
cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom
|
||||
}
|
||||
|
||||
// This makes sure that if we have an inset on one side of the screen, we mirror it on
|
||||
@@ -993,8 +876,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val xKey = "$buttonId-X$orientation"
|
||||
val yKey = "$buttonId-Y$orientation"
|
||||
val xKey = "$buttonId$orientation-X"
|
||||
val yKey = "$buttonId$orientation-Y"
|
||||
val drawableXPercent = sPrefs.getFloat(xKey, 0f)
|
||||
val drawableYPercent = sPrefs.getFloat(yKey, 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
@@ -1074,8 +957,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-X$orientation", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-Y$orientation", 0f)
|
||||
val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-X", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-Y", 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||
val width = overlayDrawable.width
|
||||
@@ -1141,8 +1024,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
|
||||
// These were set in the input overlay configuration menu.
|
||||
val drawableXPercent = sPrefs.getFloat("$button-X$orientation", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("$button-Y$orientation", 0f)
|
||||
val drawableXPercent = sPrefs.getFloat("$button$orientation-X", 0f)
|
||||
val drawableYPercent = sPrefs.getFloat("$button$orientation-Y", 0f)
|
||||
val drawableX = (drawableXPercent * max.x + min.x).toInt()
|
||||
val drawableY = (drawableYPercent * max.y + min.y).toInt()
|
||||
val outerScale = 1.66f
|
||||
|
||||
@@ -133,10 +133,7 @@ class InputOverlayDrawableDpad(
|
||||
downButtonState = axisY > VIRT_AXIS_DEADZONE
|
||||
leftButtonState = axisX < -VIRT_AXIS_DEADZONE
|
||||
rightButtonState = axisX > VIRT_AXIS_DEADZONE
|
||||
return oldUpState != upButtonState ||
|
||||
oldDownState != downButtonState ||
|
||||
oldLeftState != leftButtonState ||
|
||||
oldRightState != rightButtonState
|
||||
return oldUpState != upButtonState || oldDownState != downButtonState || oldLeftState != leftButtonState || oldRightState != rightButtonState
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@ import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.view.MotionEvent
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
|
||||
|
||||
/**
|
||||
* Custom [BitmapDrawable] that is capable
|
||||
@@ -241,22 +241,14 @@ class InputOverlayDrawableJoystick(
|
||||
private fun setInnerBounds() {
|
||||
var x = virtBounds.centerX() + (xAxis * (virtBounds.width() / 2)).toInt()
|
||||
var y = virtBounds.centerY() + (yAxis * (virtBounds.height() / 2)).toInt()
|
||||
if (x > virtBounds.centerX() + virtBounds.width() / 2) {
|
||||
x =
|
||||
virtBounds.centerX() + virtBounds.width() / 2
|
||||
}
|
||||
if (x < virtBounds.centerX() - virtBounds.width() / 2) {
|
||||
x =
|
||||
virtBounds.centerX() - virtBounds.width() / 2
|
||||
}
|
||||
if (y > virtBounds.centerY() + virtBounds.height() / 2) {
|
||||
y =
|
||||
virtBounds.centerY() + virtBounds.height() / 2
|
||||
}
|
||||
if (y < virtBounds.centerY() - virtBounds.height() / 2) {
|
||||
y =
|
||||
virtBounds.centerY() - virtBounds.height() / 2
|
||||
}
|
||||
if (x > virtBounds.centerX() + virtBounds.width() / 2) x =
|
||||
virtBounds.centerX() + virtBounds.width() / 2
|
||||
if (x < virtBounds.centerX() - virtBounds.width() / 2) x =
|
||||
virtBounds.centerX() - virtBounds.width() / 2
|
||||
if (y > virtBounds.centerY() + virtBounds.height() / 2) y =
|
||||
virtBounds.centerY() + virtBounds.height() / 2
|
||||
if (y < virtBounds.centerY() - virtBounds.height() / 2) y =
|
||||
virtBounds.centerY() - virtBounds.height() / 2
|
||||
val width = pressedStateInnerBitmap.bounds.width() / 2
|
||||
val height = pressedStateInnerBitmap.bounds.height() / 2
|
||||
defaultStateInnerBitmap.setBounds(
|
||||
|
||||
@@ -99,9 +99,7 @@ class GamesFragment : Fragment() {
|
||||
}
|
||||
shouldSwapData.observe(viewLifecycleOwner) { shouldSwapData ->
|
||||
if (shouldSwapData) {
|
||||
(binding.gridGames.adapter as GameAdapter).submitList(
|
||||
gamesViewModel.games.value!!
|
||||
)
|
||||
(binding.gridGames.adapter as GameAdapter).submitList(gamesViewModel.games.value!!)
|
||||
gamesViewModel.setShouldSwapData(false)
|
||||
}
|
||||
}
|
||||
@@ -130,9 +128,7 @@ class GamesFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
val extraListSpacing = resources.getDimensionPixelSize(R.dimen.spacing_large)
|
||||
|
||||
@@ -26,9 +26,6 @@ import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.navigation.NavigationBarView
|
||||
import java.io.File
|
||||
import java.io.FilenameFilter
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -38,21 +35,19 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
||||
import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment
|
||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.utils.*
|
||||
import java.io.IOException
|
||||
|
||||
class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
private val homeViewModel: HomeViewModel by viewModels()
|
||||
private val gamesViewModel: GamesViewModel by viewModels()
|
||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
|
||||
override var themeId: Int = 0
|
||||
|
||||
@@ -60,8 +55,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
val splashScreen = installSplashScreen()
|
||||
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
|
||||
|
||||
settingsViewModel.settings.loadSettings()
|
||||
|
||||
ThemeHelper.setTheme(this)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -86,9 +79,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
ThemeHelper.SYSTEM_BAR_ALPHA
|
||||
)
|
||||
)
|
||||
if (InsetsHelper.getSystemGestureType(applicationContext) !=
|
||||
InsetsHelper.GESTURE_NAVIGATION
|
||||
) {
|
||||
if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION) {
|
||||
binding.navigationBarShade.setBackgroundColor(
|
||||
ThemeHelper.getColorWithOpacity(
|
||||
MaterialColors.getColor(
|
||||
@@ -174,9 +165,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
binding.navigationView.height.toFloat() * 2
|
||||
translationY(0f)
|
||||
} else {
|
||||
if (ViewCompat.getLayoutDirection(binding.navigationView) ==
|
||||
ViewCompat.LAYOUT_DIRECTION_LTR
|
||||
) {
|
||||
if (ViewCompat.getLayoutDirection(binding.navigationView) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
||||
binding.navigationView.translationX =
|
||||
binding.navigationView.width.toFloat() * -2
|
||||
translationX(0f)
|
||||
@@ -193,9 +182,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
if (smallLayout) {
|
||||
translationY(binding.navigationView.height.toFloat() * 2)
|
||||
} else {
|
||||
if (ViewCompat.getLayoutDirection(binding.navigationView) ==
|
||||
ViewCompat.LAYOUT_DIRECTION_LTR
|
||||
) {
|
||||
if (ViewCompat.getLayoutDirection(binding.navigationView) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
||||
translationX(binding.navigationView.width.toFloat() * -2)
|
||||
} else {
|
||||
translationX(binding.navigationView.width.toFloat() * 2)
|
||||
@@ -240,9 +227,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val mlpStatusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
|
||||
mlpStatusShade.height = insets.top
|
||||
@@ -264,9 +249,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
|
||||
val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
contentResolver.takePersistableUriPermission(
|
||||
result,
|
||||
@@ -290,14 +274,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
|
||||
val getProdKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
if (!FileUtil.hasExtension(result, "keys")) {
|
||||
if (!FileUtil.hasExtension(result.toString(), "keys")) {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.reading_keys_failure,
|
||||
R.string.install_prod_keys_failure_extension_description
|
||||
R.string.install_keys_failure_extension_description
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
@@ -332,69 +315,15 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
val getFirmware =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val inputZip = contentResolver.openInputStream(result)
|
||||
if (inputZip == null) {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
getString(R.string.fatal_error),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
|
||||
|
||||
val firmwarePath =
|
||||
File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
|
||||
val cacheFirmwareDir = File("${cacheDir.path}/registered/")
|
||||
|
||||
val task: () -> Any = {
|
||||
var messageToShow: Any
|
||||
try {
|
||||
FileUtil.unzip(inputZip, cacheFirmwareDir)
|
||||
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
|
||||
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
|
||||
messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.firmware_installed_failure,
|
||||
R.string.firmware_installed_failure_description
|
||||
)
|
||||
} else {
|
||||
firmwarePath.deleteRecursively()
|
||||
cacheFirmwareDir.copyRecursively(firmwarePath, true)
|
||||
getString(R.string.save_file_imported_success)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
messageToShow = getString(R.string.fatal_error)
|
||||
} finally {
|
||||
cacheFirmwareDir.deleteRecursively()
|
||||
}
|
||||
messageToShow
|
||||
}
|
||||
|
||||
IndeterminateProgressDialogFragment.newInstance(
|
||||
this,
|
||||
R.string.firmware_installing,
|
||||
task
|
||||
).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
val getAmiiboKey =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
if (!FileUtil.hasExtension(result, "bin")) {
|
||||
if (!FileUtil.hasExtension(result.toString(), "bin")) {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.reading_keys_failure,
|
||||
R.string.install_amiibo_keys_failure_extension_description
|
||||
R.string.install_keys_failure_extension_description
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
@@ -430,9 +359,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
|
||||
val getDriver =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
if (result == null)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val takeFlags =
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
@@ -480,63 +408,4 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val installGameUpdate =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) {
|
||||
if (it == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
IndeterminateProgressDialogFragment.newInstance(
|
||||
this@MainActivity,
|
||||
R.string.install_game_content
|
||||
) {
|
||||
val result = NativeLibrary.installFileToNand(it.toString())
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
NativeLibrary.InstallFileToNandResult.Success -> {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.install_game_content_success,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
NativeLibrary.InstallFileToNandResult.SuccessFileOverwritten -> {
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
R.string.install_game_content_success_overwrite,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
NativeLibrary.InstallFileToNandResult.ErrorBaseGame -> {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.install_game_content_failure,
|
||||
R.string.install_game_content_failure_base
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
|
||||
NativeLibrary.InstallFileToNandResult.ErrorFilenameExtension -> {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.install_game_content_failure,
|
||||
R.string.install_game_content_failure_file_extension,
|
||||
R.string.install_game_content_help_link
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
|
||||
else -> {
|
||||
MessageDialogFragment.newInstance(
|
||||
R.string.install_game_content_failure,
|
||||
R.string.install_game_content_failure_description,
|
||||
R.string.install_game_content_help_link
|
||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return@newInstance result
|
||||
}.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ class ControllerMappingHelper {
|
||||
// The two analog triggers generate analog motion events as well as a keycode.
|
||||
// We always prefer to use the analog values, so throw away the button press
|
||||
keyCode == KeyEvent.KEYCODE_BUTTON_L2 || keyCode == KeyEvent.KEYCODE_BUTTON_R2
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else false
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.content.Context
|
||||
import java.io.IOException
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import java.io.IOException
|
||||
|
||||
object DirectoryInitialization {
|
||||
private var userPath: String? = null
|
||||
|
||||
@@ -5,10 +5,10 @@ package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.model.MinimalDocumentFile
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class DocumentsTree {
|
||||
private var root: DocumentsNode? = null
|
||||
@@ -29,20 +29,13 @@ class DocumentsTree {
|
||||
val node = resolvePath(filepath)
|
||||
return if (node == null || node.isDirectory) {
|
||||
0
|
||||
} else {
|
||||
FileUtil.getFileSize(YuzuApplication.appContext, node.uri.toString())
|
||||
}
|
||||
} else FileUtil.getFileSize(YuzuApplication.appContext, node.uri.toString())
|
||||
}
|
||||
|
||||
fun exists(filepath: String): Boolean {
|
||||
return resolvePath(filepath) != null
|
||||
}
|
||||
|
||||
fun isDirectory(filepath: String): Boolean {
|
||||
val node = resolvePath(filepath)
|
||||
return node != null && node.isDirectory
|
||||
}
|
||||
|
||||
private fun resolvePath(filepath: String): DocumentsNode? {
|
||||
val tokens = StringTokenizer(filepath, File.separator, false)
|
||||
var iterator = root
|
||||
@@ -113,9 +106,7 @@ class DocumentsTree {
|
||||
fun isNativePath(path: String): Boolean {
|
||||
return if (path.isNotEmpty()) {
|
||||
path[0] == '/'
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,14 @@ object EmulationMenuSettings {
|
||||
private val preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
// These must match what is defined in src/core/settings.h
|
||||
const val LayoutOption_Default = 0
|
||||
const val LayoutOption_SingleScreen = 1
|
||||
const val LayoutOption_LargeScreen = 2
|
||||
const val LayoutOption_SideScreen = 3
|
||||
const val LayoutOption_MobilePortrait = 4
|
||||
const val LayoutOption_MobileLandscape = 5
|
||||
|
||||
var joystickRelCenter: Boolean
|
||||
get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER, true)
|
||||
set(value) {
|
||||
@@ -33,6 +41,16 @@ object EmulationMenuSettings {
|
||||
.apply()
|
||||
}
|
||||
|
||||
var screenLayout: Int
|
||||
get() = preferences.getInt(
|
||||
Settings.PREF_MENU_SETTINGS_SCREEN_LAYOUT,
|
||||
LayoutOption_MobileLandscape
|
||||
)
|
||||
set(value) {
|
||||
preferences.edit()
|
||||
.putInt(Settings.PREF_MENU_SETTINGS_SCREEN_LAYOUT, value)
|
||||
.apply()
|
||||
}
|
||||
var showFps: Boolean
|
||||
get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_SHOW_FPS, false)
|
||||
set(value) {
|
||||
|
||||
@@ -7,18 +7,12 @@ import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.OpenableColumns
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import org.yuzu.yuzu_emu.model.MinimalDocumentFile
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.net.URLDecoder
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.model.MinimalDocumentFile
|
||||
|
||||
object FileUtil {
|
||||
const val PATH_TREE = "tree"
|
||||
@@ -282,34 +276,6 @@ object FileUtil {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the given zip file into the given directory.
|
||||
* @exception IOException if the file was being created outside of the target directory
|
||||
*/
|
||||
@Throws(SecurityException::class)
|
||||
fun unzip(zipStream: InputStream, destDir: File): Boolean {
|
||||
ZipInputStream(BufferedInputStream(zipStream)).use { zis ->
|
||||
var entry: ZipEntry? = zis.nextEntry
|
||||
while (entry != null) {
|
||||
val entryName = entry.name
|
||||
val entryFile = File(destDir, entryName)
|
||||
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) {
|
||||
throw SecurityException("Entry is outside of the target dir: " + entryFile.name)
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
entryFile.mkdirs()
|
||||
} else {
|
||||
entryFile.parentFile?.mkdirs()
|
||||
entryFile.createNewFile()
|
||||
entryFile.outputStream().use { fos -> zis.copyTo(fos) }
|
||||
}
|
||||
entry = zis.nextEntry
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun isRootTreeUri(uri: Uri): Boolean {
|
||||
val paths = uri.pathSegments
|
||||
return paths.size == 2 && PATH_TREE == paths[0]
|
||||
@@ -326,25 +292,7 @@ object FileUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun hasExtension(path: String, extension: String): Boolean =
|
||||
path.substring(path.lastIndexOf(".") + 1).contains(extension)
|
||||
|
||||
fun hasExtension(uri: Uri, extension: String): Boolean {
|
||||
val fileName: String?
|
||||
val cursor = YuzuApplication.appContext.contentResolver.query(uri, null, null, null, null)
|
||||
val nameIndex = cursor?.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||
cursor?.moveToFirst()
|
||||
|
||||
if (nameIndex == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
fileName = cursor.getString(nameIndex)
|
||||
cursor.close()
|
||||
|
||||
if (fileName == null) {
|
||||
return false
|
||||
}
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1).contains(extension)
|
||||
fun hasExtension(path: String, extension: String): Boolean {
|
||||
return path.substring(path.lastIndexOf(".") + 1).contains(extension)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class ForegroundService : Service() {
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (intent == null) {
|
||||
return START_NOT_STICKY
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
if (intent.action == ACTION_STOP) {
|
||||
NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION)
|
||||
|
||||
@@ -6,12 +6,13 @@ package org.yuzu.yuzu_emu.utils
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import androidx.preference.PreferenceManager
|
||||
import java.util.*
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import java.util.*
|
||||
|
||||
object GameHelper {
|
||||
const val KEY_GAME_PATH = "game_path"
|
||||
@@ -82,8 +83,7 @@ object GameHelper {
|
||||
NativeLibrary.getRegions(filePath),
|
||||
filePath,
|
||||
gameId,
|
||||
NativeLibrary.getCompany(filePath),
|
||||
NativeLibrary.isHomebrew(filePath)
|
||||
NativeLibrary.getCompany(filePath)
|
||||
)
|
||||
|
||||
val addedTime = preferences.getLong(newGame.keyAddedToLibraryTime, 0L)
|
||||
|
||||
@@ -5,14 +5,14 @@ package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.copyUriToInternalStorage
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.zip.ZipInputStream
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil.copyUriToInternalStorage
|
||||
|
||||
object GpuDriverHelper {
|
||||
private const val META_JSON_FILENAME = "meta.json"
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
class GpuDriverMetadata(metadataFilePath: String) {
|
||||
var name: String? = null
|
||||
|
||||
@@ -5,8 +5,8 @@ package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import kotlin.math.sqrt
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class InputHandler {
|
||||
fun initialize() {
|
||||
@@ -68,11 +68,7 @@ class InputHandler {
|
||||
6 -> NativeLibrary.Player6Device
|
||||
7 -> NativeLibrary.Player7Device
|
||||
8 -> NativeLibrary.Player8Device
|
||||
else -> if (NativeLibrary.isHandheldOnly()) {
|
||||
NativeLibrary.ConsoleDevice
|
||||
} else {
|
||||
NativeLibrary.Player1Device
|
||||
}
|
||||
else -> if (NativeLibrary.isHandheldOnly()) NativeLibrary.ConsoleDevice else NativeLibrary.Player1Device
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +107,7 @@ class InputHandler {
|
||||
}
|
||||
|
||||
private fun getAxisToButton(axis: Float): Int {
|
||||
return if (axis > 0.5f) {
|
||||
NativeLibrary.ButtonState.PRESSED
|
||||
} else {
|
||||
NativeLibrary.ButtonState.RELEASED
|
||||
}
|
||||
return if (axis > 0.5f) NativeLibrary.ButtonState.PRESSED else NativeLibrary.ButtonState.RELEASED
|
||||
}
|
||||
|
||||
private fun setAxisDpadState(playerNumber: Int, xAxis: Float, yAxis: Float) {
|
||||
@@ -295,6 +287,7 @@ class InputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setJoyconAxisInput(event: MotionEvent, axis: Int) {
|
||||
// Joycon support is half dead. Right joystick doesn't work
|
||||
val playerNumber = getPlayerNumber(event.device.controllerNumber)
|
||||
@@ -362,4 +355,6 @@ class InputHandler {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,7 +4,9 @@
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
|
||||
object InsetsHelper {
|
||||
const val THREE_BUTTON_NAVIGATION = 0
|
||||
@@ -18,8 +20,12 @@ object InsetsHelper {
|
||||
resources.getIdentifier("config_navBarInteractionMode", "integer", "android")
|
||||
return if (resourceId != 0) {
|
||||
resources.getInteger(resourceId)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else 0
|
||||
}
|
||||
|
||||
fun getBottomPaddingRequired(activity: Activity): Int {
|
||||
val visibleFrame = Rect()
|
||||
activity.window.decorView.getWindowVisibleDisplayFrame(visibleFrame)
|
||||
return visibleFrame.bottom - visibleFrame.top - activity.resources.displayMetrics.heightPixels
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import android.nfc.tech.NfcA
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import java.io.IOException
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import java.io.IOException
|
||||
|
||||
class NfcReader(private val activity: Activity) {
|
||||
private var nfcAdapter: NfcAdapter? = null
|
||||
@@ -25,13 +25,10 @@ class NfcReader(private val activity: Activity) {
|
||||
|
||||
pendingIntent = PendingIntent.getActivity(
|
||||
activity,
|
||||
0,
|
||||
Intent(activity, activity.javaClass),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
0, Intent(activity, activity.javaClass),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
else PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
|
||||
@@ -48,9 +45,9 @@ class NfcReader(private val activity: Activity) {
|
||||
|
||||
fun onNewIntent(intent: Intent) {
|
||||
val action = intent.action
|
||||
if (NfcAdapter.ACTION_TAG_DISCOVERED != action &&
|
||||
NfcAdapter.ACTION_TECH_DISCOVERED != action &&
|
||||
NfcAdapter.ACTION_NDEF_DISCOVERED != action
|
||||
if (NfcAdapter.ACTION_TAG_DISCOVERED != action
|
||||
&& NfcAdapter.ACTION_TECH_DISCOVERED != action
|
||||
&& NfcAdapter.ACTION_NDEF_DISCOVERED != action
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -87,7 +84,7 @@ class NfcReader(private val activity: Activity) {
|
||||
}
|
||||
|
||||
private fun ntag215ReadAll(amiibo: NfcA): ByteArray? {
|
||||
val bufferSize = amiibo.maxTransceiveLength
|
||||
val bufferSize = amiibo.maxTransceiveLength;
|
||||
val tagSize = 0x21C
|
||||
val pageSize = 4
|
||||
val lastPage = tagSize / pageSize - 1
|
||||
@@ -106,7 +103,7 @@ class NfcReader(private val activity: Activity) {
|
||||
val data = ntag215FastRead(amiibo, dataStart, dataEnd - 1)
|
||||
System.arraycopy(data, 0, tagData, i, (dataEnd - dataStart) * pageSize)
|
||||
} catch (e: IOException) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return tagData
|
||||
|
||||
@@ -11,34 +11,30 @@ import java.io.Serializable
|
||||
|
||||
object SerializableHelper {
|
||||
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
getSerializable(key, T::class.java)
|
||||
} else {
|
||||
else
|
||||
getSerializable(key) as? T
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Serializable> Intent.serializable(key: String): T? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
getSerializableExtra(key, T::class.java)
|
||||
} else {
|
||||
else
|
||||
getSerializableExtra(key) as? T
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Parcelable> Bundle.parcelable(key: String): T? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
getParcelable(key, T::class.java)
|
||||
} else {
|
||||
else
|
||||
getParcelable(key) as? T
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Parcelable> Intent.parcelable(key: String): T? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
getParcelableExtra(key, T::class.java)
|
||||
} else {
|
||||
else
|
||||
getParcelableExtra(key) as? T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,21 @@
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import kotlin.math.roundToInt
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.ui.main.ThemeProvider
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object ThemeHelper {
|
||||
const val SYSTEM_BAR_ALPHA = 0.9f
|
||||
@@ -34,8 +36,8 @@ object ThemeHelper {
|
||||
// Using a specific night mode check because this could apply incorrectly when using the
|
||||
// light app mode, dark system mode, and black backgrounds. Launching the settings activity
|
||||
// will then show light mode colors/navigation bars but with black backgrounds.
|
||||
if (preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false) &&
|
||||
isNightMode(activity)
|
||||
if (preferences.getBoolean(Settings.PREF_BLACK_BACKGROUNDS, false)
|
||||
&& isNightMode(activity)
|
||||
) {
|
||||
activity.setTheme(R.style.ThemeOverlay_Yuzu_Dark)
|
||||
}
|
||||
@@ -44,10 +46,8 @@ object ThemeHelper {
|
||||
@ColorInt
|
||||
fun getColorWithOpacity(@ColorInt color: Int, alphaFactor: Float): Int {
|
||||
return Color.argb(
|
||||
(alphaFactor * Color.alpha(color)).roundToInt(),
|
||||
Color.red(color),
|
||||
Color.green(color),
|
||||
Color.blue(color)
|
||||
(alphaFactor * Color.alpha(color)).roundToInt(), Color.red(color),
|
||||
Color.green(color), Color.blue(color)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.views
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Rational
|
||||
import android.view.SurfaceView
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class FixedRatioSurfaceView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : SurfaceView(context, attrs, defStyleAttr) {
|
||||
private var aspectRatio: Float = 0f // (width / height), 0f is a special value for stretch
|
||||
|
||||
/**
|
||||
* Sets the desired aspect ratio for this view
|
||||
* @param ratio the ratio to force the view to, or null to stretch to fit
|
||||
*/
|
||||
fun setAspectRatio(ratio: Rational?) {
|
||||
aspectRatio = ratio?.toFloat() ?: 0f
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
val width = MeasureSpec.getSize(widthMeasureSpec)
|
||||
val height = MeasureSpec.getSize(heightMeasureSpec)
|
||||
if (aspectRatio != 0f) {
|
||||
val newWidth: Int
|
||||
val newHeight: Int
|
||||
if (height * aspectRatio < width) {
|
||||
newWidth = (height * aspectRatio).roundToInt()
|
||||
newHeight = height
|
||||
} else {
|
||||
newWidth = width
|
||||
newHeight = (width / aspectRatio).roundToInt()
|
||||
}
|
||||
val left = (width - newWidth) / 2
|
||||
val top = (height - newHeight) / 2
|
||||
setLeftTopRightBottom(left, top, left + newWidth, top + newHeight)
|
||||
} else {
|
||||
setLeftTopRightBottom(0, 0, width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,13 +235,9 @@ void Config::ReadValues() {
|
||||
Settings::values.async_presentation =
|
||||
config->GetBoolean("Renderer", "async_presentation", true);
|
||||
|
||||
// Disable force_max_clock by default on Android
|
||||
// Enable force_max_clock by default on Android
|
||||
Settings::values.renderer_force_max_clock =
|
||||
config->GetBoolean("Renderer", "force_max_clock", false);
|
||||
|
||||
// Disable use_reactive_flushing by default on Android
|
||||
Settings::values.use_reactive_flushing =
|
||||
config->GetBoolean("Renderer", "use_reactive_flushing", false);
|
||||
config->GetBoolean("Renderer", "force_max_clock", true);
|
||||
|
||||
// Audio
|
||||
ReadSetting("Audio", Settings::values.sink_id);
|
||||
|
||||
@@ -251,7 +251,7 @@ backend =
|
||||
# 0: Off, 1 (default): On
|
||||
async_presentation =
|
||||
|
||||
# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied).
|
||||
# Enable graphics API debugging mode.
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
force_max_clock =
|
||||
|
||||
@@ -328,10 +328,6 @@ shader_backend =
|
||||
# 0 (default): Off, 1: On
|
||||
use_asynchronous_shaders =
|
||||
|
||||
# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.
|
||||
# 0 (default): Off, 1: On
|
||||
use_reactive_flushing =
|
||||
|
||||
# NVDEC emulation.
|
||||
# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding
|
||||
nvdec_emulation =
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include <core/loader/nro.h>
|
||||
|
||||
#include "common/detached_tasks.h"
|
||||
#include "common/dynamic_library.h"
|
||||
@@ -28,10 +27,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/submission_package.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
#include "core/frontend/applets/cabinet.h"
|
||||
#include "core/frontend/applets/controller.h"
|
||||
@@ -97,72 +93,12 @@ public:
|
||||
m_native_window = native_window;
|
||||
}
|
||||
|
||||
int InstallFileToNand(std::string filename) {
|
||||
const auto copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
|
||||
std::size_t block_size) {
|
||||
if (src == nullptr || dest == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!dest->Resize(src->GetSize())) {
|
||||
return false;
|
||||
}
|
||||
u32 ScreenRotation() const {
|
||||
return m_screen_rotation;
|
||||
}
|
||||
|
||||
using namespace Common::Literals;
|
||||
std::vector<u8> buffer(1_MiB);
|
||||
|
||||
for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
|
||||
const auto read = src->Read(buffer.data(), buffer.size(), i);
|
||||
dest->Write(buffer.data(), read, i);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
enum InstallResult {
|
||||
Success = 0,
|
||||
SuccessFileOverwritten = 1,
|
||||
InstallError = 2,
|
||||
ErrorBaseGame = 3,
|
||||
ErrorFilenameExtension = 4,
|
||||
};
|
||||
|
||||
m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||
m_system.GetFileSystemController().CreateFactories(*m_vfs);
|
||||
|
||||
std::shared_ptr<FileSys::NSP> nsp;
|
||||
if (filename.ends_with("nsp")) {
|
||||
nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
|
||||
if (nsp->IsExtractedType()) {
|
||||
return InstallError;
|
||||
}
|
||||
} else if (filename.ends_with("xci")) {
|
||||
const auto xci =
|
||||
std::make_shared<FileSys::XCI>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
|
||||
nsp = xci->GetSecurePartitionNSP();
|
||||
} else {
|
||||
return ErrorFilenameExtension;
|
||||
}
|
||||
|
||||
if (!nsp) {
|
||||
return InstallError;
|
||||
}
|
||||
|
||||
if (nsp->GetStatus() != Loader::ResultStatus::Success) {
|
||||
return InstallError;
|
||||
}
|
||||
|
||||
const auto res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(
|
||||
*nsp, true, copy_func);
|
||||
|
||||
switch (res) {
|
||||
case FileSys::InstallResult::Success:
|
||||
return Success;
|
||||
case FileSys::InstallResult::OverwriteExisting:
|
||||
return SuccessFileOverwritten;
|
||||
case FileSys::InstallResult::ErrorBaseInstall:
|
||||
return ErrorBaseGame;
|
||||
default:
|
||||
return InstallError;
|
||||
}
|
||||
void SetScreenRotation(u32 screen_rotation) {
|
||||
m_screen_rotation = screen_rotation;
|
||||
}
|
||||
|
||||
void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
|
||||
@@ -202,11 +138,6 @@ public:
|
||||
return m_is_running;
|
||||
}
|
||||
|
||||
bool IsPaused() const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_is_running && m_is_paused;
|
||||
}
|
||||
|
||||
const Core::PerfStatsResults& PerfStats() const {
|
||||
std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
|
||||
return m_perf_stats;
|
||||
@@ -230,14 +161,14 @@ public:
|
||||
m_window = std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window,
|
||||
m_vulkan_library);
|
||||
|
||||
m_system.SetFilesystem(m_vfs);
|
||||
|
||||
// Initialize system.
|
||||
auto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
|
||||
m_software_keyboard = android_keyboard.get();
|
||||
m_system.SetShuttingDown(false);
|
||||
m_system.ApplySettings();
|
||||
m_system.HIDCore().ReloadInputDevices();
|
||||
m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||
m_system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
|
||||
m_system.SetAppletFrontendSet({
|
||||
nullptr, // Amiibo Settings
|
||||
nullptr, // Controller Selector
|
||||
@@ -249,8 +180,7 @@ public:
|
||||
std::move(android_keyboard), // Software Keyboard
|
||||
nullptr, // Web Browser
|
||||
});
|
||||
m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||
m_system.GetFileSystemController().CreateFactories(*m_vfs);
|
||||
m_system.GetFileSystemController().CreateFactories(*m_system.GetFilesystem());
|
||||
|
||||
// Initialize account manager
|
||||
m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
|
||||
@@ -292,13 +222,11 @@ public:
|
||||
void PauseEmulation() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_system.Pause();
|
||||
m_is_paused = true;
|
||||
}
|
||||
|
||||
void UnPauseEmulation() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_system.Run();
|
||||
m_is_paused = false;
|
||||
}
|
||||
|
||||
void HaltEmulation() {
|
||||
@@ -353,10 +281,6 @@ public:
|
||||
return GetRomMetadata(path).icon;
|
||||
}
|
||||
|
||||
bool GetIsHomebrew(const std::string& path) {
|
||||
return GetRomMetadata(path).isHomebrew;
|
||||
}
|
||||
|
||||
void ResetRomMetadata() {
|
||||
m_rom_metadata_cache.clear();
|
||||
}
|
||||
@@ -424,7 +348,6 @@ private:
|
||||
struct RomMetadata {
|
||||
std::string title;
|
||||
std::vector<u8> icon;
|
||||
bool isHomebrew;
|
||||
};
|
||||
|
||||
RomMetadata GetRomMetadata(const std::string& path) {
|
||||
@@ -437,17 +360,11 @@ private:
|
||||
|
||||
RomMetadata CacheRomMetadata(const std::string& path) {
|
||||
const auto file = Core::GetGameFileFromPath(m_vfs, path);
|
||||
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
|
||||
const auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
|
||||
|
||||
RomMetadata entry;
|
||||
loader->ReadTitle(entry.title);
|
||||
loader->ReadIcon(entry.icon);
|
||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||
auto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||
} else {
|
||||
entry.isHomebrew = false;
|
||||
}
|
||||
|
||||
m_rom_metadata_cache[path] = entry;
|
||||
|
||||
@@ -471,16 +388,16 @@ private:
|
||||
// Window management
|
||||
std::unique_ptr<EmuWindow_Android> m_window;
|
||||
ANativeWindow* m_native_window{};
|
||||
u32 m_screen_rotation{};
|
||||
|
||||
// Core emulation
|
||||
Core::System m_system;
|
||||
InputCommon::InputSubsystem m_input_subsystem;
|
||||
Common::DetachedTasks m_detached_tasks;
|
||||
Core::PerfStatsResults m_perf_stats{};
|
||||
std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
|
||||
std::shared_ptr<FileSys::RealVfsFilesystem> m_vfs;
|
||||
Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized};
|
||||
bool m_is_running{};
|
||||
bool m_is_paused{};
|
||||
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
|
||||
std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
|
||||
|
||||
@@ -497,6 +414,10 @@ private:
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
u32 GetAndroidScreenRotation() {
|
||||
return EmulationSession::GetInstance().ScreenRotation();
|
||||
}
|
||||
|
||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
|
||||
Common::Log::Initialize();
|
||||
Common::Log::SetColorConsoleBackendEnabled(true);
|
||||
@@ -540,18 +461,19 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env,
|
||||
EmulationSession::GetInstance().SurfaceChanged();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_notifyOrientationChange(JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
jint layout_option,
|
||||
jint rotation) {
|
||||
return EmulationSession::GetInstance().SetScreenRotation(static_cast<u32>(rotation));
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
jstring j_directory) {
|
||||
Common::FS::SetAppDirectory(GetJString(env, j_directory));
|
||||
}
|
||||
|
||||
int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
jstring j_file) {
|
||||
return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file));
|
||||
}
|
||||
|
||||
void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(
|
||||
JNIEnv* env, [[maybe_unused]] jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir,
|
||||
jstring custom_driver_name, jstring file_redirect_dir) {
|
||||
@@ -591,11 +513,6 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning([[maybe_unused]] JNIEnv
|
||||
return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isPaused([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz) {
|
||||
return static_cast<jboolean>(EmulationSession::GetInstance().IsPaused());
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHandheldOnly([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz) {
|
||||
return EmulationSession::GetInstance().IsHandheldOnly();
|
||||
@@ -745,12 +662,6 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany([[maybe_unused]] JNIEnv
|
||||
return env->NewStringUTF("");
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHomebrew([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
[[maybe_unused]] jstring j_filename) {
|
||||
return EmulationSession::GetInstance().GetIsHomebrew(GetJString(env, j_filename));
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation
|
||||
[[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) {
|
||||
// Create the default config.ini.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,840Q127,840 103.5,816.5Q80,793 80,760L80,200Q80,167 103.5,143.5Q127,120 160,120L720,120Q753,120 776.5,143.5Q800,167 800,200L800,280L840,280Q857,280 868.5,291.5Q880,303 880,320Q880,337 868.5,348.5Q857,360 840,360L800,360L800,440L840,440Q857,440 868.5,451.5Q880,463 880,480Q880,497 868.5,508.5Q857,520 840,520L800,520L800,600L840,600Q857,600 868.5,611.5Q880,623 880,640Q880,657 868.5,668.5Q857,680 840,680L800,680L800,760Q800,793 776.5,816.5Q753,840 720,840L160,840ZM160,760L720,760Q720,760 720,760Q720,760 720,760L720,200Q720,200 720,200Q720,200 720,200L160,200Q160,200 160,200Q160,200 160,200L160,760Q160,760 160,760Q160,760 160,760ZM280,680L400,680Q417,680 428.5,668.5Q440,657 440,640L440,560Q440,543 428.5,531.5Q417,520 400,520L280,520Q263,520 251.5,531.5Q240,543 240,560L240,640Q240,657 251.5,668.5Q263,680 280,680ZM520,400L600,400Q617,400 628.5,388.5Q640,377 640,360L640,320Q640,303 628.5,291.5Q617,280 600,280L520,280Q503,280 491.5,291.5Q480,303 480,320L480,360Q480,377 491.5,388.5Q503,400 520,400ZM280,480L400,480Q417,480 428.5,468.5Q440,457 440,440L440,320Q440,303 428.5,291.5Q417,280 400,280L280,280Q263,280 251.5,291.5Q240,303 240,320L240,440Q240,457 251.5,468.5Q263,480 280,480ZM520,680L600,680Q617,680 628.5,668.5Q640,657 640,640L640,480Q640,463 628.5,451.5Q617,440 600,440L520,440Q503,440 491.5,451.5Q480,463 480,480L480,640Q480,657 491.5,668.5Q503,680 520,680ZM160,200L160,200Q160,200 160,200Q160,200 160,200L160,760Q160,760 160,760Q160,760 160,760L160,760Q160,760 160,760Q160,760 160,760L160,200Q160,200 160,200Q160,200 160,200Z"/>
|
||||
</vector>
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M360,720L600,720Q617,720 628.5,708.5Q640,697 640,680Q640,663 628.5,651.5Q617,640 600,640L360,640Q343,640 331.5,651.5Q320,663 320,680Q320,697 331.5,708.5Q343,720 360,720ZM360,560L600,560Q617,560 628.5,548.5Q640,537 640,520Q640,503 628.5,491.5Q617,480 600,480L360,480Q343,480 331.5,491.5Q320,503 320,520Q320,537 331.5,548.5Q343,560 360,560ZM240,880Q207,880 183.5,856.5Q160,833 160,800L160,160Q160,127 183.5,103.5Q207,80 240,80L527,80Q543,80 557.5,86Q572,92 583,103L777,297Q788,308 794,322.5Q800,337 800,353L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM520,320L520,160L240,160Q240,160 240,160Q240,160 240,160L240,800Q240,800 240,800Q240,800 240,800L720,800Q720,800 720,800Q720,800 720,800L720,360L560,360Q543,360 531.5,348.5Q520,337 520,320ZM240,160L240,160L240,320Q240,337 240,348.5Q240,360 240,360L240,360L240,160L240,320Q240,337 240,348.5Q240,360 240,360L240,360L240,800Q240,800 240,800Q240,800 240,800L240,800Q240,800 240,800Q240,800 240,800L240,160Q240,160 240,160Q240,160 240,160Z"/>
|
||||
</vector>
|
||||
@@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z" />
|
||||
</vector>
|
||||
@@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M8,5v14l11,-7z" />
|
||||
</vector>
|
||||
@@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M140,800q-24,0 -42,-18t-18,-42v-520q0,-24 18,-42t42,-18h250v60L140,220v520h680v-520L570,220v-60h250q24,0 42,18t18,42v520q0,24 -18,42t-42,18L140,800ZM480,615L280,415l43,-43 127,127v-339h60v339l127,-127 43,43 -200,200Z"/>
|
||||
</vector>
|
||||
@@ -1,9 +1,13 @@
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/fragment_container"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:id="@+id/frame_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true"
|
||||
app:defaultNavHost="true" />
|
||||
android:keepScreenOn="true">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/frame_emulation_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginHorizontal="16dp">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.HeadlineLarge"
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
tools:text="@string/license_adreno_tools" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:id="@+id/text_link"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp"
|
||||
android:autoLink="all"
|
||||
tools:text="@string/license_adreno_tools_link" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:id="@+id/text_copyright"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textStyle="bold"
|
||||
tools:text="@string/license_adreno_tools_copyright" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:id="@+id/text_license"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:autoLink="all"
|
||||
tools:text="@string/license_adreno_tools_text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -109,39 +109,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/licenses" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/licenses_description" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -12,65 +12,48 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/emulation_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- This is what everything is rendered to during emulation -->
|
||||
<org.yuzu.yuzu_emu.views.FixedRatioSurfaceView
|
||||
android:id="@+id/surface_emulation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/input_container"
|
||||
<!-- This is what everything is rendered to during emulation -->
|
||||
<SurfaceView
|
||||
android:id="@+id/surface_emulation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="bottom">
|
||||
|
||||
<!-- This is the onscreen input overlay -->
|
||||
<org.yuzu.yuzu_emu.overlay.InputOverlay
|
||||
android:id="@+id/surface_input_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true" />
|
||||
|
||||
<Button
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:id="@+id/done_control_config"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/emulation_done"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/overlay_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="bottom">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/show_fps_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:shadowColor="@android:color/black"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
<!-- This is the onscreen input overlay -->
|
||||
<org.yuzu.yuzu_emu.overlay.InputOverlay
|
||||
android:id="@+id/surface_input_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/show_fps_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:shadowColor="@android:color/black"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
<Button
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:id="@+id/done_control_config"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/emulation_done"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/coordinator_licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/licenses"
|
||||
app:navigationIcon="@drawable/ic_back" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list_licenses"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -6,6 +6,26 @@
|
||||
android:title="@string/emulation_fps_counter"
|
||||
android:checkable="true" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_screen_layout"
|
||||
android:title="@string/emulation_screen_rotation">
|
||||
<menu>
|
||||
<group
|
||||
android:id="@+id/menu_screen_layout_group"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/menu_screen_layout_landscape"
|
||||
android:title="@string/emulation_screen_rotation_landscape"/>
|
||||
<item
|
||||
android:id="@+id/menu_screen_layout_portrait"
|
||||
android:title="@string/emulation_screen_rotation_portrait"/>
|
||||
<item
|
||||
android:id="@+id/menu_screen_layout_auto"
|
||||
android:title="@string/emulation_screen_rotation_auto"/>
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_edit_overlay"
|
||||
android:title="@string/emulation_touch_overlay_edit" />
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/emulation_navigation"
|
||||
app:startDestination="@id/emulationFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/emulationFragment"
|
||||
android:name="org.yuzu.yuzu_emu.fragments.EmulationFragment"
|
||||
android:label="fragment_emulation"
|
||||
tools:layout="@layout/fragment_emulation" >
|
||||
<argument
|
||||
android:name="game"
|
||||
app:argType="org.yuzu.yuzu_emu.model.Game" />
|
||||
</fragment>
|
||||
|
||||
</navigation>
|
||||
@@ -40,34 +40,11 @@
|
||||
<fragment
|
||||
android:id="@+id/aboutFragment"
|
||||
android:name="org.yuzu.yuzu_emu.fragments.AboutFragment"
|
||||
android:label="AboutFragment" >
|
||||
<action
|
||||
android:id="@+id/action_aboutFragment_to_licensesFragment"
|
||||
app:destination="@id/licensesFragment" />
|
||||
</fragment>
|
||||
android:label="AboutFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/earlyAccessFragment"
|
||||
android:name="org.yuzu.yuzu_emu.fragments.EarlyAccessFragment"
|
||||
android:label="EarlyAccessFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/licensesFragment"
|
||||
android:name="org.yuzu.yuzu_emu.fragments.LicensesFragment"
|
||||
android:label="LicensesFragment" />
|
||||
|
||||
<activity
|
||||
android:id="@+id/emulationActivity"
|
||||
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
|
||||
android:label="EmulationActivity">
|
||||
<argument
|
||||
android:name="game"
|
||||
app:argType="org.yuzu.yuzu_emu.model.Game" />
|
||||
</activity>
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_emulationActivity"
|
||||
app:destination="@id/emulationActivity"
|
||||
app:launchSingleTop="true" />
|
||||
|
||||
</navigation>
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">Diese Software kann Spiele für die Nintendo Switch abspielen. Keine Spiele oder Spielekeys sind enthalten.<br /><br />Bevor du beginnst, bitte halte deine <![CDATA[<b> prod.keys </b>]]> auf deinem Gerät bereit. .<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Mehr Infos</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">Emulation ist aktiv</string>
|
||||
<string name="emulation_notification_channel_description">Zeigt eine dauerhafte Benachrichtigung an, wenn die Emulation läuft.</string>
|
||||
<string name="emulation_notification_running">yuzu läuft</string>
|
||||
<string name="notice_notification_channel_name">Hinweise und Fehler</string>
|
||||
<string name="notice_notification_channel_description">Zeigt Benachrichtigungen an, wenn etwas schief läuft.</string>
|
||||
<string name="notification_permission_not_granted">Berechtigung für Benachrichtigungen nicht erlaubt!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">Willkommen!</string>
|
||||
<string name="welcome_description">Erfahre wie man <b>yuzu</b> einrichtet und beginne mit der Emulation.</string>
|
||||
<string name="get_started">Erste Schritte</string>
|
||||
<string name="keys">Schlüssel</string>
|
||||
<string name="keys_description">Wähle deine <b>prod.keys</b> Datei mit dem Button unten aus.</string>
|
||||
<string name="select_keys">Schlüssel auswählen</string>
|
||||
<string name="games">Spiele</string>
|
||||
<string name="games_description">Wähle mit dem Knopf unten den <b>Spiele</b>-Ordner aus.</string>
|
||||
<string name="done">Fertig</string>
|
||||
<string name="done_description">Wir können loslegen.\nViel Spaß!</string>
|
||||
<string name="text_continue">Fortsetzen</string>
|
||||
<string name="next">Weiter</string>
|
||||
<string name="back">Zurück</string>
|
||||
<string name="add_games">Spiele hinzufügen</string>
|
||||
<string name="add_games_description">Spieleverzeichnis auswählen</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">Spiele</string>
|
||||
<string name="home_search">Suche</string>
|
||||
<string name="home_settings">Einstellungen</string>
|
||||
<string name="empty_gamelist">Es wurden keine Dateien gefunden oder es wurde noch kein Spielverzeichnis ausgewählt.</string>
|
||||
<string name="search_and_filter_games">Spiele suchen und filtern</string>
|
||||
<string name="select_games_folder">Spieleverzeichnis auswählen</string>
|
||||
<string name="select_games_folder_description">Erlaubt yuzu die Spieleliste zu füllen</string>
|
||||
<string name="add_games_warning">Auswahl des Spieleverzeichnisses überspringen?</string>
|
||||
<string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">Spiele suchen</string>
|
||||
<string name="games_dir_selected">Spieleverzeichnis ausgewählt</string>
|
||||
<string name="install_prod_keys">prod.keys installieren</string>
|
||||
<string name="install_prod_keys_description">Zum Entschlüsseln von Spielen benötigt</string>
|
||||
<string name="install_prod_keys_warning">Hinzufügen der Schlüssel überspringen?</string>
|
||||
<string name="install_prod_keys_warning_description">Für die Emulation von Spielen sind gültige Schlüssel erforderlich. Wenn du fortfährst, funktionieren nur Homebrew-Anwendungen.</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">Benachrichtigungen</string>
|
||||
<string name="notifications_description">Erteile mit dem Knopf unten die Berechtigung, Benachrichtigungen zu senden.</string>
|
||||
<string name="give_permission">Berechtigung erteilen</string>
|
||||
<string name="notification_warning_description">yuzu wird dich nicht über wichtige Informationen benachrichtigen können.</string>
|
||||
<string name="permission_denied">Zugriff verweigert</string>
|
||||
<string name="permission_denied_description">Du hast diese Berechtigung zu oft verweigert und musst sie nun manuell in den Systemeinstellungen erteilen.</string>
|
||||
<string name="about">Über</string>
|
||||
<string name="about_description">Build-Version, Credits und mehr</string>
|
||||
<string name="warning_help">Hilfe</string>
|
||||
<string name="warning_skip">Überspringen</string>
|
||||
<string name="warning_cancel">Abbrechen</string>
|
||||
<string name="install_amiibo_keys">Amiibo-Schlüssel installieren</string>
|
||||
<string name="install_amiibo_keys_description">Benötigt um Amiibos im Spiel zu verwenden</string>
|
||||
<string name="invalid_keys_file">Ungültige Schlüsseldatei ausgewählt</string>
|
||||
<string name="install_keys_success">Schlüssel erfolgreich installiert</string>
|
||||
<string name="reading_keys_failure">Fehler beim Lesen der Schlüssel</string>
|
||||
<string name="invalid_keys_error">Ungültige Schlüssel</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_gpu_driver">GPU-Treiber installieren</string>
|
||||
<string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
|
||||
<string name="advanced_settings">Erweiterte Einstellungen</string>
|
||||
<string name="settings_description">Emulatoreinstellungen konfigurieren</string>
|
||||
<string name="search_recently_played">Kürzlich gespielt</string>
|
||||
<string name="search_recently_added">Kürzlich hinzugefügt</string>
|
||||
<string name="search_retail">Spiele</string>
|
||||
<string name="search_homebrew">Homebrew</string>
|
||||
<string name="open_user_folder">yuzu-Ordner öffnen</string>
|
||||
<string name="open_user_folder_description">yuzu\'s interne Dateien verwalten</string>
|
||||
<string name="theme_and_color_description">Das Aussehen der App ändern</string>
|
||||
<string name="no_file_manager">Kein Dateimanager gefunden</string>
|
||||
<string name="notification_no_directory_link">yuzu-Verzeichnis konnte nicht geöffnet werden</string>
|
||||
<string name="notification_no_directory_link_description">Bitte suche den Benutzerordner manuell über die Seitenleiste des Dateimanagers.</string>
|
||||
<string name="manage_save_data">Speicherdaten verwalten</string>
|
||||
<string name="manage_save_data_description">Speicherdaten gefunden. Bitte wähle unten eine Option aus.</string>
|
||||
<string name="import_export_saves_description">Speicherdaten importieren oder exportieren</string>
|
||||
<string name="import_export_saves_no_profile">Keine Speicherdaten gefunden. Bitte starte ein Spiel und versuche es erneut.</string>
|
||||
<string name="save_file_imported_success">Erfolgreich importiert</string>
|
||||
<string name="save_file_invalid_zip_structure">Ungültige Speicherverzeichnisstruktur</string>
|
||||
<string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string>
|
||||
<string name="import_saves">Importieren</string>
|
||||
<string name="export_saves">Exportieren</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia ist nicht real</string>
|
||||
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
|
||||
<string name="about_app_description">Ein quelloffener Switch-Emulator</string>
|
||||
<string name="contributors">Beitragende</string>
|
||||
<string name="contributors_description">Gemacht mit \u2764 vom yuzu Team</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">Build</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
<string name="get_early_access">Early Access bekommen</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">Neueste Features, frühzeitiger Zugriff auf Updates und mehr</string>
|
||||
<string name="early_access_benefits">Early Access Vorteile</string>
|
||||
<string name="cutting_edge_features">Neueste Features</string>
|
||||
<string name="early_access_updates">Früherer Zugriff auf Updates</string>
|
||||
<string name="no_manual_installation">Keine manuelle Installation</string>
|
||||
<string name="prioritized_support">Priorisierte Unterstützung</string>
|
||||
<string name="our_eternal_gratitude">Unsere ewige Dankbarkeit</string>
|
||||
<string name="are_you_interested">Bist du interessiert?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">Geschwindigkeitsbegrenzung aktivieren</string>
|
||||
<string name="frame_limit_enable_description">Wenn aktiviert, wird die Emulationsgeschwindigkeit auf einen Prozentsatz der normalen Geschwindigkeit begrenzt.</string>
|
||||
<string name="frame_limit_slider">Geschwindkeitsbegrenzung in Prozent</string>
|
||||
<string name="frame_limit_slider_description">Legt den Prozentsatz der Bergrenzung der Emulationsgeschwindigkeit fest. Mit dem Standardwert von 100% wird die Emulation auf die normale Geschwindigkeit begrenzt. Höhere oder niedrigere Werte erhöhen oder verringern die Geschwindigkeitsbegrenzung.</string>
|
||||
<string name="cpu_accuracy">CPU-Genauigkeit</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">Dock-Modus</string>
|
||||
<string name="use_docked_mode_description">Emuliert im Dock-Modus, was die Auflösung verbessert, aber die Leistung senkt.</string>
|
||||
<string name="emulated_region">Emulierte Region</string>
|
||||
<string name="emulated_language">Emulierte Sprache</string>
|
||||
<string name="select_rtc_date">RTC-Datum auswählen</string>
|
||||
<string name="select_rtc_time">RTC-Zeit auswählen</string>
|
||||
<string name="use_custom_rtc">Benutzerdefinierte RTC aktivieren</string>
|
||||
<string name="use_custom_rtc_description">Mit dieser Einstellung kann eine benutzerdefinierte Echtzeituhr unabhängig von der aktuellen Systemzeit verwendet werden.</string>
|
||||
<string name="set_custom_rtc">Benutzerdefinierte RTC einstellen</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">Genauigkeitsstufe</string>
|
||||
<string name="renderer_resolution">Auflösung</string>
|
||||
<string name="renderer_vsync">VSync-Modus</string>
|
||||
<string name="renderer_aspect_ratio">Seitenverhältnis</string>
|
||||
<string name="renderer_scaling_filter">Fensteranpassungsfilter</string>
|
||||
<string name="renderer_anti_aliasing">Kantenglättungs-Methode</string>
|
||||
<string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string>
|
||||
<string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</string>
|
||||
<string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Kompiliert Shader asynchron, was Ruckler reduziert, aber zu Glitches führen kann.</string>
|
||||
<string name="renderer_debug">Grafik-Debugging aktivieren</string>
|
||||
<string name="renderer_debug_description">Wenn aktiviert, schaltet die Grafik-API in einen langsameren Debugging-Modus.</string>
|
||||
<string name="use_disk_shader_cache">Nutze Festplatten-Shader-Cache</string>
|
||||
<string name="use_disk_shader_cache_description">Ruckeln wird durch das Speichern und Laden von generierten Shadern auf der Festplatte reduziert.</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">Lautstärke</string>
|
||||
<string name="audio_volume_description">Legt die Lautstärke der Audioausgabe fest.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">Standard</string>
|
||||
<string name="ini_saved">Einstellungen gespeichert</string>
|
||||
<string name="gameid_saved">Einstellungen für %1$s gespeichert</string>
|
||||
<string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string>
|
||||
<string name="loading">Lädt...</string>
|
||||
<string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string>
|
||||
<string name="reset_to_default">Auf Standard zurücksetzen</string>
|
||||
<string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string>
|
||||
<string name="reset_all_settings_description">Alle erweiterten Einstellungen werden auf ihren Standardwert zurückgesetzt. Dies kann nicht rückgängig gemacht werden.</string>
|
||||
<string name="settings_reset">Einstellungen zurückgesetzt</string>
|
||||
<string name="close">Schließen</string>
|
||||
<string name="learn_more">Mehr erfahren</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">GPU-Treiber auswählen</string>
|
||||
<string name="select_gpu_driver_title">Möchtest du deinen aktuellen GPU-Treiber ersetzen?</string>
|
||||
<string name="select_gpu_driver_install">Installieren</string>
|
||||
<string name="select_gpu_driver_default">Standard</string>
|
||||
<string name="select_gpu_driver_install_success">%s wurde installiert</string>
|
||||
<string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string>
|
||||
<string name="select_gpu_driver_error">Ungültiger Treiber ausgewählt, Standard-Treiber wird verwendet!</string>
|
||||
<string name="system_gpu_driver">System GPU-Treiber</string>
|
||||
<string name="installing_driver">Treiber wird installiert...</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">Einstellungen</string>
|
||||
<string name="preferences_general">Allgemein</string>
|
||||
<string name="preferences_system">System</string>
|
||||
<string name="preferences_graphics">Grafik</string>
|
||||
<string name="preferences_audio">Audio</string>
|
||||
<string name="preferences_theme">Theme und Farbe</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">Das ROM ist verschlüsselt</string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Bitte stelle sicher dass die <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> Datei installiert ist, damit Spiele entschlüsselt werden können.]]></string>
|
||||
<string name="loader_error_video_core">Bei der Initialisierung des Videokerns ist ein Fehler aufgetreten</string>
|
||||
<string name="loader_error_video_core_description">Dies wird normalerweise durch einen inkompatiblen GPU-Treiber verursacht. Die Installation eines passenden GPU-Treibers kann dieses Problem beheben.</string>
|
||||
<string name="loader_error_invalid_format">ROM konnte nicht geladen werden</string>
|
||||
<string name="loader_error_file_not_found">ROM-Datei existiert nicht</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">Emulation beenden</string>
|
||||
<string name="emulation_done">Fertig</string>
|
||||
<string name="emulation_fps_counter">FPS Zähler</string>
|
||||
<string name="emulation_toggle_controls">Steuerung umschalten</string>
|
||||
<string name="emulation_rel_stick_center">Relative Stick-Mitte</string>
|
||||
<string name="emulation_dpad_slide">DPad Slide</string>
|
||||
<string name="emulation_haptics">Haptik</string>
|
||||
<string name="emulation_show_overlay">Overlay anzeigen</string>
|
||||
<string name="emulation_toggle_all">Alle umschalten</string>
|
||||
<string name="emulation_control_adjust">Overlay anpassen</string>
|
||||
<string name="emulation_control_scale">Größe</string>
|
||||
<string name="emulation_control_opacity">Transparenz</string>
|
||||
<string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string>
|
||||
<string name="emulation_touch_overlay_edit">Overlay bearbeiten</string>
|
||||
<string name="emulation_pause">Emulation pausieren</string>
|
||||
<string name="emulation_unpause">Emulation fortsetzen</string>
|
||||
<string name="emulation_input_overlay">Overlay-Optionen</string>
|
||||
<string name="emulation_game_loading">Spiel lädt…</string>
|
||||
|
||||
<string name="load_settings">Lädt Einstellungen...</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">Software-Tastatur</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">Abbrechen</string>
|
||||
<string name="continue_button">Fortsetzen</string>
|
||||
<string name="system_archive_not_found">Systemarchiv nicht gefunden</string>
|
||||
<string name="system_archive_general">Ein System-Archiv</string>
|
||||
<string name="save_load_error">Speicher-/Ladefehler</string>
|
||||
<string name="fatal_error">Schwerwiegender Fehler</string>
|
||||
<string name="fatal_error_message">Ein schwerwiegender Fehler ist aufgetreten. Einzelheiten wurden im Log protokolliert.\nDas Fortsetzen der Emulation kann zu Abstürzen und Bugs führen.</string>
|
||||
<string name="performance_warning">Das Deaktivieren dieser Einstellung führt zu erheblichen Leistungsverlusten! Für ein optimales Erlebnis wird empfohlen, sie aktiviert zu lassen.</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">Japan</string>
|
||||
<string name="region_usa">USA</string>
|
||||
<string name="region_europe">Europa</string>
|
||||
<string name="region_australia">Australien</string>
|
||||
<string name="region_china">China</string>
|
||||
<string name="region_korea">Korea</string>
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japanisch (日本語)</string>
|
||||
<string name="language_english">Englisch</string>
|
||||
<string name="language_french">Französisch (Français)</string>
|
||||
<string name="langauge_german">Deutsch (German)</string>
|
||||
<string name="language_italian">Italienisch (Italiano)</string>
|
||||
<string name="language_spanish">Spanisch (Español)</string>
|
||||
<string name="language_chinese">Chinesisch (简体中文)</string>
|
||||
<string name="language_korean">Koreanisch (한국어)</string>
|
||||
<string name="language_dutch">Niederländisch (Nederlands)</string>
|
||||
<string name="language_portuguese">Portugiesisch (Português)</string>
|
||||
<string name="language_russian">Russisch (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanesisch (台湾)</string>
|
||||
<string name="language_british_english">Britisches Englisch</string>
|
||||
<string name="language_canadian_french">Kanadisches Französisch (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Lateinamerikanisches Spanisch (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Vereinfachtes Chinesisch (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Traditionelles Chinesisch (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Brasilianisches Portugiesisch (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">Keiner</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">Normal</string>
|
||||
<string name="renderer_accuracy_high">Hoch</string>
|
||||
<string name="renderer_accuracy_extreme">Extrem (Langsam)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">1X (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (Langsam)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (Langsam)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (Langsam)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Direkt (Aus)</string>
|
||||
<string name="renderer_vsync_mailbox">Mailbox</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (An)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">Nächste-Nachbarn</string>
|
||||
<string name="scaling_filter_bilinear">Bilinear</string>
|
||||
<string name="scaling_filter_bicubic">Bikubisch</string>
|
||||
<string name="scaling_filter_gaussian">Gaussian</string>
|
||||
<string name="scaling_filter_scale_force">ScaleForce</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™ Super Resolution</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">Keiner</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">Standard (16:9)</string>
|
||||
<string name="ratio_force_four_three">4:3 erzwingen</string>
|
||||
<string name="ratio_force_twenty_one_nine">21:9 erzwingen</string>
|
||||
<string name="ratio_force_sixteen_ten">Erzwinge 16:10</string>
|
||||
<string name="ratio_stretch">Auf Fenster anpassen</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">Akkurat</string>
|
||||
<string name="cpu_accuracy_unsafe">Unsicher</string>
|
||||
<string name="cpu_accuracy_paranoid">Paranoid (Langsam)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">Steuerkreuz</string>
|
||||
<string name="gamepad_left_stick">Linker Analogstick</string>
|
||||
<string name="gamepad_right_stick">Rechter Analogstick</string>
|
||||
<string name="gamepad_home">Home</string>
|
||||
<string name="gamepad_screenshot">Screenshot</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">Shader werden vorbereitet</string>
|
||||
<string name="building_shaders">Shader werden erstellt</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">App-Theme ändern</string>
|
||||
<string name="theme_default">Standard</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">Theme-Modus ändern</string>
|
||||
<string name="theme_mode_follow_system">System folgen</string>
|
||||
<string name="theme_mode_light">Hell</string>
|
||||
<string name="theme_mode_dark">Dunkel</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">Schwarze Hintergünde verwenden</string>
|
||||
<string name="use_black_backgrounds_description">Bei Verwendung des dunklen Themes, schwarze Hintergründe verwenden.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,337 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">Este software ejecuta juegos para la videoconsola Nintendo Switch. Los videojuegos o keys no vienen incluidos.<br /><br />Antes de empezar, por favor, localice el archivo <![CDATA[<b> prod.keys </b>]]>en el almacenamiento de su dispositivo..<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Saber más</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">Emulación activa</string>
|
||||
<string name="emulation_notification_channel_description">Muestra una notificación persistente cuando la emulación está activa.</string>
|
||||
<string name="emulation_notification_running">yuzu esta ejecutándose</string>
|
||||
<string name="notice_notification_channel_name">Avisos y errores</string>
|
||||
<string name="notice_notification_channel_description">Mostrar notificaciones cuándo algo vaya mal.</string>
|
||||
<string name="notification_permission_not_granted">¡Permisos de notificación no concedidos!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">¡Bienvenido!</string>
|
||||
<string name="welcome_description">Aprende cómo configurar <b>yuzu</b> y avanza a la emulación.</string>
|
||||
<string name="get_started">Empezar</string>
|
||||
<string name="keys">Claves</string>
|
||||
<string name="keys_description">Selecciona el archivo <b>prod.keys</b> utilizando el botón de abajo.</string>
|
||||
<string name="select_keys">Seleccionar las claves</string>
|
||||
<string name="games">Juegos</string>
|
||||
<string name="games_description">Selecciona la carpeta <b>Games</b> utilizando el botón de abajo</string>
|
||||
<string name="done">Hecho</string>
|
||||
<string name="done_description">Todo listo.\n¡Disfrute de sus juegos!</string>
|
||||
<string name="text_continue">Continuar</string>
|
||||
<string name="next">Siguiente</string>
|
||||
<string name="back">Atrás</string>
|
||||
<string name="add_games">Añadir Juegos</string>
|
||||
<string name="add_games_description">Selecciona la carpeta de juegos</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">Juegos</string>
|
||||
<string name="home_search">Buscar</string>
|
||||
<string name="home_settings">Ajustes</string>
|
||||
<string name="empty_gamelist">No se ha encontrado ningún archivo o aún no se ha seleccionado ningún directorio de juegos.</string>
|
||||
<string name="search_and_filter_games">Busca y filtra juegos</string>
|
||||
<string name="select_games_folder">Seleccionar carpeta de juegos</string>
|
||||
<string name="select_games_folder_description">Permite que yuzu llene la lista de juegos</string>
|
||||
<string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string>
|
||||
<string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una carpeta de juegos.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">Buscar Juegos</string>
|
||||
<string name="games_dir_selected">Directorio de juegos seleccionado</string>
|
||||
<string name="install_prod_keys">Instalar prod.keys</string>
|
||||
<string name="install_prod_keys_description">Requerido para descifrar juegos</string>
|
||||
<string name="install_prod_keys_warning">¿Omitir agregar claves?</string>
|
||||
<string name="install_prod_keys_warning_description">Se requieren claves válidas para emular juegos. Solo las aplicaciones homebrew funcionarán si continúas.</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">Notificaciones</string>
|
||||
<string name="notifications_description">Otorgue el permiso de notificación con el botón de abajo.</string>
|
||||
<string name="give_permission">Conceder permiso</string>
|
||||
<string name="notification_warning">¿Omitir conceder el permiso de notificación?</string>
|
||||
<string name="notification_warning_description">yuzu no podrá notificarte información importante.</string>
|
||||
<string name="permission_denied">Permiso denegado</string>
|
||||
<string name="permission_denied_description">Negó este permiso demasiadas veces y ahora debe otorgarlo manualmente en la configuración del sistema.</string>
|
||||
<string name="about">Acerca de</string>
|
||||
<string name="about_description">Versión, créditos y más</string>
|
||||
<string name="warning_help">Ayuda</string>
|
||||
<string name="warning_skip">Siguiente</string>
|
||||
<string name="warning_cancel">Cancelar</string>
|
||||
<string name="install_amiibo_keys">Instalar clave de Amiiboo</string>
|
||||
<string name="install_amiibo_keys_description">Necesario para usar Amiibo en el juego</string>
|
||||
<string name="invalid_keys_file">Archivo de claves inválido seleccionado</string>
|
||||
<string name="install_keys_success">Claves instaladas correctamente</string>
|
||||
<string name="reading_keys_failure">Error al leer las claves de cifrado</string>
|
||||
<string name="invalid_keys_error">Claves de cifrado no válidas</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string>
|
||||
<string name="install_gpu_driver">Instalar driver de GPU</string>
|
||||
<string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string>
|
||||
<string name="advanced_settings">Opciones avanzadas</string>
|
||||
<string name="settings_description">Configurar las opciones del emulador</string>
|
||||
<string name="search_recently_played">Jugado recientemente</string>
|
||||
<string name="search_recently_added">Añadido recientemente</string>
|
||||
<string name="search_retail">Juegos</string>
|
||||
<string name="search_homebrew">Homebrew</string>
|
||||
<string name="open_user_folder">Abrir la carpeta de yuzu</string>
|
||||
<string name="open_user_folder_description">Administrar los archivos internos de yuzu</string>
|
||||
<string name="theme_and_color_description">Modificar la apariencia de la aplicación</string>
|
||||
<string name="no_file_manager">Explorador de archivos no encontrado</string>
|
||||
<string name="notification_no_directory_link">No se pudo abrir la carpeta yuzu</string>
|
||||
<string name="notification_no_directory_link_description">Por favor, busque la carpeta user con el panel lateral del explorador de archivos de forma manual.</string>
|
||||
<string name="manage_save_data">Administrar datos de guardado</string>
|
||||
<string name="manage_save_data_description">Guardar los datos encontrados. Por favor, seleccione una opción de abajo.</string>
|
||||
<string name="import_export_saves_description">Importar o exportar archivos de guardado</string>
|
||||
<string name="import_export_saves_no_profile">No se han encontrado datos de guardado. Por favor, ejecute un juego y vuelva a intentarlo.</string>
|
||||
<string name="save_file_imported_success">Importado correctamente</string>
|
||||
<string name="save_file_invalid_zip_structure">Estructura del directorio de guardado no válido</string>
|
||||
<string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string>
|
||||
<string name="import_saves">Importar</string>
|
||||
<string name="export_saves">Exportar</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia no es real</string>
|
||||
<string name="copied_to_clipboard">Copiado al portapapeles</string>
|
||||
<string name="about_app_description">Un emulador de Switch de código abierto</string>
|
||||
<string name="contributors">Contribuidores</string>
|
||||
<string name="contributors_description">Hecho con \u2764 del equipo yuzu</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">Versión</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
<string name="get_early_access">Conseguir Early Access</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">Funciones de vanguardia, acceso anticipado a actualizaciones y más</string>
|
||||
<string name="early_access_benefits">Beneficios Early Access</string>
|
||||
<string name="cutting_edge_features">Características de vanguardia</string>
|
||||
<string name="early_access_updates">Acceso anticipado a las actualizaciones</string>
|
||||
<string name="no_manual_installation">Sin instalación manual</string>
|
||||
<string name="prioritized_support">Soporte prioritario</string>
|
||||
<string name="helping_game_preservation">Ayudarás a la preservación de juegos</string>
|
||||
<string name="our_eternal_gratitude">Nuestra eterna gratitud</string>
|
||||
<string name="are_you_interested">¿Estás interesado?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">Activar limite de velocidad</string>
|
||||
<string name="frame_limit_enable_description">Cuando está habilitado, la velocidad de emulación se limitará a un porcentaje específico de la velocidad normal.</string>
|
||||
<string name="frame_limit_slider">Limitar porcentaje de velocidad</string>
|
||||
<string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. Con el valor predeterminado del 100 %, la emulación se limitará a la velocidad normal. Valores más altos o más bajos aumentarán o disminuirán el límite de velocidad.</string>
|
||||
<string name="cpu_accuracy">Precisión de CPU</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">Modo sobremesa</string>
|
||||
<string name="use_docked_mode_description">Emula en modo sobremesa, lo que aumenta la resolución perjudicando el rendimiento.</string>
|
||||
<string name="emulated_region">Región emulada</string>
|
||||
<string name="emulated_language">Idioma emulado</string>
|
||||
<string name="select_rtc_date">Seleccionar Fecha RTC</string>
|
||||
<string name="select_rtc_time">Seleccionar Tiempo RTC</string>
|
||||
<string name="use_custom_rtc">Habilitar RTC Personalizado</string>
|
||||
<string name="use_custom_rtc_description">Esta configuración le permite configurar un reloj de tiempo real personalizado diferente a la hora actual de su sistema</string>
|
||||
<string name="set_custom_rtc">Establecer RTC Personalizado</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">Nivel de precisión</string>
|
||||
<string name="renderer_resolution">Resolución</string>
|
||||
<string name="renderer_vsync">Modo VSync</string>
|
||||
<string name="renderer_aspect_ratio">Relación de aspecto</string>
|
||||
<string name="renderer_scaling_filter">Filtro de adaptación de ventana</string>
|
||||
<string name="renderer_anti_aliasing">Metodo Anti Aliasing</string>
|
||||
<string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string>
|
||||
<string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string>
|
||||
<string name="renderer_asynchronous_shaders">Usar shaders asíncronos</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compila shaders de forma asincrónica, lo que reducirá los parones pero puede introducir fallos.</string>
|
||||
<string name="renderer_debug">Habilitar la depuración de gráficos</string>
|
||||
<string name="renderer_debug_description">Cuando esté marcado, la API de gráficos entra en un modo de depuración más lento.</string>
|
||||
<string name="use_disk_shader_cache">Usar caché de shaders en disco</string>
|
||||
<string name="use_disk_shader_cache_description">Reduzca los parones almacenando y cargando shaders generados en el disco.</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">Volumen</string>
|
||||
<string name="audio_volume_description">Especifica el volumen de la salida de audio.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">Predeterminado</string>
|
||||
<string name="ini_saved">Configuración guardada</string>
|
||||
<string name="gameid_saved">Configuración guardada para %1$s</string>
|
||||
<string name="error_saving">Error guardando %1$s.ini: %2$s</string>
|
||||
<string name="loading">Cargando...</string>
|
||||
<string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string>
|
||||
<string name="reset_to_default">Restablecer a predeterminado</string>
|
||||
<string name="reset_all_settings">¿Restablecer todas las configuraciones?</string>
|
||||
<string name="reset_all_settings_description">Todas las configuraciones avanzadas se restablecerán a su configuración predeterminada. Esto no se puede deshacer.</string>
|
||||
<string name="settings_reset">Reiniciar la configuracion</string>
|
||||
<string name="close">Cerrar</string>
|
||||
<string name="learn_more">Más información</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">Seleccionar driver GPU</string>
|
||||
<string name="select_gpu_driver_title">¿Quiere reemplazar el driver de GPU actual?</string>
|
||||
<string name="select_gpu_driver_install">Instalar</string>
|
||||
<string name="select_gpu_driver_default">Predeterminado</string>
|
||||
<string name="select_gpu_driver_install_success">Instalado %s</string>
|
||||
<string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string>
|
||||
<string name="select_gpu_driver_error">¡Driver no válido, utilizando el predeterminado del sistema!</string>
|
||||
<string name="system_gpu_driver">Driver GPU del sistema</string>
|
||||
<string name="installing_driver">Instalando driver...</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">Ajustes</string>
|
||||
<string name="preferences_general">General</string>
|
||||
<string name="preferences_system">Sistema</string>
|
||||
<string name="preferences_graphics">Gráficos</string>
|
||||
<string name="preferences_audio">Audio</string>
|
||||
<string name="preferences_theme">Tema y color</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">Su ROM está encriptada</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga las guías para redumpear <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titulos instalados</a>.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Por favor, compruebe que su archivo <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado, para que los juegos sean descifrados.]]></string>
|
||||
<string name="loader_error_video_core">Ocurrió un error al inicializar el núcleo de video, posiblemente debido a una incompatibilidad con el driver seleccionado</string>
|
||||
<string name="loader_error_video_core_description">Esto suele deberse a un driver de GPU incompatible. La instalación de un controlador de GPU personalizado puede resolver este problema.</string>
|
||||
<string name="loader_error_invalid_format">No se pudo cargar la ROM</string>
|
||||
<string name="loader_error_file_not_found">Archivo ROM no existe</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">Salir de la emulación</string>
|
||||
<string name="emulation_done">Hecho</string>
|
||||
<string name="emulation_fps_counter">Contador de FPS</string>
|
||||
<string name="emulation_toggle_controls">Alternar Controles</string>
|
||||
<string name="emulation_rel_stick_center">Centro Relativo del Stick</string>
|
||||
<string name="emulation_dpad_slide">Deslizamiento de la Cruceta</string>
|
||||
<string name="emulation_haptics">Hápticos</string>
|
||||
<string name="emulation_show_overlay">Mostrar pantalla</string>
|
||||
<string name="emulation_toggle_all">Alternar Todo</string>
|
||||
<string name="emulation_control_adjust">Ajustar pantalla</string>
|
||||
<string name="emulation_control_scale">Escala</string>
|
||||
<string name="emulation_control_opacity">Opacidad</string>
|
||||
<string name="emulation_touch_overlay_reset">Reiniciar pantalla</string>
|
||||
<string name="emulation_touch_overlay_edit">Editar pantalla</string>
|
||||
<string name="emulation_pause">Pausar Emulación</string>
|
||||
<string name="emulation_unpause">Reanudar Emulación</string>
|
||||
<string name="emulation_input_overlay">Opciones de pantalla </string>
|
||||
<string name="emulation_game_loading">Cargando juego...</string>
|
||||
|
||||
<string name="load_settings">Cargando configuración...</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">Software del teclado</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">Abortar</string>
|
||||
<string name="continue_button">Continuar</string>
|
||||
<string name="system_archive_not_found">Archivo del sistema no encontrado</string>
|
||||
<string name="system_archive_not_found_message">%s no se ha encontrado. Vacíe los archivos de su sistema.\nContinuar con la emulación puede provocar bloqueos y errores.</string>
|
||||
<string name="system_archive_general">Un archivo del sistema</string>
|
||||
<string name="save_load_error">Error de Guardado/Carga</string>
|
||||
<string name="fatal_error">Error fatal</string>
|
||||
<string name="fatal_error_message">Ocurrió un error fatal. Consulte el registro para obtener más detalles.\nContinuar con la emulación puede provocar bloqueos y errores.</string>
|
||||
<string name="performance_warning">¡Desactivar esta configuración reducirá significativamente el rendimiento de la emulación! Para obtener la mejor experiencia, se recomienda dejar esta configuración habilitada.</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">Japón</string>
|
||||
<string name="region_usa">EEUU</string>
|
||||
<string name="region_europe">Europa</string>
|
||||
<string name="region_australia">Australia</string>
|
||||
<string name="region_china">China</string>
|
||||
<string name="region_korea">Corea</string>
|
||||
<string name="region_taiwan">Taiwán</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japonés (日本語)</string>
|
||||
<string name="language_english">Inglés (English)</string>
|
||||
<string name="language_french">Francés (Français)</string>
|
||||
<string name="langauge_german">Alemán (deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Español (Español)</string>
|
||||
<string name="language_chinese">Chino (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Holandés (nederlands)</string>
|
||||
<string name="language_portuguese">Portugués (Português)</string>
|
||||
<string name="language_russian">Ruso (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanés (台湾)</string>
|
||||
<string name="language_british_english">Inglés británico</string>
|
||||
<string name="language_canadian_french">Francés Canadiense (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Español Latinoamericano (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Chino Simplificado (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chino tradicional (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portugués Brasileño (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">Ninguno</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">Normal</string>
|
||||
<string name="renderer_accuracy_high">Alto</string>
|
||||
<string name="renderer_accuracy_extreme">Extremo (Lento)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">x1 (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (Lento)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (Lento)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (Lento)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Inmediata (Desactivado)</string>
|
||||
<string name="renderer_vsync_mailbox">Mailbox</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (Activado)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO Relajado</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">Vecino más próximo</string>
|
||||
<string name="scaling_filter_bilinear">Bilineal</string>
|
||||
<string name="scaling_filter_bicubic">Bicúbico</string>
|
||||
<string name="scaling_filter_gaussian">Gaussiano</string>
|
||||
<string name="scaling_filter_scale_force">ScaleForce</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™ Super Resolución</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">Ninguno</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">Predeterminado (16:9)</string>
|
||||
<string name="ratio_force_four_three">Forzar 4:3</string>
|
||||
<string name="ratio_force_twenty_one_nine">Forzar 21:9</string>
|
||||
<string name="ratio_force_sixteen_ten">Forzar 16:10</string>
|
||||
<string name="ratio_stretch">Ajustar a la ventana</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">Preciso</string>
|
||||
<string name="cpu_accuracy_unsafe">Impreciso</string>
|
||||
<string name="cpu_accuracy_paranoid">Paranoico (Lento)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">Cruceta</string>
|
||||
<string name="gamepad_left_stick">Palanca izquierda</string>
|
||||
<string name="gamepad_right_stick">Palanca derecha</string>
|
||||
<string name="gamepad_home">Home</string>
|
||||
<string name="gamepad_screenshot">Captura de pantalla</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">Preparando shaders</string>
|
||||
<string name="building_shaders">Construyendo shaders</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">Cambiar Tema</string>
|
||||
<string name="theme_default">Predeterminado</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">Cambiar modo del tema</string>
|
||||
<string name="theme_mode_follow_system">Igual al sistema</string>
|
||||
<string name="theme_mode_light">Claro</string>
|
||||
<string name="theme_mode_dark">Oscuro</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">Usar Fondos Negros</string>
|
||||
<string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,337 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">Ce logiciel exécutera des jeux pour la console de jeu Nintendo Switch. Aucun jeux ou clés n\'est inclus.<br /><br />Avant de commencer, veuillez localiser votre fichier <![CDATA[<b> prod.keys </b>]]> sur le stockage de votre appareil.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">En savoir plus</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">L\'émulation est active</string>
|
||||
<string name="emulation_notification_channel_description">Affiche une notification persistante lorsque l\'émulation est en cours d\'exécution.</string>
|
||||
<string name="emulation_notification_running">yuzu est en cours d\'exécution</string>
|
||||
<string name="notice_notification_channel_name">Avis et erreurs</string>
|
||||
<string name="notice_notification_channel_description">Affiche des notifications en cas de problème.</string>
|
||||
<string name="notification_permission_not_granted">Permission de notification non accordée !</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">Bienvenue !</string>
|
||||
<string name="welcome_description">Apprenez à configurer <b>yuzu</b> et passez à l\'émulation.</string>
|
||||
<string name="get_started">Commencer</string>
|
||||
<string name="keys">Clés</string>
|
||||
<string name="keys_description">Sélectionnez votre fichier <b>prod.keys</b> avec le bouton ci-dessous.</string>
|
||||
<string name="select_keys">Sélectionner les clés</string>
|
||||
<string name="games">Jeux</string>
|
||||
<string name="games_description">Sélectionnez votre dossier <b>de Jeux</b> avec le bouton ci-dessous.</string>
|
||||
<string name="done">Terminé</string>
|
||||
<string name="done_description">Vous êtes prêt.\nProfitez de vos jeux !</string>
|
||||
<string name="text_continue">Continuer</string>
|
||||
<string name="next">Suivant</string>
|
||||
<string name="back">Retour</string>
|
||||
<string name="add_games">Ajouter des jeux</string>
|
||||
<string name="add_games_description">Sélectionner votre dossier de jeux</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">Jeux</string>
|
||||
<string name="home_search">Rechercher</string>
|
||||
<string name="home_settings">Paramètres</string>
|
||||
<string name="empty_gamelist">Aucun fichier n\'a été trouvé ou aucun répertoire de jeu n\'a encore été sélectionné.</string>
|
||||
<string name="search_and_filter_games">Rechercher et filtrer les jeux</string>
|
||||
<string name="select_games_folder">Sélectionner le dossier de jeux</string>
|
||||
<string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string>
|
||||
<string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string>
|
||||
<string name="add_games_warning_description">Les jeux ne seront pas affichés dans la liste des jeux si aucun dossier n\'est sélectionné.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">Rechercher des jeux</string>
|
||||
<string name="games_dir_selected">Répertoire de jeux sélectionné</string>
|
||||
<string name="install_prod_keys">Installer prod.keys</string>
|
||||
<string name="install_prod_keys_description">Nécessaire pour décrypter les jeux commerciaux.</string>
|
||||
<string name="install_prod_keys_warning">Sauter l\'ajout des clés ?</string>
|
||||
<string name="install_prod_keys_warning_description">Des clés valides sont nécessaires pour émuler des jeux commerciaux. Seules les applications homebrew fonctionneront si vous continuez.</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">Notifications</string>
|
||||
<string name="notifications_description">Accordez l\'autorisation de notification avec le bouton ci-dessous.</string>
|
||||
<string name="give_permission">Donner la permission</string>
|
||||
<string name="notification_warning">Ne pas accorder la permission de notification ?</string>
|
||||
<string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string>
|
||||
<string name="permission_denied">Permission refusée</string>
|
||||
<string name="permission_denied_description">Vous avez refusé cette permission trop de fois et vous devez maintenant l\'accorder manuellement dans les paramètres système.</string>
|
||||
<string name="about">À propos</string>
|
||||
<string name="about_description">Numéro de build, crédits et plus encore</string>
|
||||
<string name="warning_help">Aide</string>
|
||||
<string name="warning_skip">Sauter</string>
|
||||
<string name="warning_cancel">Annuler</string>
|
||||
<string name="install_amiibo_keys">Installer les clés Amiibo</string>
|
||||
<string name="install_amiibo_keys_description">Nécessaire pour utiliser les Amiibo en jeu</string>
|
||||
<string name="invalid_keys_file">Fichier de clés sélectionné invalide</string>
|
||||
<string name="install_keys_success">Clés installées avec succès</string>
|
||||
<string name="reading_keys_failure">Erreur lors de la lecture des clés de chiffrement</string>
|
||||
<string name="invalid_keys_error">Clés de chiffrement invalides</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string>
|
||||
<string name="install_gpu_driver">Installer le pilote du GPU</string>
|
||||
<string name="install_gpu_driver_description">Installez des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string>
|
||||
<string name="advanced_settings">Paramètres avancés</string>
|
||||
<string name="settings_description">Configurer les paramètres de l\'émulateur</string>
|
||||
<string name="search_recently_played">Joué récemment</string>
|
||||
<string name="search_recently_added">Ajouté récemment</string>
|
||||
<string name="search_retail">Commercial</string>
|
||||
<string name="search_homebrew">Homebrew</string>
|
||||
<string name="open_user_folder">Ouvrir le dossier de yuzu</string>
|
||||
<string name="open_user_folder_description">Gérer les fichiers internes de yuzu</string>
|
||||
<string name="theme_and_color_description">Modifier l\'apparence de l\'application</string>
|
||||
<string name="no_file_manager">Aucun gestionnaire de fichiers trouvé</string>
|
||||
<string name="notification_no_directory_link">Impossible d\'ouvrir le répertoire de yuzu</string>
|
||||
<string name="notification_no_directory_link_description">Veuillez localiser manuellement le dossier utilisateur avec le panneau latéral du gestionnaire de fichiers.</string>
|
||||
<string name="manage_save_data">Gérer les données de sauvegarde</string>
|
||||
<string name="manage_save_data_description">Données de sauvegarde trouvées. Veuillez sélectionner une option ci-dessous.</string>
|
||||
<string name="import_export_saves_description">Importer ou exporter des fichiers de sauvegarde</string>
|
||||
<string name="import_export_saves_no_profile">Aucune données de sauvegarde trouvées. Veuillez lancer un jeu et réessayer.</string>
|
||||
<string name="save_file_imported_success">Importé avec succès</string>
|
||||
<string name="save_file_invalid_zip_structure">Structure de répertoire de sauvegarde non valide</string>
|
||||
<string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</string>
|
||||
<string name="import_saves">Importer</string>
|
||||
<string name="export_saves">Exporter</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia n\'est pas réel</string>
|
||||
<string name="copied_to_clipboard">Copié dans le presse-papier</string>
|
||||
<string name="about_app_description">Un émulateur Switch open source</string>
|
||||
<string name="contributors">Contributeurs</string>
|
||||
<string name="contributors_description">Fait avec \u2764 de l\'équipe yuzu</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">Build</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
<string name="get_early_access">Obtenir l\'Early Access</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">Fonctionnalités de pointe, accès anticipé aux mises à jour, et plus encore</string>
|
||||
<string name="early_access_benefits">Avantages de l\'Early Access</string>
|
||||
<string name="cutting_edge_features">Fonctionnalités de pointe</string>
|
||||
<string name="early_access_updates">Accès anticipé aux mises à jour</string>
|
||||
<string name="no_manual_installation">Pas d\'installation manuelle</string>
|
||||
<string name="prioritized_support">Assistance prioritaire</string>
|
||||
<string name="helping_game_preservation">Contribuer à la préservation des jeux</string>
|
||||
<string name="our_eternal_gratitude">Notre gratitude éternelle</string>
|
||||
<string name="are_you_interested">Es tu intéressé ?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">Activer la vitesse limite</string>
|
||||
<string name="frame_limit_enable_description">Lorsqu\'elle est activée, la vitesse d\'émulation sera limitée à un pourcentage spécifié de la vitesse normale.</string>
|
||||
<string name="frame_limit_slider">Limite en pourcentage de vitesse</string>
|
||||
<string name="frame_limit_slider_description">Spécifie le pourcentage pour limiter la vitesse d\'émulation. Avec la valeur par défaut de 100%, l\'émulation sera limitée à la vitesse normale. Des valeurs supérieures ou inférieures augmenteront ou diminueront la limite de vitesse.</string>
|
||||
<string name="cpu_accuracy">Précision du CPU</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">Mode TV</string>
|
||||
<string name="use_docked_mode_description">Émuler en mode TV augmente la résolution au détriment des performances.</string>
|
||||
<string name="emulated_region">Région émulée</string>
|
||||
<string name="emulated_language">Langue émulée</string>
|
||||
<string name="select_rtc_date">Sélectionner la date RTC</string>
|
||||
<string name="select_rtc_time">Sélectionner l\'heure RTC</string>
|
||||
<string name="use_custom_rtc">Activer l\'horloge RTC personnalisée</string>
|
||||
<string name="use_custom_rtc_description">Ce paramètre vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string>
|
||||
<string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">Niveau de précision</string>
|
||||
<string name="renderer_resolution">Résolution</string>
|
||||
<string name="renderer_vsync">Mode VSync</string>
|
||||
<string name="renderer_aspect_ratio">Format</string>
|
||||
<string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string>
|
||||
<string name="renderer_anti_aliasing">Méthode d\'anticrénelage :</string>
|
||||
<string name="renderer_force_max_clock">Forcer la fréquence d\'horloge maximale (Adreno uniquement)</string>
|
||||
<string name="renderer_force_max_clock_description">Force le GPU à fonctionner au maximum d\'horloges possibles (les contraintes thermiques seront toujours appliquées).</string>
|
||||
<string name="renderer_asynchronous_shaders">Utiliser les shaders asynchrones</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compile les shaders de manière asynchrone, ce qui réduira les saccades mais peut entraîner des problèmes visuels.</string>
|
||||
<string name="renderer_debug">Activer le débogage des graphismes</string>
|
||||
<string name="renderer_debug_description">Lorsque cette case est cochée, l\'API graphique entre dans un mode de débogage plus lent.</string>
|
||||
<string name="use_disk_shader_cache">Utiliser les shader cache de disque</string>
|
||||
<string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant les shaders générés sur le disque.</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">Volume</string>
|
||||
<string name="audio_volume_description">Spécifie le volume de la sortie audio.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">Défaut</string>
|
||||
<string name="ini_saved">Paramètres enregistrés</string>
|
||||
<string name="gameid_saved">Paramètres enregistrés pour %1$s</string>
|
||||
<string name="error_saving">Erreur lors de l\'enregistrement de %1$s.ini: %2$s</string>
|
||||
<string name="loading">Chargement...</string>
|
||||
<string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string>
|
||||
<string name="reset_to_default">Réinitialiser par défaut</string>
|
||||
<string name="reset_all_settings">Réinitialiser tous les réglages ?</string>
|
||||
<string name="reset_all_settings_description">Tous les paramètres avancés seront réinitialisés à leur configuration par défaut. Ça ne peut pas être annulé.</string>
|
||||
<string name="settings_reset">Paramètres réinitialisés</string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="learn_more">Plus d\'informations</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">Sélectionner le pilote du GPU</string>
|
||||
<string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string>
|
||||
<string name="select_gpu_driver_install">Installer</string>
|
||||
<string name="select_gpu_driver_default">Défaut</string>
|
||||
<string name="select_gpu_driver_install_success">%s Installé</string>
|
||||
<string name="select_gpu_driver_use_default">Utilisation du pilote de GPU par défaut</string>
|
||||
<string name="select_gpu_driver_error">Pilote non valide sélectionné, utilisation du paramètre par défaut du système !</string>
|
||||
<string name="system_gpu_driver">Pilote du GPU du système</string>
|
||||
<string name="installing_driver">Installation du pilote...</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">Paramètres</string>
|
||||
<string name="preferences_general">Général</string>
|
||||
<string name="preferences_system">Système</string>
|
||||
<string name="preferences_graphics">Vidéo</string>
|
||||
<string name="preferences_audio">Audio</string>
|
||||
<string name="preferences_theme">Thème et couleur</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">Votre ROM est cryptée</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour redumper vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">cartouches de jeu</a> ou <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titres installés</a>.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Veuillez vous assurer que votre fichier <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> est installé pour que les jeux puissent être déchiffrés.]]></string>
|
||||
<string name="loader_error_video_core">Une erreur s\'est produite lors de l\'initialisation du noyau vidéo</string>
|
||||
<string name="loader_error_video_core_description">Cela est généralement dû à un pilote du GPU incompatible. L\'installation d\'un pilote du GPU personnalisé peut résoudre ce problème.</string>
|
||||
<string name="loader_error_invalid_format">Impossible de charger la ROM</string>
|
||||
<string name="loader_error_file_not_found">Le fichier ROM n\'existe pas</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">Quitter l\'émulation</string>
|
||||
<string name="emulation_done">Terminé</string>
|
||||
<string name="emulation_fps_counter">Compteur FPS</string>
|
||||
<string name="emulation_toggle_controls">Activer/Désactiver les contrôles</string>
|
||||
<string name="emulation_rel_stick_center">Centre du stick relatif</string>
|
||||
<string name="emulation_dpad_slide">Glissement du DPad</string>
|
||||
<string name="emulation_haptics">Haptique</string>
|
||||
<string name="emulation_show_overlay">Afficher l\'overlay</string>
|
||||
<string name="emulation_toggle_all">Tout basculer</string>
|
||||
<string name="emulation_control_adjust">Ajuster l\'overlay</string>
|
||||
<string name="emulation_control_scale">Échelle</string>
|
||||
<string name="emulation_control_opacity">Opacité</string>
|
||||
<string name="emulation_touch_overlay_reset">Réinitialiser l\'overlay</string>
|
||||
<string name="emulation_touch_overlay_edit">Modifier l\'overlay</string>
|
||||
<string name="emulation_pause">Mettre en pause l\'émulation</string>
|
||||
<string name="emulation_unpause">Reprendre l\'émulation</string>
|
||||
<string name="emulation_input_overlay">Options de l\'overlay</string>
|
||||
<string name="emulation_game_loading">Chargement du jeu...</string>
|
||||
|
||||
<string name="load_settings">Chargement des paramètres…</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">Clavier virtuel</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">Abandonner</string>
|
||||
<string name="continue_button">Continuer</string>
|
||||
<string name="system_archive_not_found">Archive système introuvable</string>
|
||||
<string name="system_archive_not_found_message">%s est manquant. Veuillez dumper vos archives système.\nContinuer peut entraîner des plantages et des bogues.</string>
|
||||
<string name="system_archive_general">Une archive système</string>
|
||||
<string name="save_load_error">Erreur de sauvegarde/chargement</string>
|
||||
<string name="fatal_error">Erreur fatale</string>
|
||||
<string name="fatal_error_message">Une erreur fatale s\'est produite. Consultez les logs pour plus de détails.\nContinuer l\'émulation peut entraîner des plantages et des bogues.</string>
|
||||
<string name="performance_warning">La désactivation de ce paramètre réduira considérablement les performances d\'émulation ! Pour une expérience optimale, il est recommandé de laisser ce paramètre activé.</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">Japon</string>
|
||||
<string name="region_usa">É.-U.A.</string>
|
||||
<string name="region_europe">Europe</string>
|
||||
<string name="region_australia">Australie</string>
|
||||
<string name="region_china">Chine</string>
|
||||
<string name="region_korea">Corée</string>
|
||||
<string name="region_taiwan">Taïwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Japonais (日本語)</string>
|
||||
<string name="language_english">Anglais</string>
|
||||
<string name="language_french">Français (Français)</string>
|
||||
<string name="langauge_german">Allemand (Deutsch)</string>
|
||||
<string name="language_italian">Italien (Italiano)</string>
|
||||
<string name="language_spanish">Espagnol (Español)</string>
|
||||
<string name="language_chinese">Chinois (简体中文)</string>
|
||||
<string name="language_korean">Coréen (한국어)</string>
|
||||
<string name="language_dutch">Néerlandais (Nederlands)</string>
|
||||
<string name="language_portuguese">Portugais (Português)</string>
|
||||
<string name="language_russian">Russe (Русский)</string>
|
||||
<string name="language_taiwanese">Taïwanais (台湾)</string>
|
||||
<string name="language_british_english">Anglais Britannique</string>
|
||||
<string name="language_canadian_french">Français canadien (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Espagnol latino-américain (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Chinois simplifié (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Chinois Traditionnel (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portugais brésilien (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">Aucune</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">Normal</string>
|
||||
<string name="renderer_accuracy_high">Haut</string>
|
||||
<string name="renderer_accuracy_extreme">Extrême (Lent)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">1X (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (Lent)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (Lent)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (Lent)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Immédiat (Désactivé)</string>
|
||||
<string name="renderer_vsync_mailbox">Mailbox</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (Activé)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO souple</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">Plus proche voisin</string>
|
||||
<string name="scaling_filter_bilinear">Bilinéaire</string>
|
||||
<string name="scaling_filter_bicubic">Bicubique</string>
|
||||
<string name="scaling_filter_gaussian">Gaussien</string>
|
||||
<string name="scaling_filter_scale_force">ScaleForce</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™ Super Resolution</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">Aucune</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">Par défaut (16:9)</string>
|
||||
<string name="ratio_force_four_three">Forcer le 4:3</string>
|
||||
<string name="ratio_force_twenty_one_nine">Forcer le 21:9</string>
|
||||
<string name="ratio_force_sixteen_ten">Forcer le 16:10</string>
|
||||
<string name="ratio_stretch">Étirer à la fenêtre</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">Précis</string>
|
||||
<string name="cpu_accuracy_unsafe">Risqué</string>
|
||||
<string name="cpu_accuracy_paranoid">Paranoïaque (Lent)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">Pavé directionnel</string>
|
||||
<string name="gamepad_left_stick">Stick Gauche</string>
|
||||
<string name="gamepad_right_stick">Stick Droit</string>
|
||||
<string name="gamepad_home">Home</string>
|
||||
<string name="gamepad_screenshot">Capture d\'écran</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">Préparation des shaders</string>
|
||||
<string name="building_shaders">Compilation des shaders</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">Changer le thème de l\'application</string>
|
||||
<string name="theme_default">Défaut</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">Changer le mode de thème</string>
|
||||
<string name="theme_mode_follow_system">Automatique</string>
|
||||
<string name="theme_mode_light">Lumineux</string>
|
||||
<string name="theme_mode_dark">Sombre</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">Utiliser des arrière-plans noirs</string>
|
||||
<string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer des arrière-plans noirs.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,337 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">Questo software permette di giocare ai giochi della console Nintendo Switch. Nessun gioco o chiave è inclusa.<br /><br />Prima di iniziare, perfavore individua il file <![CDATA[<b>prod.keys </b>]]> nella memoria del tuo dispositivo.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Scopri di più</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">L\'emulatore è attivo</string>
|
||||
<string name="emulation_notification_channel_description">Mostra una notifica persistente quando l\'emulatore è in esecuzione.</string>
|
||||
<string name="emulation_notification_running">yuzu è in esecuzione</string>
|
||||
<string name="notice_notification_channel_name">Avvisi ed errori</string>
|
||||
<string name="notice_notification_channel_description">Mostra le notifiche quando qualcosa va storto.</string>
|
||||
<string name="notification_permission_not_granted">Autorizzazione di notifica non concessa!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">Benvenuto!</string>
|
||||
<string name="welcome_description">Scopri come configurare <b>yuzu</b> e passare all\'emulazione.</string>
|
||||
<string name="get_started">Iniziare</string>
|
||||
<string name="keys">Pulsanti</string>
|
||||
<string name="keys_description">Seleziona il tuo file <b>prod.keys</b> con il pulsante in basso.</string>
|
||||
<string name="select_keys">Selezione Pulsanti</string>
|
||||
<string name="games">Giochi</string>
|
||||
<string name="games_description">Seleziona la cartella <b>Games</b> con il pulsante in basso.</string>
|
||||
<string name="done">Fatto</string>
|
||||
<string name="done_description">È tutto pronto.\nDivertiti a giocare!</string>
|
||||
<string name="text_continue">Continua</string>
|
||||
<string name="next">Successivo</string>
|
||||
<string name="back">Indietro</string>
|
||||
<string name="add_games">Aggiungi giochi</string>
|
||||
<string name="add_games_description">Seleziona la cartella dei giochi</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">Giochi</string>
|
||||
<string name="home_search">Cerca</string>
|
||||
<string name="home_settings">Impostazioni</string>
|
||||
<string name="empty_gamelist">Non sono stati trovati file o non è stata ancora selezionata alcuna directory di gioco.</string>
|
||||
<string name="search_and_filter_games">Cerca e filtra i giochi</string>
|
||||
<string name="select_games_folder">Seleziona la cartella di gioco</string>
|
||||
<string name="select_games_folder_description">Consente a yuzu di popolare l\'elenco dei giochi</string>
|
||||
<string name="add_games_warning">Saltare la selezione della cartella dei giochi?</string>
|
||||
<string name="add_games_warning_description">I giochi non saranno mostrati nella lista dei giochi se una cartella non è selezionata.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">Cerca giochi</string>
|
||||
<string name="games_dir_selected">Cartella dei giochi selezionata</string>
|
||||
<string name="install_prod_keys">Installa prod.keys</string>
|
||||
<string name="install_prod_keys_description">Necessario per decrittografare i giochi</string>
|
||||
<string name="install_prod_keys_warning">Saltare l\'aggiunta delle chiavi?</string>
|
||||
<string name="install_prod_keys_warning_description">Sono necessarie delle chiavi valide per emulare i giochi. Se continui, funzioneranno solo le app homebrew.</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">Notifiche</string>
|
||||
<string name="notifications_description">Concedi l\'autorizzazione alle notifiche con il pulsante in basso.</string>
|
||||
<string name="give_permission">Concedere l\'autorizzazione</string>
|
||||
<string name="notification_warning">Saltare la concessione dell\'autorizzazione alle notifiche?</string>
|
||||
<string name="notification_warning_description">yuzu non sarà in grado di notificarti informazioni importanti.</string>
|
||||
<string name="permission_denied">Permesso negato</string>
|
||||
<string name="permission_denied_description">Hai negato l\'autorizzazione troppe volte ed ora devi concederla manualmente nelle impostazioni di sistema.</string>
|
||||
<string name="about">Informazioni</string>
|
||||
<string name="about_description">Versione build, crediti ed altro</string>
|
||||
<string name="warning_help">Aiuto</string>
|
||||
<string name="warning_skip">Salta</string>
|
||||
<string name="warning_cancel">Annulla</string>
|
||||
<string name="install_amiibo_keys">Installa le chiavi degli Amiibo</string>
|
||||
<string name="install_amiibo_keys_description">Necessario per usare gli Amiibo in gioco</string>
|
||||
<string name="invalid_keys_file">Selezionate chiavi non valide</string>
|
||||
<string name="install_keys_success">Chiavi installate correttamente</string>
|
||||
<string name="reading_keys_failure">Errore durante la lettura delle chiavi di crittografia</string>
|
||||
<string name="invalid_keys_error">Chiavi di crittografia non valide</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string>
|
||||
<string name="install_gpu_driver">Installa i driver GPU</string>
|
||||
<string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string>
|
||||
<string name="advanced_settings">Impostazioni avanzate</string>
|
||||
<string name="settings_description">Configura le impostazioni dell\'emulatore</string>
|
||||
<string name="search_recently_played">Giocato recentemente</string>
|
||||
<string name="search_recently_added">Aggiunto recentemente</string>
|
||||
<string name="search_retail">Rivenditore</string>
|
||||
<string name="search_homebrew">Homebrew</string>
|
||||
<string name="open_user_folder">Apri la cartella di yuzu</string>
|
||||
<string name="open_user_folder_description">Gestisci i file interni di yuzu</string>
|
||||
<string name="theme_and_color_description">Modifica l\'aspetto dell\'app</string>
|
||||
<string name="no_file_manager">Nessun file manager trovato</string>
|
||||
<string name="notification_no_directory_link">Impossibile aprire la cartella di yuzu</string>
|
||||
<string name="notification_no_directory_link_description">Per favore individua la cartella dell\'utente manualmente con il pannello laterale del file manager.</string>
|
||||
<string name="manage_save_data">Gestisci i salvataggi</string>
|
||||
<string name="manage_save_data_description">Salvataggio non trovato. Seleziona un\'opzione di seguito.</string>
|
||||
<string name="import_export_saves_description">Importa o esporta i salvataggi</string>
|
||||
<string name="import_export_saves_no_profile">Nessun salvataggio trovato. Avvia un gioco e riprova.</string>
|
||||
<string name="save_file_imported_success">Importato con successo</string>
|
||||
<string name="save_file_invalid_zip_structure">La struttura della cartella dei salvataggi è invalida</string>
|
||||
<string name="save_file_invalid_zip_structure_description">La prima sotto cartella <b>deve</b> chiamarsi come l\'ID del titolo del gioco.</string>
|
||||
<string name="import_saves">Importa</string>
|
||||
<string name="export_saves">Esporta</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia non è reale</string>
|
||||
<string name="copied_to_clipboard">Copiato negli appunti</string>
|
||||
<string name="about_app_description">Un emulatore della Switch open-source.</string>
|
||||
<string name="contributors">Collaboratori</string>
|
||||
<string name="contributors_description">Realizzato con \u2764 dal team yuzu</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">Compilazione</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Accesso Anticipato</string>
|
||||
<string name="get_early_access">Ottieni l\'accesso anticipato</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">Funzionalità all\'avanguardia, aggiornamenti in anticipo e altro</string>
|
||||
<string name="early_access_benefits">Vantaggi dell\'accesso anticipato</string>
|
||||
<string name="cutting_edge_features">Funzionalità all\'avanguardia</string>
|
||||
<string name="early_access_updates">Accesso anticipato agli aggiornamenti</string>
|
||||
<string name="no_manual_installation">Non installare manualmente.</string>
|
||||
<string name="prioritized_support">Supporto prioritario</string>
|
||||
<string name="helping_game_preservation">Aiuta a preservare il gioco</string>
|
||||
<string name="our_eternal_gratitude">La nostra gratitudine eterna</string>
|
||||
<string name="are_you_interested">Sei interessato?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">Abilita il limite di velocità</string>
|
||||
<string name="frame_limit_enable_description">Quando abilitato, la velocità di emulazione verrà limitata a una specifica percentuale della velocità normale.</string>
|
||||
<string name="frame_limit_slider">Limite velocità percentuale</string>
|
||||
<string name="frame_limit_slider_description">Specifica la percentuale del limite della velocità di emulazione. Con quella preimpostata al 100% l\'emulazione verrà limitata alla velocità normale. Valori più alti o bassi aumenteranno o diminuiranno il limite di velocità.</string>
|
||||
<string name="cpu_accuracy">Accuratezza della CPU</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">Modalità docked</string>
|
||||
<string name="use_docked_mode_description">Emula in modalità docked, questo aumenta la risoluzione a spese delle performance.</string>
|
||||
<string name="emulated_region">Regione emulata</string>
|
||||
<string name="emulated_language">Lingua emulata</string>
|
||||
<string name="select_rtc_date">Seleziona la data dall\'orologio in tempo reale</string>
|
||||
<string name="select_rtc_time">Seleziona il tempo dall\'orologio in tempo reale</string>
|
||||
<string name="use_custom_rtc">Abilità l\'orologio in tempo reale personalizzato</string>
|
||||
<string name="use_custom_rtc_description">Questa impostazione ti permette di impostare un orologio in tempo reale personalizzato separato da quello del tuo sistema corrente.</string>
|
||||
<string name="set_custom_rtc">Imposta l\'orologio in tempo reale personalizzato</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">Livello di accuratezza</string>
|
||||
<string name="renderer_resolution">Risoluzione</string>
|
||||
<string name="renderer_vsync">Modalità VSync</string>
|
||||
<string name="renderer_aspect_ratio">Rapporto d\'aspetto</string>
|
||||
<string name="renderer_scaling_filter">Filtro di adattamento alla finestra</string>
|
||||
<string name="renderer_anti_aliasing">Metodo di anti-aliasing</string>
|
||||
<string name="renderer_force_max_clock">Forza clock massimi (solo Adreno)</string>
|
||||
<string name="renderer_force_max_clock_description">Forza la GPU a girare col massimo clock possibile (i vincoli alla temperatura saranno comunque applicati)</string>
|
||||
<string name="renderer_asynchronous_shaders">Usa shaders asincrone</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compila le shaders asincronamente, questo riduce lo shutter ma potrebbe introdurre dei glitch. </string>
|
||||
<string name="renderer_debug">Abilità il debug grafico</string>
|
||||
<string name="renderer_debug_description">Quando l\'opzione è selezionata, l\'API grafica entra in una modalità di debug più lenta</string>
|
||||
<string name="use_disk_shader_cache">Usa cache shader su disco</string>
|
||||
<string name="use_disk_shader_cache_description">Riduce lo stuttering salvando e caricando le shader generate sul disco.</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">Volume</string>
|
||||
<string name="audio_volume_description">Specifica il volume dell\'audio in uscita.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">Predefinito</string>
|
||||
<string name="ini_saved">Impostazioni salvate</string>
|
||||
<string name="gameid_saved">Impostazioni salvate per %1$s</string>
|
||||
<string name="error_saving">Errore nel salvare %1$s.ini %2$s</string>
|
||||
<string name="loading">Caricamento…</string>
|
||||
<string name="reset_setting_confirmation">Vuoi ripristinare queste impostazioni al loro valore originale?</string>
|
||||
<string name="reset_to_default">Riportare alle impostazioni originali</string>
|
||||
<string name="reset_all_settings">Resettare tutte le impostazioni?</string>
|
||||
<string name="reset_all_settings_description">Tutte le Impostazioni Avanzate saranno ripristinate a quelle originali. Questa operazione non è reversibile</string>
|
||||
<string name="settings_reset">Reimposta le impostazioni</string>
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="learn_more">Per saperne di più</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">Seleziona il driver della GPU</string>
|
||||
<string name="select_gpu_driver_title">Vuoi sostituire il driver della tua GPU attuale?</string>
|
||||
<string name="select_gpu_driver_install">Installa</string>
|
||||
<string name="select_gpu_driver_default">Predefinito</string>
|
||||
<string name="select_gpu_driver_install_success">Installato%s</string>
|
||||
<string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string>
|
||||
<string name="select_gpu_driver_error">Il driver selezionato è invalido, è in utilizzo quello predefinito di sistema!</string>
|
||||
<string name="system_gpu_driver">Driver GPU del sistema</string>
|
||||
<string name="installing_driver">Installando i driver...</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">Impostazioni</string>
|
||||
<string name="preferences_general">Generali</string>
|
||||
<string name="preferences_system">Sistema</string>
|
||||
<string name="preferences_graphics">Grafica</string>
|
||||
<string name="preferences_audio">Audio</string>
|
||||
<string name="preferences_theme">Tema e colori</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">La tua ROM è criptata</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Per favore segui la guida per eseguire il dump della <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">cartuccia di gioco</a> o i <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titoli installati</a>.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Per favore assicurati che il file <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> sia installato in modo che i giochi possano essere decrittati.]]></string>
|
||||
<string name="loader_error_video_core">È stato riscontrato un errore nell\'inizializzazione del core video</string>
|
||||
<string name="loader_error_video_core_description">Questo è causato solitamente dal driver incompatibile di una GPU. L\'installazione di driver GPU personalizzati potrebbe risolvere questo problema.</string>
|
||||
<string name="loader_error_invalid_format">Impossibile caricare la ROM</string>
|
||||
<string name="loader_error_file_not_found">Il file della ROM non esiste</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">Uscire dall\'emulazione</string>
|
||||
<string name="emulation_done">Fatto</string>
|
||||
<string name="emulation_fps_counter">Contatore degli FPS</string>
|
||||
<string name="emulation_toggle_controls">Controlli a interruttore</string>
|
||||
<string name="emulation_rel_stick_center">Centro relativo degli Stick</string>
|
||||
<string name="emulation_dpad_slide">Slittamento del Pad Direzionale</string>
|
||||
<string name="emulation_haptics">Aptico</string>
|
||||
<string name="emulation_show_overlay">Mostra Overlay</string>
|
||||
<string name="emulation_toggle_all">Attiva/disattiva tutto</string>
|
||||
<string name="emulation_control_adjust">Aggiusta Overlay</string>
|
||||
<string name="emulation_control_scale">Scala</string>
|
||||
<string name="emulation_control_opacity">Opacità</string>
|
||||
<string name="emulation_touch_overlay_reset">Reimposta Overlay</string>
|
||||
<string name="emulation_touch_overlay_edit">Modifica Overlay</string>
|
||||
<string name="emulation_pause">Metti in pausa l\'emulazione</string>
|
||||
<string name="emulation_unpause">Riprendi Emulazione</string>
|
||||
<string name="emulation_input_overlay">Impostazioni Overlay</string>
|
||||
<string name="emulation_game_loading">Caricamento del gioco...</string>
|
||||
|
||||
<string name="load_settings">Caricamento delle impostazioni...</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">Tastiera software</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">Interrompi</string>
|
||||
<string name="continue_button">Continua</string>
|
||||
<string name="system_archive_not_found">Archivio di sistema non trovato</string>
|
||||
<string name="system_archive_not_found_message">%s è mancante. Per favore esegui il dump degli archivi del tuo sistema.\nContinuare ad emulare potrebbe portare bug o causare crash.</string>
|
||||
<string name="system_archive_general">Un archivio di sistema</string>
|
||||
<string name="save_load_error">Errore di salvataggio/caricamento</string>
|
||||
<string name="fatal_error">Errore Fatale</string>
|
||||
<string name="fatal_error_message">Un errore fatale è accaduto. Controlla i log per i dettagli.\nContinuare ad emulare potrebbe portare bug o causare crash.</string>
|
||||
<string name="performance_warning">Disattivare questa impostazione può ridurre significativamente le performance di emulazione! Per una migliore esperienza, è consigliato lasciare questa impostazione attivata.</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">Giappone</string>
|
||||
<string name="region_usa">USA</string>
|
||||
<string name="region_europe">Europa</string>
|
||||
<string name="region_australia">Australia</string>
|
||||
<string name="region_china">Cina</string>
|
||||
<string name="region_korea">Corea</string>
|
||||
<string name="region_taiwan">Taiwan</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">Giapponese (日本語)</string>
|
||||
<string name="language_english">Inglese (English)</string>
|
||||
<string name="language_french">Francese (Français)</string>
|
||||
<string name="langauge_german">Tedesco (Deutsch)</string>
|
||||
<string name="language_italian">Italiano (Italiano)</string>
|
||||
<string name="language_spanish">Spagnolo (Español)</string>
|
||||
<string name="language_chinese">Cinese (简体中文)</string>
|
||||
<string name="language_korean">Coreano (한국어)</string>
|
||||
<string name="language_dutch">Olandese (Nederlands)</string>
|
||||
<string name="language_portuguese">Portoghese (Português)</string>
|
||||
<string name="language_russian">Russo (Русский)</string>
|
||||
<string name="language_taiwanese">Taiwanese (台湾)</string>
|
||||
<string name="language_british_english">Inglese britannico</string>
|
||||
<string name="language_canadian_french">Francese Canadese (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">Spagnolo Latino Americano (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">Cinese Semplificato (简体中文)</string>
|
||||
<string name="language_traditional_chinese">Cinese tradizionale (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">Portoghese (Português)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">Nessuna</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">Normale</string>
|
||||
<string name="renderer_accuracy_high">Alta</string>
|
||||
<string name="renderer_accuracy_extreme">Estrema (Lenta)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">1X (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (Slow)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (Slow)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (Slow)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Immediato (Off)</string>
|
||||
<string name="renderer_vsync_mailbox">Cassella postale</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (On)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO Rilassato</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">Nearest neighbor</string>
|
||||
<string name="scaling_filter_bilinear">Bilineare</string>
|
||||
<string name="scaling_filter_bicubic">Bicubico</string>
|
||||
<string name="scaling_filter_gaussian">Gaussiano</string>
|
||||
<string name="scaling_filter_scale_force">ScaleForce</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™️ Super Resolution</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">Nessuna</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">Predefinito (16:9)</string>
|
||||
<string name="ratio_force_four_three">Forza 4:3</string>
|
||||
<string name="ratio_force_twenty_one_nine">Forza 21:9</string>
|
||||
<string name="ratio_force_sixteen_ten">Forza 16:10</string>
|
||||
<string name="ratio_stretch">Allunga a finestra</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">Accurata</string>
|
||||
<string name="cpu_accuracy_unsafe">Non sicura</string>
|
||||
<string name="cpu_accuracy_paranoid">Paranoico (Lento)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">D-Pad</string>
|
||||
<string name="gamepad_left_stick">Levetta sinistra</string>
|
||||
<string name="gamepad_right_stick">Levetta destra</string>
|
||||
<string name="gamepad_home">Home</string>
|
||||
<string name="gamepad_screenshot">Screenshot</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">Preparazione degli shaders</string>
|
||||
<string name="building_shaders">Costruendo gli shaders</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">Cambia il tema dell\'app</string>
|
||||
<string name="theme_default">Predefinito</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">Cambia la modalità del tema</string>
|
||||
<string name="theme_mode_follow_system">Segue il Sistema</string>
|
||||
<string name="theme_mode_light">Chiaro</string>
|
||||
<string name="theme_mode_dark">Scuro</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">Usa sfondi neri</string>
|
||||
<string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,335 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">このソフトウェアは、Nintendo Switch用のゲームを実行します。 ゲームソフトやキーは含まれません。<br /><br />事前に、 <![CDATA[<b> prod.keys </b>]]> ファイルをデバイスのストレージに配置しておいてください。<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">詳細</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">エミュレーションが有効です</string>
|
||||
<string name="emulation_notification_channel_description">エミュレーションの実行中に常設通知を表示します。</string>
|
||||
<string name="emulation_notification_running">yuzu は実行中です</string>
|
||||
<string name="notice_notification_channel_description">問題が発生したときに通知を表示します。</string>
|
||||
<string name="notification_permission_not_granted">通知が許可されていません!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">ようこそ!</string>
|
||||
<string name="welcome_description"><b>yuzu</b> のセットアップ方法を学び、エミュレーションに飛び込みましょう。</string>
|
||||
<string name="get_started">はじめる</string>
|
||||
<string name="keys">キー</string>
|
||||
<string name="keys_description">下のボタンから <b>prod.keys</b> ファイルを選択してください。</string>
|
||||
<string name="select_keys">キーを選択</string>
|
||||
<string name="games">ゲーム</string>
|
||||
<string name="games_description">下のボタンから<b>ゲーム</b>があるフォルダを選択してください。</string>
|
||||
<string name="done">完了</string>
|
||||
<string name="done_description">準備が完了しました。\nゲームをお楽しみください!</string>
|
||||
<string name="text_continue">続行</string>
|
||||
<string name="next">次へ</string>
|
||||
<string name="back">戻る</string>
|
||||
<string name="add_games">ゲームを追加</string>
|
||||
<string name="add_games_description">ゲームフォルダを選択</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">ゲーム</string>
|
||||
<string name="home_search">検索</string>
|
||||
<string name="home_settings">設定</string>
|
||||
<string name="empty_gamelist">ファイルが見つからないか、ゲームディレクトリがまだ選択されていません。</string>
|
||||
<string name="search_and_filter_games">ゲームの検索と絞り込み</string>
|
||||
<string name="select_games_folder">ゲームフォルダを選択</string>
|
||||
<string name="select_games_folder_description">yuzu がゲームリストに追加できるようにします</string>
|
||||
<string name="add_games_warning">ゲームフォルダの選択をスキップしますか?</string>
|
||||
<string name="add_games_warning_description">フォルダを選択しない場合、ゲームはゲームリストに表示されません。</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">ゲームを検索</string>
|
||||
<string name="games_dir_selected">ゲームディレクトリが選択されました</string>
|
||||
<string name="install_prod_keys">prod.keys をインストール</string>
|
||||
<string name="install_prod_keys_description">ゲームの復号化に必要</string>
|
||||
<string name="install_prod_keys_warning">キーの追加をスキップしますか?</string>
|
||||
<string name="install_prod_keys_warning_description">製品版ゲームのエミュレーションには、有効なキーが必要です。続行すると自作アプリしか機能しません。</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">通知</string>
|
||||
<string name="notifications_description">下のボタンで通知の権限を許可してください。</string>
|
||||
<string name="give_permission">許可</string>
|
||||
<string name="notification_warning">通知の許可をスキップしますか?</string>
|
||||
<string name="notification_warning_description">yuzuは重要なお知らせを通知できません。</string>
|
||||
<string name="permission_denied">権限が拒否されました</string>
|
||||
<string name="permission_denied_description">この権限を複数回拒否したため、システム設定で手動で許可する必要があります。</string>
|
||||
<string name="about">情報</string>
|
||||
<string name="about_description">ビルドバージョン、クレジットなど</string>
|
||||
<string name="warning_help">ヘルプ</string>
|
||||
<string name="warning_skip">スキップ</string>
|
||||
<string name="warning_cancel">キャンセル</string>
|
||||
<string name="install_amiibo_keys">Amiibo キーをインストール</string>
|
||||
<string name="install_amiibo_keys_description">ゲーム内での Amiibo の使用に必要</string>
|
||||
<string name="invalid_keys_file">無効なキーファイルが選択されました</string>
|
||||
<string name="install_keys_success">正常にインストールされました</string>
|
||||
<string name="reading_keys_failure">暗号化キーの読み取りエラー</string>
|
||||
<string name="invalid_keys_error">暗号化キーが無効です</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_keys_failure_description">選択されたファイルが不正または破損しています。キーを再ダンプしてください。</string>
|
||||
<string name="install_gpu_driver">GPUドライバーをインストール</string>
|
||||
<string name="install_gpu_driver_description">代替ドライバーをインストールしてパフォーマンスや精度を向上させます</string>
|
||||
<string name="advanced_settings">高度な設定</string>
|
||||
<string name="settings_description">エミュレーターの設定を構成します</string>
|
||||
<string name="search_recently_played">最近プレイした</string>
|
||||
<string name="search_recently_added">最近追加された</string>
|
||||
<string name="search_retail">製品版</string>
|
||||
<string name="search_homebrew">自作</string>
|
||||
<string name="open_user_folder">yuzu フォルダを開く</string>
|
||||
<string name="open_user_folder_description">yuzu内部のファイルを管理します</string>
|
||||
<string name="theme_and_color_description">アプリの見た目を変更</string>
|
||||
<string name="no_file_manager">ファイルマネージャーが見つかりませんでした</string>
|
||||
<string name="notification_no_directory_link">yuzuのディレクトリを開けません</string>
|
||||
<string name="notification_no_directory_link_description">ファイルマネージャのサイドパネルでユーザーフォルダを手動で探してください。</string>
|
||||
<string name="manage_save_data">セーブデータを管理</string>
|
||||
<string name="manage_save_data_description">セーブデータが見つかりました。以下のオプションから選択してください。</string>
|
||||
<string name="import_export_saves_description">セーブファイルをインポート/エクスポート</string>
|
||||
<string name="import_export_saves_no_profile">セーブデータがありません。ゲームを起動してから再度お試しください。</string>
|
||||
<string name="save_file_imported_success">インポートが完了しました</string>
|
||||
<string name="save_file_invalid_zip_structure">セーブデータのディレクトリ構造が無効です</string>
|
||||
<string name="save_file_invalid_zip_structure_description">最初のサブフォルダ名は、ゲームのタイトルIDである必要があります。</string>
|
||||
<string name="import_saves">インポート</string>
|
||||
<string name="export_saves">エクスポート</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">ガイアは実在しない</string>
|
||||
<string name="copied_to_clipboard">クリップボードにコピーしました</string>
|
||||
<string name="about_app_description">オープンソースのSwitchエミュレータ</string>
|
||||
<string name="contributors">貢献者</string>
|
||||
<string name="contributors_description">yuzuチームの\u2764で作られた</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">ビルド</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">早期アクセス</string>
|
||||
<string name="get_early_access">早期アクセスを手に入れる</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">最先端の機能、アップデートの早期アクセスなど</string>
|
||||
<string name="early_access_benefits">早期アクセスのメリット</string>
|
||||
<string name="cutting_edge_features">最先端の機能</string>
|
||||
<string name="early_access_updates">アップデートの早期アクセス</string>
|
||||
<string name="no_manual_installation">手動インストールが不要</string>
|
||||
<string name="prioritized_support">優先的なサポート</string>
|
||||
<string name="helping_game_preservation">ゲームの保存に貢献</string>
|
||||
<string name="our_eternal_gratitude">私たちの永遠の感謝</string>
|
||||
<string name="are_you_interested">興味がありますか?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">速度制限を有効化</string>
|
||||
<string name="frame_limit_enable_description">有効にすると、エミュレーション速度が任意の割合に制限されます。</string>
|
||||
<string name="frame_limit_slider">エミュレーション速度の制限</string>
|
||||
<string name="frame_limit_slider_description">エミュレーション速度を制限する割合を指定します。デフォルトの100%では、エミュレーションは通常の速度に制限されます。値が高いまたは低いほど、速度制限が増加または減少します。</string>
|
||||
<string name="cpu_accuracy">CPU精度</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">TVモード</string>
|
||||
<string name="use_docked_mode_description">TVモードでエミュレートします。パフォーマンスが犠牲になりますが、解像度が向上します。</string>
|
||||
<string name="emulated_region">地域</string>
|
||||
<string name="emulated_language">言語</string>
|
||||
<string name="select_rtc_date">RTCの日付を選択</string>
|
||||
<string name="select_rtc_time">RTCの時刻を選択</string>
|
||||
<string name="use_custom_rtc">カスタムRTC</string>
|
||||
<string name="use_custom_rtc_description">現在のシステム時間とは別にカスタムのリアルタイムクロックを設定できます。</string>
|
||||
<string name="set_custom_rtc">カスタムRTCを設定</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">精度</string>
|
||||
<string name="renderer_resolution">解像度</string>
|
||||
<string name="renderer_vsync">垂直同期モード</string>
|
||||
<string name="renderer_aspect_ratio">アスペクト比</string>
|
||||
<string name="renderer_scaling_filter">ウィンドウ適応フィルター</string>
|
||||
<string name="renderer_anti_aliasing">アンチエイリアス方式</string>
|
||||
<string name="renderer_force_max_clock">最大クロックを強制 (Adrenoのみ)</string>
|
||||
<string name="renderer_force_max_clock_description">GPUを可能な限り最大クロックで動作させます (過熱制限は引き続き適用されます)。</string>
|
||||
<string name="renderer_asynchronous_shaders">非同期シェーダー</string>
|
||||
<string name="renderer_asynchronous_shaders_description">シェーダーを非同期でコンパイルします。コマ落ちが軽減されますが、不具合が発生する可能性があります。</string>
|
||||
<string name="renderer_debug">グラフィックデバッグ</string>
|
||||
<string name="renderer_debug_description">オンにすると、グラフィックAPI は低速のデバッグモードに入ります。</string>
|
||||
<string name="use_disk_shader_cache">シェーダーキャッシュを使用</string>
|
||||
<string name="use_disk_shader_cache_description">生成したシェーダーをディスクに保存して読み込むことで、コマ落ちを軽減します。</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">音量</string>
|
||||
<string name="audio_volume_description">オーディオ出力の音量を指定します</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">デフォルト</string>
|
||||
<string name="ini_saved">設定を保存しました</string>
|
||||
<string name="gameid_saved">%1$sの設定を保存しました</string>
|
||||
<string name="error_saving">%1$s.ini の保存エラー: %2$s</string>
|
||||
<string name="loading">読み込み中…</string>
|
||||
<string name="reset_setting_confirmation">この設定を初期値にリセットしますか?</string>
|
||||
<string name="reset_to_default">初期設定に戻す</string>
|
||||
<string name="reset_all_settings">すべての設定をリセットしますか?</string>
|
||||
<string name="reset_all_settings_description">すべての詳細設定が初期設定に戻されます。この操作は元に戻せません。</string>
|
||||
<string name="settings_reset">設定をリセットしました</string>
|
||||
<string name="close">閉じる</string>
|
||||
<string name="learn_more">詳細情報</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">GPUドライバを選択</string>
|
||||
<string name="select_gpu_driver_title">現在のGPUドライバーを置き換えますか?</string>
|
||||
<string name="select_gpu_driver_install">インストール</string>
|
||||
<string name="select_gpu_driver_default">デフォルト</string>
|
||||
<string name="select_gpu_driver_install_success">%s をインストールしました</string>
|
||||
<string name="select_gpu_driver_use_default">デフォルトのGPUドライバーを使用します</string>
|
||||
<string name="select_gpu_driver_error">選択されたドライバが無効なため、システムのデフォルトを使用します!</string>
|
||||
<string name="system_gpu_driver">システムのGPUドライバ</string>
|
||||
<string name="installing_driver">インストール中…</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">設定</string>
|
||||
<string name="preferences_general">全般</string>
|
||||
<string name="preferences_system">システム</string>
|
||||
<string name="preferences_graphics">グラフィック</string>
|
||||
<string name="preferences_audio">サウンド</string>
|
||||
<string name="preferences_theme">テーマと色</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">ROMが暗号化されています</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">ゲームカートリッジ</a>や<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">インストール済みのタイトル</a>を再度ダンプするためのガイドに従ってください。]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[ゲームを復号化するために <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルがインストールされていることを確認してください。]]></string>
|
||||
<string name="loader_error_video_core">ビデオコアの初期化中にエラーが発生しました</string>
|
||||
<string name="loader_error_video_core_description">これは通常、互換性のないGPUドライバーが原因で発生します。 カスタムGPUドライバーをインストールすると、問題が解決する可能性があります。</string>
|
||||
<string name="loader_error_invalid_format">ROMの読み込みに失敗しました</string>
|
||||
<string name="loader_error_file_not_found">ROMファイルが存在しません</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">エミュレーションを終了</string>
|
||||
<string name="emulation_done">完了</string>
|
||||
<string name="emulation_fps_counter">FPSカウンター</string>
|
||||
<string name="emulation_toggle_controls">コントロールを切り替え</string>
|
||||
<string name="emulation_dpad_slide">十字キーのスライド操作</string>
|
||||
<string name="emulation_haptics">振動</string>
|
||||
<string name="emulation_show_overlay">オーバーレイを表示</string>
|
||||
<string name="emulation_toggle_all">すべて選択</string>
|
||||
<string name="emulation_control_adjust">オーバーレイを調整</string>
|
||||
<string name="emulation_control_scale">大きさ</string>
|
||||
<string name="emulation_control_opacity">不透明度</string>
|
||||
<string name="emulation_touch_overlay_reset">リセット</string>
|
||||
<string name="emulation_touch_overlay_edit">オーバーレイを編集</string>
|
||||
<string name="emulation_pause">エミュレーションを一時停止</string>
|
||||
<string name="emulation_unpause">エミュレーションを再開</string>
|
||||
<string name="emulation_input_overlay">オーバーレイオプション</string>
|
||||
<string name="emulation_game_loading">ロード中…</string>
|
||||
|
||||
<string name="load_settings">設定をロード中…</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">ソフトウェアキーボード</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">中断</string>
|
||||
<string name="continue_button">続行</string>
|
||||
<string name="system_archive_not_found">システムアーカイブが見つかりません</string>
|
||||
<string name="system_archive_not_found_message">%s が見つかりません。システムアーカイブをダンプしてください。\nエミュレーションを続行すると、クラッシュやバグが発生する可能性があります。</string>
|
||||
<string name="system_archive_general">システムアーカイブ</string>
|
||||
<string name="save_load_error">セーブ/ロード エラー</string>
|
||||
<string name="fatal_error">致命的なエラー</string>
|
||||
<string name="fatal_error_message">致命的なエラーが発生しました。詳細はログを確認してください。\nエミュレーションを続行するとクラッシュやバグが発生する可能性があります。</string>
|
||||
<string name="performance_warning">この設定をオフにすると、エミュレーションのパフォーマンスが著しく低下します!最高の体験を得るためには、この設定を有効にしておくことをお勧めします。</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">日本</string>
|
||||
<string name="region_usa">アメリカ</string>
|
||||
<string name="region_europe">ヨーロッパ</string>
|
||||
<string name="region_australia">オーストラリア</string>
|
||||
<string name="region_china">中国</string>
|
||||
<string name="region_korea">韓国</string>
|
||||
<string name="region_taiwan">台湾</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">日本語</string>
|
||||
<string name="language_english">英語</string>
|
||||
<string name="language_french">フランス語 (Français)</string>
|
||||
<string name="langauge_german">ドイツ語 (Deutsch)</string>
|
||||
<string name="language_italian">イタリア語 (Italiano)</string>
|
||||
<string name="language_spanish">スペイン語 (Español)</string>
|
||||
<string name="language_chinese">中国語 (简体中文)</string>
|
||||
<string name="language_korean">韓国語 (한국어)</string>
|
||||
<string name="language_dutch">オランダ語 (Nederlands)</string>
|
||||
<string name="language_portuguese">ポルトガル語 (Português)</string>
|
||||
<string name="language_russian">ロシア語 (Русский)</string>
|
||||
<string name="language_taiwanese">台湾語 (台湾)</string>
|
||||
<string name="language_british_english">イギリス英語</string>
|
||||
<string name="language_canadian_french">フランス語(カナダ) (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">スペイン語(ラテンアメリカ) (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">中国語 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">繁体字中国語 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">ポルトガル語(ブラジル) (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">Vulkan</string>
|
||||
<string name="renderer_none">なし</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">標準</string>
|
||||
<string name="renderer_accuracy_high">高い</string>
|
||||
<string name="renderer_accuracy_extreme">最高 (低速)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">1X (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (低速)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (低速)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (低速)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Immediate (オフ)</string>
|
||||
<string name="renderer_vsync_mailbox">Mailbox</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (オン)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">Nearest Neighbor</string>
|
||||
<string name="scaling_filter_bilinear">Bilinear</string>
|
||||
<string name="scaling_filter_bicubic">Bicubic</string>
|
||||
<string name="scaling_filter_gaussian">Gaussian</string>
|
||||
<string name="scaling_filter_scale_force">ScaleForce</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™ Super Resolution</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">なし</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">デフォルト (16:9)</string>
|
||||
<string name="ratio_force_four_three">強制 4:3</string>
|
||||
<string name="ratio_force_twenty_one_nine">強制 21:9</string>
|
||||
<string name="ratio_force_sixteen_ten">強制 16:10</string>
|
||||
<string name="ratio_stretch">ウィンドウに合わせる</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">正確</string>
|
||||
<string name="cpu_accuracy_unsafe">不安定</string>
|
||||
<string name="cpu_accuracy_paranoid">パラノイド (低速)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">方向ボタン</string>
|
||||
<string name="gamepad_left_stick">Lスティック</string>
|
||||
<string name="gamepad_right_stick">Rスティック</string>
|
||||
<string name="gamepad_home">HOMEボタン</string>
|
||||
<string name="gamepad_screenshot">スクリーンショット</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">シェーダーを準備しています</string>
|
||||
<string name="building_shaders">シェーダーを構築しています</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">アプリのテーマ</string>
|
||||
<string name="theme_default">デフォルト</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">テーマモード</string>
|
||||
<string name="theme_mode_follow_system">システムに従う</string>
|
||||
<string name="theme_mode_light">ライト</string>
|
||||
<string name="theme_mode_dark">ダーク</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">黒色の背景を使用</string>
|
||||
<string name="use_black_backgrounds_description">ダークテーマの使用時は、黒色の背景を有効にしてください。</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,337 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_disclaimer">이 소프트웨어는 닌텐도 스위치 게임 콘솔용 게임을 실행합니다. 게임 타이틀이나 keys는 포함되어 있지 않습니다.<br /><br />시작하기 전에 장치 저장소에서 <![CDATA[<b> prod.keys </b>]]> 파일을 찾아주세요.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">자세히 알아보기</a>]]></string>
|
||||
<string name="emulation_notification_channel_name">에뮬레이션이 활성화됨</string>
|
||||
<string name="emulation_notification_channel_description">에뮬레이션이 실행 중일 때 영구 알림을 표시합니다.</string>
|
||||
<string name="emulation_notification_running">yuzu가 실행 중입니다.</string>
|
||||
<string name="notice_notification_channel_name">알림 및 오류</string>
|
||||
<string name="notice_notification_channel_description">문제가 발생하면 알림을 표시합니다.</string>
|
||||
<string name="notification_permission_not_granted">알림 권한이 부여되지 않았습니다!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">환영합니다!</string>
|
||||
<string name="welcome_description"><b>yuzu</b> 를 설정하고 에뮬레이션으로 이동하는 방법을 알아보세요.</string>
|
||||
<string name="get_started">시작하기</string>
|
||||
<string name="keys">Keys</string>
|
||||
<string name="keys_description">아래 버튼을 사용하여 <b>prod.keys</b> 파일을 선택합니다.</string>
|
||||
<string name="select_keys">keys 선택</string>
|
||||
<string name="games">게임</string>
|
||||
<string name="games_description">아래 버튼으로 <b>게임</b> 폴더를 선택합니다.</string>
|
||||
<string name="done">완료</string>
|
||||
<string name="done_description">모든 준비가 완료되었습니다.\n게임을 즐기세요!</string>
|
||||
<string name="text_continue">계속</string>
|
||||
<string name="next">다음</string>
|
||||
<string name="back">뒤로</string>
|
||||
<string name="add_games">게임 추가</string>
|
||||
<string name="add_games_description">게임 폴더 선택</string>
|
||||
|
||||
<!-- Home strings -->
|
||||
<string name="home_games">게임</string>
|
||||
<string name="home_search">검색</string>
|
||||
<string name="home_settings">설정</string>
|
||||
<string name="empty_gamelist">파일을 찾을 수 없거나 아직 게임 디렉토리를 선택하지 않았습니다.</string>
|
||||
<string name="search_and_filter_games">게임 검색 및 필터링</string>
|
||||
<string name="select_games_folder">게임 폴더 선택</string>
|
||||
<string name="select_games_folder_description">yuzu가 게임 목록을 채울 수 있도록 허용</string>
|
||||
<string name="add_games_warning">게임 폴더 선택을 건너뛰겠습니까?</string>
|
||||
<string name="add_games_warning_description">폴더를 선택하지 않으면 게임 목록에 게임이 표시되지 않습니다.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">게임 검색</string>
|
||||
<string name="games_dir_selected">게임 디렉터리 선택</string>
|
||||
<string name="install_prod_keys">prod.keys 설치</string>
|
||||
<string name="install_prod_keys_description">판매용 게임 암호 해독에 요구</string>
|
||||
<string name="install_prod_keys_warning">keys 추가를 건너뛰겠습니까?</string>
|
||||
<string name="install_prod_keys_warning_description">정품 게임을 에뮬레이트하려면 유효한 keys가 필요합니다. 계속하면 자체 제작 앱만 작동합니다.</string>
|
||||
<string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">알림</string>
|
||||
<string name="notifications_description">아래 버튼으로 알림 권한을 부여합니다.</string>
|
||||
<string name="give_permission">권한 부여</string>
|
||||
<string name="notification_warning">알림 권한 부여를 건너뛰겠습니까?</string>
|
||||
<string name="notification_warning_description">yuzu는 중요한 정보를 알려드리지 않습니다.</string>
|
||||
<string name="permission_denied">권한 거부됨</string>
|
||||
<string name="permission_denied_description">이 권한을 너무 많이 거부했으므로 이제 시스템 설정에서 수동으로 권한을 부여해야 합니다.</string>
|
||||
<string name="about">정보</string>
|
||||
<string name="about_description">빌드 버전, 크레딧 등</string>
|
||||
<string name="warning_help">도움말</string>
|
||||
<string name="warning_skip">건너뛰기</string>
|
||||
<string name="warning_cancel">취소</string>
|
||||
<string name="install_amiibo_keys">Amiibo keys 설치</string>
|
||||
<string name="install_amiibo_keys_description">게임에서 아미보 사용 시 필요</string>
|
||||
<string name="invalid_keys_file">잘못된 keys 파일 선택</string>
|
||||
<string name="install_keys_success">keys가 성공적으로 설치됨</string>
|
||||
<string name="reading_keys_failure">암호화 keys 읽기 오류</string>
|
||||
<string name="invalid_keys_error">잘못된 암호화 keys</string>
|
||||
<string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
|
||||
<string name="install_keys_failure_description">선택한 파일이 잘못되었거나 손상되었습니다. keys를 다시 덤프하세요.</string>
|
||||
<string name="install_gpu_driver">GPU 드라이버 설치</string>
|
||||
<string name="install_gpu_driver_description">잠재적으로 더 나은 성능 또는 정확성을 위해 대체 드라이버를 설치하세요.</string>
|
||||
<string name="advanced_settings">고급 설정</string>
|
||||
<string name="settings_description">에뮬레이터 설정 구성</string>
|
||||
<string name="search_recently_played">최근 플레이한 게임</string>
|
||||
<string name="search_recently_added">최근 추가한 게임</string>
|
||||
<string name="search_retail">판매용</string>
|
||||
<string name="search_homebrew">홈브류</string>
|
||||
<string name="open_user_folder">yuzu 폴더 열기</string>
|
||||
<string name="open_user_folder_description">yuzu의 내부 파일 관리</string>
|
||||
<string name="theme_and_color_description">앱 모양 수정</string>
|
||||
<string name="no_file_manager">파일 관리자를 찾을 수 없음</string>
|
||||
<string name="notification_no_directory_link">yuzu 디렉토리를 열 수 없음</string>
|
||||
<string name="notification_no_directory_link_description">파일 관리자의 사이드 패널에서 사용자 폴더를 수동으로 찾아주세요.</string>
|
||||
<string name="manage_save_data">저장 데이터 관리</string>
|
||||
<string name="manage_save_data_description">데이터를 저장했습니다. 아래에서 옵션을 선택하세요.</string>
|
||||
<string name="import_export_saves_description">저장 파일 가져오기 또는 내보내기</string>
|
||||
<string name="import_export_saves_no_profile">저장 데이터를 찾을 수 없습니다. 게임을 실행한 후 다시 시도하세요.</string>
|
||||
<string name="save_file_imported_success">가져오기 성공</string>
|
||||
<string name="save_file_invalid_zip_structure">저장 디렉터리 구조가 잘못됨</string>
|
||||
<string name="save_file_invalid_zip_structure_description">첫 번째 하위 폴더 이름은 게임의 타이틀 ID여야 합니다.</string>
|
||||
<string name="import_saves">가져오기</string>
|
||||
<string name="export_saves">내보내기</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">가이아는 진짜가 아님</string>
|
||||
<string name="copied_to_clipboard">클립보드에 복사</string>
|
||||
<string name="about_app_description">오픈 소스 스위치 에뮬레이터</string>
|
||||
<string name="contributors">기여자</string>
|
||||
<string name="contributors_description">yuzu 팀의 \u2764로 제작</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="build">빌드</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">미리 체험하기</string>
|
||||
<string name="get_early_access">미리 체험하기 신청</string>
|
||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
||||
<string name="get_early_access_description">최첨단 기능, 미리 체험하기 업데이트 등</string>
|
||||
<string name="early_access_benefits">미리 체험하기 혜택</string>
|
||||
<string name="cutting_edge_features">최첨단 기능</string>
|
||||
<string name="early_access_updates">미리 체험하기 업데이트</string>
|
||||
<string name="no_manual_installation">수동 설치 불필요</string>
|
||||
<string name="prioritized_support">우선 지원</string>
|
||||
<string name="helping_game_preservation">게임 보존 도움주기</string>
|
||||
<string name="our_eternal_gratitude">영원한 감사의 마음을 전합니다</string>
|
||||
<string name="are_you_interested">관심 있으세요?</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">제한 속도 활성화</string>
|
||||
<string name="frame_limit_enable_description">활성화하면 에뮬레이션 속도가 정상 속도의 지정된 비율로 제한됩니다.</string>
|
||||
<string name="frame_limit_slider">속도 제한 비율</string>
|
||||
<string name="frame_limit_slider_description">에뮬레이션 속도를 제한할 비율을 지정합니다. 기본값인 100%로 설정하면 에뮬레이션이 정상 속도로 제한됩니다. 값이 높거나 낮으면 속도 제한이 증가하거나 감소합니다.</string>
|
||||
<string name="cpu_accuracy">CPU 정확도</string>
|
||||
|
||||
<!-- System settings strings -->
|
||||
<string name="use_docked_mode">도킹 모드</string>
|
||||
<string name="use_docked_mode_description">도킹 모드에서 에뮬레이션하면 성능이 저하되는 대신 해상도가 향상됩니다.</string>
|
||||
<string name="emulated_region">에뮬레이트된 지역</string>
|
||||
<string name="emulated_language">에뮬레이트된 언어</string>
|
||||
<string name="select_rtc_date">RTC 날짜 선택</string>
|
||||
<string name="select_rtc_time">RTC 시간 선택</string>
|
||||
<string name="use_custom_rtc">커스텀 RTC 활성화</string>
|
||||
<string name="use_custom_rtc_description">이 설정을 사용하면 현재 시스템 시간과 별도로 사용자 지정 실시간 시계를 설정할 수 있음</string>
|
||||
<string name="set_custom_rtc">커스텀 RTC 설정</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer_api">API</string>
|
||||
<string name="renderer_accuracy">정확도 수준</string>
|
||||
<string name="renderer_resolution">해상도</string>
|
||||
<string name="renderer_vsync">수직동기화 모드</string>
|
||||
<string name="renderer_aspect_ratio">화면비</string>
|
||||
<string name="renderer_scaling_filter">창 적응 필터</string>
|
||||
<string name="renderer_anti_aliasing">안티-에일리어싱 방법</string>
|
||||
<string name="renderer_force_max_clock">최대 클럭 강제 설정 (아드레노만 해당)</string>
|
||||
<string name="renderer_force_max_clock_description">GPU가 가능한 최대 클럭으로 실행되도록 강제합니다 (열 제약 조건은 여전히 적용됩니다).</string>
|
||||
<string name="renderer_asynchronous_shaders">비동기 셰이더 사용</string>
|
||||
<string name="renderer_asynchronous_shaders_description">셰이더를 비동기식으로 컴파일하므로 끊김 현상이 줄어들지만 글리치가 발생할 수 있습니다.</string>
|
||||
<string name="renderer_debug">그래픽 디버깅 활성화</string>
|
||||
<string name="renderer_debug_description">이 옵션을 선택하면 그래픽 API가 느린 디버깅 모드로 전환됩니다.</string>
|
||||
<string name="use_disk_shader_cache">디스크 셰이더 캐시 사용</string>
|
||||
<string name="use_disk_shader_cache_description">생성된 셰이더를 디스크에 저장하고 불러오기하여 끊김 현상을 줄입니다.</string>
|
||||
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">볼륨</string>
|
||||
<string name="audio_volume_description">오디오 출력의 볼륨을 지정합니다.</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="slider_default">기본값</string>
|
||||
<string name="ini_saved">저장된 설정</string>
|
||||
<string name="gameid_saved">%1$s를 위해 저장된 설정</string>
|
||||
<string name="error_saving">%1$s.ini 저장 중 오류: %2$s</string>
|
||||
<string name="loading">불러오기 중...</string>
|
||||
<string name="reset_setting_confirmation">이 설정을 기본값으로 되돌리겠습니까?</string>
|
||||
<string name="reset_to_default">기본값으로 재설정</string>
|
||||
<string name="reset_all_settings">모든 설정을 초기화하겠습니까?</string>
|
||||
<string name="reset_all_settings_description">모든 고급 설정이 기본 구성으로 재설정됩니다. 이 설정은 되돌릴 수 없습니다.</string>
|
||||
<string name="settings_reset">설정 초기화</string>
|
||||
<string name="close">닫기</string>
|
||||
<string name="learn_more">자세히 알아보기</string>
|
||||
|
||||
<!-- GPU driver installation -->
|
||||
<string name="select_gpu_driver">GPU 드라이버 선택</string>
|
||||
<string name="select_gpu_driver_title">현재 사용 중인 GPU 드라이버를 교체하겠습니까?</string>
|
||||
<string name="select_gpu_driver_install">설치</string>
|
||||
<string name="select_gpu_driver_default">기본값</string>
|
||||
<string name="select_gpu_driver_install_success">설치된 %s</string>
|
||||
<string name="select_gpu_driver_use_default">기본 GPU 드라이버 사용</string>
|
||||
<string name="select_gpu_driver_error">시스템 기본값을 사용하여 잘못된 드라이버를 선택했습니다!</string>
|
||||
<string name="system_gpu_driver">시스템 GPU 드라이버</string>
|
||||
<string name="installing_driver">드라이버 설치 중...</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">설정</string>
|
||||
<string name="preferences_general">일반</string>
|
||||
<string name="preferences_system">시스템</string>
|
||||
<string name="preferences_graphics">그래픽</string>
|
||||
<string name="preferences_audio">오디오</string>
|
||||
<string name="preferences_theme">테마 및 색상</string>
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">롬이 암호화되었음</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[가이드에 따라 <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">게임 카트리지</a> 또는 <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">설치된 타이틀</a>를 다시 덤프하세요.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[P게임을 해독할 수 있도록 <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파일이 설치되어 있는지 확인하세요.]]></string>
|
||||
<string name="loader_error_video_core">비디오 코어를 초기화하는 동안 오류 발생</string>
|
||||
<string name="loader_error_video_core_description">이 문제는 일반적으로 호환되지 않는 GPU 드라이버로 인해 발생합니다. 사용자 지정 GPU 드라이버를 설치하면 이 문제가 해결될 수 있습니다.</string>
|
||||
<string name="loader_error_invalid_format">롬을 불러올 수 없음</string>
|
||||
<string name="loader_error_file_not_found">롬 파일이 존재하지 않음</string>
|
||||
|
||||
<!-- Emulation Menu -->
|
||||
<string name="emulation_exit">에뮬레이션 종료</string>
|
||||
<string name="emulation_done">완료</string>
|
||||
<string name="emulation_fps_counter">FPS 카운터</string>
|
||||
<string name="emulation_toggle_controls">토글 제어</string>
|
||||
<string name="emulation_rel_stick_center">상대 스틱 센터</string>
|
||||
<string name="emulation_dpad_slide">십자패드 슬라이드</string>
|
||||
<string name="emulation_haptics">햅틱</string>
|
||||
<string name="emulation_show_overlay">오버레이 표시</string>
|
||||
<string name="emulation_toggle_all">모두 토글</string>
|
||||
<string name="emulation_control_adjust">오버레이 조정</string>
|
||||
<string name="emulation_control_scale">스케일</string>
|
||||
<string name="emulation_control_opacity">불투명도</string>
|
||||
<string name="emulation_touch_overlay_reset">오버레이 재설정</string>
|
||||
<string name="emulation_touch_overlay_edit">오버레이 편집</string>
|
||||
<string name="emulation_pause">에뮬레이션 일시 중지</string>
|
||||
<string name="emulation_unpause">에뮬레이션 일시 중지 해제</string>
|
||||
<string name="emulation_input_overlay">오버레이 옵션</string>
|
||||
<string name="emulation_game_loading">게임 불러오기 중...</string>
|
||||
|
||||
<string name="load_settings">설정 불러오기 중...</string>
|
||||
|
||||
<!-- Software keyboard -->
|
||||
<string name="software_keyboard">가상 키보드</string>
|
||||
|
||||
<!-- Errors and warnings -->
|
||||
<string name="abort_button">정보</string>
|
||||
<string name="continue_button">계속</string>
|
||||
<string name="system_archive_not_found">시스템 아카이브를 찾을 수 없음</string>
|
||||
<string name="system_archive_not_found_message">%s가 누락되었습니다. 시스템 아카이브를 덤프하세요.\n에뮬레이션을 계속하면 충돌 및 버그가 발생할 수 있습니다.</string>
|
||||
<string name="system_archive_general">시스템 아카이브</string>
|
||||
<string name="save_load_error">저장하기/불러오기 오류</string>
|
||||
<string name="fatal_error">치명적인 오류</string>
|
||||
<string name="fatal_error_message">치명적인 오류가 발생했습니다. 자세한 내용은 로그를 확인하십시오.\n에뮬레이션을 계속하면 충돌 및 버그가 발생할 수 있습니다.</string>
|
||||
<string name="performance_warning">이 설정을 끄면 에뮬레이션 성능이 크게 저하됩니다! 최상의 환경을 위해 이 설정을 활성화된 상태로 두는 것이 좋습니다.</string>
|
||||
|
||||
<!-- Region Names -->
|
||||
<string name="region_japan">일본</string>
|
||||
<string name="region_usa">미국</string>
|
||||
<string name="region_europe">유럽</string>
|
||||
<string name="region_australia">호주</string>
|
||||
<string name="region_china">중국</string>
|
||||
<string name="region_korea">대한민국</string>
|
||||
<string name="region_taiwan">타이완</string>
|
||||
|
||||
<!-- Language Names -->
|
||||
<string name="language_japanese">일본어 (日本語)</string>
|
||||
<string name="language_english">영어 (English)</string>
|
||||
<string name="language_french">프랑스어 (Français)</string>
|
||||
<string name="langauge_german">독일어(Deutsch)</string>
|
||||
<string name="language_italian">이탈리아어 (Italiano)</string>
|
||||
<string name="language_spanish">스페인어 (Español)</string>
|
||||
<string name="language_chinese">중국어 (简体中文)</string>
|
||||
<string name="language_korean">한국어 (Korean)</string>
|
||||
<string name="language_dutch">네덜란드어 (Nederlands)</string>
|
||||
<string name="language_portuguese">포르투갈어 (Português)</string>
|
||||
<string name="language_russian">러시아어 (Русский)</string>
|
||||
<string name="language_taiwanese">대만어 (台湾)</string>
|
||||
<string name="language_british_english">영어 (British English)</string>
|
||||
<string name="language_canadian_french">캐나다 프랑스어 (Français canadien)</string>
|
||||
<string name="language_latin_american_spanish">라틴 아메리카 스페인어 (Español latinoamericano)</string>
|
||||
<string name="language_simplified_chinese">중국어 간체 (简体中文)</string>
|
||||
<string name="language_traditional_chinese">중국어 번체 (正體中文)</string>
|
||||
<string name="language_brazilian_portuguese">브라질 포르투갈어 (Português do Brasil)</string>
|
||||
|
||||
<!-- Renderer APIs -->
|
||||
<string name="renderer_vulkan">불칸</string>
|
||||
<string name="renderer_none">없음</string>
|
||||
|
||||
<!-- Renderer Accuracy -->
|
||||
<string name="renderer_accuracy_normal">보통</string>
|
||||
<string name="renderer_accuracy_high">높음</string>
|
||||
<string name="renderer_accuracy_extreme">극한 (느림)</string>
|
||||
|
||||
<!-- Resolutions -->
|
||||
<string name="resolution_half">0.5X (360p/540p)</string>
|
||||
<string name="resolution_three_quarter">0.75X (540p/810p)</string>
|
||||
<string name="resolution_one">1X (720p/1080p)</string>
|
||||
<string name="resolution_two">2X (1440p/2160p) (느림)</string>
|
||||
<string name="resolution_three">3X (2160p/3240p) (느림)</string>
|
||||
<string name="resolution_four">4X (2880p/4320p) (느림)</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">즉시 (끔)</string>
|
||||
<string name="renderer_vsync_mailbox">메일박스</string>
|
||||
<string name="renderer_vsync_fifo">FIFO (켬)</string>
|
||||
<string name="renderer_vsync_fifo_relaxed">FIFO 릴랙스</string>
|
||||
|
||||
<!-- Scaling Filters -->
|
||||
<string name="scaling_filter_nearest_neighbor">가장 가까운 이웃</string>
|
||||
<string name="scaling_filter_bilinear">이중선형</string>
|
||||
<string name="scaling_filter_bicubic">고등차수보간</string>
|
||||
<string name="scaling_filter_gaussian">가우시안</string>
|
||||
<string name="scaling_filter_scale_force">스케일포스</string>
|
||||
<string name="scaling_filter_fsr">AMD FidelityFX™ 초고해상도</string>
|
||||
|
||||
<!-- Anti-Aliasing -->
|
||||
<string name="anti_aliasing_none">없음</string>
|
||||
<string name="anti_aliasing_fxaa">FXAA</string>
|
||||
<string name="anti_aliasing_smaa">SMAA</string>
|
||||
|
||||
<!-- Aspect Ratios -->
|
||||
<string name="ratio_default">기본 (16:9)</string>
|
||||
<string name="ratio_force_four_three">강제 4:3</string>
|
||||
<string name="ratio_force_twenty_one_nine">강제 21:9</string>
|
||||
<string name="ratio_force_sixteen_ten">강제 16:10</string>
|
||||
<string name="ratio_stretch">창에 맞게 늘림</string>
|
||||
|
||||
<!-- CPU Accuracy -->
|
||||
<string name="cpu_accuracy_accurate">정확함</string>
|
||||
<string name="cpu_accuracy_unsafe">안전하지 않음</string>
|
||||
<string name="cpu_accuracy_paranoid">편집증 (느림)</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">십자패드</string>
|
||||
<string name="gamepad_left_stick">L 스틱</string>
|
||||
<string name="gamepad_right_stick">R 스틱</string>
|
||||
<string name="gamepad_home">홈</string>
|
||||
<string name="gamepad_screenshot">스크린샷</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="preparing_shaders">셰이더 준비하기</string>
|
||||
<string name="building_shaders">셰이더 빌드 중</string>
|
||||
|
||||
<!-- Theme options -->
|
||||
<string name="change_app_theme">앱 테마 변경</string>
|
||||
<string name="theme_default">기본값</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">테마 모드 변경</string>
|
||||
<string name="theme_mode_follow_system">팔로우 시스템</string>
|
||||
<string name="theme_mode_light">밝음</string>
|
||||
<string name="theme_mode_dark">어두움</string>
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">검은색 배경 사용</string>
|
||||
<string name="use_black_backgrounds_description">어두운 테마를 사용할 때는 검은색 배경을 적용합니다.</string>
|
||||
|
||||
</resources>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user