mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-08 18:31:29 -06:00
Merge branch 'master' into Shader-JIT-Multithreading
This commit is contained in:
commit
641691c497
@ -9,8 +9,14 @@ fi
|
||||
|
||||
cd src/android
|
||||
chmod +x ./gradlew
|
||||
./gradlew assembleRelease
|
||||
./gradlew bundleRelease
|
||||
|
||||
if [[ "$TARGET" == "googleplay" ]]; then
|
||||
./gradlew assembleGooglePlayRelease
|
||||
./gradlew bundleGooglePlayRelease
|
||||
else
|
||||
./gradlew assembleVanillaRelease
|
||||
./gradlew bundleVanillaRelease
|
||||
fi
|
||||
|
||||
ccache -s -v
|
||||
|
||||
|
||||
17
.ci/docker.sh
Executable file
17
.ci/docker.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
GITREV="`git show -s --format='%h'`" || true
|
||||
|
||||
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
||||
TAG_NAME=$GITHUB_REF_NAME
|
||||
elif [[ -n $GITREV ]]; then
|
||||
TAG_NAME=$GITREV
|
||||
else
|
||||
TAG_NAME=unknown
|
||||
fi
|
||||
|
||||
echo "Tag name is: $TAG_NAME"
|
||||
|
||||
docker build -f docker/azahar-room/Dockerfile -t azahar-room:$TAG_NAME .
|
||||
mkdir -p build
|
||||
docker save azahar-room:$TAG_NAME > build/azahar-room-$TAG_NAME.dockerimage
|
||||
12
.ci/linux.sh
12
.ci/linux.sh
@ -1,14 +1,16 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
if [ "$TARGET" = "appimage" ]; then
|
||||
if [[ "$TARGET" == "appimage"* ]]; then
|
||||
# Compile the AppImage we distribute with Clang.
|
||||
export EXTRA_CMAKE_FLAGS=(-DCMAKE_CXX_COMPILER=clang++
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_LINKER=/etc/bin/ld.lld
|
||||
-DENABLE_ROOM_STANDALONE=OFF)
|
||||
# Bundle required QT wayland libraries
|
||||
export EXTRA_QT_PLUGINS="waylandcompositor"
|
||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
||||
if [ "$TARGET" = "appimage-wayland" ]; then
|
||||
# Bundle required QT wayland libraries
|
||||
export EXTRA_QT_PLUGINS="waylandcompositor"
|
||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
||||
fi
|
||||
else
|
||||
# For the linux-fresh verification target, verify compilation without PCH as well.
|
||||
export EXTRA_CMAKE_FLAGS=(-DCITRA_USE_PRECOMPILED_HEADERS=OFF)
|
||||
@ -30,7 +32,7 @@ cmake .. -G Ninja \
|
||||
ninja
|
||||
strip -s bin/Release/*
|
||||
|
||||
if [ "$TARGET" = "appimage" ]; then
|
||||
if [[ "$TARGET" == "appimage"* ]]; then
|
||||
ninja bundle
|
||||
# TODO: Our AppImage environment currently uses an older ccache version without the verbose flag.
|
||||
ccache -s
|
||||
|
||||
60
.github/workflows/build.yml
vendored
60
.github/workflows/build.yml
vendored
@ -22,12 +22,13 @@ jobs:
|
||||
with:
|
||||
name: source
|
||||
path: artifacts/
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ["appimage", "fresh"]
|
||||
target: ["appimage", "appimage-wayland", "fresh"]
|
||||
container:
|
||||
image: opensauce04/azahar-build-environment:latest
|
||||
options: -u 1001
|
||||
@ -51,16 +52,21 @@ jobs:
|
||||
- name: Build
|
||||
run: ./.ci/linux.sh
|
||||
- name: Move AppImage to artifacts directory
|
||||
if: ${{ matrix.target == 'appimage' }}
|
||||
if: ${{ contains(matrix.target, 'appimage') }}
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
mv build/bundle/*.AppImage artifacts/
|
||||
- name: Rename AppImage
|
||||
if: ${{ matrix.target == 'appimage-wayland' }}
|
||||
run: |
|
||||
mv artifacts/azahar.AppImage artifacts/azahar-wayland.AppImage
|
||||
- name: Upload
|
||||
if: ${{ matrix.target == 'appimage' }}
|
||||
if: ${{ contains(matrix.target, 'appimage') }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
|
||||
macos:
|
||||
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-15-intel') || 'macos-26' }}
|
||||
strategy:
|
||||
@ -102,6 +108,7 @@ jobs:
|
||||
with:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
|
||||
macos-universal:
|
||||
runs-on: macos-26
|
||||
needs: macos
|
||||
@ -133,6 +140,7 @@ jobs:
|
||||
with:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
@ -210,54 +218,92 @@ jobs:
|
||||
with:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
|
||||
android:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ["vanilla", "googleplay"]
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPILERCHECK: content
|
||||
CCACHE_SLOPPINESS: time_macros
|
||||
OS: android
|
||||
TARGET: universal
|
||||
TARGET: ${{ matrix.target }}
|
||||
SHOULD_RUN: ${{ (matrix.target == 'vanilla' || github.ref_type == 'tag') }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up cache
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
${{ env.CCACHE_DIR }}
|
||||
key: ${{ runner.os }}-android-${{ github.sha }}
|
||||
key: ${{ runner.os }}-${{ env.OS }}-${{ matrix.target }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-android-
|
||||
${{ runner.os }}-${{ env.OS }}-${{ matrix.target }}-
|
||||
- name: Set tag name
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
|
||||
echo "GIT_TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
|
||||
fi
|
||||
echo $GIT_TAG_NAME
|
||||
- name: Deps
|
||||
- name: Install tools
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install ccache apksigner -y
|
||||
- name: Update Android SDK CMake version
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
run: |
|
||||
echo "y" | ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "cmake;3.30.3"
|
||||
- name: Build
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
run: JAVA_HOME=$JAVA_HOME_17_X64 ./.ci/android.sh
|
||||
env:
|
||||
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
|
||||
- name: Pack
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
run: ../../../.ci/pack.sh
|
||||
working-directory: src/android/app
|
||||
env:
|
||||
UNPACKED: 1
|
||||
- name: Upload
|
||||
if: ${{ env.SHOULD_RUN == 'true' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: src/android/app/artifacts/
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker:dind
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install tools
|
||||
run: apk add bash
|
||||
- name: Fix git ownership
|
||||
run: git config --global --add safe.directory .
|
||||
- name: Build Docker image
|
||||
run: ./.ci/docker.sh
|
||||
- name: Move Docker image to artifacts directory
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
mv build/*.dockerimage artifacts/
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docker
|
||||
path: artifacts/
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,9 @@ src/installer/*.exe
|
||||
src/common/scm_rev.cpp
|
||||
.travis.descriptor.json
|
||||
|
||||
# Docker image files
|
||||
*.dockerimage
|
||||
|
||||
# Project/editor files
|
||||
*.swp
|
||||
*.kdev4
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -100,3 +100,6 @@
|
||||
[submodule "spirv-headers"]
|
||||
path = externals/spirv-headers
|
||||
url = https://github.com/KhronosGroup/SPIRV-Headers
|
||||
[submodule "externals/xxHash"]
|
||||
path = externals/xxHash
|
||||
url = https://github.com/Cyan4973/xxHash.git
|
||||
|
||||
42
README.md
42
README.md
@ -1,7 +1,9 @@
|
||||

|
||||
|
||||

|
||||
 <!--  -->
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
<b>Azahar</b> is an open-source 3DS emulator project based on Citra.
|
||||
@ -14,9 +16,11 @@ The goal of this project is to be the de-facto platform for future development.
|
||||
|
||||
### Windows
|
||||
|
||||
Download the latest release from [Releases](https://github.com/azahar-emu/azahar/releases).
|
||||
Azahar is available as both an installer and a zip archive.
|
||||
|
||||
If you are unsure of whether you want to use MSYS2 or MSVC, use MSYS2.
|
||||
Download the latest release in your preferred format from the [Releases](https://github.com/azahar-emu/azahar/releases) page.
|
||||
|
||||
If you are unsure of whether you want to use MSVC or MSYS2, use MSYS2.
|
||||
|
||||
---
|
||||
|
||||
@ -30,23 +34,30 @@ Alternatively, if you wish to download a build specifically for your Mac, you ca
|
||||
- `macos-x86_64` for Intel Macs
|
||||
|
||||
---
|
||||
|
||||
### Android
|
||||
The recommended method of downloading Azahar on Android is via the Google Play store:
|
||||
|
||||
There are two variants of Azahar available on Android, those being the Vanilla and Google Play builds.
|
||||
|
||||
The Vanilla build is technically superior, as it uses an alternative method of file management which is faster, but isn't permitted on the Google Play store.
|
||||
|
||||
For most users, we currently recommended downloading Azahar on Android via the Google Play Store for ease of accessibility:
|
||||
|
||||
<a href='https://play.google.com/store/apps/details?id=io.github.lime3ds.android'><img width='180' alt='Get it on Google Play' src='https://raw.githubusercontent.com/pioug/google-play-badges/06ccd9252af1501613da2ca28eaffe31307a4e6d/svg/English.svg'/></a>
|
||||
|
||||
Alternatively, you can install the app using Obtainium:
|
||||
Alternatively, you can install the app using Obtainium, allowing you to use the Vanilla variant:
|
||||
1. Download and install Obtainium from [here](https://github.com/ImranR98/Obtainium/releases) (use the file named `app-release.apk`)
|
||||
2. Open Obtainium and click 'Add App'
|
||||
3. Type `https://github.com/azahar-emu/azahar` into the 'App Source URL' section
|
||||
4. Click 'Add'
|
||||
5. Click 'Install'
|
||||
5. Click 'Install', and select the preferred variant
|
||||
|
||||
If you wish, you can also simply install the latest APK from the [Releases](https://github.com/azahar-emu/azahar/releases) page.
|
||||
|
||||
Keep in mind that you will not recieve automatic updates when installing via the APK.
|
||||
|
||||
---
|
||||
|
||||
### Linux
|
||||
|
||||
The recommended format for using Azahar on Linux is the Flatpak available on Flathub:
|
||||
@ -55,6 +66,13 @@ The recommended format for using Azahar on Linux is the Flatpak available on Fla
|
||||
|
||||
Azahar is also available as an AppImage on the [Releases](https://github.com/azahar-emu/azahar/releases) page.
|
||||
|
||||
There are two variants of the AppImage available, those being `azahar.AppImage` and `azahar-wayland.AppImage`.
|
||||
|
||||
If you are unsure of which variant to use, we recommend using the default `azahar.AppImage`. This is because of upstream issues in the Wayland ecosystem which may cause problems when running the emulator (e.g. [#1162](https://github.com/azahar-emu/azahar/issues/1162)).
|
||||
|
||||
Unless you explicitly require native Wayland support (e.g. you are running a system with no Xwayland), the non-Wayland variant is recommended.
|
||||
|
||||
The Flatpak build of Azahar also has native Wayland support disabled by default. If you require native Wayland support, it can be enabled using [Flatseal](https://flathub.org/en/apps/com.github.tchx84.Flatseal).
|
||||
|
||||
# Build instructions
|
||||
|
||||
@ -86,18 +104,23 @@ To do so, simply read https://github.com/azahar-emu/compatibility-list/blob/mast
|
||||
Contributing compatibility data helps more accurately reflect the current capabilities of the emulator, so it would be highly appreciated if you could go through the reporting process after completing a game.
|
||||
|
||||
# Minimum requirements
|
||||
|
||||
Below are the minimum requirements to run Azahar:
|
||||
|
||||
### Desktop
|
||||
|
||||
```
|
||||
Operating System: Windows 10 (64-bit), MacOS 13.4 (Ventura), or modern 64-bit Linux
|
||||
CPU: x86-64/ARM64 CPU (Windows for ARM not supported). Single core performance higher than 1,800 on Passmark
|
||||
CPU: x86-64/ARM64 CPU (Windows for ARM not supported).
|
||||
Single core performance higher than 1,800 on Passmark.
|
||||
SSE4.2 required on x86_64.
|
||||
GPU: OpenGL 4.3 or Vulkan 1.1 support
|
||||
Memory: 2GB of RAM. 4GB is recommended
|
||||
```
|
||||
### Android
|
||||
|
||||
```
|
||||
Operating System: Android 9.0+ (64-bit)
|
||||
Operating System: Android 10.0+ (64-bit)
|
||||
CPU: Snapdragon 835 SoC or better
|
||||
GPU: OpenGL ES 3.2 or Vulkan 1.1 support
|
||||
Memory: 2GB of RAM. 4GB is recommended
|
||||
@ -110,6 +133,7 @@ We share public roadmaps for upcoming releases in the form of GitHub milestones.
|
||||
You can find these at https://github.com/azahar-emu/azahar/milestones.
|
||||
|
||||
# Join the conversation
|
||||
|
||||
We have a community Discord server where you can chat about the project, keep up to date with the latest announcements, or coordinate emulator development.
|
||||
|
||||
[](https://discord.gg/4ZjMpAp3M6)
|
||||
Join at https://discord.gg/4ZjMpAp3M6
|
||||
|
||||
2
dist/compatibility_list
vendored
2
dist/compatibility_list
vendored
@ -1 +1 @@
|
||||
Subproject commit a36decbe43d0e5a570ac3d3ba9a0b226dc832a17
|
||||
Subproject commit eadcdfb84b6f3b95734e867d99fe16a9e8db717f
|
||||
1041
dist/languages/ca_ES_valencia.ts
vendored
1041
dist/languages/ca_ES_valencia.ts
vendored
File diff suppressed because it is too large
Load Diff
997
dist/languages/da_DK.ts
vendored
997
dist/languages/da_DK.ts
vendored
File diff suppressed because it is too large
Load Diff
1029
dist/languages/de.ts
vendored
1029
dist/languages/de.ts
vendored
File diff suppressed because it is too large
Load Diff
991
dist/languages/el.ts
vendored
991
dist/languages/el.ts
vendored
File diff suppressed because it is too large
Load Diff
995
dist/languages/es_ES.ts
vendored
995
dist/languages/es_ES.ts
vendored
File diff suppressed because it is too large
Load Diff
987
dist/languages/fi.ts
vendored
987
dist/languages/fi.ts
vendored
File diff suppressed because it is too large
Load Diff
1041
dist/languages/fr.ts
vendored
1041
dist/languages/fr.ts
vendored
File diff suppressed because it is too large
Load Diff
999
dist/languages/hu_HU.ts
vendored
999
dist/languages/hu_HU.ts
vendored
File diff suppressed because it is too large
Load Diff
993
dist/languages/id.ts
vendored
993
dist/languages/id.ts
vendored
File diff suppressed because it is too large
Load Diff
1061
dist/languages/it.ts
vendored
1061
dist/languages/it.ts
vendored
File diff suppressed because it is too large
Load Diff
1071
dist/languages/ja_JP.ts
vendored
1071
dist/languages/ja_JP.ts
vendored
File diff suppressed because it is too large
Load Diff
1007
dist/languages/ko_KR.ts
vendored
1007
dist/languages/ko_KR.ts
vendored
File diff suppressed because it is too large
Load Diff
987
dist/languages/lt_LT.ts
vendored
987
dist/languages/lt_LT.ts
vendored
File diff suppressed because it is too large
Load Diff
991
dist/languages/nb.ts
vendored
991
dist/languages/nb.ts
vendored
File diff suppressed because it is too large
Load Diff
1017
dist/languages/nl.ts
vendored
1017
dist/languages/nl.ts
vendored
File diff suppressed because it is too large
Load Diff
998
dist/languages/pl_PL.ts
vendored
998
dist/languages/pl_PL.ts
vendored
File diff suppressed because it is too large
Load Diff
1069
dist/languages/pt_BR.ts
vendored
1069
dist/languages/pt_BR.ts
vendored
File diff suppressed because it is too large
Load Diff
1021
dist/languages/ro_RO.ts
vendored
1021
dist/languages/ro_RO.ts
vendored
File diff suppressed because it is too large
Load Diff
1029
dist/languages/ru_RU.ts
vendored
1029
dist/languages/ru_RU.ts
vendored
File diff suppressed because it is too large
Load Diff
1034
dist/languages/sv.ts
vendored
1034
dist/languages/sv.ts
vendored
File diff suppressed because it is too large
Load Diff
1057
dist/languages/tr_TR.ts
vendored
1057
dist/languages/tr_TR.ts
vendored
File diff suppressed because it is too large
Load Diff
1007
dist/languages/vi_VN.ts
vendored
1007
dist/languages/vi_VN.ts
vendored
File diff suppressed because it is too large
Load Diff
1015
dist/languages/zh_CN.ts
vendored
1015
dist/languages/zh_CN.ts
vendored
File diff suppressed because it is too large
Load Diff
1003
dist/languages/zh_TW.ts
vendored
1003
dist/languages/zh_TW.ts
vendored
File diff suppressed because it is too large
Load Diff
1
dist/license.md
vendored
1
dist/license.md
vendored
@ -16,6 +16,7 @@ qt_themes/default/icons/48x48/no_avatar.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/128x128/cartridge.png | CC0 1.0 | Designed by PabloMK7
|
||||
qt_themes/qdarkstyle/icons/16x16/connected.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/connected_notification.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/disconnected.png | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
BIN
dist/qt_themes/default/icons/128x128/cartridge.png
vendored
Normal file
BIN
dist/qt_themes/default/icons/128x128/cartridge.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
7
dist/qt_themes/default/icons/index.theme
vendored
7
dist/qt_themes/default/icons/index.theme
vendored
@ -1,13 +1,16 @@
|
||||
[Icon Theme]
|
||||
Name=default
|
||||
Comment=default theme
|
||||
Directories=16x16,48x48,256x256
|
||||
Directories=16x16,48x48,128x128,256x256
|
||||
|
||||
[16x16]
|
||||
Size=16
|
||||
|
||||
[48x48]
|
||||
Size=48
|
||||
|
||||
|
||||
[128x128]
|
||||
Size=128
|
||||
|
||||
[256x256]
|
||||
Size=256
|
||||
BIN
dist/qt_themes/default/icons_light/128x128/cartridge.png
vendored
Normal file
BIN
dist/qt_themes/default/icons_light/128x128/cartridge.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@ -1,13 +1,16 @@
|
||||
[Icon Theme]
|
||||
Name=default
|
||||
Comment=default theme
|
||||
Directories=16x16,48x48,256x256
|
||||
Directories=16x16,48x48,128x128,256x256
|
||||
|
||||
[16x16]
|
||||
Size=16
|
||||
|
||||
[48x48]
|
||||
Size=48
|
||||
|
||||
|
||||
[128x128]
|
||||
Size=128
|
||||
|
||||
[256x256]
|
||||
Size=256
|
||||
2
dist/qt_themes/default/theme_default.qrc
vendored
2
dist/qt_themes/default/theme_default.qrc
vendored
@ -13,6 +13,7 @@
|
||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="128x128/cartridge.png">icons/128x128/cartridge.png</file>
|
||||
<file alias="256x256/azahar.png">icons/256x256/azahar.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
@ -31,6 +32,7 @@
|
||||
<file alias="48x48/no_avatar.png">icons_light/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/plus.png">icons_light/48x48/plus.png</file>
|
||||
<file alias="48x48/sd_card.png">icons_light/48x48/sd_card.png</file>
|
||||
<file alias="128x128/cartridge.png">icons_light/128x128/cartridge.png</file>
|
||||
<file alias="256x256/azahar.png">icons_light/256x256/azahar.png</file>
|
||||
<file alias="48x48/star.png">icons_light/48x48/star.png</file>
|
||||
<file alias="256x256/plus_folder.png">icons_light/256x256/plus_folder.png</file>
|
||||
|
||||
31
docker/azahar-room/Dockerfile
Normal file
31
docker/azahar-room/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
||||
# This Dockerfile assumes that it is being built from the project root directory, e.g.:
|
||||
# $ docker build -f docker/azahar-room/Dockerfile -t azahar-room .
|
||||
|
||||
# --- Builder ----------------
|
||||
FROM opensauce04/azahar-build-environment:latest AS builder
|
||||
|
||||
COPY . /var/azahar-src
|
||||
|
||||
RUN mkdir builddir && cd builddir && \
|
||||
cmake /var/azahar-src -G Ninja \
|
||||
-DENABLE_QT=OFF \
|
||||
-DENABLE_TESTS=OFF \
|
||||
-DENABLE_ROOM=ON \
|
||||
-DENABLE_ROOM_STANDALONE=ON \
|
||||
-DENABLE_OPENGL=OFF $( : "TODO: Can we disable these automatically when there's no frontend?") \
|
||||
-DENABLE_VULKAN=OFF \
|
||||
-DENABLE_SDL2=OFF \
|
||||
-DENABLE_LIBUSB=OFF \
|
||||
-DENABLE_CUBEB=OFF \
|
||||
-DENABLE_OPENAL=OFF && \
|
||||
ninja && \
|
||||
mv bin/Release/azahar-room /usr/local/bin/ && \
|
||||
cd .. && rm -rf builddir
|
||||
|
||||
# --- Final ------------------
|
||||
FROM debian:trixie AS final
|
||||
|
||||
RUN apt-get update && apt-get -y full-upgrade
|
||||
RUN apt-get install -y iputils-ping net-tools
|
||||
|
||||
COPY --from=builder /usr/local/bin/azahar-room /usr/local/bin/azahar-room
|
||||
23
externals/CMakeLists.txt
vendored
23
externals/CMakeLists.txt
vendored
@ -243,13 +243,8 @@ else()
|
||||
)
|
||||
target_link_libraries(zstd_seekable PUBLIC libzstd_static)
|
||||
|
||||
target_link_libraries(libzstd_static INTERFACE zstd_seekable)
|
||||
|
||||
add_library(zstd ALIAS libzstd_static)
|
||||
|
||||
install(TARGETS zstd_seekable
|
||||
EXPORT zstdExports
|
||||
)
|
||||
add_library(zstd INTERFACE)
|
||||
target_link_libraries(zstd INTERFACE libzstd_static zstd_seekable)
|
||||
endif()
|
||||
|
||||
# ENet
|
||||
@ -494,3 +489,17 @@ if (ENABLE_VULKAN)
|
||||
add_subdirectory(libadrenotools)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(XXHASH_BUILD_XXHSUM OFF)
|
||||
add_subdirectory(xxHash/cmake_unofficial EXCLUDE_FROM_ALL)
|
||||
target_compile_definitions(xxhash PRIVATE XXH_FORCE_MEMORY_ACCESS=2)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
|
||||
target_compile_definitions(xxhash PRIVATE XXH_VECTOR=XXH_SSE2)
|
||||
message(STATUS "Enabling SSE2 for xxHash")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|armv8")
|
||||
target_compile_definitions(xxhash PRIVATE XXH_VECTOR=XXH_NEON)
|
||||
message(STATUS "Enabling NEON for xxHash")
|
||||
else()
|
||||
target_compile_definitions(xxhash PRIVATE XXH_VECTOR=XXH_SCALAR)
|
||||
message(STATUS "Disabling SIMD for xxHash")
|
||||
endif()
|
||||
2
externals/boost
vendored
2
externals/boost
vendored
@ -1 +1 @@
|
||||
Subproject commit 3c27c785ad0f8a742af02e620dc225673f3a12d8
|
||||
Subproject commit 2c82bd787302398bcae990e3c9ab2b451284f4ca
|
||||
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
@ -1 +1 @@
|
||||
Subproject commit 278405bd71999ed3f3c77c5f78344a06fef798b9
|
||||
Subproject commit 526227eebe1efff3fb14dbf494b9c5b44c2e9c1f
|
||||
2
externals/teakra
vendored
2
externals/teakra
vendored
@ -1 +1 @@
|
||||
Subproject commit 01db7cdd00aabcce559a8dddce8798dabb71949b
|
||||
Subproject commit 3d697a18df504f4677b65129d9ab14c7c597e3eb
|
||||
1
externals/xxHash
vendored
Submodule
1
externals/xxHash
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e626a72bc2321cd320e953a0ccf1584cad60f363
|
||||
@ -357,3 +357,4 @@ plus.png (Default, Dark) | CC0 1.0 | Designed by BreadFish64 fro
|
||||
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||
sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
star.png | CC BY-ND 3.0 | https://icons8.com
|
||||
cartridge.png | CC0 1.0 | Designed by PabloMK7
|
||||
|
||||
@ -125,7 +125,7 @@ android {
|
||||
applicationIdSuffix = ".debug"
|
||||
versionNameSuffix = "-debug"
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isShrinkResources = true
|
||||
isShrinkResources = true // TODO: Does this actually do anything when isDebuggable is enabled? -OS
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
proguardFiles(
|
||||
@ -135,6 +135,22 @@ android {
|
||||
isDefault = true
|
||||
}
|
||||
|
||||
// Same as above, but with isDebuggable disabled.
|
||||
// Primarily exists to allow development on hardened_malloc systems (e.g. GrapheneOS) without constantly tripping over years-old and seemingly harmless memory bugs.
|
||||
// We should fix those bugs eventually, but for now this exists as a workaround to allow other work to be done.
|
||||
register("relWithDebInfoLite") {
|
||||
initWith(getByName("relWithDebInfo"))
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isDebuggable = false
|
||||
installation {
|
||||
enableBaselineProfile = false // Disabled by default when isDebuggable is true
|
||||
}
|
||||
lint {
|
||||
checkReleaseBuilds = false // Ditto
|
||||
// The name of this property is misleading, this doesn't actually disable linting for the `release` build.
|
||||
}
|
||||
}
|
||||
|
||||
// Signed by debug key disallowing distribution on Play Store.
|
||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||
debug {
|
||||
@ -148,6 +164,18 @@ android {
|
||||
|
||||
flavorDimensions.add("version")
|
||||
|
||||
productFlavors {
|
||||
register("vanilla") {
|
||||
isDefault = true
|
||||
dimension = "version"
|
||||
versionNameSuffix = "-vanilla"
|
||||
}
|
||||
register("googlePlay") {
|
||||
dimension = "version"
|
||||
versionNameSuffix = "-googleplay"
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version = "3.25.0+"
|
||||
|
||||
8
src/android/app/src/googlePlay/AndroidManifest.xml
Normal file
8
src/android/app/src/googlePlay/AndroidManifest.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- These permissions aren't allowed by Google. We asked, and they declined. -->
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
|
||||
|
||||
</manifest>
|
||||
@ -29,6 +29,8 @@
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name="org.citra.citra_emu.CitraApplication"
|
||||
|
||||
@ -7,10 +7,12 @@ package org.citra.citra_emu
|
||||
import android.Manifest.permission
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.Surface
|
||||
@ -18,11 +20,16 @@ import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.Keep
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citra.citra_emu.activities.EmulationActivity
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
import org.citra.citra_emu.utils.FileUtil
|
||||
import org.citra.citra_emu.utils.Log
|
||||
import org.citra.citra_emu.utils.RemovableStorageHelper
|
||||
import org.citra.citra_emu.viewmodel.CompressProgressDialogViewModel
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.Date
|
||||
|
||||
@ -132,6 +139,12 @@ object NativeLibrary {
|
||||
external fun createLogFile()
|
||||
external fun logUserDirectory(directory: String)
|
||||
|
||||
/**
|
||||
* Set the inserted cartridge that will appear
|
||||
* in the home menu. Empty string to clear.
|
||||
*/
|
||||
external fun setInsertedCartridge(path: String)
|
||||
|
||||
/**
|
||||
* Begins emulation.
|
||||
*/
|
||||
@ -267,6 +280,12 @@ object NativeLibrary {
|
||||
canContinue = false
|
||||
}
|
||||
|
||||
CoreError.ErrorN3DSApplication -> {
|
||||
title = emulationActivity.getString(R.string.invalid_system_mode)
|
||||
message = emulationActivity.getString(R.string.invalid_system_mode_message)
|
||||
canContinue = false
|
||||
}
|
||||
|
||||
CoreError.ErrorUnknown -> {
|
||||
title = emulationActivity.getString(R.string.fatal_error)
|
||||
message = emulationActivity.getString(R.string.fatal_error_message)
|
||||
@ -589,6 +608,47 @@ object NativeLibrary {
|
||||
*/
|
||||
external fun logDeviceInfo()
|
||||
|
||||
enum class CompressStatus(val value: Int) {
|
||||
SUCCESS(0),
|
||||
COMPRESS_UNSUPPORTED(1),
|
||||
COMPRESS_ALREADY_COMPRESSED(2),
|
||||
COMPRESS_FAILED(3),
|
||||
DECOMPRESS_UNSUPPORTED(4),
|
||||
DECOMPRESS_NOT_COMPRESSED(5),
|
||||
DECOMPRESS_FAILED(6),
|
||||
INSTALLED_APPLICATION(7);
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): CompressStatus =
|
||||
CompressStatus.entries.first { it.value == value }
|
||||
}
|
||||
}
|
||||
|
||||
// Compression / Decompression
|
||||
private external fun compressFileNative(inputPath: String?, outputPath: String): Int
|
||||
|
||||
fun compressFile(inputPath: String?, outputPath: String): CompressStatus {
|
||||
return CompressStatus.fromValue(
|
||||
compressFileNative(inputPath, outputPath)
|
||||
)
|
||||
}
|
||||
|
||||
private external fun decompressFileNative(inputPath: String?, outputPath: String): Int
|
||||
|
||||
fun decompressFile(inputPath: String?, outputPath: String): CompressStatus {
|
||||
return CompressStatus.fromValue(
|
||||
decompressFileNative(inputPath, outputPath)
|
||||
)
|
||||
}
|
||||
|
||||
external fun getRecommendedExtension(inputPath: String?, shouldCompress: Boolean): String
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun onCompressProgress(total: Long, current: Long) {
|
||||
CompressProgressDialogViewModel.update(total, current)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun createFile(directory: String, filename: String): Boolean =
|
||||
@ -629,6 +689,38 @@ object NativeLibrary {
|
||||
FileUtil.getFilesName(path)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun getUserDirectory(uriOverride: Uri? = null): String {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
|
||||
val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||
|
||||
val dirSep = "/"
|
||||
val udUri = uriOverride ?:
|
||||
preferences.getString("CITRA_DIRECTORY", "")!!.toUri()
|
||||
val udPathSegment = udUri.lastPathSegment!!
|
||||
val udVirtualPath = udPathSegment.substringAfter(":")
|
||||
|
||||
if (udPathSegment.startsWith("primary:")) { // User directory is located in primary storage
|
||||
val primaryStoragePath = Environment.getExternalStorageDirectory().absolutePath
|
||||
return primaryStoragePath + dirSep + udVirtualPath + dirSep
|
||||
} else { // User directory probably located on a removable storage device
|
||||
val storageIdString = udPathSegment.substringBefore(":")
|
||||
val udRemovablePath = RemovableStorageHelper.getRemovableStoragePath(storageIdString)
|
||||
|
||||
if (udRemovablePath == null) {
|
||||
android.util.Log.e("NativeLibrary",
|
||||
"Unknown mount location for storage device '$storageIdString' (URI: $udUri)"
|
||||
)
|
||||
return ""
|
||||
}
|
||||
return udRemovablePath + dirSep + udVirtualPath + dirSep
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun getSize(path: String): Long =
|
||||
@ -638,6 +730,10 @@ object NativeLibrary {
|
||||
FileUtil.getFileSize(path)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun getBuildFlavor(): String = BuildConfig.FLAVOR
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun fileExists(path: String): Boolean =
|
||||
@ -689,6 +785,24 @@ object NativeLibrary {
|
||||
FileUtil.renameFile(path, destinationFilename)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun updateDocumentLocation(sourcePath: String, destinationPath: String): Boolean =
|
||||
CitraApplication.documentsTree.updateDocumentLocation(sourcePath, destinationPath)
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun moveFile(filename: String, sourceDirPath: String, destinationDirPath: String): Boolean =
|
||||
if (FileUtil.isNativePath(sourceDirPath)) {
|
||||
try {
|
||||
CitraApplication.documentsTree.moveFile(filename, sourceDirPath, destinationDirPath)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
FileUtil.moveFile(filename, sourceDirPath, destinationDirPath)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun deleteDocument(path: String): Boolean =
|
||||
@ -702,6 +816,7 @@ object NativeLibrary {
|
||||
ErrorSystemFiles,
|
||||
ErrorSavestate,
|
||||
ErrorArticDisconnected,
|
||||
ErrorN3DSApplication,
|
||||
ErrorUnknown
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.InputDevice
|
||||
import android.view.KeyEvent
|
||||
@ -47,6 +48,7 @@ import org.citra.citra_emu.utils.FileBrowserHelper
|
||||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||
import org.citra.citra_emu.utils.Log
|
||||
import org.citra.citra_emu.utils.RefreshRateUtil
|
||||
import org.citra.citra_emu.utils.ThemeUtil
|
||||
import org.citra.citra_emu.viewmodel.EmulationViewModel
|
||||
|
||||
@ -82,6 +84,8 @@ class EmulationActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
|
||||
RefreshRateUtil.enforceRefreshRate(this, sixtyHz = true)
|
||||
|
||||
ThemeUtil.setTheme(this)
|
||||
settingsViewModel.settings.loadSettings()
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -338,6 +342,7 @@ class EmulationActivity : AppCompatActivity() {
|
||||
preferences.getInt(InputBindingSetting.getInputAxisButtonKey(axis), -1)
|
||||
val guestOrientation =
|
||||
preferences.getInt(InputBindingSetting.getInputAxisOrientationKey(axis), -1)
|
||||
val inverted = preferences.getBoolean(InputBindingSetting.getInputAxisInvertedKey(axis),false);
|
||||
if (nextMapping == -1 || guestOrientation == -1) {
|
||||
// Axis is unmapped
|
||||
continue
|
||||
@ -346,6 +351,8 @@ class EmulationActivity : AppCompatActivity() {
|
||||
// Skip joystick wobble
|
||||
value = 0f
|
||||
}
|
||||
if (inverted) value = -value;
|
||||
|
||||
when (nextMapping) {
|
||||
NativeLibrary.ButtonType.STICK_LEFT -> {
|
||||
axisValuesCirclePad[guestOrientation] = value
|
||||
|
||||
@ -13,6 +13,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.widget.TextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
@ -57,13 +58,21 @@ import org.citra.citra_emu.utils.FileUtil
|
||||
import org.citra.citra_emu.utils.GameIconUtils
|
||||
import org.citra.citra_emu.viewmodel.GamesViewModel
|
||||
|
||||
class GameAdapter(private val activity: AppCompatActivity, private val inflater: LayoutInflater, private val openImageLauncher: ActivityResultLauncher<String>?) :
|
||||
class GameAdapter(
|
||||
private val activity: AppCompatActivity,
|
||||
private val inflater: LayoutInflater,
|
||||
private val openImageLauncher: ActivityResultLauncher<String>?,
|
||||
private val onRequestCompressOrDecompress: ((inputPath: String, suggestedName: String, shouldCompress: Boolean) -> Unit)? = null
|
||||
) :
|
||||
ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()),
|
||||
View.OnClickListener, View.OnLongClickListener {
|
||||
private var lastClickTime = 0L
|
||||
private var imagePath: String? = null
|
||||
private var dialogShortcutBinding: DialogShortcutBinding? = null
|
||||
|
||||
private val preferences: SharedPreferences
|
||||
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||
|
||||
fun handleShortcutImageResult(uri: Uri?) {
|
||||
val path = uri?.toString()
|
||||
if (path != null) {
|
||||
@ -191,6 +200,11 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
|
||||
binding.textGameTitle.text = game.title
|
||||
binding.textCompany.text = game.company
|
||||
binding.textGameRegion.text = game.regions
|
||||
binding.imageCartridge.visibility = if (preferences.getString("insertedCartridge", "") != game.path) {
|
||||
View.GONE
|
||||
} else {
|
||||
View.VISIBLE
|
||||
}
|
||||
|
||||
val backgroundColorId =
|
||||
if (
|
||||
@ -340,12 +354,29 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
|
||||
val bottomSheetDialog = BottomSheetDialog(context)
|
||||
bottomSheetDialog.setContentView(bottomSheetView)
|
||||
|
||||
val insertable = game.isInsertable
|
||||
val inserted = insertable && (preferences.getString("insertedCartridge", "") == game.path)
|
||||
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_title).text = game.title
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_company).text = game.company
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_region).text = game.regions
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_id).text = context.getString(R.string.game_context_id) + " " + String.format("%016X", game.titleId)
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_filename).text = context.getString(R.string.game_context_file) + " " + game.filename
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_filetype).text = context.getString(R.string.game_context_type) + " " + game.fileType
|
||||
|
||||
val insertButton = bottomSheetView.findViewById<MaterialButton>(R.id.insert_cartridge_button)
|
||||
insertButton.text = if (inserted) { context.getString(R.string.game_context_eject) } else { context.getString(R.string.game_context_insert) }
|
||||
insertButton.visibility = if (insertable) View.VISIBLE else View.GONE
|
||||
insertButton.setOnClickListener {
|
||||
if (inserted) {
|
||||
preferences.edit().putString("insertedCartridge", "").apply()
|
||||
} else {
|
||||
preferences.edit().putString("insertedCartridge", game.path).apply()
|
||||
}
|
||||
bottomSheetDialog.dismiss()
|
||||
notifyItemRangeChanged(0, currentList.size)
|
||||
}
|
||||
|
||||
GameIconUtils.loadGameIcon(activity, game, bottomSheetView.findViewById(R.id.game_icon))
|
||||
|
||||
bottomSheetView.findViewById<MaterialButton>(R.id.about_game_play).setOnClickListener {
|
||||
@ -441,6 +472,27 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
|
||||
bottomSheetDialog.dismiss()
|
||||
}
|
||||
|
||||
val compressDecompressButton = bottomSheetView.findViewById<MaterialButton>(R.id.compress_decompress)
|
||||
if (game.isInstalled) {
|
||||
compressDecompressButton.setOnClickListener {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.compress_decompress_installed_app),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
compressDecompressButton.alpha = 0.38f
|
||||
} else {
|
||||
compressDecompressButton.setOnClickListener {
|
||||
val shouldCompress = !game.isCompressed
|
||||
val recommendedExt = NativeLibrary.getRecommendedExtension(holder.game.path, shouldCompress)
|
||||
val baseName = holder.game.filename.substringBeforeLast('.')
|
||||
onRequestCompressOrDecompress?.invoke(holder.game.path, "$baseName.$recommendedExt", shouldCompress)
|
||||
bottomSheetDialog.dismiss()
|
||||
}
|
||||
}
|
||||
compressDecompressButton.text = context.getString(if (!game.isCompressed) R.string.compress else R.string.decompress)
|
||||
|
||||
bottomSheetView.findViewById<MaterialButton>(R.id.menu_button_open).setOnClickListener {
|
||||
showOpenContextMenu(it, game)
|
||||
}
|
||||
|
||||
@ -63,4 +63,37 @@ enum class SecondaryDisplayLayout(val int: Int) {
|
||||
return entries.firstOrNull { it.int == int } ?: NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class StereoWhichDisplay(val int: Int) {
|
||||
// These must match what is defined in src/common/settings.h
|
||||
|
||||
NONE(0), // equivalent to StereoRenderOption = Off
|
||||
BOTH(1),
|
||||
PRIMARY_ONLY(2),
|
||||
SECONDARY_ONLY(3);
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): StereoWhichDisplay {
|
||||
return entries.firstOrNull { it.int == int } ?: NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class StereoMode(val int: Int) {
|
||||
// These must match what is defined in src/common/settings.h
|
||||
|
||||
OFF(0),
|
||||
SIDE_BY_SIDE(1),
|
||||
SIDE_BY_SIDE_FULL(2),
|
||||
ANAGLYPH(3),
|
||||
INTERLACED(4),
|
||||
REVERSE_INTERLACED (5),
|
||||
CARDBOARD_VR (6);
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): StereoMode {
|
||||
return entries.firstOrNull { it.int == int } ?: OFF
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,9 +47,18 @@ class SecondaryDisplay(val context: Context) : DisplayManager.DisplayListener {
|
||||
|
||||
private fun getExternalDisplay(context: Context): Display? {
|
||||
val dm = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
val internalId = context.display.displayId ?: Display.DEFAULT_DISPLAY
|
||||
val displays = dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)
|
||||
return displays.firstOrNull { it.displayId != internalId && it.name != "HiddenDisplay" }
|
||||
val currentDisplayId = context.display.displayId
|
||||
val displays = dm.displays
|
||||
val presDisplays = dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
|
||||
return displays.firstOrNull {
|
||||
val isPresentable = presDisplays.any { pd -> pd.displayId == it.displayId }
|
||||
val isNotDefaultOrPresentable = it.displayId != Display.DEFAULT_DISPLAY || isPresentable
|
||||
isNotDefaultOrPresentable &&
|
||||
it.displayId != currentDisplayId &&
|
||||
it.name != "HiddenDisplay" &&
|
||||
it.state != Display.STATE_OFF &&
|
||||
it.isValid
|
||||
}
|
||||
}
|
||||
|
||||
fun updateDisplay() {
|
||||
|
||||
@ -19,6 +19,7 @@ enum class BooleanSetting(
|
||||
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false),
|
||||
ENABLE_RPC_SERVER("enable_rpc_server", Settings.SECTION_DEBUG, false),
|
||||
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
|
||||
SWAP_EYES_3D("swap_eyes_3d",Settings.SECTION_RENDERER,false),
|
||||
PERF_OVERLAY_ENABLE("performance_overlay_enable", Settings.SECTION_LAYOUT, false),
|
||||
PERF_OVERLAY_SHOW_FPS("performance_overlay_show_fps", Settings.SECTION_LAYOUT, true),
|
||||
PERF_OVERLAY_SHOW_FRAMETIME("performance_overlay_show_frame_time", Settings.SECTION_LAYOUT, false),
|
||||
@ -51,7 +52,8 @@ enum class BooleanSetting(
|
||||
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false),
|
||||
UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false),
|
||||
COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false),
|
||||
ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false);
|
||||
ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false),
|
||||
APPLY_REGION_FREE_PATCH("apply_region_free_patch", Settings.SECTION_SYSTEM, true);
|
||||
|
||||
override var boolean: Boolean = defaultValue
|
||||
|
||||
@ -86,7 +88,8 @@ enum class BooleanSetting(
|
||||
USE_ARTIC_BASE_CONTROLLER,
|
||||
COMPRESS_INSTALLED_CIA_CONTENT,
|
||||
ANDROID_HIDE_IMAGES,
|
||||
PERF_OVERLAY_ENABLE // Works in overlay options, but not from the settings menu
|
||||
PERF_OVERLAY_ENABLE, // Works in overlay options, but not from the settings menu
|
||||
APPLY_REGION_FREE_PATCH
|
||||
)
|
||||
|
||||
fun from(key: String): BooleanSetting? =
|
||||
|
||||
@ -17,7 +17,7 @@ enum class IntSetting(
|
||||
CAMERA_OUTER_RIGHT_FLIP("camera_outer_right_flip", Settings.SECTION_CAMERA, 0),
|
||||
GRAPHICS_API("graphics_api", Settings.SECTION_RENDERER, 1),
|
||||
RESOLUTION_FACTOR("resolution_factor", Settings.SECTION_RENDERER, 1),
|
||||
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 0),
|
||||
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 2),
|
||||
STEREOSCOPIC_3D_DEPTH("factor_3d", Settings.SECTION_RENDERER, 0),
|
||||
STEPS_PER_HOUR("steps_per_hour", Settings.SECTION_SYSTEM, 0),
|
||||
CARDBOARD_SCREEN_SIZE("cardboard_screen_size", Settings.SECTION_LAYOUT, 85),
|
||||
@ -53,6 +53,7 @@ enum class IntSetting(
|
||||
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
|
||||
TURBO_LIMIT("turbo_limit", Settings.SECTION_CORE, 200),
|
||||
PERFORMANCE_OVERLAY_POSITION("performance_overlay_position", Settings.SECTION_LAYOUT, 0),
|
||||
RENDER_3D_WHICH_DISPLAY("render_3d_which_display",Settings.SECTION_RENDERER,0),
|
||||
ASPECT_RATIO("aspect_ratio", Settings.SECTION_LAYOUT, 0);
|
||||
|
||||
override var int: Int = defaultValue
|
||||
|
||||
@ -16,6 +16,7 @@ import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.features.hotkeys.Hotkey
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractStringSetting
|
||||
import org.citra.citra_emu.features.settings.model.Settings
|
||||
|
||||
class InputBindingSetting(
|
||||
@ -161,12 +162,14 @@ class InputBindingSetting(
|
||||
fun removeOldMapping() {
|
||||
// Try remove all possible keys we wrote for this setting
|
||||
val oldKey = preferences.getString(reverseKey, "")
|
||||
(setting as AbstractStringSetting).string = ""
|
||||
if (oldKey != "") {
|
||||
preferences.edit()
|
||||
.remove(abstractSetting.key) // Used for ui text
|
||||
.remove(oldKey) // Used for button mapping
|
||||
.remove(oldKey + "_GuestOrientation") // Used for axis orientation
|
||||
.remove(oldKey + "_GuestButton") // Used for axis button
|
||||
.remove(oldKey + "_Inverted") // used for axis inversion
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
@ -200,7 +203,7 @@ class InputBindingSetting(
|
||||
/**
|
||||
* Helper function to write a gamepad axis mapping for the setting.
|
||||
*/
|
||||
private fun writeAxisMapping(axis: Int, value: Int) {
|
||||
private fun writeAxisMapping(axis: Int, value: Int, inverted: Boolean) {
|
||||
// Cleanup old mapping
|
||||
removeOldMapping()
|
||||
|
||||
@ -208,6 +211,7 @@ class InputBindingSetting(
|
||||
preferences.edit()
|
||||
.putInt(getInputAxisOrientationKey(axis), if (isHorizontalOrientation()) 0 else 1)
|
||||
.putInt(getInputAxisButtonKey(axis), value)
|
||||
.putBoolean(getInputAxisInvertedKey(axis),inverted)
|
||||
// Write next reverse mapping for future cleanup
|
||||
.putString(reverseKey, getInputAxisKey(axis))
|
||||
.apply()
|
||||
@ -235,7 +239,7 @@ class InputBindingSetting(
|
||||
*
|
||||
* @param device InputDevice from which the input event originated.
|
||||
* @param motionRange MotionRange of the movement
|
||||
* @param axisDir Either '-' or '+' (currently unused)
|
||||
* @param axisDir Either '-' or '+'
|
||||
*/
|
||||
fun onMotionInput(device: InputDevice, motionRange: MotionRange, axisDir: Char) {
|
||||
if (!isAxisMappingSupported()) {
|
||||
@ -251,8 +255,8 @@ class InputBindingSetting(
|
||||
} else {
|
||||
buttonCode
|
||||
}
|
||||
writeAxisMapping(motionRange.axis, button)
|
||||
val uiString = "${device.name}: Axis ${motionRange.axis}"
|
||||
writeAxisMapping(motionRange.axis, button, axisDir == '-')
|
||||
val uiString = "${device.name}: Axis ${motionRange.axis}" + axisDir
|
||||
value = uiString
|
||||
}
|
||||
|
||||
@ -307,6 +311,11 @@ class InputBindingSetting(
|
||||
*/
|
||||
fun getInputAxisButtonKey(axis: Int): String = "${getInputAxisKey(axis)}_GuestButton"
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an whether a gamepad axis is inverted.
|
||||
*/
|
||||
fun getInputAxisInvertedKey(axis: Int): String = "${getInputAxisKey(axis)}_Inverted"
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an gamepad axis orientation.
|
||||
*/
|
||||
|
||||
@ -7,6 +7,7 @@ package org.citra.citra_emu.features.settings.ui
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
@ -37,6 +38,7 @@ import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||
import org.citra.citra_emu.utils.SystemSaveGame
|
||||
import org.citra.citra_emu.utils.DirectoryInitialization
|
||||
import org.citra.citra_emu.utils.InsetsHelper
|
||||
import org.citra.citra_emu.utils.RefreshRateUtil
|
||||
import org.citra.citra_emu.utils.ThemeUtil
|
||||
|
||||
class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
@ -49,6 +51,8 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
||||
override val settings: Settings get() = settingsViewModel.settings
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
RefreshRateUtil.enforceRefreshRate(this)
|
||||
|
||||
ThemeUtil.setTheme(this)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@ -555,6 +555,21 @@ class SettingsAdapter(
|
||||
return true
|
||||
}
|
||||
|
||||
fun onInputBindingLongClick(setting: InputBindingSetting, position: Int): Boolean {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setMessage(R.string.reset_setting_confirmation)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||
setting.removeOldMapping()
|
||||
notifyItemChanged(position)
|
||||
fragmentView.onSettingChanged()
|
||||
fragmentView.loadSettingsList()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun onClickDisabledSetting(isRuntimeDisabled: Boolean) {
|
||||
val titleId = if (isRuntimeDisabled)
|
||||
R.string.setting_not_editable
|
||||
|
||||
@ -16,6 +16,9 @@ import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.display.ScreenLayout
|
||||
import org.citra.citra_emu.display.StereoMode
|
||||
import org.citra.citra_emu.display.StereoWhichDisplay
|
||||
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractIntSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
@ -44,7 +47,6 @@ import org.citra.citra_emu.utils.BirthdayMonth
|
||||
import org.citra.citra_emu.utils.Log
|
||||
import org.citra.citra_emu.utils.SystemSaveGame
|
||||
import org.citra.citra_emu.utils.ThemeUtil
|
||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||
|
||||
class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) {
|
||||
private var menuTag: String? = null
|
||||
@ -111,20 +113,24 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
}
|
||||
|
||||
/** Returns the portrait mode width */
|
||||
private fun getWidth(): Int {
|
||||
val dm = Resources.getSystem().displayMetrics;
|
||||
return if (dm.widthPixels < dm.heightPixels)
|
||||
dm.widthPixels
|
||||
else
|
||||
dm.heightPixels
|
||||
private fun getDimensions(): IntArray {
|
||||
val dm = Resources.getSystem().displayMetrics
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val wm = settingsActivity.windowManager.maximumWindowMetrics
|
||||
val height = wm.bounds.height().coerceAtLeast(dm.heightPixels)
|
||||
val width = wm.bounds.width().coerceAtLeast(dm.widthPixels)
|
||||
intArrayOf(width, height)
|
||||
} else {
|
||||
intArrayOf(dm.widthPixels, dm.heightPixels)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getHeight(): Int {
|
||||
val dm = Resources.getSystem().displayMetrics;
|
||||
return if (dm.widthPixels < dm.heightPixels)
|
||||
dm.heightPixels
|
||||
else
|
||||
dm.widthPixels
|
||||
private fun getSmallerDimension(): Int {
|
||||
return getDimensions().min()
|
||||
}
|
||||
|
||||
private fun getLargerDimension(): Int {
|
||||
return getDimensions().max()
|
||||
}
|
||||
|
||||
private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
|
||||
@ -354,6 +360,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.array.regionValues,
|
||||
)
|
||||
)
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.APPLY_REGION_FREE_PATCH,
|
||||
R.string.apply_region_free_patch,
|
||||
R.string.apply_region_free_patch_desc,
|
||||
BooleanSetting.APPLY_REGION_FREE_PATCH.key,
|
||||
BooleanSetting.APPLY_REGION_FREE_PATCH.defaultValue
|
||||
)
|
||||
)
|
||||
val systemCountrySetting = object : AbstractShortSetting {
|
||||
override var short: Short
|
||||
get() {
|
||||
@ -936,17 +951,30 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
|
||||
add(HeaderSetting(R.string.stereoscopy))
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY,
|
||||
R.string.render_3d_which_display,
|
||||
R.string.render_3d_which_display_description,
|
||||
R.array.render3dWhichDisplay,
|
||||
R.array.render3dDisplayValues,
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY.key,
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.STEREOSCOPIC_3D_MODE,
|
||||
R.string.render3d,
|
||||
0,
|
||||
R.string.render3d_description,
|
||||
R.array.render3dModes,
|
||||
R.array.render3dValues,
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.key,
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.defaultValue
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.defaultValue,
|
||||
isEnabled = IntSetting.RENDER_3D_WHICH_DISPLAY.int != StereoWhichDisplay.NONE.int
|
||||
)
|
||||
)
|
||||
|
||||
add(
|
||||
SliderSetting(
|
||||
IntSetting.STEREOSCOPIC_3D_DEPTH,
|
||||
@ -969,6 +997,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
)
|
||||
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.SWAP_EYES_3D,
|
||||
R.string.swap_eyes_3d,
|
||||
R.string.swap_eyes_3d_description,
|
||||
BooleanSetting.SWAP_EYES_3D.key,
|
||||
BooleanSetting.SWAP_EYES_3D.defaultValue,
|
||||
isEnabled = IntSetting.RENDER_3D_WHICH_DISPLAY.int != StereoWhichDisplay.NONE.int
|
||||
)
|
||||
)
|
||||
|
||||
add(HeaderSetting(R.string.cardboard_vr))
|
||||
add(
|
||||
SliderSetting(
|
||||
@ -979,7 +1018,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.key,
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -991,7 +1031,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_X_SHIFT.key,
|
||||
IntSetting.CARDBOARD_X_SHIFT.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_X_SHIFT.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -1003,7 +1044,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_Y_SHIFT.key,
|
||||
IntSetting.CARDBOARD_Y_SHIFT.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_Y_SHIFT.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
|
||||
@ -1137,7 +1179,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.array.aspectRatioValues,
|
||||
IntSetting.ASPECT_RATIO.key,
|
||||
IntSetting.ASPECT_RATIO.defaultValue,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == 1,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == ScreenLayout.SINGLE_SCREEN.int,
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -1185,7 +1227,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
"%",
|
||||
FloatSetting.SECOND_SCREEN_OPACITY.key,
|
||||
FloatSetting.SECOND_SCREEN_OPACITY.defaultValue,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == 5
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == ScreenLayout.CUSTOM_LAYOUT.int
|
||||
)
|
||||
)
|
||||
add(HeaderSetting(R.string.bg_color, R.string.bg_color_description))
|
||||
@ -1396,7 +1438,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_x,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_TOP_X.key,
|
||||
IntSetting.LANDSCAPE_TOP_X.defaultValue.toFloat()
|
||||
@ -1408,7 +1450,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_y,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_TOP_Y.key,
|
||||
IntSetting.LANDSCAPE_TOP_Y.defaultValue.toFloat()
|
||||
@ -1420,7 +1462,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_width,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_TOP_WIDTH.key,
|
||||
IntSetting.LANDSCAPE_TOP_WIDTH.defaultValue.toFloat()
|
||||
@ -1432,7 +1474,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_height,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_TOP_HEIGHT.key,
|
||||
IntSetting.LANDSCAPE_TOP_HEIGHT.defaultValue.toFloat()
|
||||
@ -1445,7 +1487,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_x,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_BOTTOM_X.key,
|
||||
IntSetting.LANDSCAPE_BOTTOM_X.defaultValue.toFloat()
|
||||
@ -1457,7 +1499,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_y,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_BOTTOM_Y.key,
|
||||
IntSetting.LANDSCAPE_BOTTOM_Y.defaultValue.toFloat()
|
||||
@ -1469,7 +1511,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_width,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_BOTTOM_WIDTH.key,
|
||||
IntSetting.LANDSCAPE_BOTTOM_WIDTH.defaultValue.toFloat()
|
||||
@ -1481,7 +1523,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_height,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.LANDSCAPE_BOTTOM_HEIGHT.key,
|
||||
IntSetting.LANDSCAPE_BOTTOM_HEIGHT.defaultValue.toFloat()
|
||||
@ -1501,7 +1543,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_x,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_TOP_X.key,
|
||||
IntSetting.PORTRAIT_TOP_X.defaultValue.toFloat()
|
||||
@ -1513,7 +1555,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_y,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_TOP_Y.key,
|
||||
IntSetting.PORTRAIT_TOP_Y.defaultValue.toFloat()
|
||||
@ -1525,7 +1567,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_width,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_TOP_WIDTH.key,
|
||||
IntSetting.PORTRAIT_TOP_WIDTH.defaultValue.toFloat()
|
||||
@ -1537,7 +1579,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_height,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_TOP_HEIGHT.key,
|
||||
IntSetting.PORTRAIT_TOP_HEIGHT.defaultValue.toFloat()
|
||||
@ -1550,7 +1592,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_x,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_BOTTOM_X.key,
|
||||
IntSetting.PORTRAIT_BOTTOM_X.defaultValue.toFloat()
|
||||
@ -1562,7 +1604,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_y,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_BOTTOM_Y.key,
|
||||
IntSetting.PORTRAIT_BOTTOM_Y.defaultValue.toFloat()
|
||||
@ -1574,7 +1616,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_width,
|
||||
0,
|
||||
0,
|
||||
getWidth(),
|
||||
getSmallerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_BOTTOM_WIDTH.key,
|
||||
IntSetting.PORTRAIT_BOTTOM_WIDTH.defaultValue.toFloat()
|
||||
@ -1586,7 +1628,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.string.emulation_custom_layout_height,
|
||||
0,
|
||||
0,
|
||||
getHeight(),
|
||||
getLargerDimension(),
|
||||
"px",
|
||||
IntSetting.PORTRAIT_BOTTOM_HEIGHT.key,
|
||||
IntSetting.PORTRAIT_BOTTOM_HEIGHT.defaultValue.toFloat()
|
||||
|
||||
@ -51,7 +51,7 @@ class InputBindingSettingViewHolder(val binding: ListItemSettingBinding, adapter
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean {
|
||||
if (setting.isEditable) {
|
||||
adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||
adapter.onInputBindingLongClick(setting, bindingAdapterPosition)
|
||||
} else {
|
||||
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -60,7 +60,7 @@ class CitraDirectoryDialogFragment : DialogFragment() {
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int ->
|
||||
if (!PermissionsHandler.hasWriteAccess(requireContext())) {
|
||||
(requireActivity() as MainActivity)?.openCitraDirectory?.launch(null)
|
||||
PermissionsHandler.compatibleSelectDirectory((requireActivity() as MainActivity).openCitraDirectory)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.fragments
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.viewmodel.CompressProgressDialogViewModel
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
|
||||
class CompressProgressDialogFragment : DialogFragment() {
|
||||
private lateinit var progressBar: ProgressBar
|
||||
private var outputPath: String? = null
|
||||
private var isCompressing: Boolean = true
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
isCompressing = it.getBoolean(ARG_IS_COMPRESSING, true)
|
||||
outputPath = it.getString(ARG_OUTPUT_PATH)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_compress_progress, null)
|
||||
progressBar = view.findViewById(R.id.compress_progress)
|
||||
val label = view.findViewById<android.widget.TextView>(R.id.compress_label)
|
||||
label.text = if (isCompressing) getString(R.string.compressing) else getString(R.string.decompressing)
|
||||
|
||||
isCancelable = false
|
||||
progressBar.isIndeterminate = true
|
||||
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
combine(CompressProgressDialogViewModel.total, CompressProgressDialogViewModel.progress) { total, progress ->
|
||||
total to progress
|
||||
}.collectLatest { (total, progress) ->
|
||||
if (total <= 0) {
|
||||
progressBar.isIndeterminate = true
|
||||
label.visibility = View.GONE
|
||||
} else {
|
||||
progressBar.isIndeterminate = false
|
||||
label.visibility = View.VISIBLE
|
||||
progressBar.max = total
|
||||
progressBar.setProgress(progress, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setView(view)
|
||||
.setCancelable(false)
|
||||
.setNegativeButton(android.R.string.cancel) { _: android.content.DialogInterface, _: Int ->
|
||||
outputPath?.let { path ->
|
||||
NativeLibrary.deleteDocument(path)
|
||||
}
|
||||
}
|
||||
|
||||
return builder.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "CompressProgressDialog"
|
||||
private const val ARG_IS_COMPRESSING = "isCompressing"
|
||||
private const val ARG_OUTPUT_PATH = "outputPath"
|
||||
|
||||
fun newInstance(isCompressing: Boolean, outputPath: String?): CompressProgressDialogFragment {
|
||||
val frag = CompressProgressDialogFragment()
|
||||
val args = Bundle()
|
||||
args.putBoolean(ARG_IS_COMPRESSING, isCompressing)
|
||||
args.putString(ARG_OUTPUT_PATH, outputPath)
|
||||
frag.arguments = args
|
||||
return frag
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ import android.content.IntentFilter
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
@ -144,6 +145,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
}
|
||||
}
|
||||
|
||||
val insertedCartridge = preferences.getString("insertedCartridge", "")
|
||||
NativeLibrary.setInsertedCartridge(insertedCartridge ?: "")
|
||||
|
||||
try {
|
||||
game = args.game ?: intentGame!!
|
||||
} catch (e: NullPointerException) {
|
||||
@ -1019,12 +1023,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
// Buttons that are disabled by default
|
||||
var defaultValue = true
|
||||
when (i) {
|
||||
// TODO: Remove these magic numbers
|
||||
6, 7, 12, 13, 14, 15 -> defaultValue = false
|
||||
}
|
||||
enabledButtons[i] = preferences.getBoolean("buttonToggle$i", defaultValue)
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.emulation_toggle_controls)
|
||||
.setMultiChoiceItems(
|
||||
R.array.n3dsButtons, enabledButtons
|
||||
@ -1036,6 +1041,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
binding.surfaceInputOverlay.refreshControls()
|
||||
}
|
||||
.show()
|
||||
|
||||
// Band-aid fix for strange dialog flickering issue
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val displayMetrics = requireActivity().windowManager.currentWindowMetrics
|
||||
val displayHeight = displayMetrics.bounds.height()
|
||||
// The layout visually breaks if we try to set the height directly rather than like this.
|
||||
// Why? Fuck you, that's why!
|
||||
val newAttributes = dialog.window?.attributes
|
||||
newAttributes?.height = (displayHeight * 0.85f).toInt()
|
||||
dialog.window?.attributes = newAttributes
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAdjustScaleDialog(target: String) {
|
||||
|
||||
@ -30,14 +30,17 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.adapters.GameAdapter
|
||||
import org.citra.citra_emu.databinding.FragmentGamesBinding
|
||||
import org.citra.citra_emu.features.settings.model.Settings
|
||||
import org.citra.citra_emu.model.Game
|
||||
import org.citra.citra_emu.viewmodel.CompressProgressDialogViewModel
|
||||
import org.citra.citra_emu.viewmodel.GamesViewModel
|
||||
import org.citra.citra_emu.viewmodel.HomeViewModel
|
||||
|
||||
@ -56,6 +59,58 @@ class GamesFragment : Fragment() {
|
||||
gameAdapter.handleShortcutImageResult(uri)
|
||||
}
|
||||
|
||||
private var shouldCompress: Boolean = true
|
||||
private var pendingCompressInvocation: String? = null
|
||||
|
||||
companion object {
|
||||
fun doCompression(fragment: Fragment, gamesViewModel: GamesViewModel, inputPath: String?, outputUri: Uri?, shouldCompress: Boolean) {
|
||||
if (outputUri != null) {
|
||||
CompressProgressDialogViewModel.reset()
|
||||
val dialog = CompressProgressDialogFragment.newInstance(shouldCompress, outputUri.toString())
|
||||
dialog.showNow(
|
||||
fragment.requireActivity().supportFragmentManager,
|
||||
CompressProgressDialogFragment.TAG
|
||||
)
|
||||
|
||||
fragment.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val status = if (shouldCompress) {
|
||||
NativeLibrary.compressFile(inputPath, outputUri.toString())
|
||||
} else {
|
||||
NativeLibrary.decompressFile(inputPath, outputUri.toString())
|
||||
}
|
||||
|
||||
fragment.requireActivity().runOnUiThread {
|
||||
dialog.dismiss()
|
||||
val resId = when (status) {
|
||||
NativeLibrary.CompressStatus.SUCCESS -> if (shouldCompress) R.string.compress_success else R.string.decompress_success
|
||||
NativeLibrary.CompressStatus.COMPRESS_UNSUPPORTED -> R.string.compress_unsupported
|
||||
NativeLibrary.CompressStatus.COMPRESS_ALREADY_COMPRESSED -> R.string.compress_already
|
||||
NativeLibrary.CompressStatus.COMPRESS_FAILED -> R.string.compress_failed
|
||||
NativeLibrary.CompressStatus.DECOMPRESS_UNSUPPORTED -> R.string.decompress_unsupported
|
||||
NativeLibrary.CompressStatus.DECOMPRESS_NOT_COMPRESSED -> R.string.decompress_not_compressed
|
||||
NativeLibrary.CompressStatus.DECOMPRESS_FAILED -> R.string.decompress_failed
|
||||
NativeLibrary.CompressStatus.INSTALLED_APPLICATION -> R.string.compress_decompress_installed_app
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(fragment.requireContext())
|
||||
.setMessage(fragment.getString(resId))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show()
|
||||
|
||||
gamesViewModel.reloadGames(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val onCompressDecompressLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.CreateDocument("application/octet-stream")
|
||||
) { uri: Uri? ->
|
||||
doCompression(this, gamesViewModel, pendingCompressInvocation, uri, shouldCompress)
|
||||
pendingCompressInvocation = null
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enterTransition = MaterialFadeThrough()
|
||||
@ -81,7 +136,12 @@ class GamesFragment : Fragment() {
|
||||
gameAdapter = GameAdapter(
|
||||
requireActivity() as AppCompatActivity,
|
||||
inflater,
|
||||
openImageLauncher
|
||||
openImageLauncher,
|
||||
onRequestCompressOrDecompress = { inputPath, suggestedName, shouldCompress ->
|
||||
pendingCompressInvocation = inputPath
|
||||
onCompressDecompressLauncher.launch(suggestedName)
|
||||
this.shouldCompress = shouldCompress
|
||||
}
|
||||
)
|
||||
|
||||
binding.gridGames.apply {
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.ui.main.MainActivity
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
|
||||
class GrantMissingFilesystemPermissionFragment : DialogFragment() {
|
||||
private lateinit var mainActivity: MainActivity
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
mainActivity = requireActivity() as MainActivity
|
||||
|
||||
isCancelable = false
|
||||
|
||||
val requestPermissionFunction =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
{
|
||||
manageExternalStoragePermissionLauncher.launch(
|
||||
Intent(
|
||||
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
||||
Uri.fromParts("package", mainActivity.packageName, null)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
{ permissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.filesystem_permission_warning)
|
||||
.setMessage(R.string.filesystem_permission_lost)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||
requestPermissionFunction()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
private val manageExternalStoragePermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (Environment.isExternalStorageManager()) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
|
||||
private val permissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
|
||||
if (isGranted) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "GrantMissingFilesystemPermissionFragment"
|
||||
|
||||
fun newInstance(): GrantMissingFilesystemPermissionFragment {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
return GrantMissingFilesystemPermissionFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +159,7 @@ class HomeSettingsFragment : Fragment() {
|
||||
R.string.select_citra_user_folder,
|
||||
R.string.select_citra_user_folder_home_description,
|
||||
R.drawable.ic_home,
|
||||
{ mainActivity?.openCitraDirectory?.launch(null) },
|
||||
{ PermissionsHandler.compatibleSelectDirectory(mainActivity.openCitraDirectory) },
|
||||
details = homeViewModel.userDir
|
||||
),
|
||||
HomeSetting(
|
||||
|
||||
@ -7,11 +7,13 @@ package org.citra.citra_emu.fragments
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
@ -26,18 +28,19 @@ import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import info.debatty.java.stringsimilarity.Jaccard
|
||||
import info.debatty.java.stringsimilarity.JaroWinkler
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.adapters.GameAdapter
|
||||
import org.citra.citra_emu.databinding.FragmentSearchBinding
|
||||
import org.citra.citra_emu.model.Game
|
||||
import org.citra.citra_emu.viewmodel.CompressProgressDialogViewModel
|
||||
import org.citra.citra_emu.viewmodel.GamesViewModel
|
||||
import org.citra.citra_emu.viewmodel.HomeViewModel
|
||||
import java.time.temporal.ChronoField
|
||||
import java.util.Locale
|
||||
import android.net.Uri
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
private var _binding: FragmentSearchBinding? = null
|
||||
@ -53,6 +56,15 @@ class SearchFragment : Fragment() {
|
||||
gameAdapter.handleShortcutImageResult(uri)
|
||||
}
|
||||
|
||||
private var shouldCompress: Boolean = true
|
||||
private var pendingCompressInvocation: String? = null
|
||||
private val onCompressDecompressLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.CreateDocument("application/octet-stream")
|
||||
) { uri: Uri? ->
|
||||
GamesFragment.doCompression(this, gamesViewModel, pendingCompressInvocation, uri, shouldCompress)
|
||||
pendingCompressInvocation = null
|
||||
}
|
||||
|
||||
private lateinit var preferences: SharedPreferences
|
||||
|
||||
companion object {
|
||||
@ -85,7 +97,13 @@ class SearchFragment : Fragment() {
|
||||
gameAdapter = GameAdapter(
|
||||
requireActivity() as AppCompatActivity,
|
||||
inflater,
|
||||
openImageLauncher
|
||||
openImageLauncher,
|
||||
onRequestCompressOrDecompress = { inputPath, suggestedName, shouldCompress ->
|
||||
pendingCompressInvocation = inputPath
|
||||
onCompressDecompressLauncher.launch(suggestedName)
|
||||
this.shouldCompress = shouldCompress
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
binding.gridGamesSearch.apply {
|
||||
|
||||
@ -13,21 +13,25 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.ui.main.MainActivity
|
||||
import org.citra.citra_emu.utils.PermissionsHandler
|
||||
import org.citra.citra_emu.viewmodel.HomeViewModel
|
||||
|
||||
class SelectUserDirectoryDialogFragment : DialogFragment() {
|
||||
class SelectUserDirectoryDialogFragment(titleOverride: Int? = null, descriptionOverride: Int? = null) : DialogFragment() {
|
||||
private lateinit var mainActivity: MainActivity
|
||||
|
||||
private val title = titleOverride ?: R.string.select_citra_user_folder
|
||||
private val description = descriptionOverride ?: R.string.selecting_user_directory_without_write_permissions
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
mainActivity = requireActivity() as MainActivity
|
||||
|
||||
isCancelable = false
|
||||
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.select_citra_user_folder)
|
||||
.setMessage(R.string.selecting_user_directory_without_write_permissions)
|
||||
.setTitle(title)
|
||||
.setMessage(description)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||
mainActivity?.openCitraDirectoryLostPermission?.launch(null)
|
||||
PermissionsHandler.compatibleSelectDirectory(mainActivity.openCitraDirectoryLostPermission)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
@ -35,9 +39,10 @@ class SelectUserDirectoryDialogFragment : DialogFragment() {
|
||||
companion object {
|
||||
const val TAG = "SelectUserDirectoryDialogFragment"
|
||||
|
||||
fun newInstance(activity: FragmentActivity): SelectUserDirectoryDialogFragment {
|
||||
fun newInstance(activity: FragmentActivity, titleOverride: Int? = null, descriptionOverride: Int? = null):
|
||||
SelectUserDirectoryDialogFragment {
|
||||
ViewModelProvider(activity)[HomeViewModel::class.java].setPickingUserDir(true)
|
||||
return SelectUserDirectoryDialogFragment()
|
||||
return SelectUserDirectoryDialogFragment(titleOverride, descriptionOverride)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,11 +11,13 @@ import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -30,7 +32,9 @@ import androidx.preference.PreferenceManager
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import org.citra.citra_emu.BuildConfig
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.adapters.SetupAdapter
|
||||
import org.citra.citra_emu.databinding.FragmentSetupBinding
|
||||
@ -41,6 +45,7 @@ import org.citra.citra_emu.model.PageState
|
||||
import org.citra.citra_emu.model.SetupCallback
|
||||
import org.citra.citra_emu.model.SetupPage
|
||||
import org.citra.citra_emu.ui.main.MainActivity
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
import org.citra.citra_emu.utils.CitraDirectoryHelper
|
||||
import org.citra.citra_emu.utils.GameHelper
|
||||
import org.citra.citra_emu.utils.PermissionsHandler
|
||||
@ -142,7 +147,56 @@ class SetupFragment : Fragment() {
|
||||
false,
|
||||
0,
|
||||
pageButtons = mutableListOf<PageButton>().apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_folder,
|
||||
R.string.filesystem_permission,
|
||||
R.string.filesystem_permission_description,
|
||||
buttonAction = {
|
||||
pageButtonCallback = it
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
manageExternalStoragePermissionLauncher.launch(
|
||||
Intent(
|
||||
android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
||||
Uri.fromParts(
|
||||
"package",
|
||||
requireActivity().packageName,
|
||||
null
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
permissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
},
|
||||
buttonState = {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (Environment.isExternalStorageManager()) {
|
||||
ButtonState.BUTTON_ACTION_COMPLETE
|
||||
} else {
|
||||
ButtonState.BUTTON_ACTION_INCOMPLETE
|
||||
}
|
||||
} else {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ButtonState.BUTTON_ACTION_COMPLETE
|
||||
} else {
|
||||
ButtonState.BUTTON_ACTION_INCOMPLETE
|
||||
}
|
||||
}
|
||||
},
|
||||
isUnskippable = true,
|
||||
hasWarning = true,
|
||||
R.string.filesystem_permission_warning,
|
||||
R.string.filesystem_permission_warning_description,
|
||||
)
|
||||
)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_notification,
|
||||
@ -214,18 +268,35 @@ class SetupFragment : Fragment() {
|
||||
)
|
||||
},
|
||||
) {
|
||||
if (
|
||||
var permissionsComplete =
|
||||
// Microphone
|
||||
ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
) == PackageManager.PERMISSION_GRANTED &&
|
||||
// Camera
|
||||
ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.CAMERA
|
||||
) == PackageManager.PERMISSION_GRANTED &&
|
||||
// Notifications
|
||||
NotificationManagerCompat.from(requireContext())
|
||||
.areNotificationsEnabled()
|
||||
) {
|
||||
// External Storage
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
permissionsComplete =
|
||||
(permissionsComplete && Environment.isExternalStorageManager())
|
||||
} else {
|
||||
permissionsComplete =
|
||||
(permissionsComplete && ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) == PackageManager.PERMISSION_GRANTED)
|
||||
}
|
||||
}
|
||||
|
||||
if (permissionsComplete) {
|
||||
PageState.PAGE_STEPS_COMPLETE
|
||||
} else {
|
||||
PageState.PAGE_STEPS_INCOMPLETE
|
||||
@ -249,7 +320,7 @@ class SetupFragment : Fragment() {
|
||||
R.string.select_citra_user_folder_description,
|
||||
buttonAction = {
|
||||
pageButtonCallback = it
|
||||
openCitraDirectory.launch(null)
|
||||
PermissionsHandler.compatibleSelectDirectory(openCitraDirectory)
|
||||
},
|
||||
buttonState = {
|
||||
if (PermissionsHandler.hasWriteAccess(requireContext())) {
|
||||
@ -452,6 +523,19 @@ class SetupFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPermissionDeniedSnackbar() {
|
||||
Snackbar.make(binding.root, R.string.permission_denied, Snackbar.LENGTH_LONG)
|
||||
.setAnchorView(binding.buttonNext)
|
||||
.setAction(R.string.grid_menu_core_settings) {
|
||||
val intent =
|
||||
Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
val uri = Uri.fromParts("package", requireActivity().packageName, null)
|
||||
intent.data = uri
|
||||
startActivity(intent)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private val permissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
|
||||
if (isGranted) {
|
||||
@ -459,16 +543,20 @@ class SetupFragment : Fragment() {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
Snackbar.make(binding.root, R.string.permission_denied, Snackbar.LENGTH_LONG)
|
||||
.setAnchorView(binding.buttonNext)
|
||||
.setAction(R.string.grid_menu_core_settings) {
|
||||
val intent =
|
||||
Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
val uri = Uri.fromParts("package", requireActivity().packageName, null)
|
||||
intent.data = uri
|
||||
startActivity(intent)
|
||||
}
|
||||
.show()
|
||||
showPermissionDeniedSnackbar()
|
||||
}
|
||||
|
||||
// We can't use permissionLauncher because MANAGE_EXTERNAL_STORAGE is a special snowflake
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
private val manageExternalStoragePermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
if (Environment.isExternalStorageManager()) {
|
||||
checkForButtonState.invoke()
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
showPermissionDeniedSnackbar()
|
||||
}
|
||||
|
||||
private val openCitraDirectory = registerForActivityResult<Uri, Uri>(
|
||||
@ -478,6 +566,17 @@ class SetupFragment : Fragment() {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
if (NativeLibrary.getUserDirectory(result) == "") {
|
||||
SelectUserDirectoryDialogFragment.newInstance(
|
||||
mainActivity,
|
||||
R.string.invalid_selection,
|
||||
R.string.invalid_user_directory
|
||||
).show(mainActivity.supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
|
||||
CitraDirectoryHelper(requireActivity(), true).showCitraDirectoryDialog(result, pageButtonCallback, checkForButtonState)
|
||||
}
|
||||
|
||||
|
||||
@ -25,8 +25,10 @@ class Game(
|
||||
val isInstalled: Boolean = false,
|
||||
val isSystemTitle: Boolean = false,
|
||||
val isVisibleSystemTitle: Boolean = false,
|
||||
val isInsertable: Boolean = false,
|
||||
val icon: IntArray? = null,
|
||||
val fileType: String = "",
|
||||
val isCompressed: Boolean = false,
|
||||
val filename: String,
|
||||
) : Parcelable {
|
||||
val keyAddedToLibraryTime get() = "${filename}_AddedToLibraryTime"
|
||||
|
||||
@ -37,6 +37,8 @@ class GameInfo(path: String) {
|
||||
|
||||
external fun getFileType(): String
|
||||
|
||||
external fun getIsInsertable(): Boolean
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
private external fun initialize(path: String): Long
|
||||
|
||||
@ -4,9 +4,13 @@
|
||||
|
||||
package org.citra.citra_emu.ui.main
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.view.WindowManager
|
||||
@ -36,6 +40,8 @@ import androidx.work.WorkManager
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.navigation.NavigationBarView
|
||||
import kotlinx.coroutines.launch
|
||||
import org.citra.citra_emu.BuildConfig
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.contracts.OpenFileResultContract
|
||||
import org.citra.citra_emu.databinding.ActivityMainBinding
|
||||
@ -43,14 +49,17 @@ import org.citra.citra_emu.features.settings.model.Settings
|
||||
import org.citra.citra_emu.features.settings.model.SettingsViewModel
|
||||
import org.citra.citra_emu.features.settings.ui.SettingsActivity
|
||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||
import org.citra.citra_emu.fragments.GrantMissingFilesystemPermissionFragment
|
||||
import org.citra.citra_emu.fragments.SelectUserDirectoryDialogFragment
|
||||
import org.citra.citra_emu.fragments.UpdateUserDirectoryDialogFragment
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
import org.citra.citra_emu.utils.CiaInstallWorker
|
||||
import org.citra.citra_emu.utils.CitraDirectoryHelper
|
||||
import org.citra.citra_emu.utils.CitraDirectoryUtils
|
||||
import org.citra.citra_emu.utils.DirectoryInitialization
|
||||
import org.citra.citra_emu.utils.FileBrowserHelper
|
||||
import org.citra.citra_emu.utils.InsetsHelper
|
||||
import org.citra.citra_emu.utils.RefreshRateUtil
|
||||
import org.citra.citra_emu.utils.PermissionsHandler
|
||||
import org.citra.citra_emu.utils.ThemeUtil
|
||||
import org.citra.citra_emu.viewmodel.GamesViewModel
|
||||
@ -66,6 +75,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
override var themeId: Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
RefreshRateUtil.enforceRefreshRate(this)
|
||||
|
||||
val splashScreen = installSplashScreen()
|
||||
CitraDirectoryUtils.attemptAutomaticUpdateDirectory()
|
||||
splashScreen.setKeepOnScreenCondition {
|
||||
@ -185,14 +196,53 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||
.getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true)
|
||||
|
||||
if (!firstTimeSetup && !PermissionsHandler.hasWriteAccess(this) &&
|
||||
!homeViewModel.isPickingUserDir.value
|
||||
) {
|
||||
if (firstTimeSetup) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
fun requestMissingFilesystemPermission() =
|
||||
GrantMissingFilesystemPermissionFragment.newInstance()
|
||||
.show(supportFragmentManager, GrantMissingFilesystemPermissionFragment.TAG)
|
||||
|
||||
if (supportFragmentManager.findFragmentByTag(GrantMissingFilesystemPermissionFragment.TAG) == null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
requestMissingFilesystemPermission()
|
||||
}
|
||||
} else {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestMissingFilesystemPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (homeViewModel.isPickingUserDir.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!PermissionsHandler.hasWriteAccess(this)) {
|
||||
SelectUserDirectoryDialogFragment.newInstance(this)
|
||||
.show(supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
||||
} else if (!firstTimeSetup && !homeViewModel.isPickingUserDir.value && CitraDirectoryUtils.needToUpdateManually()) {
|
||||
return
|
||||
} else if (CitraDirectoryUtils.needToUpdateManually()) {
|
||||
UpdateUserDirectoryDialogFragment.newInstance(this)
|
||||
.show(supportFragmentManager,UpdateUserDirectoryDialogFragment.TAG)
|
||||
return
|
||||
}
|
||||
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
if (supportFragmentManager.findFragmentByTag(SelectUserDirectoryDialogFragment.TAG) == null) {
|
||||
if (NativeLibrary.getUserDirectory() == "") {
|
||||
SelectUserDirectoryDialogFragment.newInstance(this)
|
||||
.show(supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,6 +366,17 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
if (NativeLibrary.getUserDirectory(result) == "") {
|
||||
SelectUserDirectoryDialogFragment.newInstance(
|
||||
this,
|
||||
R.string.invalid_selection,
|
||||
R.string.invalid_user_directory
|
||||
).show(supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
||||
return@registerForActivityResult
|
||||
}
|
||||
}
|
||||
|
||||
CitraDirectoryHelper(this@MainActivity, permissionsLost)
|
||||
.showCitraDirectoryDialog(result, buttonState = {})
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.utils
|
||||
|
||||
import org.citra.citra_emu.BuildConfig
|
||||
|
||||
object BuildUtil {
|
||||
@Suppress("unused")
|
||||
object BuildFlavors {
|
||||
const val GOOGLEPLAY = "googlePlay"
|
||||
const val VANILLA = "vanilla"
|
||||
}
|
||||
|
||||
fun assertNotGooglePlay() {
|
||||
if (isGooglePlayBuild) {
|
||||
error("Non-GooglePlay code being called in GooglePlay build")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("SimplifyBooleanWithConstants", "KotlinConstantConditions")
|
||||
val isGooglePlayBuild =
|
||||
BuildConfig.FLAVOR == BuildFlavors.GOOGLEPLAY
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -28,8 +28,8 @@ object DirectoryInitialization {
|
||||
@Volatile
|
||||
private var directoryState: DirectoryInitializationState? = null
|
||||
var userPath: String? = null
|
||||
val internalUserPath
|
||||
get() = CitraApplication.appContext.getExternalFilesDir(null)!!.canonicalPath
|
||||
val internalUserPath: String
|
||||
get() = CitraApplication.appContext.filesDir.canonicalPath
|
||||
private val isCitraDirectoryInitializationRunning = AtomicBoolean(false)
|
||||
|
||||
val context: Context get() = CitraApplication.appContext
|
||||
|
||||
@ -6,10 +6,12 @@ package org.citra.citra_emu.utils
|
||||
|
||||
import android.net.Uri
|
||||
import android.provider.DocumentsContract
|
||||
import androidx.core.net.toUri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.model.CheapDocument
|
||||
import java.net.URLDecoder
|
||||
import java.nio.file.Paths
|
||||
import java.util.StringTokenizer
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@ -191,7 +193,7 @@ class DocumentsTree {
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun renameFile(filepath: String, destinationFilename: String?): Boolean {
|
||||
fun renameFile(filepath: String, destinationFilename: String): Boolean {
|
||||
val node = resolvePath(filepath) ?: return false
|
||||
try {
|
||||
val filename = URLDecoder.decode(destinationFilename, FileUtil.DECODE_METHOD)
|
||||
@ -203,6 +205,20 @@ class DocumentsTree {
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun moveFile(filename: String, sourceDirPath: String, destDirPath: String): Boolean {
|
||||
val sourceFileNode = resolvePath(sourceDirPath + "/" + filename) ?: return false
|
||||
val sourceDirNode = resolvePath(sourceDirPath) ?: return false
|
||||
val destDirNode = resolvePath(destDirPath) ?: return false
|
||||
try {
|
||||
val newUri = DocumentsContract.moveDocument(context.contentResolver, sourceFileNode.uri!!, sourceDirNode.uri!!, destDirNode.uri!!)
|
||||
updateDocumentLocation("$sourceDirPath/$filename", "$destDirPath/$filename")
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
error("[DocumentsTree]: Cannot move file, error: " + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun deleteDocument(filepath: String): Boolean {
|
||||
val node = resolvePath(filepath) ?: return false
|
||||
@ -219,6 +235,29 @@ class DocumentsTree {
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateDocumentLocation(sourcePath: String, destinationPath: String): Boolean {
|
||||
val sourceNode = resolvePath(sourcePath)
|
||||
val newName = Paths.get(destinationPath).fileName.toString()
|
||||
val parentPath = Paths.get(destinationPath).parent.toString()
|
||||
val newParent = resolvePath(parentPath)
|
||||
val newUri = (getUri(parentPath).toString() + "%2F$newName").toUri() // <- Is there a better way?
|
||||
|
||||
if (sourceNode == null || newParent == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
sourceNode.parent!!.removeChild(sourceNode)
|
||||
|
||||
sourceNode.name = newName
|
||||
sourceNode.parent = newParent
|
||||
sourceNode.uri = newUri
|
||||
|
||||
newParent.addChild(sourceNode)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun resolvePath(filepath: String): DocumentsNode? {
|
||||
root ?: return null
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -11,6 +11,7 @@ import android.net.Uri
|
||||
import android.provider.DocumentsContract
|
||||
import android.system.Os
|
||||
import android.util.Pair
|
||||
import androidx.core.net.toUri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.model.CheapDocument
|
||||
@ -434,6 +435,20 @@ object FileUtil {
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun moveFile(filename: String, sourceDirUriString: String, destDirUriString: String): Boolean {
|
||||
try {
|
||||
val sourceFileUri = ("$sourceDirUriString%2F$filename").toUri()
|
||||
val sourceDirUri = sourceDirUriString.toUri()
|
||||
val destDirUri = destDirUriString.toUri()
|
||||
DocumentsContract.moveDocument(context.contentResolver, sourceFileUri, sourceDirUri, destDirUri)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.error("[FileUtil]: Cannot move file, error: " + e.message)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteDocument(path: String): Boolean {
|
||||
try {
|
||||
|
||||
@ -88,8 +88,10 @@ object GameHelper {
|
||||
isInstalled,
|
||||
gameInfo?.isSystemTitle() ?: false,
|
||||
gameInfo?.getIsVisibleSystemTitle() ?: false,
|
||||
gameInfo?.getIsInsertable() ?: false,
|
||||
gameInfo?.getIcon(),
|
||||
gameInfo?.getFileType() ?: "",
|
||||
gameInfo?.getFileType()?.contains("(Z)") ?: false,
|
||||
if (FileUtil.isNativePath(filePath)) {
|
||||
CitraApplication.documentsTree.getFilename(filePath)
|
||||
} else {
|
||||
|
||||
@ -8,6 +8,9 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.DocumentsContract
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
@ -48,4 +51,17 @@ object PermissionsHandler {
|
||||
|
||||
fun setCitraDirectory(uriString: String?) =
|
||||
preferences.edit().putString(CITRA_DIRECTORY, uriString).apply()
|
||||
|
||||
fun compatibleSelectDirectory(activityLauncher: ActivityResultLauncher<Uri?>) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
activityLauncher.launch(null)
|
||||
} else {
|
||||
val initialUri = DocumentsContract.buildRootUri(
|
||||
"com.android.externalstorage.documents",
|
||||
"primary"
|
||||
)
|
||||
activityLauncher.launch(initialUri)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.utils
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
object RefreshRateUtil {
|
||||
// Since Android 15, the OS automatically runs apps categorized as games with a
|
||||
// 60hz refresh rate by default, regardless of the refresh rate set by the user.
|
||||
//
|
||||
// This function sets the refresh rate to either the maximum allowed refresh rate or
|
||||
// 60hz depending on the value of the `sixtyHz` parameter.
|
||||
//
|
||||
// Note: This isn't always the maximum refresh rate that the display is *capable of*,
|
||||
// but is instead the refresh rate chosen by the user in the Android system settings.
|
||||
// For example, if the user selected 120hz in the settings, but the display is capable
|
||||
// of 144hz, 120hz will be treated as the maximum within this function.
|
||||
fun enforceRefreshRate(activity: Activity, sixtyHz: Boolean = false) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
return
|
||||
}
|
||||
|
||||
val display = activity.display
|
||||
val window = activity.window
|
||||
|
||||
display?.let {
|
||||
// Get all supported modes and find the one with the highest refresh rate
|
||||
val supportedModes = it.supportedModes
|
||||
val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate }
|
||||
|
||||
if (maxRefreshRate == null) {
|
||||
return
|
||||
}
|
||||
|
||||
var newModeId: Int?
|
||||
if (sixtyHz) {
|
||||
newModeId = supportedModes.firstOrNull { mode -> mode.refreshRate == 60f }?.modeId
|
||||
} else {
|
||||
// Set the preferred display mode to the one with the highest refresh rate
|
||||
newModeId = maxRefreshRate.modeId
|
||||
}
|
||||
|
||||
if (newModeId == null) {
|
||||
return
|
||||
}
|
||||
|
||||
window.attributes.preferredDisplayModeId = newModeId
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.utils
|
||||
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
import java.io.File
|
||||
|
||||
object RemovableStorageHelper {
|
||||
// This really shouldn't be necessary, but the Android API seemingly
|
||||
// doesn't have a way of doing this?
|
||||
fun getRemovableStoragePath(idString: String): String? {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
|
||||
// On certain Android flavours the external storage mount location can
|
||||
// vary, so add extra cases here if we discover them.
|
||||
val possibleMountPaths = listOf("/mnt/media_rw/$idString", "/storage/$idString")
|
||||
|
||||
for (mountPath in possibleMountPaths) {
|
||||
val pathFile = File(mountPath);
|
||||
if (pathFile.exists()) {
|
||||
// TODO: Cache which mount location is being used for the remainder of the
|
||||
// session, as it should never change. -OS
|
||||
return pathFile.absolutePath
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
||||
object CompressProgressDialogViewModel: ViewModel() {
|
||||
private val _progress = MutableStateFlow(0)
|
||||
val progress = _progress.asStateFlow()
|
||||
|
||||
private val _total = MutableStateFlow(0)
|
||||
val total = _total.asStateFlow()
|
||||
|
||||
private val _message = MutableStateFlow("")
|
||||
val message = _message.asStateFlow()
|
||||
|
||||
fun update(totalBytes: Long, currentBytes: Long) {
|
||||
val percent = ((currentBytes * 100L) / totalBytes).coerceIn(0L, 100L).toInt()
|
||||
_total.value = 100
|
||||
_progress.value = percent
|
||||
_message.value = ""
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
_progress.value = 0
|
||||
_total.value = 0
|
||||
_message.value = ""
|
||||
}
|
||||
}
|
||||
@ -175,7 +175,8 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.custom_second_layer_opacity);
|
||||
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||
ReadSetting("Renderer", Settings::values.disable_right_eye_render);
|
||||
|
||||
ReadSetting("Renderer", Settings::values.swap_eyes_3d);
|
||||
ReadSetting("Renderer", Settings::values.render_3d_which_display);
|
||||
// Layout
|
||||
// Somewhat inelegant solution to ensure layout value is between 0 and 5 on read
|
||||
// since older config files may have other values
|
||||
@ -262,6 +263,7 @@ void Config::ReadValues() {
|
||||
ReadSetting("System", Settings::values.plugin_loader_enabled);
|
||||
ReadSetting("System", Settings::values.allow_plugin_loader);
|
||||
ReadSetting("System", Settings::values.steps_per_hour);
|
||||
ReadSetting("System", Settings::values.apply_region_free_patch);
|
||||
|
||||
// Camera
|
||||
using namespace Service::CAM;
|
||||
|
||||
@ -170,13 +170,23 @@ bg_green =
|
||||
custom_second_layer_opacity =
|
||||
|
||||
# Whether and how Stereoscopic 3D should be rendered
|
||||
# 0 (default): Off, 1: Side by Side, 2: Reverse Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
|
||||
# 0: Off, 1: Half Width Side by Side, 2 (default): Full Width Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
|
||||
# 0 is no longer supported in the interface, as using render_3d_which_display = 0 has the same effect, but supported here for backwards compatibility
|
||||
render_3d =
|
||||
|
||||
# Change 3D Intensity
|
||||
# 0 - 255: Intensity. 0 (default)
|
||||
factor_3d =
|
||||
|
||||
# Swap Eyes in 3d
|
||||
# true: Swap eyes, false (default): Do not swap eyes
|
||||
swap_eyes_3d =
|
||||
|
||||
# Which Display to render 3d mode to
|
||||
# 0 (default) - None. Equivalent to render_3d=0
|
||||
# 1: Both, 2: Primary Only, 3: Secondary Only
|
||||
render_3d_which_display =
|
||||
|
||||
# The name of the post processing shader to apply.
|
||||
# Loaded from shaders if render_3d is off or side by side.
|
||||
pp_shader_name =
|
||||
@ -413,6 +423,11 @@ steps_per_hour =
|
||||
plugin_loader =
|
||||
allow_plugin_loader =
|
||||
|
||||
# Apply region free patch to installed applications
|
||||
# Patches the region of installed applications to be region free, so that they always appear on the home menu.
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
apply_region_free_patch =
|
||||
|
||||
[Camera]
|
||||
# Which camera engine to use for the right outer camera
|
||||
# blank: a dummy camera that always returns black image
|
||||
|
||||
@ -25,6 +25,7 @@ struct GameInfoData {
|
||||
bool loaded = false;
|
||||
bool is_encrypted = false;
|
||||
std::string file_type = "";
|
||||
bool is_insertable = false;
|
||||
};
|
||||
|
||||
GameInfoData* GetNewGameInfoData(const std::string& path) {
|
||||
@ -89,6 +90,7 @@ GameInfoData* GetNewGameInfoData(const std::string& path) {
|
||||
gid->is_encrypted = is_encrypted;
|
||||
gid->title_id = program_id;
|
||||
gid->file_type = Loader::GetFileTypeString(loader->GetFileType(), loader->IsFileCompressed());
|
||||
gid->is_insertable = loader->GetFileType() == Loader::FileType::CCI;
|
||||
|
||||
return gid;
|
||||
}
|
||||
@ -222,7 +224,7 @@ jboolean Java_org_citra_citra_1emu_model_GameInfo_getIsVisibleSystemTitle(JNIEnv
|
||||
return false;
|
||||
}
|
||||
|
||||
return smdh->flags & Loader::SMDH::Flags::Visible;
|
||||
return smdh->flags.visible;
|
||||
}
|
||||
|
||||
jstring Java_org_citra_citra_1emu_model_GameInfo_getFileType(JNIEnv* env, jobject obj) {
|
||||
@ -230,4 +232,7 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getFileType(JNIEnv* env, jobjec
|
||||
|
||||
return ToJString(env, file_type);
|
||||
}
|
||||
jboolean Java_org_citra_citra_1emu_model_GameInfo_getIsInsertable(JNIEnv* env, jobject obj) {
|
||||
return GetPointer(env, obj)->is_insertable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -40,6 +40,7 @@ static jfieldID s_game_info_pointer;
|
||||
|
||||
static jclass s_disk_cache_progress_class;
|
||||
static jmethodID s_disk_cache_load_progress;
|
||||
static jmethodID s_compress_progress_method;
|
||||
static std::unordered_map<VideoCore::LoadCallbackStage, jobject> s_java_load_callback_stages;
|
||||
|
||||
static jclass s_cia_install_helper_class;
|
||||
@ -131,6 +132,10 @@ jmethodID GetDiskCacheLoadProgress() {
|
||||
return s_disk_cache_load_progress;
|
||||
}
|
||||
|
||||
jmethodID GetCompressProgressMethod() {
|
||||
return s_compress_progress_method;
|
||||
}
|
||||
|
||||
jobject GetJavaLoadCallbackStage(VideoCore::LoadCallbackStage stage) {
|
||||
const auto it = s_java_load_callback_stages.find(stage);
|
||||
ASSERT_MSG(it != s_java_load_callback_stages.end(), "Invalid LoadCallbackStage: {}", stage);
|
||||
@ -205,6 +210,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
s_disk_cache_load_progress = env->GetStaticMethodID(
|
||||
s_disk_cache_progress_class, "loadProgress",
|
||||
"(Lorg/citra/citra_emu/utils/DiskShaderCacheProgress$LoadCallbackStage;II)V");
|
||||
s_compress_progress_method =
|
||||
env->GetStaticMethodID(s_native_library_class, "onCompressProgress", "(JJ)V");
|
||||
// Initialize LoadCallbackStage map
|
||||
const auto to_java_load_callback_stage = [env,
|
||||
load_callback_stage_class](const std::string& stage) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -40,6 +40,7 @@ jfieldID GetGameInfoPointer();
|
||||
|
||||
jclass GetDiskCacheProgressClass();
|
||||
jmethodID GetDiskCacheLoadProgress();
|
||||
jmethodID GetCompressProgressMethod();
|
||||
jobject GetJavaLoadCallbackStage(VideoCore::LoadCallbackStage stage);
|
||||
|
||||
jclass GetCiaInstallHelperClass();
|
||||
|
||||
@ -34,10 +34,12 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/zstd_compression.h"
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/applets/default_applets.h"
|
||||
#include "core/frontend/camera/factory.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/hle/service/nfc/nfc.h"
|
||||
#include "core/hw/unique_data.h"
|
||||
#include "core/loader/loader.h"
|
||||
@ -74,6 +76,17 @@ namespace {
|
||||
ANativeWindow* s_surface;
|
||||
ANativeWindow* s_secondary_surface;
|
||||
|
||||
enum class CompressionStatus : jint {
|
||||
Success = 0,
|
||||
Compress_Unsupported = 1,
|
||||
Compress_AlreadyCompressed = 2,
|
||||
Compress_Failed = 3,
|
||||
Decompress_Unsupported = 4,
|
||||
Decompress_NotCompressed = 5,
|
||||
Decompress_Failed = 6,
|
||||
Installed_Application = 7,
|
||||
};
|
||||
|
||||
std::shared_ptr<Common::DynamicLibrary> vulkan_library{};
|
||||
std::unique_ptr<EmuWindow_Android> window;
|
||||
std::unique_ptr<EmuWindow_Android> secondary_window;
|
||||
@ -88,6 +101,8 @@ std::mutex paused_mutex;
|
||||
std::mutex running_mutex;
|
||||
std::condition_variable running_cv;
|
||||
|
||||
std::string inserted_cartridge;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
static jobject ToJavaCoreError(Core::System::ResultStatus result) {
|
||||
@ -95,6 +110,7 @@ static jobject ToJavaCoreError(Core::System::ResultStatus result) {
|
||||
{Core::System::ResultStatus::ErrorSystemFiles, "ErrorSystemFiles"},
|
||||
{Core::System::ResultStatus::ErrorSavestate, "ErrorSavestate"},
|
||||
{Core::System::ResultStatus::ErrorArticDisconnected, "ErrorArticDisconnected"},
|
||||
{Core::System::ResultStatus::ErrorN3DSApplication, "ErrorN3DSApplication"},
|
||||
{Core::System::ResultStatus::ErrorUnknown, "ErrorUnknown"},
|
||||
};
|
||||
|
||||
@ -134,7 +150,10 @@ static void TryShutdown() {
|
||||
secondary_window->DoneCurrent();
|
||||
}
|
||||
|
||||
Core::System::GetInstance().Shutdown();
|
||||
Core::System& system{Core::System::GetInstance()};
|
||||
|
||||
system.Shutdown();
|
||||
system.EjectCartridge();
|
||||
|
||||
window.reset();
|
||||
if (secondary_window) {
|
||||
@ -165,6 +184,10 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||
|
||||
Core::System& system{Core::System::GetInstance()};
|
||||
|
||||
if (!inserted_cartridge.empty()) {
|
||||
system.InsertCartridge(inserted_cartridge);
|
||||
}
|
||||
|
||||
const auto graphics_api = Settings::values.graphics_api.GetValue();
|
||||
EGLContext* shared_context;
|
||||
switch (graphics_api) {
|
||||
@ -463,6 +486,163 @@ jstring Java_org_citra_citra_1emu_NativeLibrary_getHomeMenuPath(JNIEnv* env,
|
||||
return ToJString(env, "");
|
||||
}
|
||||
|
||||
static CompressionStatus GetCompressFileInfo(Loader::AppLoader::CompressFileInfo& out_info,
|
||||
size_t& out_frame_size, const std::string& filepath,
|
||||
bool compress) {
|
||||
|
||||
if (Service::FS::IsInstalledApplication(filepath)) {
|
||||
return CompressionStatus::Installed_Application;
|
||||
}
|
||||
|
||||
Loader::AppLoader::CompressFileInfo compress_info{};
|
||||
compress_info.is_supported = false;
|
||||
size_t frame_size{};
|
||||
auto loader = Loader::GetLoader(filepath);
|
||||
if (loader) {
|
||||
compress_info = loader->GetCompressFileInfo();
|
||||
frame_size = FileUtil::Z3DSWriteIOFile::DEFAULT_FRAME_SIZE;
|
||||
} else {
|
||||
bool is_compressed = false;
|
||||
if (Service::AM::CheckCIAToInstall(filepath, is_compressed, compress ? true : false) ==
|
||||
Service::AM::InstallStatus::Success) {
|
||||
compress_info.is_supported = true;
|
||||
compress_info.is_compressed = is_compressed;
|
||||
compress_info.recommended_compressed_extension = "zcia";
|
||||
compress_info.recommended_uncompressed_extension = "cia";
|
||||
compress_info.underlying_magic = std::array<u8, 4>({'C', 'I', 'A', '\0'});
|
||||
frame_size = FileUtil::Z3DSWriteIOFile::DEFAULT_CIA_FRAME_SIZE;
|
||||
if (compress) {
|
||||
auto meta_info = Service::AM::GetCIAInfos(filepath);
|
||||
if (meta_info.Succeeded()) {
|
||||
const auto& meta_info_val = meta_info.Unwrap();
|
||||
std::vector<u8> value(sizeof(Service::AM::TitleInfo));
|
||||
memcpy(value.data(), &meta_info_val.first, sizeof(Service::AM::TitleInfo));
|
||||
compress_info.default_metadata.emplace("titleinfo", value);
|
||||
if (meta_info_val.second) {
|
||||
value.resize(sizeof(Loader::SMDH));
|
||||
memcpy(value.data(), meta_info_val.second.get(), sizeof(Loader::SMDH));
|
||||
compress_info.default_metadata.emplace("smdh", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!compress_info.is_supported) {
|
||||
LOG_ERROR(Frontend,
|
||||
"Error {} file {}, the selected file is not a compatible 3DS ROM format or is "
|
||||
"encrypted.",
|
||||
compress ? "compressing" : "decompressing", filepath);
|
||||
return compress ? CompressionStatus::Compress_Unsupported
|
||||
: CompressionStatus::Decompress_Unsupported;
|
||||
}
|
||||
if (compress_info.is_compressed && compress) {
|
||||
LOG_ERROR(Frontend, "Error compressing file {}, the selected file is already compressed",
|
||||
filepath);
|
||||
return CompressionStatus::Compress_AlreadyCompressed;
|
||||
}
|
||||
if (!compress_info.is_compressed && !compress) {
|
||||
LOG_ERROR(Frontend,
|
||||
"Error decompressing file {}, the selected file is already decompressed",
|
||||
filepath);
|
||||
return CompressionStatus::Decompress_NotCompressed;
|
||||
}
|
||||
|
||||
out_info = compress_info;
|
||||
out_frame_size = frame_size;
|
||||
return CompressionStatus::Success;
|
||||
}
|
||||
|
||||
jint Java_org_citra_citra_1emu_NativeLibrary_compressFileNative(JNIEnv* env, jobject obj,
|
||||
jstring j_input_path,
|
||||
jstring j_output_path) {
|
||||
const std::string input_path = GetJString(env, j_input_path);
|
||||
const std::string output_path = GetJString(env, j_output_path);
|
||||
|
||||
Loader::AppLoader::CompressFileInfo compress_info{};
|
||||
size_t frame_size{};
|
||||
CompressionStatus stat = GetCompressFileInfo(compress_info, frame_size, input_path, true);
|
||||
if (stat != CompressionStatus::Success) {
|
||||
return static_cast<jint>(stat);
|
||||
}
|
||||
|
||||
auto progress = [](std::size_t processed, std::size_t total) {
|
||||
JNIEnv* env = IDCache::GetEnvForThread();
|
||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::GetCompressProgressMethod(), static_cast<jlong>(total),
|
||||
static_cast<jlong>(processed));
|
||||
};
|
||||
|
||||
bool success =
|
||||
FileUtil::CompressZ3DSFile(input_path, output_path, compress_info.underlying_magic,
|
||||
frame_size, progress, compress_info.default_metadata);
|
||||
if (!success) {
|
||||
FileUtil::Delete(output_path);
|
||||
return static_cast<jint>(CompressionStatus::Compress_Failed);
|
||||
}
|
||||
|
||||
return static_cast<jint>(CompressionStatus::Success);
|
||||
}
|
||||
|
||||
jint Java_org_citra_citra_1emu_NativeLibrary_decompressFileNative(JNIEnv* env, jobject obj,
|
||||
jstring j_input_path,
|
||||
jstring j_output_path) {
|
||||
const std::string input_path = GetJString(env, j_input_path);
|
||||
const std::string output_path = GetJString(env, j_output_path);
|
||||
|
||||
Loader::AppLoader::CompressFileInfo compress_info{};
|
||||
size_t frame_size{};
|
||||
CompressionStatus stat = GetCompressFileInfo(compress_info, frame_size, input_path, false);
|
||||
if (stat != CompressionStatus::Success) {
|
||||
return static_cast<jint>(stat);
|
||||
}
|
||||
|
||||
auto progress = [](std::size_t processed, std::size_t total) {
|
||||
JNIEnv* env = IDCache::GetEnvForThread();
|
||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::GetCompressProgressMethod(), static_cast<jlong>(total),
|
||||
static_cast<jlong>(processed));
|
||||
};
|
||||
|
||||
bool success = FileUtil::DeCompressZ3DSFile(input_path, output_path, progress);
|
||||
if (!success) {
|
||||
FileUtil::Delete(output_path);
|
||||
return static_cast<jint>(CompressionStatus::Decompress_Failed);
|
||||
}
|
||||
|
||||
return static_cast<jint>(CompressionStatus::Success);
|
||||
}
|
||||
|
||||
jstring Java_org_citra_citra_1emu_NativeLibrary_getRecommendedExtension(
|
||||
JNIEnv* env, jobject obj, jstring j_input_path, jboolean j_should_compress) {
|
||||
const std::string input_path = GetJString(env, j_input_path);
|
||||
|
||||
std::string compressed_ext;
|
||||
std::string uncompressed_ext;
|
||||
|
||||
auto loader = Loader::GetLoader(input_path);
|
||||
if (loader) {
|
||||
auto compress_info = loader->GetCompressFileInfo();
|
||||
if (compress_info.is_supported) {
|
||||
compressed_ext = compress_info.recommended_compressed_extension;
|
||||
uncompressed_ext = compress_info.recommended_uncompressed_extension;
|
||||
}
|
||||
} else {
|
||||
bool is_compressed = false;
|
||||
if (Service::AM::CheckCIAToInstall(input_path, is_compressed, true) ==
|
||||
Service::AM::InstallStatus::Success) {
|
||||
compressed_ext = "zcia";
|
||||
uncompressed_ext = "cia";
|
||||
}
|
||||
}
|
||||
|
||||
if (compressed_ext.empty()) {
|
||||
return env->NewStringUTF("");
|
||||
}
|
||||
|
||||
return env->NewStringUTF(j_should_compress ? compressed_ext.c_str() : uncompressed_ext.c_str());
|
||||
}
|
||||
|
||||
void Java_org_citra_citra_1emu_NativeLibrary_setUserDirectory(JNIEnv* env,
|
||||
[[maybe_unused]] jobject obj,
|
||||
jstring j_directory) {
|
||||
@ -919,4 +1099,9 @@ jlong Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerGetCurrentTitleId(J
|
||||
return ptm_current_title_id;
|
||||
}
|
||||
|
||||
void Java_org_citra_citra_1emu_NativeLibrary_setInsertedCartridge(JNIEnv* env, jobject obj,
|
||||
jstring path) {
|
||||
inserted_cartridge = GetJString(env, path);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
BIN
src/android/app/src/main/res/drawable/cartridge.png
Normal file
BIN
src/android/app/src/main/res/drawable/cartridge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@ -28,6 +28,16 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_cartridge"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/cartridge"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@ -45,7 +45,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" app:layout_constraintStart_toStartOf="parent"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Application Title" />
|
||||
|
||||
@ -120,12 +121,13 @@
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/about_game_play"
|
||||
style="@style/Widget.Material3.Button.Icon"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="142dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
android:contentDescription="@string/play"
|
||||
android:focusedByDefault="true"
|
||||
android:text="@string/play"
|
||||
android:textAlignment="center"
|
||||
app:icon="@drawable/ic_play" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
@ -166,7 +168,6 @@
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="start|center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/horizontal_layout">
|
||||
@ -179,6 +180,37 @@
|
||||
android:contentDescription="@string/cheats"
|
||||
android:text="@string/cheats" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/insert_cartridge_button"
|
||||
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/compress_decompress"
|
||||
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/compress"
|
||||
android:text="@string/compress" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/compress_tray"
|
||||
style="@style/ThemeOverlay.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="start|center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/game_button_tray">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/compress_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:visibility="visible"
|
||||
android:paddingBottom="8dp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/compress_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -122,8 +122,6 @@
|
||||
<string name="input_dialog_description">Pulsa o mou un botó/palanca.</string>
|
||||
<string name="input_binding">Assignació de botons</string>
|
||||
<string name="input_binding_description">Prem o mou una entrada per enllaçar-la a %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Mou el joystick amunt o avall.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Mou el joystick a esquerra o dreta.</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Intercanviar Pantalles</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -217,21 +215,18 @@
|
||||
<string name="spirv_shader_gen_description">Usa SPIR-V en vez de GLSL per a emetre el fragment de ombrejador utilitzat per a emular PICA.</string>
|
||||
<string name="disable_spirv_optimizer">Desativar l\'optimitzador SPIR-V</string>
|
||||
<string name="disable_spirv_optimizer_description">Desactiva la passada d\'optimització SPIR-V reduint considerablement el quequeig i afectant poc el rendiment.</string>
|
||||
<string name="async_shaders">Activar compilació de ombrejadors asíncrona</string>
|
||||
<string name="async_shaders_description">Compila els ombrejats en segón pla per a reduir les aturades durant la partida.
|
||||
S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="linear_filtering">Filtre Linear</string>
|
||||
<string name="linear_filtering_description">Activa el filtre linear, que fa que els gràfics del joc es vegen més suaus.</string>
|
||||
<string name="texture_filter_name">Filtre de Textures</string>
|
||||
<string name="texture_filter_description">Millora l\'aspecte visual de les aplicacions aplicant un filtre a les textures. Els filtres compatibles són Anime4K, Ultrafast, Bicubic, ScaleForce, xBRZ Freescale i MMPX.</string>
|
||||
<string name="delay_render_thread">Endarrerir fil de renderitzat del joc</string>
|
||||
<string name="delay_render_thread_description">Retarda el fil de renderitzat del joc en enviar dades a la GPU. Ajuda a solucionar problemes de rendiment en les (poques) aplicacions amb velocitats de fotogrames dinàmiques.</string>
|
||||
<string name="advanced">Avançat</string>
|
||||
<string name="texture_sampling_name">Mostreig de Textures</string>
|
||||
<string name="texture_sampling_description">Sobreescriu el filtre de mostreig usat en jocs. Pot ser útil en uns certs casos de jocs amb baix rendiment en pujar la resolució. Si no estàs segur, possa\'l en Controlat per Joc.</string>
|
||||
<string name="shaders_accurate_mul">Multiplicació Precisa</string>
|
||||
<string name="shaders_accurate_mul_description">Usa multiplicacions més precises en els ombrejos de Hardware, que podrien arreglar uns certs problemes gràfics. Quan s\'active, el rendiment es reduirà.</string>
|
||||
<string name="asynchronous_gpu">Activar Emulació Asíncrona de la GPU</string>
|
||||
<string name="asynchronous_gpu_description">Usa un fil separat per a emular la GPU de manera asíncrona. Quan s\'active, el rendiment millorarà.</string>
|
||||
<string name="frame_limit_enable">Límit de velocitat</string>
|
||||
<string name="frame_limit_enable_description">Quan s\'active, la velocitat d\'emulació estarà limitada a un percentatge determinat de la velocitat normal. Quan es desactive, la velocitat d\'emulació no tindrà límit i la tecla d\'accés ràpid de velocitat turbo no funcionarà.</string>
|
||||
@ -286,7 +281,6 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="audio_volume">Volum</string>
|
||||
<string name="audio_stretch">Extensió d\'Àudio</string>
|
||||
<string name="audio_stretch_description">Estén l\'àudio per a reduir les aturades. Quan s\'active, la latència d\'àudio s\'incrementarà i reduirà un poc el rendiment.</string>
|
||||
<string name="realtime_audio">Activar àudio en temps real</string>
|
||||
<string name="realtime_audio_description">Ajusta la velocitat de reproducció d\'àudio per a compensar les caigudes en la velocitat d\'emulació de quadres. Això significa que l\'àudio es reproduirà a velocitat completa fins i tot quan la velocitat de quadres del joc siga baixa. Pot causar problemes de desincronització d\'àudio.</string>
|
||||
<string name="audio_input_type">Dispositiu d\'entrada d\'àudio</string>
|
||||
<string name="sound_output_mode">Mode d\'eixida de l\'àudio</string>
|
||||
@ -298,12 +292,9 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="hw_shaders_description">Usa el hardware per a emular els ombrejadors de 3DS. Quan s\'active, el rendiment millorarà notablement.</string>
|
||||
<string name="cpu_clock_speed">Velocitat de rellotge de la CPU</string>
|
||||
<string name="vsync">Activar Sincronització Vertical</string>
|
||||
<string name="vsync_description">Sincronitza els quadres per segon del joc amb la taxa de refresc del teu dispositiu.</string>
|
||||
<string name="renderer_debug">Renderitzador de depuració</string>
|
||||
<string name="renderer_debug_description">Arxiva informació addicional gràfica relacionada amb la depuració. Quan està activada, el rendiment dels jocs serà reduït considerablement</string>
|
||||
<string name="instant_debug_log">Guardar l\'eixida del registre en cada missatge</string>
|
||||
<string name="instant_debug_log_description">Envia immediatament el registre de depuració a un arxiu. Usa-ho si Azahar falla i es talla l\'eixida del registre.</string>
|
||||
<string name="delay_start_lle_modules">Inici diferit amb mòduls LLE</string>
|
||||
<string name="delay_start_lle_modules_description">Retarda l\'inici de l\'aplicació quan els mòduls LLE estan habilitats.</string>
|
||||
<string name="deterministic_async_operations">Operacions asíncrones deterministes</string>
|
||||
<string name="deterministic_async_operations_description">Fa que les operacions asíncrones siguen deterministes per a la depuració. Habilitar esta opció pot causar bloquejos.</string>
|
||||
@ -523,7 +514,6 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="fatal_error">Error Fatal</string>
|
||||
<string name="fatal_error_message">Ha ocorregut un error fatal. Mira el registre per a més detalls.\nSeguir amb l\'emulació podria resultar en diversos penges i problemes.</string>
|
||||
<string name="unsupported_encrypted">Aplicació cifrada no suportada</string>
|
||||
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Preparant ombrejadors</string>
|
||||
<string name="building_shaders">Construint ombrejadors</string>
|
||||
@ -550,35 +540,11 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Fitxer:</string>
|
||||
<string name="game_context_type">Tipus:</string>
|
||||
|
||||
<!-- Performance Overlay settings -->
|
||||
<string name="performance_overlay_show">Mostrar informació de rendiment</string>
|
||||
<string name="performance_overlay_options">Informació de rendiment</string>
|
||||
<string name="performance_overlay_enable">Activar informació de rendiment</string>
|
||||
<string name="performance_overlay_options_description">Configura la informació de rendiment</string>
|
||||
<string name="overlay_show_fps">Mostrar FPS</string>
|
||||
<string name="overlay_show_fps_description">Mostra els fotogrames per segon actuals.</string>
|
||||
<string name="overlay_show_frametime">Mostrar duració de fotogrames</string>
|
||||
<string name="overlay_show_frametime_description">Mostra la duració actual de cada fotograma.</string>
|
||||
<string name="overlay_show_speed">Mostrar velocitat</string>
|
||||
<string name="overlay_show_speed_description">Mostra el percentatge de velocitat d\'emulació actual.</string>
|
||||
<string name="overlay_show_app_ram_usage">Mostrar l\'ús de memòria de l\'aplicació</string>
|
||||
<string name="overlay_show_app_ram_usage_description">Mostra la quantitat de memòria RAM que esta usant l\'emulador.</string>
|
||||
<string name="overlay_show_available_ram">Mostrar memòria disponible</string>
|
||||
<string name="overlay_show_available_ram_description">Mostra la quantitat de memòria RAM que esta disponible.</string>
|
||||
<string name="overlay_show_battery_temp">Mostrar la temperatura de la bateria</string>
|
||||
<string name="overlay_show_battery_temp_description">Mostra la temperatura actual de la bateria en Celsius i Fahrenheit.</string>
|
||||
<string name="overlay_position">Posició de la informació</string>
|
||||
<string name="overlay_position_description">Tria on la informació de rendiment serà mostrada en la pantalla.</string>
|
||||
<string name="overlay_position_top_left">Dalt a l\'esquerra</string>
|
||||
<string name="overlay_position_top_right">Dalt a la dreta</string>
|
||||
<string name="overlay_position_bottom_left">Avall a l\'esquerra</string>
|
||||
<string name="overlay_position_bottom_right">Avall a la dreta</string>
|
||||
<string name="overlay_position_center_top">Dalt al centre</string>
|
||||
<string name="overlay_position_center_bottom">Avall al centre</string>
|
||||
<string name="overlay_background">Fons de la informació</string>
|
||||
<string name="overlay_background_description">Agrega un fons darrere de la informació per a fer-la més llegible.</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Trucs</string>
|
||||
<string name="cheats_add">Afegir trucs</string>
|
||||
@ -681,7 +647,6 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">De costat a costat</string>
|
||||
<string name="reverse_side_by_side">De costat a costat invers</string>
|
||||
<string name="anaglyph">Anàglifo</string>
|
||||
<string name="interlaced">Entrellaçat</string>
|
||||
<string name="reverse_interlaced">Entrellaçat invers</string>
|
||||
@ -870,4 +835,4 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||
<string name="emulation_occupied_quicksave_slot">Guardat ràpid - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Guardat ràpid no disponible.</string>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@ -67,10 +67,14 @@
|
||||
<string name="give_permission">Giv tilladelse</string>
|
||||
<string name="notification_warning">Vil du droppe at give tilladelse til meddelelser?</string>
|
||||
<string name="notification_warning_description">Azahar vil ikke være i stand til at give dig meddelelse om vigtige oplysninger.</string>
|
||||
<string name="filesystem_permission_warning">Manglende tilladelser</string>
|
||||
<string name="filesystem_permission_warning_description">Azahar kræver tilladelse til at administrere filer på denne enhed for at kunne gemme og administrere dens data.\n\nGiv venligst tilladelsen \"Filsystem\", før du fortsætter.</string>
|
||||
<string name="camera_permission">Kamera</string>
|
||||
<string name="camera_permission_description">Giv kameraet tilladelse nedenfor til at efterligne 3DS-kameraet.</string>
|
||||
<string name="microphone_permission">Mikrofon</string>
|
||||
<string name="microphone_permission_description">Giv mikrofonen tilladelse nedenfor til at efterligne 3DS-mikrofonen.</string>
|
||||
<string name="filesystem_permission">Filsystem</string>
|
||||
<string name="filesystem_permission_description">Giv filsystemet tilladelse nedenfor for at tillade Azahar at gemme filer.</string>
|
||||
<string name="permission_denied">Tilladelse nægtet</string>
|
||||
<string name="add_games_warning">Vil du droppe at vælge applikationsmappen?</string>
|
||||
<string name="add_games_warning_description">Software vil ikke blive vist på applikationslisten, hvis en mappe ikke er valgt.</string>
|
||||
@ -90,6 +94,9 @@
|
||||
<string name="cannot_skip">Du kan ikke springe opsætningen af brugermappen over </string>
|
||||
<string name="cannot_skip_directory_description">Dette trin er påkrævet for at Azahar kan fungere. Vælg en mappe og så kan du fortsætte.</string>
|
||||
<string name="selecting_user_directory_without_write_permissions">Du har mistet skrivetilladelse i din <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">brugerdata</a> mappe, hvor gemte tilstande og anden information er gemt. Dette kan ske efter en app- eller Android-opdatering. Vælg venligst mappen for at give tilladelse igen, så du kan fortsætte.</string>
|
||||
<string name="invalid_selection">Ugyldigt valg</string>
|
||||
<string name="invalid_user_directory">Valget af brugermappe var ugyldigt.\nVælg venligst brugermappen igen, og sørg for at navigere til den fra roden af din enheds lager.</string>
|
||||
<string name="filesystem_permission_lost">Azahar har mistet tilladelsen til at administrere filer på denne enhed. Dette kan ske efter nogle app- eller Android-opdateringer. Giv venligst denne tilladelse igen på den næste skærm for at fortsætte med at bruge appen.</string>
|
||||
<string name="set_up_theme_settings">Temaindstillinger</string>
|
||||
<string name="setup_theme_settings_description">Konfigurer dine temaindstillinger for Azahar.</string>
|
||||
<string name="setup_set_theme">Indstil tema</string>
|
||||
@ -122,8 +129,8 @@
|
||||
<string name="input_dialog_description">Tryk på eller flyt et input.</string>
|
||||
<string name="input_binding">Inputbinding</string>
|
||||
<string name="input_binding_description">Tryk på eller flyt et input for at binde det til %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Bevæg joysticket op eller ned.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Bevæg joysticket til venstre eller højre</string>
|
||||
<string name="input_binding_description_vertical_axis">Bevæg joysticket ned</string>
|
||||
<string name="input_binding_description_horizontal_axis">Bevæg joysticket til højre</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Byt skærme</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -162,6 +169,8 @@
|
||||
<string name="username">Brugernavn</string>
|
||||
<string name="new_3ds">Ny 3DS tilstand</string>
|
||||
<string name="lle_applets">Brug LLE Applets (hvis installeret)</string>
|
||||
<string name="apply_region_free_patch">Anvend regionfri programrettelse på installerede programmer</string>
|
||||
<string name="apply_region_free_patch_desc">Opdaterer regionen for installerede programmer, så de altid vises i startmenuen.</string>
|
||||
<string name="enable_required_online_lle_modules">Aktiver nødvendige LLE moduler til onlinefunktioner (hvis installeret)</string>
|
||||
<string name="enable_required_online_lle_modules_desc">Aktiverer de LLE moduler, der kræves til online multiplayer, eShop-adgang osv.</string>
|
||||
<string name="clock">Ur</string>
|
||||
@ -193,6 +202,10 @@
|
||||
<string name="region_mismatch">Advarsel om uoverensstemmelse i region</string>
|
||||
<string name="region_mismatch_emulated">Landeindstillingen er ikke gyldig for det valgte emulerede område.</string>
|
||||
<string name="region_mismatch_console">Landeindstillingen er ikke gyldig for den aktuelle forbundne konsol.</string>
|
||||
<string name="storage">Lager</string>
|
||||
<string name="compress_cia_installs">Komprimer installeret CIA-indhold</string>
|
||||
<string name="compress_cia_installs_description">Komprimerer indholdet af CIA-filer, når de installeres på det emulerede SD-kort. Påvirker kun CIA-indhold, der installeres, når indstillingen er aktiveret.</string>
|
||||
|
||||
<!-- Camera settings strings -->
|
||||
<string name="inner_camera">Indre kamera</string>
|
||||
<string name="outer_left_camera">Ydre venstre kamera</string>
|
||||
@ -219,7 +232,7 @@
|
||||
<string name="linear_filtering_description">Aktiverer lineær filtrering, hvilket får spillets grafik til at se mere jævnt ud.</string>
|
||||
<string name="texture_filter_name">Teksturfilter</string>
|
||||
<string name="texture_filter_description">Forbedrer det visuelle i applikationer ved at anvende et filter på teksturer. De understøttede filtre er Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale og MMPX.</string>
|
||||
<string name="delay_render_thread">Forsinket spillets renderingstråd</string>
|
||||
<string name="delay_render_thread">Forsink spillets renderingstråd</string>
|
||||
<string name="delay_render_thread_description">Forsink spillets remderingstråd, når den sender data til GPU\'en. Hjælper med ydeevneproblemer i de (meget få) applikationer med dynamiske framerates.</string>
|
||||
<string name="advanced">Avanceret</string>
|
||||
<string name="texture_sampling_name">Tekstur sampling</string>
|
||||
@ -232,6 +245,8 @@
|
||||
<string name="frame_limit_enable_description">Når aktiveret, vil emuleringshastigheden være begrænset til en specificeret procentdel af normal hastighed. Hvis deaktiveret, vil emuleringshastigheden være ubegrænset, og genvejstasten for turbohastighed vil ikke fungere.</string>
|
||||
<string name="frame_limit_slider">Begræns hastighedsprocent</string>
|
||||
<string name="frame_limit_slider_description">Angiver procentdelen emuleringshastigheden skal begrænses til. Med standardværdien på 100% vil emulering være begrænset til normal hastighed. Værdier højere eller lavere vil øge eller mindske hastighedsgrænsen.</string>
|
||||
<string name="android_hide_images">Skjul 3DS-afbildninger fra Android</string>
|
||||
<string name="android_hide_images_description">Forhindre at Android indekserer og viser billeder fra 3DS-kamera, skærmbilleder og brugerdefinerede teksturer i galleriet. Din enhed skal muligvis genstartes, efter at du har ændret denne indstilling, for at den træder i kraft.</string>
|
||||
<string name="turbo_limit">Turbohastighedsgrænse</string>
|
||||
<string name="turbo_limit_description">Grænse for emuleringens hastighed bruges, når turbo-genvejstasten er aktiv.</string>
|
||||
<string name="expand_to_cutout_area">Anvend området ved frontkamera</string>
|
||||
@ -253,10 +268,18 @@
|
||||
<string name="debug_warning">Advarsel: Ændringer i disse indstillinger vil gøre emuleringen langsommere</string>
|
||||
<string name="stereoscopy">Stereoskopi</string>
|
||||
<string name="render3d">Stereoskopisk 3D-tilstand</string>
|
||||
<string name="render3d_description">Vælg den stereoskopiske 3D-tilstand til 3D-gengivelse. Side om side-tilstande er mest almindelige i moderne brug. Anaglyf- og interlaced-tilstande vil altid gælde for alle tilsluttede skærme.</string>
|
||||
<string name="factor3d">Dybde</string>
|
||||
<string name="factor3d_description">Angiver værdien af 3D-skyderen. Denne bør sættes højere end 0 %, når stereoskopisk 3D-tilstand er aktiveret.\nBemærk: Dybdeværdier over 100 % er ikke muligt på rigtig hardware og kan forårsage grafiske problemer</string>
|
||||
<string name="disable_right_eye_render">Deaktiver rendering af højre øje</string>
|
||||
<string name="disable_right_eye_render_description">Forbedrer ydeevnen betydeligt i nogle applikationer, men kan forårsage flimren i andre.</string>
|
||||
<string name="swap_eyes_3d">Skift øjne</string>
|
||||
<string name="swap_eyes_3d_description">Bytter om på hvilket øje, der skal se hvilken side. Kombineret med side om side-tilstanden er det muligt at se 3D ved at krydse øjnene!</string>
|
||||
<string name="render_3d_which_display">Gengiv stereoskopisk 3D</string>
|
||||
<string name="render_3d_which_display_description">Om stereoskopisk 3D skal aktiveres, og på hvilke skærme. Indstillingerne for en enkel skærm er kun relevant, når flere skærme er tilsluttet.</string>
|
||||
<string name="render_3d_which_display_both">Til (alle skærme)</string>
|
||||
<string name="render_3d_which_display_primary">Til (kun primær skærm)</string>
|
||||
<string name="render_3d_which_display_secondary">Til (kun sekundær skærm)</string>
|
||||
<string name="cardboard_vr">Cardboard VR</string>
|
||||
<string name="cardboard_screen_size">Cardboard skærmstørrelse</string>
|
||||
<string name="cardboard_screen_size_description">Skalerer skærmen til en procentdel af dens oprindelige størrelse.</string>
|
||||
@ -293,12 +316,12 @@
|
||||
<string name="hw_shaders_description">Bruger hardware til at efterligne 3DS shaders. Når det er aktiveret, vil spillets ydeevne blive væsentligt forbedret.</string>
|
||||
<string name="cpu_clock_speed">CPU Clock hastighed</string>
|
||||
<string name="vsync">Aktiver V-Sync</string>
|
||||
<string name="vsync_description">Synkroniserer spillets frame rate med opdateringshastigheden på din enhed.</string>
|
||||
<string name="vsync_description">Synkroniserer spillets billedhastighed med din enheds opdateringshastighed. Kan forårsage yderligere inputforsinkelse, men kan reducere tearing i nogle tilfælde.</string>
|
||||
<string name="renderer_debug">Fejlsøg renderingen</string>
|
||||
<string name="renderer_debug_description">Log yderligere grafikrelaterede fejlfindingsoplysninger. Når det er aktiveret, vil spillets ydeevne blive væsentligt reduceret.</string>
|
||||
<string name="instant_debug_log">Tøm loggen for alle beskeder</string>
|
||||
<string name="instant_debug_log">Tøm loggen ved hver besked</string>
|
||||
<string name="instant_debug_log_description">Overfør øjeblikkeligt fejlretningsloggen til fil. Brug dette, hvis Azahar går ned, og logoutputtet afbrydes.</string>
|
||||
<string name="delay_start_lle_modules">Forsinket start med LLE moduler</string>
|
||||
<string name="delay_start_lle_modules">Forsink start med LLE moduler</string>
|
||||
<string name="delay_start_lle_modules_description">Forsinker starten af appen, når LLE moduler er aktiveret.</string>
|
||||
<string name="deterministic_async_operations">Deterministiske asynkrone operationer</string>
|
||||
<string name="deterministic_async_operations_description">Gør asynkrone operationer deterministiske for fejlretning. Aktivering af dette kan forårsage at programmet fryser fast.</string>
|
||||
@ -396,18 +419,24 @@
|
||||
<string name="emulation_configure_controls">Konfigurer kontroller</string>
|
||||
<string name="emulation_edit_layout">Rediger layout</string>
|
||||
<string name="emulation_done">Færdig</string>
|
||||
<string name="emulation_button_sliding">Knap flytning</string>
|
||||
<string name="emulation_button_sliding_disabled">Hold den oprindeligt trykkede knap nede</string>
|
||||
<string name="emulation_button_sliding_enabled">Hold den aktuelt nede knap nede</string>
|
||||
<string name="emulation_button_sliding_alternative">Hold den oprindelige og den aktuelt nedtrykkede knap nede</string>
|
||||
<string name="emulation_toggle_controls">Skift kontrol</string>
|
||||
<string name="emulation_control_scale">Juster skala</string>
|
||||
<string name="emulation_control_scale_global">Global skala</string>
|
||||
<string name="emulation_control_scale_reset_all">Nulstil alle</string>
|
||||
<string name="emulation_control_opacity">Juster opacitet</string>
|
||||
<string name="emulation_control_joystick_rel_center">Relativt stick centrum</string>
|
||||
<string name="emulation_control_dpad_slide_enable">D-Pad glidning</string>
|
||||
<string name="emulation_control_dpad_slide_enable">D-Pad flytning</string>
|
||||
<string name="emulation_open_settings">Åbn Indstillinger</string>
|
||||
<string name="emulation_open_cheats">Åbn snydekoder</string>
|
||||
<string name="emulation_aspect_ratio">Billedformat</string>
|
||||
<string name="emulation_switch_screen_layout">Landskab skærmlayout</string>
|
||||
<string name="emulation_switch_portrait_layout">Portræt skærmlayout</string>
|
||||
<string name="emulation_switch_secondary_layout">Layout af sekundær skærm</string>
|
||||
<string name="emulation_switch_secondary_layout_description">Layoutet, der bruges af en tilsluttet sekundær skærm, kablet eller trådløs (Chromecast, Miracast)</string>
|
||||
<string name="emulation_screen_layout_largescreen">Stor skærm</string>
|
||||
<string name="emulation_screen_layout_portrait">Portræt</string>
|
||||
<string name="emulation_screen_layout_single">Enkelt skærm</string>
|
||||
@ -415,7 +444,15 @@
|
||||
<string name="emulation_screen_layout_hybrid">Hybrid skærme</string>
|
||||
<string name="emulation_screen_layout_original">Original</string>
|
||||
<string name="emulation_portrait_layout_top_full">Standard</string>
|
||||
<string name="emulation_secondary_display_default">Systemstandard (spejl)</string>
|
||||
<string name="emulation_screen_layout_custom">Brugerdefineret layout</string>
|
||||
<string name="bg_color">Baggrundsfarve</string>
|
||||
<string name="bg_color_description">Farven, der vises bag skærmene under emulering, repræsenteret som en RGB-værdi.</string>
|
||||
<string name="bg_red">Rød</string>
|
||||
<string name="bg_green">Grøn</string>
|
||||
<string name="bg_blue">Blå</string>
|
||||
<string name="second_screen_opacity">Brugerdefineret layout skærmopacitet for anden skærm</string>
|
||||
<string name="second_screen_opacity_description">Opaciteten af den anden 3DS-skærm, når der bruges et brugerdefineret skærmlayout. Nyttig, hvis den anden skærm skal placeres oven på den første skærm.</string>
|
||||
<string name="emulation_small_screen_position">Position for lille skærm</string>
|
||||
<string name="small_screen_position_description">Hvor skal den lille skærm vises i forhold til den store i storskærmslayout?</string>
|
||||
<string name="small_screen_position_top_right">Øverst til højre</string>
|
||||
@ -511,6 +548,8 @@
|
||||
<string name="fatal_error">Fatal fejl</string>
|
||||
<string name="fatal_error_message">Der opstod en fatal fejl. Kontroller loggen for detaljer.\nFortsat emulering kan resultere i nedbrud og fejl.</string>
|
||||
<string name="unsupported_encrypted">Ikke understøttet krypteret applikation</string>
|
||||
<string name="invalid_system_mode">Ugyldig systemtilstand</string>
|
||||
<string name="invalid_system_mode_message">Nye 3DS-eksklusive applikationer kan ikke indlæses uden at aktivere den nye 3DS-tilstand.</string>
|
||||
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Forberedelse af shaders</string>
|
||||
@ -535,33 +574,39 @@
|
||||
<string name="create_shortcut">Opret genvej</string>
|
||||
<string name="shortcut_name_empty">Genvejsnavnet må ikke være tomt</string>
|
||||
<string name="shortcut_image_stretch_toggle">Stræk for at tilpasse billedet</string>
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Fil:</string>
|
||||
<string name="game_context_type">Type:</string>
|
||||
<string name="game_context_insert">Indsæt kassette</string>
|
||||
<string name="game_context_eject">Udtag kassette</string>
|
||||
|
||||
<!-- Performance Overlay settings -->
|
||||
<string name="performance_overlay_show">Vis ydelsesoverlejring</string>
|
||||
<string name="performance_overlay_options">Ydelsesoverlejring</string>
|
||||
<string name="performance_overlay_enable">Aktivér ydelsesoverlejring</string>
|
||||
<string name="performance_overlay_options_description">Konfigurer, om ydelsesoverlejringen skal vises, og hvilke oplysninger der vises.</string>
|
||||
<string name="overlay_show_fps">Vis FPS</string>
|
||||
<string name="overlay_show_fps_description">Vis aktuelle billeder pr. sekund.</string>
|
||||
<string name="overlay_show_frametime">Vis billedtid</string>
|
||||
<string name="overlay_show_frametime_description">Vis aktuel billedtid.</string>
|
||||
<string name="overlay_show_speed">Vis hastighed</string>
|
||||
<string name="overlay_show_speed_description">Vis den aktuelle emuleringshastighed i procent.</string>
|
||||
<string name="overlay_show_app_ram_usage">Vis hukommelsesforbrug for app</string>
|
||||
<string name="overlay_show_app_ram_usage_description">Vis mængden af RAM, der bruges af emulatoren.</string>
|
||||
<string name="overlay_show_available_ram">Vis tilgængelig hukommelse</string>
|
||||
<string name="overlay_show_available_ram_description">Vis mængden af RAM, der er tilgængelig.</string>
|
||||
<string name="overlay_show_battery_temp">Vis batteritemperatur</string>
|
||||
<string name="overlay_show_battery_temp_description">Viser den aktuelle batteritemperatur i Celsius og Fahrenheit.</string>
|
||||
<string name="overlay_position">Position af overlejring</string>
|
||||
<string name="overlay_position_description">Vælg, hvor ydelsesoverlejringen skal vises på skærmen.</string>
|
||||
<string name="overlay_position_top_left">Øverst til venstre</string>
|
||||
<string name="overlay_position_top_right">Øverst til højre</string>
|
||||
<string name="overlay_position_bottom_left">Nederst til venstre</string>
|
||||
<string name="overlay_position_bottom_right">Nederst til højre</string>
|
||||
<string name="overlay_position_center_top">Midten øverst</string>
|
||||
<string name="overlay_position_center_bottom">Midten nederst</string>
|
||||
<string name="overlay_background">Overlejret baggrund</string>
|
||||
<string name="overlay_background_description">Tilføjer en baggrund bag overlejringen for lettere læsning.</string>
|
||||
<string name="performance_overlay_show_fps">Vis FPS</string>
|
||||
<string name="performance_overlay_show_fps_description">Vis aktuelle billeder pr. sekund.</string>
|
||||
<string name="performance_overlay_show_frametime">Vis billedtid</string>
|
||||
<string name="performance_overlay_show_frametime_description">Vis aktuel billedtid.</string>
|
||||
<string name="performance_overlay_show_speed">Vis hastighed</string>
|
||||
<string name="performance_overlay_show_speed_description">Vis den aktuelle emuleringshastighed i procent.</string>
|
||||
<string name="performance_overlay_show_app_ram_usage">Vis hukommelsesforbrug for app</string>
|
||||
<string name="performance_overlay_show_app_ram_usage_description">Vis mængden af RAM, der bruges af emulatoren.</string>
|
||||
<string name="performance_overlay_show_available_ram">Vis tilgængelig hukommelse</string>
|
||||
<string name="performance_overlay_show_available_ram_description">Vis mængden af RAM, der er tilgængelig.</string>
|
||||
<string name="performance_overlay_show_battery_temp">Vis batteritemperatur</string>
|
||||
<string name="performance_overlay_show_battery_temp_description">Viser den aktuelle batteritemperatur i Celsius og Fahrenheit.</string>
|
||||
<string name="performance_overlay_position">Overlejret-position</string>
|
||||
<string name="performance_overlay_position_description">Vælg, hvor performance-overlayet skal vises på skærmen.</string>
|
||||
<string name="performance_overlay_position_top_left">Øverst til venstre</string>
|
||||
<string name="performance_overlay_position_top_right">Øverst til højre</string>
|
||||
<string name="performance_overlay_position_bottom_left">Nederst til venstre</string>
|
||||
<string name="performance_overlay_position_bottom_right">Nederst til højre</string>
|
||||
<string name="performance_overlay_position_center_top">Centreret top</string>
|
||||
<string name="performance_overlay_position_center_bottom">Centreret bund</string>
|
||||
<string name="performance_overlay_background">Overlejret baggrund</string>
|
||||
<string name="performance_overlay_background_description">Tilføjer en baggrund bag det overlejrede for lettere læsning.</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Snyd</string>
|
||||
@ -665,7 +710,7 @@
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">Side om Side</string>
|
||||
<string name="reverse_side_by_side">Omvendt side om side</string>
|
||||
<string name="side_by_side_full">Side om side i fuld bredde</string>
|
||||
<string name="anaglyph">Anaglyph</string>
|
||||
<string name="interlaced">Interlaced</string>
|
||||
<string name="reverse_interlaced">Omvendt interlaced</string>
|
||||
@ -854,4 +899,19 @@
|
||||
<string name="emulation_occupied_quicksave_slot">Hurtig lagring - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Ingen hurtig lagring tilgængelig.</string>
|
||||
|
||||
<!-- File Compression -->
|
||||
<string name="compress">Komprimer</string>
|
||||
<string name="compressing">Komprimerer…</string>
|
||||
<string name="decompress">Dekomprimer</string>
|
||||
<string name="decompressing">Dekomprimerer…</string>
|
||||
<string name="compress_success">Komprimering gennemført.</string>
|
||||
<string name="compress_unsupported">Komprimering understøttes ikke for denne fil.</string>
|
||||
<string name="compress_already">Filen er allerede komprimeret.</string>
|
||||
<string name="compress_failed">Komprimeringen mislykkedes.</string>
|
||||
<string name="decompress_success">Dekomprimeringen er gennemført.</string>
|
||||
<string name="decompress_unsupported">Dekomprimering understøttes ikke for denne fil.</string>
|
||||
<string name="decompress_not_compressed">Filen er ikke komprimeret.</string>
|
||||
<string name="decompress_failed">Dekomprimeringen mislykkedes.</string>
|
||||
<string name="compress_decompress_installed_app">Allerede installerede programmer kan ikke komprimeres eller dekomprimeres.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@ -67,10 +67,13 @@
|
||||
<string name="give_permission">Conceder permiso</string>
|
||||
<string name="notification_warning">¿Saltarse la concesión del permiso de notificaciones?</string>
|
||||
<string name="notification_warning_description">Azahar no podrá notificarte sobre información importante.</string>
|
||||
<string name="filesystem_permission_warning">Falta Permisos</string>
|
||||
<string name="camera_permission">Cámara</string>
|
||||
<string name="camera_permission_description">Concede el permiso de cámara debajo para emular la cámara de la 3DS.</string>
|
||||
<string name="microphone_permission">Micrófono</string>
|
||||
<string name="microphone_permission_description">Concede el permiso de micrófono debajo para emular el micrófono de la 3DS.</string>
|
||||
<string name="filesystem_permission">Sistema de archivos</string>
|
||||
<string name="filesystem_permission_description">Concede el permiso de sistema de archivos debajo para permitir que Azahar almacene archivos.</string>
|
||||
<string name="permission_denied">Permiso denegado</string>
|
||||
<string name="add_games_warning">¿Saltarse la selección de la carpeta de aplicaciones?</string>
|
||||
<string name="add_games_warning_description">Nada se mostrará en la lista de aplicaciones si no se selecciona una carpeta.</string>
|
||||
@ -90,6 +93,7 @@
|
||||
<string name="cannot_skip">No puedes saltarte el configuración de la carpeta de usuario</string>
|
||||
<string name="cannot_skip_directory_description">Este paso es necesario para permitir que Azahar funcione. Por favor, seleccione un directorio y luego puede continuar.</string>
|
||||
<string name="selecting_user_directory_without_write_permissions">Has perdido los permisos de escritura en tu <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">directorio de datos de usuario</a>, donde se guardan las partidas guardadas y otra información. Esto puede ocurrir después de algunas actualizaciones de aplicaciones o de Android. Vuelve a seleccionar el directorio para recuperar los permisos y poder continuar.</string>
|
||||
<string name="invalid_selection">Selección no válido</string>
|
||||
<string name="set_up_theme_settings">Configuración de tema</string>
|
||||
<string name="setup_theme_settings_description">Configura tus preferencias de tema de Azahar.</string>
|
||||
<string name="setup_set_theme">Establecer tema</string>
|
||||
@ -122,8 +126,8 @@
|
||||
<string name="input_dialog_description">Pulsa o mueve un botón/palanca.</string>
|
||||
<string name="input_binding">Asignación de botones</string>
|
||||
<string name="input_binding_description">Pulsa o mueve un botón para asignarlo a %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Mueve el joystick arriba o abajo.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Mueve el joystick a izquierda o derecha.</string>
|
||||
<string name="input_binding_description_vertical_axis">Mueve el joystick abajo</string>
|
||||
<string name="input_binding_description_horizontal_axis">Mueve el joystick a la derecha</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Intercambiar Pantallas</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -237,6 +241,7 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="frame_limit_enable_description">Cuando se active, la velocidad de emulación estará limitada a un porcentaje determinado de la velocidad normal. Cuando se desactive, la velocidad de emulación no tendrá límite y la tecla de acceso rápido de velocidad turbo no funcionará.</string>
|
||||
<string name="frame_limit_slider">Limitar porcentaje de velocidad</string>
|
||||
<string name="frame_limit_slider_description">Especifica el valor al que se limita la velocidad de emulación. Con el valor por defecto del 100%, la emulación se limitará a la velocidad normal. Los valores altos o altos incrementarán o reducirán el límite de velocidad.</string>
|
||||
<string name="android_hide_images">Ocultar imágenes 3DS de Android</string>
|
||||
<string name="turbo_limit">Límite de Velocidad Turbo</string>
|
||||
<string name="turbo_limit_description">Límite de velocidad de emulación utilizado mientras la tecla de acceso rápido turbo está activa.</string>
|
||||
<string name="expand_to_cutout_area">Expandir al área de recorte</string>
|
||||
@ -262,6 +267,11 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="factor3d_description">Especifica el valor del regulador 3D. Debería estar puesto a más allá del 0% cuando el Modo 3D Estereoscópico está activado.\nNota: Los valores de profundidad superiores al 100 % no son posibles en hardware real y pueden causar problemas gráficos.</string>
|
||||
<string name="disable_right_eye_render">Desactivar Renderizado de Ojo Derecho</string>
|
||||
<string name="disable_right_eye_render_description">Mejora significativamente el rendimiento en algunas aplicaciones, pero puede causar parpadeo en otros.</string>
|
||||
<string name="swap_eyes_3d">Intercambiar Ojos</string>
|
||||
<string name="render_3d_which_display">Renderizado 3D Estereoscópico</string>
|
||||
<string name="render_3d_which_display_both">Activado (todas las pantallas)</string>
|
||||
<string name="render_3d_which_display_primary">Activado (solo pantalla principal)</string>
|
||||
<string name="render_3d_which_display_secondary">Activado (solo pantalla secundaria)</string>
|
||||
<string name="cardboard_vr">Cardboard VR</string>
|
||||
<string name="cardboard_screen_size">Tamaño de la pantalla Cardboard</string>
|
||||
<string name="cardboard_screen_size_description">Escala la pantalla a un porcentaje de su tamaño original.</string>
|
||||
@ -298,7 +308,6 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="hw_shaders_description">Usa el hardware para emular los sombreadores de 3DS. Cuando se active, el rendimiento mejorará notablemente.</string>
|
||||
<string name="cpu_clock_speed">Velocidad de reloj de la CPU</string>
|
||||
<string name="vsync">Activar Sincronización Vertical</string>
|
||||
<string name="vsync_description">Sincroniza los cuadros por segundo del juego con la tasa de refresco de tu dispositivo.</string>
|
||||
<string name="renderer_debug">Renderizador de depuración</string>
|
||||
<string name="renderer_debug_description">Archiva información adicional gráfica relacionada con la depuración. Cuando está activada, el rendimiento de los juegos será reducido considerablemente</string>
|
||||
<string name="instant_debug_log">Limpiar la salida del registro en cada mensaje</string>
|
||||
@ -428,6 +437,12 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="emulation_portrait_layout_top_full">Por defecto</string>
|
||||
<string name="emulation_secondary_display_default">Por defecto del sistema (espejo)</string>
|
||||
<string name="emulation_screen_layout_custom">Estilo personalizado</string>
|
||||
<string name="bg_color">Color de fondo</string>
|
||||
<string name="bg_red">Rojo</string>
|
||||
<string name="bg_green">Verde</string>
|
||||
<string name="bg_blue">Azul</string>
|
||||
<string name="second_screen_opacity">Opacidad personalizado de la segunda pantalla</string>
|
||||
<string name="second_screen_opacity_description">La opacidad de la segunda pantalla 3DS al usar el pantalla personalizado. Útil si la segunda pantalla ésta posición en la parte superior de la primera pantalla.</string>
|
||||
<string name="emulation_small_screen_position">Posición Pantalla Pequeña</string>
|
||||
<string name="small_screen_position_description">¿Dónde debería aparecer la pantalla pequeña en relación con la grande en Disposicion de Pantalla Grande?</string>
|
||||
<string name="small_screen_position_top_right">Arriba a la Derecha</string>
|
||||
@ -523,7 +538,7 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="fatal_error">Error Fatal</string>
|
||||
<string name="fatal_error_message">Ha ocurrido un error fatal. Mira el registro para más detalles.\nSeguir con la emulación podría resultar en diversos cuelgues y bugs.</string>
|
||||
<string name="unsupported_encrypted">Aplicación encriptada no soportada</string>
|
||||
|
||||
<string name="invalid_system_mode">Modo de sistema no válido</string>
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Preparando shaders</string>
|
||||
<string name="building_shaders">Construyendo shaders</string>
|
||||
@ -550,34 +565,36 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Archivo:</string>
|
||||
<string name="game_context_type">Tipo:</string>
|
||||
<string name="game_context_insert">Insertar Cartucho</string>
|
||||
<string name="game_context_eject">Expulsar Cartucho</string>
|
||||
|
||||
<!-- Performance Overlay settings -->
|
||||
<string name="performance_overlay_show">Mostrar información de rendimiento</string>
|
||||
<string name="performance_overlay_options">Información de rendimiento</string>
|
||||
<string name="performance_overlay_enable">Activar información de rendimiento</string>
|
||||
<string name="performance_overlay_options_description">Configura la información de rendimiento</string>
|
||||
<string name="overlay_show_fps">Mostrar FPS</string>
|
||||
<string name="overlay_show_fps_description">Muestra los fotogramas por segundo actuales.</string>
|
||||
<string name="overlay_show_frametime">Mostrar duración de fotogramas</string>
|
||||
<string name="overlay_show_frametime_description">Muestra la duración actual de cada fotograma.</string>
|
||||
<string name="overlay_show_speed">Mostrar velocidad</string>
|
||||
<string name="overlay_show_speed_description">Muestra el porcentaje de velocidad de emulación actual.</string>
|
||||
<string name="overlay_show_app_ram_usage">Mostrar el uso de memoria de la aplicación</string>
|
||||
<string name="overlay_show_app_ram_usage_description">Muestra la cantidad de memoria RAM que esta usando el emulador.</string>
|
||||
<string name="overlay_show_available_ram">Mostrar memoria disponible</string>
|
||||
<string name="overlay_show_available_ram_description">Muestra la cantidad de memoria RAM que esta disponible.</string>
|
||||
<string name="overlay_show_battery_temp">Mostrar la temperatura de la batería</string>
|
||||
<string name="overlay_show_battery_temp_description">Muestra la temperatura actual de la batería en Celsius y Fahrenheit.</string>
|
||||
<string name="overlay_position">Posición de la información</string>
|
||||
<string name="overlay_position_description">Elige donde la información de rendimiento será mostrada en la pantalla.</string>
|
||||
<string name="overlay_position_top_left">Arriba a la izquierda</string>
|
||||
<string name="overlay_position_top_right">Arriba a la derecha</string>
|
||||
<string name="overlay_position_bottom_left">Abajo a la izquierda</string>
|
||||
<string name="overlay_position_bottom_right">Abajo a la derecha</string>
|
||||
<string name="overlay_position_center_top">Centro superior</string>
|
||||
<string name="overlay_position_center_bottom">Centro inferior </string>
|
||||
<string name="overlay_background">Fondo de la información</string>
|
||||
<string name="overlay_background_description">Agrega un fondo detrás de la información para hacerla más legible.</string>
|
||||
<string name="performance_overlay_show_fps">Mostrar FPS</string>
|
||||
<string name="performance_overlay_show_fps_description">Muestra los fotogramas por segundo actuales.</string>
|
||||
<string name="performance_overlay_show_frametime">Mostrar duración de fotogramas</string>
|
||||
<string name="performance_overlay_show_frametime_description">Muestra la duración actual de cada fotograma.</string>
|
||||
<string name="performance_overlay_show_speed">Mostrar velocidad</string>
|
||||
<string name="performance_overlay_show_speed_description">Muestra el porcentaje de velocidad de emulación actual.</string>
|
||||
<string name="performance_overlay_show_app_ram_usage">Mostrar el uso de memoria de la aplicación</string>
|
||||
<string name="performance_overlay_show_app_ram_usage_description">Muestra la cantidad de memoria RAM que esta usando el emulador.</string>
|
||||
<string name="performance_overlay_show_available_ram">Mostrar memoria disponible</string>
|
||||
<string name="performance_overlay_show_available_ram_description">Muestra la cantidad de memoria RAM que esta disponible.</string>
|
||||
<string name="performance_overlay_show_battery_temp">Mostrar la temperatura de la batería</string>
|
||||
<string name="performance_overlay_show_battery_temp_description">Muestra la temperatura actual de la batería en Celsius y Fahrenheit.</string>
|
||||
<string name="performance_overlay_position">Posición de la información</string>
|
||||
<string name="performance_overlay_position_description">Elegir donde el superposición de rendimiento esta mostrado en el pantalla</string>
|
||||
<string name="performance_overlay_position_top_left">Arriba a la Izquierda</string>
|
||||
<string name="performance_overlay_position_top_right">Arriba a la Derecha</string>
|
||||
<string name="performance_overlay_position_bottom_left">Abajo a la Izquierda</string>
|
||||
<string name="performance_overlay_position_bottom_right">Abajo a la Derecha</string>
|
||||
<string name="performance_overlay_position_center_top">Centro Superior</string>
|
||||
<string name="performance_overlay_position_center_bottom">Centro Inferior</string>
|
||||
<string name="performance_overlay_background">Fondo de la información</string>
|
||||
<string name="performance_overlay_background_description">Agrega un fondo detrás de la información para hacerla más legible.</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Trucos</string>
|
||||
@ -682,7 +699,7 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">De lado a lado</string>
|
||||
<string name="reverse_side_by_side">De lado a lado inverso</string>
|
||||
<string name="side_by_side_full">De lado a lado ancho completo</string>
|
||||
<string name="anaglyph">Anáglifo</string>
|
||||
<string name="interlaced">Entrelazado</string>
|
||||
<string name="reverse_interlaced">Entrelazado inverso</string>
|
||||
@ -871,4 +888,17 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||
<string name="emulation_occupied_quicksave_slot">Guardado rápido - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Guardado rápido no disponible.</string>
|
||||
|
||||
</resources>
|
||||
<!-- File Compression -->
|
||||
<string name="compress">Comprimir</string>
|
||||
<string name="compressing">Compresando...</string>
|
||||
<string name="decompress">Descomprimir</string>
|
||||
<string name="decompressing">Descomprimiendo…</string>
|
||||
<string name="compress_success">Compresión completada con éxito.</string>
|
||||
<string name="compress_unsupported">Compresión no está soportado con este archivo.</string>
|
||||
<string name="compress_already">Este archivo ya está comprimido.</string>
|
||||
<string name="compress_failed">Falló la compresión.</string>
|
||||
<string name="decompress_success">Descompresión completada con éxito.</string>
|
||||
<string name="decompress_unsupported">Descompresión no está soportado con este archivo.</string>
|
||||
<string name="decompress_not_compressed">El archivo no está comprimido.</string>
|
||||
<string name="decompress_failed"> Falló la descompresión.</string>
|
||||
</resources>
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
<string name="mac_address">MACアドレス</string>
|
||||
<string name="regenerate_mac_address">MACアドレスを再生成</string>
|
||||
<string name="regenerate_mac_address_description">これを行うと、今のMACアドレスを新しいもので置き換えます。セットアップツールで実機からMACアドレスを吸い出した場合、これをするのは推奨しません。続行しますか?</string>
|
||||
<string name="delay_render_thread">描写スレッドを遅延する</string>
|
||||
<string name="delay_render_thread_description">GPUにデータを送信する間、ゲームの描写スレッドを遅延します。動的フレームレートである(ほんの一部の)アプリケーションでのパフォーマンスが向上します。</string>
|
||||
<string name="instant_debug_log_description">デバッグログを即座にファイルに書き込みます。Azaharがクラッシュしてログが途切れるときに有効にしてください。</string>
|
||||
<string name="miscellaneous">その他</string>
|
||||
|
||||
@ -61,7 +61,6 @@
|
||||
<!-- Audio settings strings -->
|
||||
<string name="audio_volume">Garsumas</string>
|
||||
<string name="audio_stretch">Garso ištempimas</string>
|
||||
<string name="realtime_audio">Įjungti realaus laiko garsą</string>
|
||||
<string name="layout_screen_orientation_auto_sensor">Automatinis</string>
|
||||
<string name="learn_more">Sužinoti daugiau</string>
|
||||
<string name="close">Uždaryti</string>
|
||||
|
||||
@ -67,10 +67,14 @@
|
||||
<string name="give_permission">Udzielenie zgody</string>
|
||||
<string name="notification_warning">Pominąć udzielanie zgody na powiadomienie?</string>
|
||||
<string name="notification_warning_description">Azahar nie będzie w stanie powiadomić cię o ważnych informacjach.</string>
|
||||
<string name="filesystem_permission_warning">Brak uprawnień</string>
|
||||
<string name="filesystem_permission_warning_description">Azahar wymaga uprawnień do zarządzania plikami na tym urządzeniu w celu przechowywania i zarządzania swoimi danymi. \n\nPrzed kontynuowaniem należy przyznać uprawnienia „System plików”.</string>
|
||||
<string name="camera_permission">Kamera</string>
|
||||
<string name="camera_permission_description">Udziel poniższych uprawnień kamery, aby emulować kamerę 3DS.</string>
|
||||
<string name="microphone_permission">Mikrofon</string>
|
||||
<string name="microphone_permission_description">Udziel poniższych uprawnień mikrofonu, aby emulować mikrofon 3DS.</string>
|
||||
<string name="filesystem_permission">System plików</string>
|
||||
<string name="filesystem_permission_description">Przyznaje poniższe uprawnienia systemu plików, aby umożliwić Azahar przechowywanie plików.</string>
|
||||
<string name="permission_denied">Odmowa zezwolenia</string>
|
||||
<string name="add_games_warning">Pominąć wybór folderu z aplikacjami?</string>
|
||||
<string name="add_games_warning_description">Oprogramowania nie będą wyświetlane na liście aplikacji, jeśli nie wybrano folderu.</string>
|
||||
@ -90,6 +94,9 @@
|
||||
<string name="cannot_skip">Nie można pominąć konfiguracji folderu użytkownika.</string>
|
||||
<string name="cannot_skip_directory_description">Ten krok jest wymagany, aby umożliwić działanie Azahar. Wybierz katalog, a następnie możesz kontynuować.</string>
|
||||
<string name="selecting_user_directory_without_write_permissions">Utraciłeś uprawnienia do zapisu w katalogu <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">danych użytkownika</a>, w którym przechowywane są zapisy i inne informacje. Może się to zdarzyć po niektórych aktualizacjach aplikacji lub systemu Android. Wybierz ponownie katalog, aby odzyskać uprawnienia i móc kontynuować.</string>
|
||||
<string name="invalid_selection">Nieprawidłowy wybór</string>
|
||||
<string name="invalid_user_directory">Wybór katalogu użytkownika był nieprawidłowy.\nProszę ponownie wybrać katalog użytkownika, upewniając się, że przechodzisz do niego z katalogu głównego pamięci urządzenia.</string>
|
||||
<string name="filesystem_permission_lost">Azahar utracił uprawnienia do zarządzania plikami na tym urządzeniu. Może się to zdarzyć po aktualizacji niektórych aplikacji lub systemu Android. Aby kontynuować korzystanie z aplikacji, należy ponownie przyznać te uprawnienia na następnym ekranie.</string>
|
||||
<string name="set_up_theme_settings">Ustawienia motywu</string>
|
||||
<string name="setup_theme_settings_description">Skonfiguruj ustawienia motywu dla Azahar.</string>
|
||||
<string name="setup_set_theme">Ustaw motyw</string>
|
||||
@ -122,8 +129,8 @@
|
||||
<string name="input_dialog_description">Naciśnij lub przenieś wejście.</string>
|
||||
<string name="input_binding">Powiązanie wejścia</string>
|
||||
<string name="input_binding_description">Naciśnij lub przesuń wejście, aby powiązać je z %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Przesuń analog w górę lub w dół.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Przesuń analog w lewo lub w prawo.</string>
|
||||
<string name="input_binding_description_vertical_axis">Przesuń analog w dół.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Przesuń analog w prawo.</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Zamień ekrany</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -162,6 +169,8 @@
|
||||
<string name="username">Nazwa użytkownika</string>
|
||||
<string name="new_3ds">Tryb New 3DS</string>
|
||||
<string name="lle_applets">Użyj apletów LLE (jeśli są zainstalowane)</string>
|
||||
<string name="apply_region_free_patch">Zastosuj łatkę bez regionu do zainstalowanych aplikacji.</string>
|
||||
<string name="apply_region_free_patch_desc">Naprawia region zainstalowanych aplikacji, aby były one wolne od ograniczeń regionalnych, dzięki czemu zawsze pojawiają się w menu głównym.</string>
|
||||
<string name="enable_required_online_lle_modules">Włącz wymagane moduły LLE dla funkcji online (jeśli są zainstalowane)</string>
|
||||
<string name="enable_required_online_lle_modules_desc">łącza moduły LLE potrzebne do gry wieloosobowej online, dostępu do eShopu itp.</string>
|
||||
<string name="clock">Zegar</string>
|
||||
@ -217,25 +226,27 @@
|
||||
<string name="spirv_shader_gen_description">Emituje fragment shaderów używany do emulacji PICA przy użyciu SPIR-V zamiast GLSL.</string>
|
||||
<string name="disable_spirv_optimizer">Wyłącz optymalizator SPIR-V</string>
|
||||
<string name="disable_spirv_optimizer_description">Wyłącza optymalizację SPIR-V, znacznie zmniejszając zacinanie się obrazu przy minimalnym wpływie na wydajność.</string>
|
||||
<string name="async_shaders">Włącz asynchroniczną kompilację shaderów</string>
|
||||
<string name="async_shaders">Włącz Asynchroniczną Kompilację Shaderów</string>
|
||||
<string name="async_shaders_description">Kompiluje shadery w tle, aby zmniejszyć zacinanie się podczas rozgrywki. Po włączeniu należy spodziewać się tymczasowych błędów graficznych</string>
|
||||
<string name="linear_filtering">Filtrowanie Linear</string>
|
||||
<string name="linear_filtering_description">Włącza filtrowanie liniowe, które sprawia, że grafika w grach jest płynniejsza.</string>
|
||||
<string name="texture_filter_name">Filtr tekstur</string>
|
||||
<string name="texture_filter_description">Ulepsza oprawę wizualną aplikacji poprzez zastosowanie filtrów do tekstur. Obsługiwane filtry to Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale i MMPX.</string>
|
||||
<string name="delay_render_thread">Opóźnienie renderowania wątku gry</string>
|
||||
<string name="delay_render_thread">Opóźnienie Renderowania Wątku Gry</string>
|
||||
<string name="delay_render_thread_description">Opóźnia wątek renderowania aplikacji podczas przesyłania danych do GPU. Pomaga w kwestiach wydajności w (bardzo niewielu) aplikacjach z dynamiczną liczbą klatek na sekundę.</string>
|
||||
<string name="advanced">Zaawansowane</string>
|
||||
<string name="texture_sampling_name">Próbkowanie tekstur</string>
|
||||
<string name="texture_sampling_description">Zastępuje filtr próbkowania używany przez gry. Może to być przydatne w niektórych przypadkach, gdy gry źle zachowują się podczas skalowania w górę. Jeśli nie masz pewności, ustaw tę opcję na Kontrolowane przez grę.</string>
|
||||
<string name="shaders_accurate_mul">Dokładne mnożenie</string>
|
||||
<string name="shaders_accurate_mul_description">Używa dokładniejszego mnożenia w shaderach sprzętu, dzięki czemu może naprawić niektóre błędy graficzne. Po włączeniu tej funkcji wydajność zostanie zmniejszona.</string>
|
||||
<string name="asynchronous_gpu">Włącz asynchroniczną emulację GPU</string>
|
||||
<string name="asynchronous_gpu">Włącz Asynchroniczną Emulację GPU</string>
|
||||
<string name="asynchronous_gpu_description">Używa oddzielnego wątku do asynchronicznej emulacji GPU. Po włączeniu, wydajność zostanie poprawiona.</string>
|
||||
<string name="frame_limit_enable">Ogranicz prędkość</string>
|
||||
<string name="frame_limit_enable_description">Po włączeniu prędkość emulacji zostanie ograniczona do określonego procentu normalnej prędkości. Jeśli opcja ta jest wyłączona, prędkość emulacji nie zostanie ograniczona, a klawisz skrótu prędkości turbo nie będzie działał.</string>
|
||||
<string name="frame_limit_slider">Ogranicz procent prędkości</string>
|
||||
<string name="frame_limit_slider_description">Określa wartość procentową ograniczenia prędkości emulacji. Przy domyślnej wartości 100% emulacja będzie ograniczona do normalnej prędkości. Wyższe lub niższe wartości zwiększają lub zmniejszają ograniczenie prędkości.</string>
|
||||
<string name="android_hide_images">Ukryj obrazy 3DS z systemu Android</string>
|
||||
<string name="android_hide_images_description">Zapobiega indeksowaniu przez system Android zdjęć wykonanych aparatem 3DS, zrzutów ekranu i niestandardowych tekstur oraz wyświetlaniu ich w galerii. Aby zmiany ustawień zaczęły obowiązywać, może być konieczne ponowne uruchomienie urządzenia.</string>
|
||||
<string name="turbo_limit">Limit prędkości Turbo</string>
|
||||
<string name="turbo_limit_description">Limit prędkości emulacji wykorzystywany, gdy aktywny jest klawisz skrótu turbo.</string>
|
||||
<string name="expand_to_cutout_area">Rozszerz do obszaru wycięcia</string>
|
||||
@ -257,10 +268,18 @@
|
||||
<string name="debug_warning">Ostrzeżenie: Zmiana tych ustawień spowolni emulację</string>
|
||||
<string name="stereoscopy">Sterowanie stereoskopowe</string>
|
||||
<string name="render3d">Tryb stereoskopowy 3D</string>
|
||||
<string name="render3d_description">Wybierz tryb stereoskopowego 3D dla renderowania 3D.Tryb ekranów obok siebie jest obecnie najczęściej stosowany. Tryby obrazu Anaglyph i Interlaced będą zawsze stosowane do wyświetlania obrazu na wszystkich podłączonych monitorach.</string>
|
||||
<string name="factor3d">Zasięg</string>
|
||||
<string name="factor3d_description">Określa wartość suwaka 3D. Powinien być ustawiony na wartość wyższą niż 0%, gdy włączony jest tryb stereoskopowy 3D.\nUwaga: Wartość przekraczająca 100% nie jest możliwa na rzeczywistym sprzęcie i może powodować problemy graficzne.</string>
|
||||
<string name="disable_right_eye_render">Wyłącz renderowanie prawego oka</string>
|
||||
<string name="disable_right_eye_render_description">Znacznie poprawia wydajność w niektórych aplikacjach, ale może powodować migotanie w innych.</string>
|
||||
<string name="swap_eyes_3d">Zamiana Oczu</string>
|
||||
<string name="swap_eyes_3d_description">Zamiana oczu jest wyświetlana po obu stronach. W połączeniu z trybem obrazów obok siebie umożliwia oglądanie obrazu 3D poprzez przesunięcie oczu!</string>
|
||||
<string name="render_3d_which_display">Render stereoskopowego 3D</string>
|
||||
<string name="render_3d_which_display_description">Czy włączyć stereoskopowe 3D i na jakich wyświetlaczach to włączyć? Opcje dotyczące pojedynczego wyświetlacza mają znaczenie tylko wtedy, gdy podłączonych jest wiele wyświetlaczy.</string>
|
||||
<string name="render_3d_which_display_both">Włącz (Wszystkie Wyświetlacze)</string>
|
||||
<string name="render_3d_which_display_primary">Włącz (Tylko Główny Wyświetlacz)</string>
|
||||
<string name="render_3d_which_display_secondary">Włącz (Tylko na Dodatkowym Wyświetlaczu)</string>
|
||||
<string name="cardboard_vr">Cardboard VR</string>
|
||||
<string name="cardboard_screen_size">Rozmiar ekranu Cardboarda</string>
|
||||
<string name="cardboard_screen_size_description">Skaluje ekran do wartości procentowej jego oryginalnego rozmiaru.</string>
|
||||
@ -285,7 +304,7 @@
|
||||
<string name="audio_volume">Głośność</string>
|
||||
<string name="audio_stretch">Rozciągnij dźwięk</string>
|
||||
<string name="audio_stretch_description">Rozciąga dźwięk, aby zredukować zacinanie się. Po włączeniu tej opcji zwiększa opóźnienie dźwięku i nieznacznie obniża wydajność.</string>
|
||||
<string name="realtime_audio">Włącz dźwięk w czasie rzeczywistym</string>
|
||||
<string name="realtime_audio">Włącz Dźwięk w Czasie Rzeczywistym</string>
|
||||
<string name="realtime_audio_description">Skaluje prędkość odtwarzania dźwięku, aby uwzględnić spadki liczby klatek na sekundę w emulacji. Oznacza to, że dźwięk będzie odtwarzany z pełną prędkością, nawet jeśli liczba klatek na sekundę w grze jest niska. Może powodować problemy z desynchronizacją dźwięku.</string>
|
||||
<string name="audio_input_type">Urządzenie wejściowe dźwięku</string>
|
||||
<string name="sound_output_mode">Tryb wyjścia dźwięku</string>
|
||||
@ -297,12 +316,12 @@
|
||||
<string name="hw_shaders_description">Używa sprzętu do emulacji shaderów 3DS. Po włączeniu, wydajność gry zostanie znacznie poprawiona.</string>
|
||||
<string name="cpu_clock_speed">Prędkość taktowania procesora</string>
|
||||
<string name="vsync">Włącz V-Sync</string>
|
||||
<string name="vsync_description">Synchronizuje liczbę klatek na sekundę gry z częstotliwością odświeżania urządzenia.</string>
|
||||
<string name="vsync_description">Synchronizuje częstotliwość klatek na sekundę w grze z częstotliwością odświeżania urządzenia. Może powodować dodatkowe opóźnienia wejściowe, ale w niektórych przypadkach może ograniczyć występowanie rozdarć obrazu.</string>
|
||||
<string name="renderer_debug">Render debugowania</string>
|
||||
<string name="renderer_debug_description">Rejestruje dodatkowe informacje debugowania związane z grafiką. Po włączeniu, wydajność gry zostanie znacznie zmniejszona.</string>
|
||||
<string name="instant_debug_log">Opróżnia log przy każdej wiadomości</string>
|
||||
<string name="instant_debug_log">Opróżnij Log Przy Każdej Wiadomości</string>
|
||||
<string name="instant_debug_log_description">Natychmiast zapisuje log debugowania do pliku. Użyj tego, jeśli azahar ulegnie awarii, a dane wyjściowe logu zostaną przerwane.</string>
|
||||
<string name="delay_start_lle_modules">Opóźnione uruchamianie z modułami LLE</string>
|
||||
<string name="delay_start_lle_modules">Opóźnij Uruchamianie z Modułami LLE</string>
|
||||
<string name="delay_start_lle_modules_description">Opóźnia uruchomienie aplikacji, gdy włączone są moduły LLE.</string>
|
||||
<string name="deterministic_async_operations">Deterministyczne operacje asynchroniczne</string>
|
||||
<string name="deterministic_async_operations_description">Sprawia, że operacje asynchroniczne są deterministyczne dla debugowania. Włączenie tej opcji może powodować zawieszanie się gry.</string>
|
||||
@ -427,6 +446,13 @@
|
||||
<string name="emulation_portrait_layout_top_full">Domyślny</string>
|
||||
<string name="emulation_secondary_display_default">Ustawienia domyślne systemu (mirror)</string>
|
||||
<string name="emulation_screen_layout_custom">Niestandardowy Układ</string>
|
||||
<string name="bg_color">Kolor tła</string>
|
||||
<string name="bg_color_description">Kolor wyświetlany za ekranami podczas emulacji, wyświetlany jako wartość RGB.</string>
|
||||
<string name="bg_red">Czerwony</string>
|
||||
<string name="bg_green">Zielony</string>
|
||||
<string name="bg_blue">Niebieski</string>
|
||||
<string name="second_screen_opacity">Niestandardowy wygląd drugiego ekranu przezroczystości</string>
|
||||
<string name="second_screen_opacity_description">Przezroczystość drugiego ekranu 3DS podczas korzystania z niestandardowego układu ekranu. Przydatne, jeśli drugi ekran ma być umieszczony nad pierwszym ekranem.</string>
|
||||
<string name="emulation_small_screen_position">Pozycja małego ekranu</string>
|
||||
<string name="small_screen_position_description">Gdzie powinien być wyświetlany mały ekran względem dużego w układzie dużego ekranu?</string>
|
||||
<string name="small_screen_position_top_right">Prawy górny róg</string>
|
||||
@ -522,6 +548,8 @@
|
||||
<string name="fatal_error">Krytyczny Błąd</string>
|
||||
<string name="fatal_error_message">Wystąpił błąd krytyczny. Kontynuowanie emulacji może spowodować awarie i błędy.</string>
|
||||
<string name="unsupported_encrypted">Nieobsługiwana zaszyfrowana aplikacja</string>
|
||||
<string name="invalid_system_mode">Nieprawidłowy moduł systemu</string>
|
||||
<string name="invalid_system_mode_message">Aplikacje dostępne wyłącznie na konsoli New 3DS nie mogą być uruchamiane bez włączenia trybu New 3DS.</string>
|
||||
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Przygotowanie shaderów</string>
|
||||
@ -549,34 +577,36 @@
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Plik:</string>
|
||||
<string name="game_context_type">Typ:</string>
|
||||
<string name="game_context_insert">Włóż Kartridż</string>
|
||||
<string name="game_context_eject">Wyjmij Kartridż</string>
|
||||
|
||||
<!-- Performance Overlay settings -->
|
||||
<string name="performance_overlay_show">Wyświetl nakładkę wydajności</string>
|
||||
<string name="performance_overlay_options">Nakładkę wydajności</string>
|
||||
<string name="performance_overlay_enable">Włącz nakładkę wydajności</string>
|
||||
<string name="performance_overlay_options_description">Konfiguruje, czy wyświetlana jest nakładka wydajności i jakie informacje są wyświetlane.</string>
|
||||
<string name="overlay_show_fps">Wyświetl FPS</string>
|
||||
<string name="overlay_show_fps_description">Wyświetla aktualną liczbę klatek na sekundę.</string>
|
||||
<string name="overlay_show_frametime">Pokaż czas klatek</string>
|
||||
<string name="overlay_show_frametime_description">Wyświetla bieżący czas klatek.</string>
|
||||
<string name="overlay_show_speed">Wyświetl Prędkość</string>
|
||||
<string name="overlay_show_speed_description">Wyświetla aktualną procentową prędkość emulacji.</string>
|
||||
<string name="overlay_show_app_ram_usage">Wyświetl użycie pamięci aplikacji</string>
|
||||
<string name="overlay_show_app_ram_usage_description">Wyświetla ilość pamięci RAM używanej przez emulator.</string>
|
||||
<string name="overlay_show_available_ram">Wyświetl dostępną pamięć</string>
|
||||
<string name="overlay_show_available_ram_description">Wyświetla ilość dostępnej pamięci RAM.</string>
|
||||
<string name="overlay_show_battery_temp">Wyświetl temperaturę baterii</string>
|
||||
<string name="overlay_show_battery_temp_description">Wyświetla bieżącą temperaturę baterii w stopniach Celcjusza i Fahrenheita.</string>
|
||||
<string name="overlay_position">Pozycja nakładki</string>
|
||||
<string name="overlay_position_description">Wybierz miejsce wyświetlania nakładki wydajności na ekranie.</string>
|
||||
<string name="overlay_position_top_left">Lewy górny róg</string>
|
||||
<string name="overlay_position_top_right">Prawy górny róg</string>
|
||||
<string name="overlay_position_bottom_left">Lewy dolny róg</string>
|
||||
<string name="overlay_position_bottom_right">Prawy dolny róg</string>
|
||||
<string name="overlay_position_center_top">Środkowy górny</string>
|
||||
<string name="overlay_position_center_bottom">Środkowy dolny</string>
|
||||
<string name="overlay_background">Tło nakładki</string>
|
||||
<string name="overlay_background_description">Dodaje tło z tyłu nakładki w celu łatwego odczytu.</string>
|
||||
<string name="performance_overlay_show_fps">Wyświetl FPS</string>
|
||||
<string name="performance_overlay_show_fps_description">Wyświetla aktualną liczbę klatek na sekundę.</string>
|
||||
<string name="performance_overlay_show_frametime">Wyświetl czas klatek</string>
|
||||
<string name="performance_overlay_show_frametime_description">Wyświetla bieżący czas klatek.</string>
|
||||
<string name="performance_overlay_show_speed">Wyświetl Prędkość</string>
|
||||
<string name="performance_overlay_show_speed_description">Wyświetla aktualną procentową prędkość emulacji.</string>
|
||||
<string name="performance_overlay_show_app_ram_usage">Wyświetl użycie pamięci aplikacji</string>
|
||||
<string name="performance_overlay_show_app_ram_usage_description">Wyświetla ilość pamięci RAM używanej przez emulator.</string>
|
||||
<string name="performance_overlay_show_available_ram">Wyświetl dostępną pamięć</string>
|
||||
<string name="performance_overlay_show_available_ram_description">Wyświetla ilość dostępnej pamięci RAM.</string>
|
||||
<string name="performance_overlay_show_battery_temp">Wyświetl temperaturę baterii</string>
|
||||
<string name="performance_overlay_show_battery_temp_description">Wyświetla bieżącą temperaturę baterii w stopniach Celcjusza i Fahrenheita.</string>
|
||||
<string name="performance_overlay_position">Pozycja nakładki</string>
|
||||
<string name="performance_overlay_position_description">Wybierz miejsce wyświetlania nakładki wydajności na ekranie.</string>
|
||||
<string name="performance_overlay_position_top_left">Lewy górny róg</string>
|
||||
<string name="performance_overlay_position_top_right">Prawy górny róg</string>
|
||||
<string name="performance_overlay_position_bottom_left">Lewy dolny róg</string>
|
||||
<string name="performance_overlay_position_bottom_right">Prawy dolny róg</string>
|
||||
<string name="performance_overlay_position_center_top">Środkowy górny</string>
|
||||
<string name="performance_overlay_position_center_bottom">Środkowy dolny</string>
|
||||
<string name="performance_overlay_background">Tło nakładki</string>
|
||||
<string name="performance_overlay_background_description">Dodaje tło z tyłu nakładki w celu łatwego odczytu.</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Cheaty</string>
|
||||
@ -682,7 +712,7 @@
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">Obok Siebie</string>
|
||||
<string name="reverse_side_by_side">Odwróć Obok Siebie</string>
|
||||
<string name="side_by_side_full">Obok Siebie na Pełną Szerokość</string>
|
||||
<string name="anaglyph">Analogiczny</string>
|
||||
<string name="interlaced">Naprzemienny</string>
|
||||
<string name="reverse_interlaced">Odwrócony Obraz</string>
|
||||
@ -871,4 +901,19 @@
|
||||
<string name="emulation_occupied_quicksave_slot">Szybkie zapisywanie - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Funkcja szybkiego zapisu nie jest dostępna.</string>
|
||||
|
||||
<!-- File Compression -->
|
||||
<string name="compress">Kompresuj</string>
|
||||
<string name="compressing">Kompresowanie…</string>
|
||||
<string name="decompress">Dekompresuj</string>
|
||||
<string name="decompressing">Dekompresowanie...</string>
|
||||
<string name="compress_success">Kompresja została zakończona pomyślnie.</string>
|
||||
<string name="compress_unsupported">Kompresja nie jest obsługiwana dla tego pliku.</string>
|
||||
<string name="compress_already">Plik jest już skompresowany.</string>
|
||||
<string name="compress_failed">Kompresja nie powiodła się.</string>
|
||||
<string name="decompress_success">Dekompresja została zakończona pomyślnie.</string>
|
||||
<string name="decompress_unsupported">Dekompresja nie jest obsługiwana dla tego pliku.</string>
|
||||
<string name="decompress_not_compressed">Plik nie jest skompresowany.</string>
|
||||
<string name="decompress_failed">Dekompresja nie powiodła się.</string>
|
||||
<string name="compress_decompress_installed_app">Aplikacje, które są już zainstalowane, nie mogą być kompresowane ani dekompresowane.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@ -67,10 +67,14 @@
|
||||
<string name="give_permission">Conceder permissão</string>
|
||||
<string name="notification_warning">Ignorar a solicitação de notificação?</string>
|
||||
<string name="notification_warning_description">O Azahar não poderá te notificar de informações importantes.</string>
|
||||
<string name="filesystem_permission_warning">Permissões Ausentes</string>
|
||||
<string name="filesystem_permission_warning_description">O Azahar requer permissão para gerenciar arquivos neste dispositivo a fim de armazenar e gerenciar seus dados.\n\nPor favor, conceda a permissão de \'Sistema de Arquivos\' antes de continuar.</string>
|
||||
<string name="camera_permission">Câmera</string>
|
||||
<string name="camera_permission_description">Conceda acesso a câmera abaixo para emular a câmera do 3DS.</string>
|
||||
<string name="microphone_permission">Microfone</string>
|
||||
<string name="microphone_permission_description">Conceda a acesso ao microfone abaixo para emular o microfone do 3DS.</string>
|
||||
<string name="filesystem_permission">Sistema de Arquivos</string>
|
||||
<string name="filesystem_permission_description">Conceda a permissão de arquivos abaixo para permitir que o Azahar armazene arquivos.</string>
|
||||
<string name="permission_denied">Permissão negada</string>
|
||||
<string name="add_games_warning">Pular a seleção da pasta de aplicativos?</string>
|
||||
<string name="add_games_warning_description">Os softwares não serão exibidos na lista de Aplicativos se uma pasta não for selecionada.</string>
|
||||
@ -90,6 +94,9 @@
|
||||
<string name="cannot_skip">Você não pode pular a configuração da pasta do usuário.</string>
|
||||
<string name="cannot_skip_directory_description">Este passo é necessário para permitir que o Azahar funcione. Selecione um diretório para continuar.</string>
|
||||
<string name="selecting_user_directory_without_write_permissions">Você perdeu suas permissões de escrita no seu diretório de <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">dados de usuário</a>, onde dados salvos e outras informações são guardadas. Isso pode acontecer depois que algum app ou Android atualiza. Re-selecione o diretório para reobter as permissões para que você possa continuar.</string>
|
||||
<string name="invalid_selection">Seleção Inválida</string>
|
||||
<string name="invalid_user_directory">A seleção do diretório de usuário é inválida.\nPor favor, selecione novamente o diretório de usuário, certificando-se de navegar até ele a partir da raiz do armazenamento do seu dispositivo.</string>
|
||||
<string name="filesystem_permission_lost">O Azahar perdeu a permissão para gerenciar arquivos neste dispositivo. Isso pode acontecer após atualizações do aplicativo ou do Android. Por favor, conceda novamente esta permissão na próxima tela para continuar usando o app.</string>
|
||||
<string name="set_up_theme_settings">Configurações de Tema</string>
|
||||
<string name="setup_theme_settings_description">Configure suas preferências de tema para o Azahar.</string>
|
||||
<string name="setup_set_theme">Definir Tema</string>
|
||||
@ -122,8 +129,8 @@
|
||||
<string name="input_dialog_description">Pressione ou mova uma entrada.</string>
|
||||
<string name="input_binding">Mapeamento de controles</string>
|
||||
<string name="input_binding_description">Pressione ou mova um botão/alavanca para mapear para %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Mova o seu joystick para cima ou para baixo.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Mova o seu joystick para esquerda ou para direita.</string>
|
||||
<string name="input_binding_description_vertical_axis">Mova o seu joystick para baixo</string>
|
||||
<string name="input_binding_description_horizontal_axis">Mova o seu joystick para a direita</string>
|
||||
<string name="button_home">Menu Principal</string>
|
||||
<string name="button_swap">Trocar telas</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -162,6 +169,8 @@
|
||||
<string name="username">Nome de usuário</string>
|
||||
<string name="new_3ds">Modo do Novo 3DS</string>
|
||||
<string name="lle_applets">Usar miniaplicativos LLE (se instalados)</string>
|
||||
<string name="apply_region_free_patch">Aplicar patch de região livre aos aplicativos instalados</string>
|
||||
<string name="apply_region_free_patch_desc">Aplica um patch de região livre nos aplicativos instalados, para que eles sempre apareçam no menu inicial.</string>
|
||||
<string name="enable_required_online_lle_modules">Ativa os módulos LLE necessários para os recursos online (se instalado)</string>
|
||||
<string name="enable_required_online_lle_modules_desc">Ativa os módulos LLE necessários para o multijogador online, acesso à eShop, etc.</string>
|
||||
<string name="clock">Relógio</string>
|
||||
@ -193,6 +202,10 @@
|
||||
<string name="region_mismatch">Aviso de inconsistência de região</string>
|
||||
<string name="region_mismatch_emulated">O país configurado não é válido para a região emulada selecionada.</string>
|
||||
<string name="region_mismatch_console">O país configurado não é válido para o console vinculado atual.</string>
|
||||
<string name="storage">Armazenamento</string>
|
||||
<string name="compress_cia_installs">Comprimir conteúdo CIA instalado</string>
|
||||
<string name="compress_cia_installs_description">Comprime o conteúdo dos arquivos CIA ao serem instalados no cartão SD emulado. Afeta apenas o conteúdo CIA instalado enquanto a opção estiver ativada.</string>
|
||||
|
||||
<!-- Camera settings strings -->
|
||||
<string name="inner_camera">Câmera frontal</string>
|
||||
<string name="outer_left_camera">Câmera traseira esquerda</string>
|
||||
@ -213,25 +226,27 @@
|
||||
<string name="spirv_shader_gen_description">Emite o fragment shader usado para emular PICA usando SPIR-V em vez de GLSL</string>
|
||||
<string name="disable_spirv_optimizer">Desativar otimizador SPIR-V</string>
|
||||
<string name="disable_spirv_optimizer_description">Desativa a etapa de otimização SPIR-V, reduzindo consideravelmente os travamentos, com impacto mínimo no desempenho.</string>
|
||||
<string name="async_shaders">Ativar a compilação assíncrona de shaders</string>
|
||||
<string name="async_shaders">Habilitar Compilação Assíncrona do Shader</string>
|
||||
<string name="async_shaders_description">Compila shaders em segundo plano para reduzir travamentos durante o jogo. Quando ativado, espere falhas gráficas temporárias</string>
|
||||
<string name="linear_filtering">Filtragem Linear</string>
|
||||
<string name="linear_filtering_description">Ativa a filtragem linear, que suaviza o visual do jogo.</string>
|
||||
<string name="texture_filter_name">Filtro de texturas</string>
|
||||
<string name="texture_filter_description">Aprimora o visual dos aplicativos ao aplicar filtros às texturas. Os filtros compatíveis são: Anime4K Ultrafast, Bicúbico, ScaleForce, xBRZ Freescale e MMPX.</string>
|
||||
<string name="delay_render_thread">Atrasar thread de renderização do aplicativo</string>
|
||||
<string name="delay_render_thread">Atrasar Thread de Renderização do Aplicativo</string>
|
||||
<string name="delay_render_thread_description">Atrasar thread de renderização do aplicativo quando for enviado dados para a GPU. Ajuda com problemas de desempenho em (muito poucos) aplicativos com taxa de quadros dinâmica.</string>
|
||||
<string name="advanced">Avançado</string>
|
||||
<string name="texture_sampling_name">Amostragem de Texturas</string>
|
||||
<string name="texture_sampling_description">Substitui o filtro de amostragem usado pelos jogos. Isso pode ser útil em certos casos com jogos que se comportem mal durante o upscaling. Em caso de dúvidas, defina como Controlado pelo Jogo.</string>
|
||||
<string name="shaders_accurate_mul">Multiplicação precisa</string>
|
||||
<string name="shaders_accurate_mul_description">Utiliza uma multiplicação mais precisa de shaders no hardware, o que pode corrigir problemas visuais. Quando ativada, pode haver redução no desempenho.</string>
|
||||
<string name="asynchronous_gpu">Ativar emulação de GPU assíncrona</string>
|
||||
<string name="asynchronous_gpu">Habilitar Emulação de GPU Assíncrona </string>
|
||||
<string name="asynchronous_gpu_description">Usa uma thread separada para emular a GPU de forma assíncrona. Esta opção aprimora o desempenho quando ativada.</string>
|
||||
<string name="frame_limit_enable">Limite de velocidade</string>
|
||||
<string name="frame_limit_enable_description">Quando ativo, a velocidade de emulação será limitada à uma porcentagem especificada da velocidade normal. Se desativado, a velocidade de emulação será destravada e a tecla de atalho do turbo não irá funcionar.</string>
|
||||
<string name="frame_limit_slider">Limite de velocidade percentual</string>
|
||||
<string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade. Com o padrão de 100% a emulação será limitada a velocidade normal. Valores maiores ou menores vão aumentar ou reduzir o limite de velocidade.</string>
|
||||
<string name="android_hide_images">Esconder Imagens do 3DS do Android</string>
|
||||
<string name="android_hide_images_description">Prevenir câmera do 3DS, screenshots e texturas personalizadas de serem indexadas pelo Android e mostradas na galeria. Seu dispositivo pode precisar ser reiniciado após mudar essa configuração para as mudanças serem efetuadas.</string>
|
||||
<string name="turbo_limit">Limite da Velocidade Turbo:</string>
|
||||
<string name="turbo_limit_description">Limite de velocidade da emulação usado enquanto a tecla de atalho turbo está ativa.</string>
|
||||
<string name="expand_to_cutout_area">Expandir para a área recortada</string>
|
||||
@ -253,10 +268,18 @@
|
||||
<string name="debug_warning">Aviso: modificar estas configurações tornará a emulação mais lenta</string>
|
||||
<string name="stereoscopy">Estereoscopia</string>
|
||||
<string name="render3d">Modo 3D Estereoscópico</string>
|
||||
<string name="render3d_description">Escolha o modo 3D estereoscópico para a renderização 3D. Os modos Lado a Lado são os mais comuns atualmente. Os modos Anáglifo e Entrelaçado serão sempre aplicados a todas as telas conectadas.</string>
|
||||
<string name="factor3d">Profundidade</string>
|
||||
<string name="factor3d_description">Especifica o valor do controle deslizante 3D. Deve ser definido como superior a 0% quando o 3D Estereoscópico estiver ativado.\nNota: Valores de profundidade acima de 100% não são possíveis no hardware real e podem causar problemas gráficos</string>
|
||||
<string name="disable_right_eye_render">Desativar a renderização do olho direito</string>
|
||||
<string name="disable_right_eye_render_description">Melhora muito o desempenho em alguns aplicativos, mas pode causar piscadas em outros.</string>
|
||||
<string name="swap_eyes_3d">Inverter Olhos</string>
|
||||
<string name="swap_eyes_3d_description">Inverte qual olho é exibido em cada lado. Combinado com o modo Lado a Lado, torna possível ver em 3D cruzando os olhos!</string>
|
||||
<string name="render_3d_which_display">Renderizar 3D Estereoscópico</string>
|
||||
<string name="render_3d_which_display_description">Define se o 3D estereoscópico deve ser ativado e em quais telas. As opções de tela única só são relevantes quando várias telas estão conectadas.</string>
|
||||
<string name="render_3d_which_display_both">Ativado (Todas as Telas)</string>
|
||||
<string name="render_3d_which_display_primary">Ativado (Apenas Tela Principal)</string>
|
||||
<string name="render_3d_which_display_secondary">Ativado (Apenas Tela Secundária)</string>
|
||||
<string name="cardboard_vr">VR Cardboard </string>
|
||||
<string name="cardboard_screen_size">Tamanho da Tela do Cardboard</string>
|
||||
<string name="cardboard_screen_size_description">Dimensiona a tela para uma porcentagem de seu tamanho original.</string>
|
||||
@ -281,7 +304,7 @@
|
||||
<string name="audio_volume">Volume</string>
|
||||
<string name="audio_stretch">Alongamento de Áudio</string>
|
||||
<string name="audio_stretch_description">Estica o áudio para reduzir engasgos. Quando ativado, aumenta a latência do áudio e reduz levemente o desempenho.</string>
|
||||
<string name="realtime_audio">Ativar áudio em tempo real</string>
|
||||
<string name="realtime_audio">Ativar Áudio em Tempo Real</string>
|
||||
<string name="realtime_audio_description">Dimensiona a velocidade de reprodução de áudio para compensar quedas na taxa de quadros da emulação. Isso significa que o áudio será reproduzido em velocidade máxima mesmo quando a taxa de quadros do jogo estiver baixa. Pode causar problemas de dessincronização de áudio.</string>
|
||||
<string name="audio_input_type">Dispositivo de entrada de áudio</string>
|
||||
<string name="sound_output_mode">Modo de Saída de Som</string>
|
||||
@ -293,12 +316,12 @@
|
||||
<string name="hw_shaders_description">Utiliza o hardware para emular os shaders do 3DS. Quando ativado, o desempenho do jogo será consideravelmente melhorado.</string>
|
||||
<string name="cpu_clock_speed">Velocidade do Clock da CPU</string>
|
||||
<string name="vsync">Ativar sincronização vertical</string>
|
||||
<string name="vsync_description">Sincroniza a taxa de quadros do jogo com a taxa de atualização da tela do seu dispositivo.</string>
|
||||
<string name="vsync_description">Sincroniza a taxa de quadros do jogo com a taxa de atualização do seu dispositivo. Pode causar latência de entrada adicional, mas pode reduzir o \"tearing\" (rasgo de tela) em alguns casos.</string>
|
||||
<string name="renderer_debug">Renderizador de Depuração</string>
|
||||
<string name="renderer_debug_description">Registre informações adicionais de depuração relacionadas a gráficos. Quando ativado, o desempenho do jogo será significativamente reduzido.</string>
|
||||
<string name="instant_debug_log">Limpar a saída do log a cada mensagem</string>
|
||||
<string name="instant_debug_log">Limpar a Saída do Log a Cada Mensagem</string>
|
||||
<string name="instant_debug_log_description">Grava imediatamente o log de depuração no arquivo. Use isto se o Azahar travar e a saída do log estiver sendo cortada.</string>
|
||||
<string name="delay_start_lle_modules">Atraso na inicialização com módulos LLE</string>
|
||||
<string name="delay_start_lle_modules">Atraso na Inicialização com Módulos LLE</string>
|
||||
<string name="delay_start_lle_modules_description">Atrasa a inicialização do aplicativo quando os módulos LLE estão ativados.</string>
|
||||
<string name="deterministic_async_operations">Operações Assíncronas Determinísticas</string>
|
||||
<string name="deterministic_async_operations_description">Torna as operações assíncronas determinísticas para depuração. Ativar essa opção pode causar congelamentos.</string>
|
||||
@ -396,6 +419,10 @@
|
||||
<string name="emulation_configure_controls">Configurar controles</string>
|
||||
<string name="emulation_edit_layout">Editar Disposição</string>
|
||||
<string name="emulation_done">Pronto</string>
|
||||
<string name="emulation_button_sliding">Deslizar Botão</string>
|
||||
<string name="emulation_button_sliding_disabled">Segurar o botão originalmente pressionado</string>
|
||||
<string name="emulation_button_sliding_enabled">Segurar o botão atualmente pressionado</string>
|
||||
<string name="emulation_button_sliding_alternative">Segurar o botão original e o atualmente pressionado</string>
|
||||
<string name="emulation_toggle_controls">Alternar controles</string>
|
||||
<string name="emulation_control_scale">Ajustar escala</string>
|
||||
<string name="emulation_control_scale_global">Escala Global</string>
|
||||
@ -408,6 +435,8 @@
|
||||
<string name="emulation_aspect_ratio">Proporção da Tela</string>
|
||||
<string name="emulation_switch_screen_layout">Disposição de tela em paisagem</string>
|
||||
<string name="emulation_switch_portrait_layout">Disposição da tela em retrato</string>
|
||||
<string name="emulation_switch_secondary_layout">Layout da Tela de Exibição Secundária</string>
|
||||
<string name="emulation_switch_secondary_layout_description">O layout usado por uma tela secundária conectada, com ou sem fio (Chromecast, Miracast)</string>
|
||||
<string name="emulation_screen_layout_largescreen">Tela Grande</string>
|
||||
<string name="emulation_screen_layout_portrait">Retrato</string>
|
||||
<string name="emulation_screen_layout_single">Tela única</string>
|
||||
@ -415,7 +444,15 @@
|
||||
<string name="emulation_screen_layout_hybrid">Telas Híbridas</string>
|
||||
<string name="emulation_screen_layout_original">Original</string>
|
||||
<string name="emulation_portrait_layout_top_full">Padrão</string>
|
||||
<string name="emulation_secondary_display_default">Padrão do Sistema (espelhamento)</string>
|
||||
<string name="emulation_screen_layout_custom">Disposição Personalizada</string>
|
||||
<string name="bg_color">Cor de Fundo</string>
|
||||
<string name="bg_color_description">A cor que aparece atrás das telas durante a emulação, representada por um valor RGB.</string>
|
||||
<string name="bg_red">Vermelho</string>
|
||||
<string name="bg_green">Verde</string>
|
||||
<string name="bg_blue">Azul</string>
|
||||
<string name="second_screen_opacity">Opacidade da Segunda Tela no Layout Personalizado</string>
|
||||
<string name="second_screen_opacity_description">A opacidade da segunda tela do 3DS ao usar um layout de telas personalizado. Útil caso a segunda tela sobreponha a primeira.</string>
|
||||
<string name="emulation_small_screen_position">Posição da Tela Pequena</string>
|
||||
<string name="small_screen_position_description">Onde a tela pequena deverá aparecer relativa à grande na Disposição da Tela Grande?</string>
|
||||
<string name="small_screen_position_top_right">Superior Direita</string>
|
||||
@ -511,6 +548,8 @@
|
||||
<string name="fatal_error">Erro Fatal</string>
|
||||
<string name="fatal_error_message">Ocorreu um erro fatal. Verifique o registro para obter detalhes.\nContinuar a emulação pode resultar em falhas e bugs.</string>
|
||||
<string name="unsupported_encrypted">Aplicativo criptografado não suportado</string>
|
||||
<string name="invalid_system_mode">Modo de sistema inválido</string>
|
||||
<string name="invalid_system_mode_message">Novos aplicativos exclusivos do New 3DS não podem ser carregados sem ativar o modo New 3DS.</string>
|
||||
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Preparando Shaders</string>
|
||||
@ -535,33 +574,39 @@
|
||||
<string name="create_shortcut">Criar Atalho</string>
|
||||
<string name="shortcut_name_empty">O nome do atalho não pode ficar vazio</string>
|
||||
<string name="shortcut_image_stretch_toggle">Esticar para ajustar à imagem</string>
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Arquivo:</string>
|
||||
<string name="game_context_type">Tipo:</string>
|
||||
<string name="game_context_insert">Inserir Cartucho</string>
|
||||
<string name="game_context_eject">Ejetar Cartucho</string>
|
||||
|
||||
<!-- Performance Overlay settings -->
|
||||
<string name="performance_overlay_show">Mostrar Sobreposição de Desempenho</string>
|
||||
<string name="performance_overlay_options">Sobreposição de Desempenho</string>
|
||||
<string name="performance_overlay_enable">Ativa a Sobreposição de Desempenho</string>
|
||||
<string name="performance_overlay_options_description">Configure se a sobreposição de desempenho será exibida e quais informações serão mostradas.</string>
|
||||
<string name="overlay_show_fps">Mostrar FPS</string>
|
||||
<string name="overlay_show_fps_description">Exibe a taxa de quadros atual por segundo.</string>
|
||||
<string name="overlay_show_frametime">Mostrar Tempo de Quadro</string>
|
||||
<string name="overlay_show_frametime_description">Exibe o tempo de quadro atual.</string>
|
||||
<string name="overlay_show_speed">Mostrar Velocidade</string>
|
||||
<string name="overlay_show_speed_description">Exibe a porcentagem atual da velocidade da emulação.</string>
|
||||
<string name="overlay_show_app_ram_usage">Mostrar o Uso de Memória do Aplicativo</string>
|
||||
<string name="overlay_show_app_ram_usage_description">Exibe a quantidade de RAM utilizada pelo emulador.</string>
|
||||
<string name="overlay_show_available_ram">Mostrar Memória Disponível</string>
|
||||
<string name="overlay_show_available_ram_description">Exibe a quantidade de RAM disponível.</string>
|
||||
<string name="overlay_show_battery_temp">Mostrar a Temperatura da Bateria</string>
|
||||
<string name="overlay_show_battery_temp_description">Exibe a temperatura atual da Bateria em Celsius e Fahrenheit.</string>
|
||||
<string name="overlay_position">Posição da Sobreposição</string>
|
||||
<string name="overlay_position_description">Escolha onde a sobreposição de desempenho será exibida na tela.</string>
|
||||
<string name="overlay_position_top_left">Superior Esquerdo</string>
|
||||
<string name="overlay_position_top_right">Superior Direito</string>
|
||||
<string name="overlay_position_bottom_left">Inferior Esquerdo</string>
|
||||
<string name="overlay_position_bottom_right">Inferior Direito</string>
|
||||
<string name="overlay_position_center_top">Centro Superior</string>
|
||||
<string name="overlay_position_center_bottom">Centro Inferior</string>
|
||||
<string name="overlay_background">Plano de Fundo da Sobreposição</string>
|
||||
<string name="overlay_background_description">Adiciona um plano de fundo atrás da sobreposição para facilitar a leitura.</string>
|
||||
<string name="performance_overlay_show_fps">Mostrar FPS</string>
|
||||
<string name="performance_overlay_show_fps_description">Mostrar frames por segundo atuais.</string>
|
||||
<string name="performance_overlay_show_frametime">Mostrar tempo de frame</string>
|
||||
<string name="performance_overlay_show_frametime_description">Mostrar tempo de frame atual.</string>
|
||||
<string name="performance_overlay_show_speed">Mostrar velocidade</string>
|
||||
<string name="performance_overlay_show_speed_description">Mostrar atual porcentagem de velocidade da emulação.</string>
|
||||
<string name="performance_overlay_show_app_ram_usage">Mostrar Uso da Memória pelo App</string>
|
||||
<string name="performance_overlay_show_app_ram_usage_description">Mostrar o consumo de RAM pelo emulador.</string>
|
||||
<string name="performance_overlay_show_available_ram">Mostrar Memória Disponível </string>
|
||||
<string name="performance_overlay_show_available_ram_description">Mostrar a quantidade de RAM livre.</string>
|
||||
<string name="performance_overlay_show_battery_temp">Mostrar Temperatura da Bateria</string>
|
||||
<string name="performance_overlay_show_battery_temp_description">Mostrar atual temperatura da Bateria em Celsius e Fahrenheit.</string>
|
||||
<string name="performance_overlay_position">Posição do Overlay</string>
|
||||
<string name="performance_overlay_position_description">Escolha onde o overlay de performance é mostrado na tela.</string>
|
||||
<string name="performance_overlay_position_top_left">Canto Superior Esquerdo</string>
|
||||
<string name="performance_overlay_position_top_right">Canto Superior Direito</string>
|
||||
<string name="performance_overlay_position_bottom_left">Canto Inferior Esquerdo</string>
|
||||
<string name="performance_overlay_position_bottom_right">Canto Inferior Direito</string>
|
||||
<string name="performance_overlay_position_center_top">Superior Central</string>
|
||||
<string name="performance_overlay_position_center_bottom">Inferior Central</string>
|
||||
<string name="performance_overlay_background">Plano de Fundo da Sobreposição</string>
|
||||
<string name="performance_overlay_background_description">Adiciona um plano de fundo atrás do overlay para uma leitura mais fácil.</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Truques</string>
|
||||
@ -666,7 +711,7 @@
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">Lado a Lado</string>
|
||||
<string name="reverse_side_by_side">Inverter Lado a Lado</string>
|
||||
<string name="side_by_side_full">Lado a Lado (Largura Total)</string>
|
||||
<string name="anaglyph">Anáglifo</string>
|
||||
<string name="interlaced">Entrelaçado</string>
|
||||
<string name="reverse_interlaced">Entrelaçado Reverso</string>
|
||||
@ -855,4 +900,19 @@
|
||||
<string name="emulation_occupied_quicksave_slot">Salvar rápido - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Nenhum Salvamento Rápido disponível.</string>
|
||||
|
||||
<!-- File Compression -->
|
||||
<string name="compress">Compactar</string>
|
||||
<string name="compressing">Compactando...</string>
|
||||
<string name="decompress">Descompactar</string>
|
||||
<string name="decompressing">Descompactando...</string>
|
||||
<string name="compress_success">Compactação concluída com sucesso.</string>
|
||||
<string name="compress_unsupported">Compactação não suportada para este arquivo.</string>
|
||||
<string name="compress_already">O arquivo já está compactado.</string>
|
||||
<string name="compress_failed">A compactação falhou.</string>
|
||||
<string name="decompress_success">Descompactação concluída com sucesso.</string>
|
||||
<string name="decompress_unsupported">Descompactação não suportada para este arquivo.</string>
|
||||
<string name="decompress_not_compressed">O arquivo não está compactado.</string>
|
||||
<string name="decompress_failed">A descompactação falhou.</string>
|
||||
<string name="compress_decompress_installed_app">Aplicativos já instalados não podem ser compactados ou descompactados.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@ -70,8 +70,6 @@
|
||||
<string name="input_dialog_description">Нажмите или отклоните элемент управления.</string>
|
||||
<string name="input_binding">Привязки ввода</string>
|
||||
<string name="input_binding_description">Нажмите или отклоните орган управления для привязки %1$s.</string>
|
||||
<string name="input_binding_description_vertical_axis">Наклоните джойстик вверх или вниз.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Наклоните джойстик влево или вправо.</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="input_message_analog_only">Данный элемент управления должен быть привязан к аналоговому стику или крестовине геймпада!</string>
|
||||
<string name="input_message_button_only">Данный элемент управления должен быть привязан к кнопке геймпада!</string>
|
||||
@ -120,14 +118,12 @@
|
||||
<string name="graphics_api">Графический API</string>
|
||||
<string name="spirv_shader_gen">Вкл. генерацию шейдеров на SPIR-V</string>
|
||||
<string name="spirv_shader_gen_description">Запускать фрагментный шейдер, используемый для эмуляции PICA на SPIR-V вместо GLSL.</string>
|
||||
<string name="async_shaders">Вкл. асинхронную компиляцию шейдеров</string>
|
||||
<string name="async_shaders_description">Компилировать шейдеры в фоновом потоке для уменьшения лагов во время игры. При включении возможны временные сбои графики.</string>
|
||||
<string name="linear_filtering">Линейное сглаживание</string>
|
||||
<string name="linear_filtering_description">Вкл. линейное сглаживание для смягчения графики в играх.</string>
|
||||
<string name="texture_filter_name">Сглаживание текстур</string>
|
||||
<string name="shaders_accurate_mul">Точное умножение</string>
|
||||
<string name="shaders_accurate_mul_description">Исп. более точное умножение для аппаратных шейдеров. Может исправлять некоторые графические баги, но при включении снижает производительность.</string>
|
||||
<string name="asynchronous_gpu">Вкл. асинхронную эмуляцию GPU</string>
|
||||
<string name="asynchronous_gpu_description">Использовать отдельный поток для асинхронной эмуляции GPU. При включении повышает производительность.</string>
|
||||
<string name="frame_limit_enable">Ограничивать скорость</string>
|
||||
<string name="frame_limit_slider">Процент ограничения скорости</string>
|
||||
@ -172,7 +168,6 @@
|
||||
<string name="hw_shaders_description">Эмулировать шейдеры 3DS аппаратными средствами. При включении существенно повышает производительность в играх.</string>
|
||||
<string name="cpu_clock_speed">Скорость процессора</string>
|
||||
<string name="vsync">Вкл. V-Sync</string>
|
||||
<string name="vsync_description">Синхронизирует кадровую частоту в играх с частотой обновления устройства.</string>
|
||||
<string name="renderer_debug">Отладка рендера</string>
|
||||
<string name="renderer_debug_description">Логировать расширенную отладочную информацию по графике. При включении существенно снижает производительность.</string>
|
||||
<!-- Miscellaneous -->
|
||||
|
||||
@ -74,6 +74,9 @@
|
||||
<string name="permission_denied">İzin reddedildi</string>
|
||||
<string name="add_games_warning">Uygulama dosyasını seçmeyi atla?</string>
|
||||
<string name="add_games_warning_description">Eğer bir dosya seçili değilse yazılımlar uygulama listesinde görünmeyecektir.</string>
|
||||
<string name="permissions">İzinler</string>
|
||||
<string name="select_emulator_data_folders">Veri Klasörleri</string>
|
||||
<string name="permissions_description">Emülatörün belirli özelliklerini kullanmak için isteğe bağlı izinler verin</string>
|
||||
<string name="warning_help">Yardım</string>
|
||||
<string name="warning_skip">Atla</string>
|
||||
<string name="warning_cancel">İptal et</string>
|
||||
@ -83,6 +86,7 @@
|
||||
<string name="keep_current_azahar_directory">Şimdiki Azahar Dizinini Koru</string>
|
||||
<string name="use_prior_lime3ds_directory">Eski Lime3DS Dizinini Kullan</string>
|
||||
<string name="select">Seç</string>
|
||||
<string name="cannot_skip">Kullanıcı klasörü ayarlamayı atlayamazsınız</string>
|
||||
<string name="cannot_skip_directory_description">Bu adım Azahar\'ın çalışması için gereklidir. Lütfen devam etmek için bir dizin seçin.</string>
|
||||
<string name="selecting_user_directory_without_write_permissions">Kayıtların ve diğer bilgilerin depolandığı <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">kullanıcı verileri</a>dizininizdeki yazma izinlerini kaybettiniz. Bu durum bazı uygulama veya Android güncellemelerinden sonra meydana gelebilir. Devam edebilmeniz için lütfen izinleri yeniden kazanmak üzere dizini yeniden seçin.</string>
|
||||
<string name="set_up_theme_settings">Tema Ayarları</string>
|
||||
@ -117,8 +121,6 @@
|
||||
<string name="input_dialog_description">Bir girdiye basın veya hareket ettirin.</string>
|
||||
<string name="input_binding">Girdi Ataması</string>
|
||||
<string name="input_binding_description">Bir girdiyi %1$s e atamak için basın veya hareket ettirin.</string>
|
||||
<string name="input_binding_description_vertical_axis">Joystick\'inizi yukarı veya aşağı kaydırın.</string>
|
||||
<string name="input_binding_description_horizontal_axis">Joystick\'inizi sağa veya sola kaydırın.</string>
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Ekranları değiştir</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
@ -185,6 +187,7 @@
|
||||
<string name="region_mismatch">Bölge Uyuşmazlık Uyarısı</string>
|
||||
<string name="region_mismatch_emulated">Ülke ayarı emülasyon bölgesi için geçerli değil.</string>
|
||||
<string name="region_mismatch_console">Ülke ayarı bağlı olan konsol için geçerli değil.</string>
|
||||
<string name="storage">Depolama</string>
|
||||
<!-- Camera settings strings -->
|
||||
<string name="inner_camera">
|
||||
İç Kamera</string>
|
||||
@ -196,23 +199,24 @@
|
||||
<string name="camera_device_description">“Görüntü Kaynağı” ayarı ‘Cihaz Kamerası’ olarak ayarlanmışsa, bu ayar kullanılacak fiziksel kamerayı ayarlar.</string>
|
||||
<string name="camera_facing_front">Ön</string>
|
||||
<string name="camera_facing_back">Geri</string>
|
||||
<string name="camera_facing_external">Harici</string>
|
||||
<string name="image_flip">Çevir</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="renderer">İşleyici</string>
|
||||
<string name="graphics_api">Grafik API\'ı</string>
|
||||
<string name="spirv_shader_gen">SPIR-V gölgelendirici oluşturmayı etkinleştir</string>
|
||||
<string name="async_shaders">Asenkron gölgeleme derlemesini etkinleştir</string>
|
||||
<string name="async_shaders_description">Oyun sırasında takılmayı azaltmak için gölgelendiricileri arka planda derler. Etkinleştirildiğinde geçici grafik hataları meydana gelebilir.</string>
|
||||
<string name="linear_filtering">Doğrusal filtreleme</string>
|
||||
<string name="linear_filtering_description">Oyun görsellerinin daha pürüzsüz görünmesini sağlayan doğrusal filtrelemeyi etkinleştirir.</string>
|
||||
<string name="texture_filter_name">Doku Filtresi</string>
|
||||
<string name="texture_filter_description">Dokulara bir filtre uygulayarak uygulamaların görsellerini geliştirir. Desteklenen filtreler Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale ve MMPX\'tir.</string>
|
||||
<string name="delay_render_thread">Oyun işleme iş parçacığını geciktir</string>
|
||||
<string name="delay_render_thread_description">GPU\'ya veri gönderirken oyun işleme iş parçacığını geciktirin. Dinamik kare hızlarına sahip (çok az sayıda) uygulamada performans sorunlarına yardımcı olur.</string>
|
||||
<string name="advanced">Gelişmiş</string>
|
||||
<string name="texture_sampling_name">Doku Örnekleme</string>
|
||||
<string name="texture_sampling_description">Uygulamalar tarafından kullanılan örnekleme filtresini geçersiz kılar. Bu, görüntü yükseltme sırasında hatalı davranan uygulamaların olduğu bazı durumlarda faydalı olabilir. Emin değilseniz, bunu Uygulama Kontrollü olarak ayarlayın.</string>
|
||||
<string name="shaders_accurate_mul">İsabetli Çoğaltma</string>
|
||||
<string name="shaders_accurate_mul_description">Donanım gölgelendiricilerinde daha doğru çarpım kullanır, bu da bazı grafik hatalarını düzeltebilir. Etkinleştirildiğinde performans düşecektir.</string>
|
||||
<string name="asynchronous_gpu">Asenkron GPU emülasyonunu etkinleştir</string>
|
||||
<string name="asynchronous_gpu_description">GPU emülasyonunu asenkron olarak yapmak için ayrı bir iş parçacığı kullanır. Etkinleştirildiğinde performans artacaktır.</string>
|
||||
<string name="frame_limit_enable">Hızı Sınırlandır</string>
|
||||
<string name="frame_limit_enable_description">Etkinleştirildiğinde, emülasyon hızı normal hızın belirli bir yüzdesiyle sınırlandırılır. Devre dışı bırakılırsa, emülasyon hızı sınırlandırılmaz ve turbo hız kısayol tuşu çalışmaz.</string>
|
||||
@ -220,6 +224,7 @@
|
||||
<string name="frame_limit_slider_description">Emülasyon hızını sınırlamak için yüzdeyi belirtir. Varsayılan değer olan %100 ile emülasyon normal hız ile sınırlandırılacaktır. Daha yüksek veya daha düşük değerler hız sınırını artıracak veya azaltacaktır Etkinleştirildiğinde, emülasyon hızı normal hızın belirli bir yüzdesiyle sınırlandırılacaktır. Devre dışı bırakılırsa, emülasyon hızı sınırlandırılmaz ve turbo hız kısayol tuşu çalışmaz.</string>
|
||||
<string name="turbo_limit">Turbo Hız Limiti</string>
|
||||
<string name="turbo_limit_description">Turbo kısayolu aktfiken kullanılan emülasyon hız limiti.</string>
|
||||
<string name="expand_to_cutout_area">Kesme Alanına Genişlet</string>
|
||||
<string name="internal_resolution">İç Çözünürlük</string>
|
||||
<string name="internal_resolution_description">Render için kullanılan çözünürlüğü belirtir. Yüksek çözünürlük görsel kaliteyi çok artıracaktır ancak performans açısından da oldukça ağırdır ve bazı uygulamalarda aksaklıklara neden olabilir.</string>
|
||||
<string name="internal_resolution_setting_auto">Otomatik (Ekran Boyutu)</string>
|
||||
@ -259,7 +264,7 @@
|
||||
<string name="audio_volume">Ses düzeyi</string>
|
||||
<string name="audio_stretch">Ses Gerdirme</string>
|
||||
<string name="audio_stretch_description">Takılmayı azaltmak için sesi esnetir. Etkinleştirildiğinde, ses gecikmesini artırır ve performansı biraz düşürür.</string>
|
||||
<string name="realtime_audio">Gerçek zamanlı sesi etkinleştir</string>
|
||||
<string name="realtime_audio">Gerçek Zamanlı Sesi Etkinleştir</string>
|
||||
<string name="realtime_audio_description">Emülasyon kare hızındaki düşüşleri hesaba katmak için ses çalma hızını ölçeklendirir. Bu, oyun kare hızı düşük olsa bile sesin tam hızda çalınacağı anlamına gelir. Ses senkronizasyon sorunlarına neden olabilir.</string>
|
||||
<string name="audio_input_type">Ses Giriş Cihazı</string>
|
||||
<string name="sound_output_mode">Ses Çıkış Modu</string>
|
||||
@ -271,15 +276,13 @@
|
||||
<string name="hw_shaders_description">3DS shader\'larının emülasyonu için donanımı kullanır. Etkinleştirildiğinde oyun performansı önemli ölçüde artacaktır.</string>
|
||||
<string name="cpu_clock_speed">CPU Saat Hızı</string>
|
||||
<string name="vsync">V-Sync\'i Etkinleştir</string>
|
||||
<string name="vsync_description">Oyun kare hızını cihazınızın yenileme hızına senkronize eder.</string>
|
||||
<string name="renderer_debug">Hata Ayıklama İşleyicisi</string>
|
||||
<string name="renderer_debug_description">Grafiklerle ilgili ek hata ayıklama bilgilerini günlüğe kaydedin. Etkinleştirildiğinde, oyun performansı önemli ölçüde azalacaktır.</string>
|
||||
<string name="instant_debug_log">Her mesajda günlük çıktısını temizle</string>
|
||||
<string name="instant_debug_log_description">Hata ayıklama günlüğünü hemen dosyaya işler. Azahar çöküyor ve günlük çıktısı kesiliyorsa bunu kullanın.</string>
|
||||
<string name="delay_start_lle_modules">LLE modülleriyle başlamayı geciktir</string>
|
||||
<string name="delay_start_lle_modules_description">LLE modülleri etkinken uygulamanın başlamasını geciktirir</string>
|
||||
<string name="deterministic_async_operations">Deterministik Asenkron İşlemler</string>
|
||||
<string name="deterministic_async_operations_description">Hata ayıklama için asenkron işlemleri deterministik hale getirir. Bunu etkinleştirmek donmalara neden olabilir.</string>
|
||||
<string name="enable_rpc_server">RPC Sunucusunu Etkinleştir</string>
|
||||
<!-- Layout settings strings -->
|
||||
<string name="layout_screen_orientation">Ekran Yönelimi</string>
|
||||
<string name="layout_screen_orientation_auto_sensor">Otomatik</string>
|
||||
@ -287,6 +290,13 @@
|
||||
<string name="layout_screen_orientation_landscape_reverse">Ters Yatay</string>
|
||||
<string name="layout_screen_orientation_portrait">Portre</string>
|
||||
<string name="layout_screen_orientation_portrait_reverse">Ters Portre</string>
|
||||
<string name="aspect_ratio_default">Varsayılan</string>
|
||||
<string name="aspect_ratio_16_9">16:9</string>
|
||||
<string name="aspect_ratio_4_3">4:3</string>
|
||||
<string name="aspect_ratio_21_9_fullscreen">21:9</string>
|
||||
<string name="aspect_ratio_16_10_fullscreen_stretched">16:10</string>
|
||||
<string name="aspect_ratio_stretch">Gerdir</string>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<string name="clear">Temizle</string>
|
||||
<string name="slider_default">Varsayılan</string>
|
||||
@ -302,6 +312,7 @@
|
||||
<string name="reset_to_default">Varsayılanlara Sıfırla</string>
|
||||
<string name="redump_games"><![CDATA[Lütfen <a href=\"https://web.archive.org/web/20240304210021/https://citra-emu.org/wiki/dumping-game-cartridges/\">oyun kartuşlarınızı</a> veya <a href=\"https://web.archive.org/web/20240304210011/https://citra-emu.org/wiki/dumping-installed-titles/\">yüklü başlıklarınızı</a>yeniden yüklemek için kılavuzları izleyin.]]></string>
|
||||
<string name="option_default">Varsayılan</string>
|
||||
<string name="auto">Otomatik</string>
|
||||
<string name="off">Kapalı</string>
|
||||
<string name="install">Yükle</string>
|
||||
<string name="delete">Sil</string>
|
||||
@ -320,6 +331,9 @@
|
||||
<string name="cancelling">İptal ediliyor...</string>
|
||||
<string name="important">Önemli</string>
|
||||
<string name="dont_show_again">Tekrar gösterme</string>
|
||||
<string name="visibility">Görünürlük</string>
|
||||
<string name="information">Bilgi</string>
|
||||
|
||||
<!-- Add Directory Screen-->
|
||||
<string name="select_game_folder">Oyun Dosyası Seç</string>
|
||||
|
||||
@ -357,12 +371,14 @@
|
||||
<string name="emulation_configure_controls">Kontrolleri Yapılandır</string>
|
||||
<string name="emulation_edit_layout">Düzeni Değiştir</string>
|
||||
<string name="emulation_done">Bitti</string>
|
||||
<string name="emulation_button_sliding">Buton Kayması</string>
|
||||
<string name="emulation_control_scale">Ölçeği Ayarla</string>
|
||||
<string name="emulation_control_scale_reset_all">Tümünü Sıfırla</string>
|
||||
<string name="emulation_control_opacity">Görünürlüğü Ayarla</string>
|
||||
<string name="emulation_control_dpad_slide_enable">D-Pad kayması</string>
|
||||
<string name="emulation_open_settings">Ayarları Aç</string>
|
||||
<string name="emulation_open_cheats">Hileleri Aç</string>
|
||||
<string name="emulation_aspect_ratio">En Boy Oranı</string>
|
||||
<string name="emulation_switch_screen_layout">Yatay Ekran Düzeni</string>
|
||||
<string name="emulation_switch_portrait_layout">Dikey Ekran Düzeni</string>
|
||||
<string name="emulation_screen_layout_largescreen">Büyük Ekran</string>
|
||||
@ -372,7 +388,12 @@
|
||||
<string name="emulation_screen_layout_hybrid">Hibrit Ekranlar</string>
|
||||
<string name="emulation_screen_layout_original">Orijinal</string>
|
||||
<string name="emulation_portrait_layout_top_full">Varsayılan</string>
|
||||
<string name="emulation_secondary_display_default">Sistem Varsayılanı (ayna)</string>
|
||||
<string name="emulation_screen_layout_custom">Özel Düzen</string>
|
||||
<string name="bg_color">Arkaplan Rengi</string>
|
||||
<string name="bg_red">Kırmızı</string>
|
||||
<string name="bg_green">Yeşil</string>
|
||||
<string name="bg_blue">Mavi</string>
|
||||
<string name="emulation_small_screen_position">Küçük Ekran Konumu</string>
|
||||
<string name="small_screen_position_description">Büyük Ekran Düzeninde küçük ekran büyük ekrana kıyasla nerede olmalı?</string>
|
||||
<string name="small_screen_position_top_right">Sağ Üst</string>
|
||||
@ -398,6 +419,7 @@
|
||||
<string name="emulation_custom_layout_height">Yükseklik</string>
|
||||
<string name="emulation_swap_screens">Ekranları Değiştir</string>
|
||||
<string name="emulation_touch_overlay_reset">Yerleşimi Sıfırla</string>
|
||||
<string name="emulation_show_controller_overlay">Kontrolcü Yerleşimini Göster</string>
|
||||
<string name="emulation_close_game">Oyunu Kapat</string>
|
||||
<string name="emulation_toggle_pause">Duraklatmayı Aç / Kapat</string>
|
||||
<string name="miscellaneous">Çeşitli</string>
|
||||
@ -462,7 +484,6 @@
|
||||
<string name="fatal_error">Ölümcül Hata</string>
|
||||
<string name="fatal_error_message">Ölümcül bir hata oluştu. Ayrıntılar için log\'u kontrol edin.\nEmülasyona devam etmek çökmelere ve hatalara neden olabilir.</string>
|
||||
<string name="unsupported_encrypted">Desteklenmeyen şifreli uygulama</string>
|
||||
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Gölgelendiriciler Hazırlanıyor</string>
|
||||
<string name="building_shaders">Gölgelendiriciler Oluşturuluyor</string>
|
||||
@ -481,6 +502,22 @@
|
||||
<string name="game_context_uninstall_dlc">DLC\'leri Sil</string>
|
||||
<string name="game_context_uninstall_updates">Güncellemeleri Sil</string>
|
||||
<string name="shortcut">Kısayol</string>
|
||||
<string name="shortcut_name">Kısayol Adı</string>
|
||||
<string name="edit_icon">Simgeyi düzenle</string>
|
||||
<string name="create_shortcut">Kısayol Oluştur</string>
|
||||
<string name="game_context_id">ID:</string>
|
||||
<string name="game_context_file">Dosya:</string>
|
||||
<string name="game_context_type">Tür:</string>
|
||||
<string name="performance_overlay_show_fps">FPS\'i Göster</string>
|
||||
<string name="performance_overlay_show_speed">Hızı Göster</string>
|
||||
<string name="performance_overlay_show_available_ram">Kullanılabilir Belleği Göster</string>
|
||||
<string name="performance_overlay_show_battery_temp">Pil Sıcaklığını Göster</string>
|
||||
<string name="performance_overlay_position_top_left">Sol Üst</string>
|
||||
<string name="performance_overlay_position_top_right">Sağ Üst</string>
|
||||
<string name="performance_overlay_position_bottom_left">Sol Alt</string>
|
||||
<string name="performance_overlay_position_bottom_right">Sağ Alt</string>
|
||||
<string name="performance_overlay_position_center_top">Orta Üst</string>
|
||||
<string name="performance_overlay_position_center_bottom">Orta Alt</string>
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Hileler</string>
|
||||
<string name="cheats_add">Hile Ekle</string>
|
||||
@ -583,7 +620,6 @@
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">Yan Yana</string>
|
||||
<string name="reverse_side_by_side">Ters Yan Yana</string>
|
||||
<string name="anaglyph">Anaglif</string>
|
||||
<string name="interlaced">Geçmeli</string>
|
||||
<string name="reverse_interlaced">Ters Geçmeli</string>
|
||||
@ -601,6 +637,7 @@
|
||||
|
||||
<!-- Texture Sampling names -->
|
||||
<string name="game_controlled">Oyun Kontrollü</string>
|
||||
<string name="nearest_neighbor">En Yakın Komşu</string>
|
||||
<string name="linear">Lineer</string>
|
||||
|
||||
<!-- Sound output modes -->
|
||||
@ -771,4 +808,4 @@
|
||||
<string name="emulation_occupied_quicksave_slot">Hızlı Kayıt - %1$tF %1$tR</string>
|
||||
<string name="quickload_not_found">Hiçbir Hızlı Kayıt mevcut değil.</string>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user