Compare commits
118 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4a34bcfcbf | ||
![]() |
5fc48cfc8d | ||
![]() |
3947f896e5 | ||
![]() |
1e8cc02d56 | ||
![]() |
b4699d9d47 | ||
![]() |
a53ce91852 | ||
![]() |
01d7ff7a08 | ||
![]() |
493f59cef5 | ||
![]() |
939a6e0f7a | ||
![]() |
975ad17442 | ||
![]() |
dcbf79df14 | ||
![]() |
eba3c2c08f | ||
![]() |
391f91f735 | ||
![]() |
bac344d059 | ||
![]() |
0051182338 | ||
![]() |
527610d599 | ||
![]() |
1ff5042685 | ||
![]() |
b1480396fa | ||
![]() |
de1b520498 | ||
![]() |
a6782e8a13 | ||
![]() |
fd3e4068b6 | ||
![]() |
8fbfb94bec | ||
![]() |
d43597b520 | ||
![]() |
967263fc80 | ||
![]() |
fdbc74b506 | ||
![]() |
544c6b4bbc | ||
![]() |
b8267c0a39 | ||
![]() |
2670b517e8 | ||
![]() |
e90930b0b9 | ||
![]() |
72eb16f933 | ||
![]() |
81ce14e0db | ||
![]() |
d974a0062f | ||
![]() |
7c9ea780b3 | ||
![]() |
4bc1655b05 | ||
![]() |
ebb462f1d5 | ||
![]() |
3a0878f40f | ||
![]() |
240e968d73 | ||
![]() |
52ccaabca8 | ||
![]() |
8acc5e22a0 | ||
![]() |
8dcef46a11 | ||
![]() |
14413d896f | ||
![]() |
bf4eef8e58 | ||
![]() |
2a7a5078fc | ||
![]() |
76a23e4c72 | ||
![]() |
8e477e35bb | ||
![]() |
89d2e67459 | ||
![]() |
32e378a29b | ||
![]() |
12bc825b8a | ||
![]() |
c69b642f54 | ||
![]() |
0e0137a9ff | ||
![]() |
4ea8c6fda5 | ||
![]() |
eb310a4a60 | ||
![]() |
903a9ad81f | ||
![]() |
e341dcf238 | ||
![]() |
8d769ed9cb | ||
![]() |
71c9c0c924 | ||
![]() |
6865b4c8a7 | ||
![]() |
c0bb7abdbc | ||
![]() |
aa58dd5f68 | ||
![]() |
9500859043 | ||
![]() |
93eeb501c0 | ||
![]() |
f298d7551c | ||
![]() |
5ade69f5f4 | ||
![]() |
e6199780a5 | ||
![]() |
2c1fc0199b | ||
![]() |
dec12bd54a | ||
![]() |
5c7622100b | ||
![]() |
eda2d6f9fa | ||
![]() |
dee576bfeb | ||
![]() |
7dda835679 | ||
![]() |
1de19fcbc2 | ||
![]() |
d8077fdea6 | ||
![]() |
9203b23868 | ||
![]() |
61feb3aee2 | ||
![]() |
bd1f5b978b | ||
![]() |
d406c5d81e | ||
![]() |
cfa59dc0bb | ||
![]() |
8cdafaa828 | ||
![]() |
f083a6e5d3 | ||
![]() |
75918be261 | ||
![]() |
2b0d412070 | ||
![]() |
5b910d6f0e | ||
![]() |
4d04f633fa | ||
![]() |
c7fe6333b5 | ||
![]() |
16dac366cf | ||
![]() |
860aace2f5 | ||
![]() |
844b166fbf | ||
![]() |
7e9b5743fb | ||
![]() |
7920188417 | ||
![]() |
3718bab5cb | ||
![]() |
ec9c3dd276 | ||
![]() |
ffb8bf15b2 | ||
![]() |
22934aa46e | ||
![]() |
17a6bfb7dd | ||
![]() |
edb01754ea | ||
![]() |
1259401889 | ||
![]() |
84e2f31415 | ||
![]() |
70be7d987e | ||
![]() |
9763488577 | ||
![]() |
b225e856df | ||
![]() |
2f28911395 | ||
![]() |
d82be7ac7c | ||
![]() |
3783ac9f49 | ||
![]() |
5acb2eee91 | ||
![]() |
19551b1eb6 | ||
![]() |
d59ea25cbe | ||
![]() |
dcd6fe8258 | ||
![]() |
fac8ae2682 | ||
![]() |
9d03856026 | ||
![]() |
0eb4a71720 | ||
![]() |
007b809ad7 | ||
![]() |
66d8e58dcd | ||
![]() |
8cb3dde72f | ||
![]() |
eb3aa52391 | ||
![]() |
c13d2d7208 | ||
![]() |
dac463d74a | ||
![]() |
d72948ca22 | ||
![]() |
ccb26303ad |
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
if [ "$TARGET" = "appimage" ]; then
|
if [ "$TARGET" = "appimage" ]; then
|
||||||
# Compile the AppImage we distribute with Clang.
|
# 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)
|
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
|
# Bundle required QT wayland libraries
|
||||||
export EXTRA_QT_PLUGINS="waylandcompositor"
|
export EXTRA_QT_PLUGINS="waylandcompositor"
|
||||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
||||||
|
|
|
@ -11,7 +11,7 @@ BASE_ARTIFACT_ARCH="${BASE_ARTIFACT##*-}"
|
||||||
mv $BASE_ARTIFACT $BUNDLE_DIR
|
mv $BASE_ARTIFACT $BUNDLE_DIR
|
||||||
|
|
||||||
# Executable binary paths that need to be combined.
|
# Executable binary paths that need to be combined.
|
||||||
BIN_PATHS=(azahar-room Azahar.app/Contents/MacOS/azahar)
|
BIN_PATHS=(Azahar.app/Contents/MacOS/azahar)
|
||||||
|
|
||||||
# Dylib paths that need to be combined.
|
# Dylib paths that need to be combined.
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
|
@ -36,8 +36,11 @@ for OTHER_ARTIFACT in "${ARTIFACTS_LIST[@]:1}"; do
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Remove leftover libs so that they aren't distributed
|
||||||
|
rm -rf "${BUNDLE_DIR}/libs"
|
||||||
|
|
||||||
# Re-sign executables and bundles after combining.
|
# Re-sign executables and bundles after combining.
|
||||||
APP_PATHS=(azahar-room Azahar.app)
|
APP_PATHS=(Azahar.app)
|
||||||
for APP_PATH in "${APP_PATHS[@]}"; do
|
for APP_PATH in "${APP_PATHS[@]}"; do
|
||||||
codesign --deep -fs - $BUNDLE_DIR/$APP_PATH
|
codesign --deep -fs - $BUNDLE_DIR/$APP_PATH
|
||||||
done
|
done
|
||||||
|
|
|
@ -11,6 +11,7 @@ cmake .. -GNinja \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
-DENABLE_QT_TRANSLATION=ON \
|
-DENABLE_QT_TRANSLATION=ON \
|
||||||
|
-DENABLE_ROOM_STANDALONE=OFF \
|
||||||
-DUSE_DISCORD_PRESENCE=ON \
|
-DUSE_DISCORD_PRESENCE=ON \
|
||||||
"${EXTRA_CMAKE_FLAGS[@]}"
|
"${EXTRA_CMAKE_FLAGS[@]}"
|
||||||
ninja
|
ninja
|
||||||
|
|
|
@ -14,7 +14,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Archive and upload the artifacts.
|
# Archive and upload the artifacts.
|
||||||
mkdir artifacts
|
mkdir -p artifacts
|
||||||
|
|
||||||
function pack_artifacts() {
|
function pack_artifacts() {
|
||||||
ARTIFACTS_PATH="$1"
|
ARTIFACTS_PATH="$1"
|
||||||
|
@ -50,11 +50,6 @@ function pack_artifacts() {
|
||||||
rm -rf "$REV_NAME"
|
rm -rf "$REV_NAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$OS" = "windows" ] && [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
|
||||||
# Move the installer to the artifacts directory
|
|
||||||
mv src/installer/bin/*.exe artifacts/
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$UNPACKED" ]; then
|
if [ -n "$UNPACKED" ]; then
|
||||||
# Copy the artifacts to be uploaded unpacked.
|
# Copy the artifacts to be uploaded unpacked.
|
||||||
for ARTIFACT in build/bundle/*; do
|
for ARTIFACT in build/bundle/*; do
|
||||||
|
|
|
@ -4,6 +4,10 @@ GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
||||||
GITREV="`git show -s --format='%h'`"
|
GITREV="`git show -s --format='%h'`"
|
||||||
REV_NAME="azahar-unified-source-${GITDATE}-${GITREV}"
|
REV_NAME="azahar-unified-source-${GITDATE}-${GITREV}"
|
||||||
|
|
||||||
|
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
||||||
|
REV_NAME="azahar-unified-source-$GITHUB_REF_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
COMPAT_LIST='dist/compatibility_list/compatibility_list.json'
|
COMPAT_LIST='dist/compatibility_list/compatibility_list.json'
|
||||||
|
|
||||||
mkdir artifacts
|
mkdir artifacts
|
||||||
|
|
32
.github/workflows/build.yml
vendored
|
@ -49,12 +49,14 @@ jobs:
|
||||||
${{ runner.os }}-${{ matrix.target }}-
|
${{ runner.os }}-${{ matrix.target }}-
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./.ci/linux.sh
|
run: ./.ci/linux.sh
|
||||||
- name: Pack
|
- name: Move AppImage to artifacts directory
|
||||||
run: ./.ci/pack.sh
|
|
||||||
if: ${{ matrix.target == 'appimage' }}
|
if: ${{ matrix.target == 'appimage' }}
|
||||||
|
run: |
|
||||||
|
mkdir -p artifacts
|
||||||
|
mv build/bundle/*.AppImage artifacts/
|
||||||
- name: Upload
|
- name: Upload
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: ${{ matrix.target == 'appimage' }}
|
if: ${{ matrix.target == 'appimage' }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||||
path: artifacts/
|
path: artifacts/
|
||||||
|
@ -148,19 +150,19 @@ jobs:
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-${{ matrix.target }}-
|
${{ runner.os }}-${{ matrix.target }}-
|
||||||
- name: Set up MSVC
|
- name: Set up MSVC
|
||||||
|
if: ${{ matrix.target == 'msvc' }}
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
if: ${{ matrix.target == 'msvc' }}
|
|
||||||
- name: Install extra tools (MSVC)
|
- name: Install extra tools (MSVC)
|
||||||
run: choco install ccache ninja wget
|
|
||||||
if: ${{ matrix.target == 'msvc' }}
|
if: ${{ matrix.target == 'msvc' }}
|
||||||
|
run: choco install ccache ninja ptime wget
|
||||||
- name: Install vulkan-sdk (MSVC)
|
- name: Install vulkan-sdk (MSVC)
|
||||||
|
if: ${{ matrix.target == 'msvc' }}
|
||||||
run: |
|
run: |
|
||||||
wget https://sdk.lunarg.com/sdk/download/1.3.296.0/windows/VulkanSDK-1.3.296.0-Installer.exe -O D:/a/_temp/vulkan.exe
|
wget https://sdk.lunarg.com/sdk/download/1.3.296.0/windows/VulkanSDK-1.3.296.0-Installer.exe -O D:/a/_temp/vulkan.exe
|
||||||
D:/a/_temp/vulkan.exe --accept-licenses --default-answer --confirm-command install
|
D:/a/_temp/vulkan.exe --accept-licenses --default-answer --confirm-command install
|
||||||
if: ${{ matrix.target == 'msvc' }}
|
|
||||||
- name: Set up MSYS2
|
- name: Set up MSYS2
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
if: ${{ matrix.target == 'msys2' }}
|
if: ${{ matrix.target == 'msys2' }}
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
msystem: clang64
|
msystem: clang64
|
||||||
update: true
|
update: true
|
||||||
|
@ -168,10 +170,16 @@ jobs:
|
||||||
pacboy: >-
|
pacboy: >-
|
||||||
toolchain:p ccache:p cmake:p ninja:p spirv-tools:p
|
toolchain:p ccache:p cmake:p ninja:p spirv-tools:p
|
||||||
qt6-base:p qt6-multimedia:p qt6-multimedia-wmf:p qt6-tools:p qt6-translations:p
|
qt6-base:p qt6-multimedia:p qt6-multimedia-wmf:p qt6-tools:p qt6-translations:p
|
||||||
|
- name: Install extra tools (MSYS2)
|
||||||
|
if: ${{ matrix.target == 'msys2' }}
|
||||||
|
uses: crazy-max/ghaction-chocolatey@v3
|
||||||
|
with:
|
||||||
|
args: install ptime wget
|
||||||
- name: Install NSIS
|
- name: Install NSIS
|
||||||
|
if: ${{ github.ref_type == 'tag' }}
|
||||||
run: |
|
run: |
|
||||||
Invoke-WebRequest https://deac-riga.dl.sourceforge.net/project/nsis/NSIS%203/3.10/nsis-3.10-setup.exe?viasf=1 -OutFile C:\WINDOWS\Temp\nsis-3.10-setup.exe
|
wget https://download.sourceforge.net/project/nsis/NSIS%203/3.11/nsis-3.11-setup.exe -O D:/a/_temp/nsis-setup.exe
|
||||||
Invoke-Expression "& C:\WINDOWS\Temp\nsis-3.10-setup.exe \S"
|
ptime D:/a/_temp/nsis-setup.exe /S
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Disable line ending translation
|
- name: Disable line ending translation
|
||||||
run: git config --global core.autocrlf input
|
run: git config --global core.autocrlf input
|
||||||
|
@ -182,8 +190,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd src\installer
|
cd src\installer
|
||||||
"C:\Program Files (x86)\NSIS\makensis.exe" /DPRODUCT_VARIANT=${{ matrix.target }} /DPRODUCT_VERSION=${{ github.ref_name }} citra.nsi
|
"C:\Program Files (x86)\NSIS\makensis.exe" /DPRODUCT_VARIANT=${{ matrix.target }} /DPRODUCT_VERSION=${{ github.ref_name }} citra.nsi
|
||||||
mkdir bin
|
mkdir ..\..\artifacts 2> NUL
|
||||||
move /y *.exe bin\
|
move /y *.exe ..\..\artifacts\
|
||||||
shell: cmd
|
shell: cmd
|
||||||
- name: Pack
|
- name: Pack
|
||||||
run: ./.ci/pack.sh
|
run: ./.ci/pack.sh
|
||||||
|
@ -241,8 +249,8 @@ jobs:
|
||||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||||
path: src/android/app/artifacts/
|
path: src/android/app/artifacts/
|
||||||
ios:
|
ios:
|
||||||
runs-on: macos-14
|
|
||||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
runs-on: macos-14
|
||||||
env:
|
env:
|
||||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||||
CCACHE_COMPILERCHECK: content
|
CCACHE_COMPILERCHECK: content
|
||||||
|
|
23
.github/workflows/stale.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: azahar-stale
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9.1.0
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-issue-stale: 90
|
||||||
|
days-before-issue-close: 10
|
||||||
|
stale-issue-message: "This issue has been marked as stale. If there is no activity within the next 10 days, this issue will be closed."
|
||||||
|
close-issue-message: "This issue has been closed as stale."
|
||||||
|
days-before-pr-stale: -1
|
||||||
|
days-before-pr-close: -1
|
||||||
|
remove-issue-stale-when-updated: true
|
||||||
|
exempt-issue-labels: "priority - low,priority - medium,priority - high,priority - urgent,documentation,enhancement,miscellaneous,task,refactor"
|
2
.gitmodules
vendored
|
@ -6,7 +6,7 @@
|
||||||
url = https://github.com/neobrain/nihstro.git
|
url = https://github.com/neobrain/nihstro.git
|
||||||
[submodule "soundtouch"]
|
[submodule "soundtouch"]
|
||||||
path = externals/soundtouch
|
path = externals/soundtouch
|
||||||
url = https://codeberg.org/soundtouch/soundtouch.git
|
url = https://github.com/azahar-emu/soundtouch.git
|
||||||
[submodule "catch2"]
|
[submodule "catch2"]
|
||||||
path = externals/catch2
|
path = externals/catch2
|
||||||
url = https://github.com/catchorg/Catch2
|
url = https://github.com/catchorg/Catch2
|
||||||
|
|
|
@ -41,8 +41,8 @@ if (APPLE)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
|
||||||
else()
|
else()
|
||||||
# Minimum macOS 11
|
# Minimum macOS 13
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.4")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -54,6 +54,13 @@ else()
|
||||||
set(IS_RELEASE_BUILD ON)
|
set(IS_RELEASE_BUILD ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_compile_options(
|
||||||
|
/wd4711 # Suppresses `function 'xxxxx' selected for automatic inline expansion` messages
|
||||||
|
/wd5045 # Suppresses `Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified` messages
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# LTO takes too much memory and time using MSVC.
|
# LTO takes too much memory and time using MSVC.
|
||||||
if (NOT MSVC AND IS_RELEASE_BUILD)
|
if (NOT MSVC AND IS_RELEASE_BUILD)
|
||||||
set(DEFAULT_ENABLE_LTO ON)
|
set(DEFAULT_ENABLE_LTO ON)
|
||||||
|
@ -79,7 +86,8 @@ option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
||||||
option(ENABLE_QT_UPDATE_CHECKER "Enable built-in update checker for the Qt frontend" OFF)
|
option(ENABLE_QT_UPDATE_CHECKER "Enable built-in update checker for the Qt frontend" OFF)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT IOS" OFF)
|
CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT IOS" OFF)
|
||||||
CMAKE_DEPENDENT_OPTION(ENABLE_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF)
|
CMAKE_DEPENDENT_OPTION(ENABLE_ROOM "Enable dedicated room functionality" ON "NOT ANDROID AND NOT IOS" OFF)
|
||||||
|
CMAKE_DEPENDENT_OPTION(ENABLE_ROOM_STANDALONE "Enable generating a standalone dedicated room executable" ON "ENABLE_ROOM" OFF)
|
||||||
|
|
||||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||||
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
|
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
|
||||||
|
@ -111,6 +119,9 @@ endif()
|
||||||
if (ENABLE_QT_TRANSLATION)
|
if (ENABLE_QT_TRANSLATION)
|
||||||
add_definitions(-DENABLE_QT_TRANSLATION)
|
add_definitions(-DENABLE_QT_TRANSLATION)
|
||||||
endif()
|
endif()
|
||||||
|
if (ENABLE_ROOM)
|
||||||
|
add_definitions(-DENABLE_ROOM)
|
||||||
|
endif()
|
||||||
if (ENABLE_SDL2_FRONTEND)
|
if (ENABLE_SDL2_FRONTEND)
|
||||||
add_definitions(-DENABLE_SDL2_FRONTEND)
|
add_definitions(-DENABLE_SDL2_FRONTEND)
|
||||||
endif()
|
endif()
|
||||||
|
@ -477,9 +488,8 @@ if (NOT ANDROID AND NOT IOS)
|
||||||
elseif (ENABLE_SDL2_FRONTEND)
|
elseif (ENABLE_SDL2_FRONTEND)
|
||||||
bundle_target(citra_meta)
|
bundle_target(citra_meta)
|
||||||
endif()
|
endif()
|
||||||
|
if (ENABLE_ROOM_STANDALONE)
|
||||||
if (ENABLE_ROOM)
|
bundle_target(citra_room_standalone)
|
||||||
bundle_target(citra_room)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -279,22 +279,12 @@ else()
|
||||||
add_custom_target(bundle)
|
add_custom_target(bundle)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET bundle
|
TARGET bundle
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/")
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/"
|
||||||
|
POST_BUILD)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET bundle
|
TARGET bundle
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/dist/")
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/dist/scripting" "${CMAKE_BINARY_DIR}/bundle/scripting"
|
||||||
add_custom_command(
|
POST_BUILD)
|
||||||
TARGET bundle
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dist/azahar.png" "${CMAKE_BINARY_DIR}/bundle/dist/azahar.png")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET bundle
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/license.txt" "${CMAKE_BINARY_DIR}/bundle/")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET bundle
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/README.md" "${CMAKE_BINARY_DIR}/bundle/")
|
|
||||||
add_custom_command(
|
|
||||||
TARGET bundle
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/dist/scripting" "${CMAKE_BINARY_DIR}/bundle/scripting")
|
|
||||||
|
|
||||||
# On Linux, add a command to prepare linuxdeploy and any required plugins before any bundling occurs.
|
# On Linux, add a command to prepare linuxdeploy and any required plugins before any bundling occurs.
|
||||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
@ -305,7 +295,8 @@ else()
|
||||||
"-DLINUXDEPLOY_PATH=${CMAKE_BINARY_DIR}/externals/linuxdeploy"
|
"-DLINUXDEPLOY_PATH=${CMAKE_BINARY_DIR}/externals/linuxdeploy"
|
||||||
"-DLINUXDEPLOY_ARCH=${CMAKE_HOST_SYSTEM_PROCESSOR}"
|
"-DLINUXDEPLOY_ARCH=${CMAKE_HOST_SYSTEM_PROCESSOR}"
|
||||||
-P "${CMAKE_SOURCE_DIR}/CMakeModules/BundleTarget.cmake"
|
-P "${CMAKE_SOURCE_DIR}/CMakeModules/BundleTarget.cmake"
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
POST_BUILD)
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
26
README.md
|
@ -10,20 +10,20 @@ It was created from the merging of PabloMK7's Citra fork and the Lime3DS project
|
||||||
|
|
||||||
The goal of this project is to be the de-facto platform for future development.
|
The goal of this project is to be the de-facto platform for future development.
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Azahar has not fully released yet. For this reason, there are no compiled binaries available for download.
|
|
||||||
>
|
|
||||||
> It is recommended that only developers and early adopters should use the emulator until our first stable release.
|
|
||||||
>
|
|
||||||
> Here be dragons.
|
|
||||||
|
|
||||||
<!--
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
### Windows & MacOS
|
### Windows
|
||||||
|
|
||||||
Download the latest release from [Releases](https://github.com/azahar-emu/azahar/releases).
|
Download the latest release from [Releases](https://github.com/azahar-emu/azahar/releases).
|
||||||
|
|
||||||
|
If you are unsure of whether you want to use MSYS2 or MSVC, use MSYS2.
|
||||||
|
|
||||||
|
### MacOS
|
||||||
|
|
||||||
|
Download the latest release from [Releases](https://github.com/azahar-emu/azahar/releases).
|
||||||
|
|
||||||
|
The `macos-universal` download will work on both Intel and Apple Silicon Macs.
|
||||||
|
|
||||||
---
|
---
|
||||||
### Android
|
### Android
|
||||||
The recommended method of downloading Azahar on Android is via the [Google Play store](https://play.google.com/store/apps/details?id=io.github.lime3ds.android).
|
The recommended method of downloading Azahar on Android is via the [Google Play store](https://play.google.com/store/apps/details?id=io.github.lime3ds.android).
|
||||||
|
@ -31,7 +31,7 @@ The recommended method of downloading Azahar on Android is via the [Google Play
|
||||||
Alternatively, you can install the app using Obtainium:
|
Alternatively, you can install the app using Obtainium:
|
||||||
1. Download and install Obtainium from [here](https://github.com/ImranR98/Obtainium/releases) (use the file named `app-release.apk`)
|
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'
|
2. Open Obtainium and click 'Add App'
|
||||||
3. Type `https://github.com/azahar/azahar-emu` into the 'App Source URL' section
|
3. Type `https://github.com/azahar-emu/azahar` into the 'App Source URL' section
|
||||||
4. Click 'Add'
|
4. Click 'Add'
|
||||||
5. Click 'Install'
|
5. Click 'Install'
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ Keep in mind that you will not recieve automatic updates when installing via the
|
||||||
|
|
||||||
Azahar is available as an AppImage on the [Releases](https://github.com/azahar-emu/azahar/releases) page.
|
Azahar is available as an AppImage on the [Releases](https://github.com/azahar-emu/azahar/releases) page.
|
||||||
|
|
||||||
|
A Flatpak distribution is currently being worked on.
|
||||||
|
<!--
|
||||||
We are also on Flathub:
|
We are also on Flathub:
|
||||||
|
|
||||||
<a href=https://flathub.org/apps/org.azahar-emu.azahar><img width='180' alt='Download on Flathub' src='https://dl.flathub.org/assets/badges/flathub-badge-en.png'/></a>
|
<a href=https://flathub.org/apps/org.azahar-emu.azahar><img width='180' alt='Download on Flathub' src='https://dl.flathub.org/assets/badges/flathub-badge-en.png'/></a>
|
||||||
|
@ -84,13 +86,13 @@ Below are the minimum requirements to run Azahar:
|
||||||
### Desktop
|
### Desktop
|
||||||
```
|
```
|
||||||
Operating System: Windows 10 (64-bit), MacOS 13 (Ventura), or modern 64-bit Linux
|
Operating System: Windows 10 (64-bit), MacOS 13 (Ventura), or modern 64-bit Linux
|
||||||
CPU: x86-64 (64-bit) CPU. 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
|
||||||
GPU: OpenGL 4.3 or Vulkan 1.1 support
|
GPU: OpenGL 4.3 or Vulkan 1.1 support
|
||||||
Memory: 2GB of RAM. 4GB is recommended
|
Memory: 2GB of RAM. 4GB is recommended
|
||||||
```
|
```
|
||||||
### Android
|
### Android
|
||||||
```
|
```
|
||||||
Operating System: Android 9.0+
|
Operating System: Android 9.0+ (64-bit)
|
||||||
CPU: Snapdragon 835 SoC or better
|
CPU: Snapdragon 835 SoC or better
|
||||||
GPU: OpenGL ES 3.2 or Vulkan 1.1 support
|
GPU: OpenGL ES 3.2 or Vulkan 1.1 support
|
||||||
Memory: 2GB of RAM. 4GB is recommended
|
Memory: 2GB of RAM. 4GB is recommended
|
||||||
|
|
2
dist/compatibility_list
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 955c560089186a86a90b67f0427f6dfdabc1f177
|
Subproject commit b153099f511759824941f5797ca69e2d39e57de3
|
710
dist/languages/ca_ES_valencia.ts
vendored
710
dist/languages/da_DK.ts
vendored
734
dist/languages/de.ts
vendored
710
dist/languages/el.ts
vendored
712
dist/languages/es_ES.ts
vendored
710
dist/languages/fi.ts
vendored
733
dist/languages/fr.ts
vendored
710
dist/languages/hu_HU.ts
vendored
710
dist/languages/id.ts
vendored
716
dist/languages/it.ts
vendored
813
dist/languages/ja_JP.ts
vendored
710
dist/languages/ko_KR.ts
vendored
714
dist/languages/lt_LT.ts
vendored
710
dist/languages/nb.ts
vendored
716
dist/languages/nl.ts
vendored
720
dist/languages/pl_PL.ts
vendored
720
dist/languages/pt_BR.ts
vendored
716
dist/languages/ro_RO.ts
vendored
710
dist/languages/ru_RU.ts
vendored
720
dist/languages/sv.ts
vendored
758
dist/languages/tr_TR.ts
vendored
710
dist/languages/vi_VN.ts
vendored
730
dist/languages/zh_CN.ts
vendored
710
dist/languages/zh_TW.ts
vendored
61
dist/scripting/citra.py
vendored
|
@ -1,15 +1,21 @@
|
||||||
|
# Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
|
# Licensed under GPLv2 or any later version
|
||||||
|
# Refer to the license.txt file included.
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import random
|
import random
|
||||||
import enum
|
import enum
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
CURRENT_REQUEST_VERSION = 1
|
CURRENT_REQUEST_VERSION = 1
|
||||||
MAX_REQUEST_DATA_SIZE = 32
|
MAX_REQUEST_DATA_SIZE = 1024
|
||||||
MAX_PACKET_SIZE = 48
|
MAX_PACKET_SIZE = 1024 + 0x10
|
||||||
|
|
||||||
class RequestType(enum.IntEnum):
|
class RequestType(enum.IntEnum):
|
||||||
ReadMemory = 1,
|
ReadMemory = 1,
|
||||||
WriteMemory = 2
|
WriteMemory = 2,
|
||||||
|
ProcessList = 3,
|
||||||
|
SetGetProcess = 4,
|
||||||
|
|
||||||
CITRA_PORT = 45987
|
CITRA_PORT = 45987
|
||||||
|
|
||||||
|
@ -34,6 +40,55 @@ class Citra:
|
||||||
return raw_reply[4*4:]
|
return raw_reply[4*4:]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def process_list(self):
|
||||||
|
processes = {}
|
||||||
|
read_processes = 0
|
||||||
|
while True:
|
||||||
|
request_data = struct.pack("II", read_processes, 0x7FFFFFFF)
|
||||||
|
request, request_id = self._generate_header(RequestType.ProcessList, len(request_data))
|
||||||
|
request += request_data
|
||||||
|
self.socket.sendto(request, (self.address, CITRA_PORT))
|
||||||
|
|
||||||
|
raw_reply = self.socket.recv(MAX_PACKET_SIZE)
|
||||||
|
reply_data = self._read_and_validate_header(raw_reply, request_id, RequestType.ProcessList)
|
||||||
|
|
||||||
|
if reply_data:
|
||||||
|
read_count = struct.unpack("I", reply_data[0:4])[0]
|
||||||
|
reply_data = reply_data[4:]
|
||||||
|
if read_count == 0:
|
||||||
|
break
|
||||||
|
read_processes += read_count
|
||||||
|
for i in range(read_count):
|
||||||
|
proc_data = reply_data[i * 0x14 : (i + 1) * 0x14]
|
||||||
|
proc_id, title_id, proc_name = struct.unpack("<IQ8s", proc_data)
|
||||||
|
proc_name = proc_name.rstrip(b"\x00").decode("ascii")
|
||||||
|
processes[proc_id] = (title_id, proc_name)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return processes
|
||||||
|
|
||||||
|
def get_process(self):
|
||||||
|
request_data = struct.pack("II", 0, 0)
|
||||||
|
request, request_id = self._generate_header(RequestType.SetGetProcess, len(request_data))
|
||||||
|
request += request_data
|
||||||
|
self.socket.sendto(request, (self.address, CITRA_PORT))
|
||||||
|
|
||||||
|
raw_reply = self.socket.recv(MAX_PACKET_SIZE)
|
||||||
|
reply_data = self._read_and_validate_header(raw_reply, request_id, RequestType.SetGetProcess)
|
||||||
|
|
||||||
|
if reply_data:
|
||||||
|
return struct.unpack("I", reply_data)[0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_process(self, process_id):
|
||||||
|
request_data = struct.pack("II", 1, process_id)
|
||||||
|
request, request_id = self._generate_header(RequestType.SetGetProcess, len(request_data))
|
||||||
|
request += request_data
|
||||||
|
self.socket.sendto(request, (self.address, CITRA_PORT))
|
||||||
|
|
||||||
|
self.socket.recv(MAX_PACKET_SIZE)
|
||||||
|
|
||||||
def read_memory(self, read_address, read_size):
|
def read_memory(self, read_address, read_size):
|
||||||
"""
|
"""
|
||||||
>>> c.read_memory(0x100000, 4)
|
>>> c.read_memory(0x100000, 4)
|
||||||
|
|
2
externals/discord-rpc
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 54eb03c20351f94850bfca3955cb87465a860ef6
|
Subproject commit cb50201fc09290cd078c7ab27917504491f7f96a
|
2
externals/sdl2/SDL
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 9e079fe9c7931738ed63d257b1d7fb8a07b66824
|
Subproject commit 2359383fc187386204c3bb22de89655a494cd128
|
|
@ -199,6 +199,10 @@ if (ENABLE_ROOM)
|
||||||
add_subdirectory(citra_room)
|
add_subdirectory(citra_room)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_ROOM_STANDALONE)
|
||||||
|
add_subdirectory(citra_room_standalone)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
add_subdirectory(android/app/src/main/jni)
|
add_subdirectory(android/app/src/main/jni)
|
||||||
target_include_directories(citra-android PRIVATE android/app/src/main)
|
target_include_directories(citra-android PRIVATE android/app/src/main)
|
||||||
|
|
|
@ -186,6 +186,10 @@ object NativeLibrary {
|
||||||
|
|
||||||
external fun unlinkConsole()
|
external fun unlinkConsole()
|
||||||
|
|
||||||
|
external fun setTemporaryFrameLimit(speed: Double)
|
||||||
|
|
||||||
|
external fun disableTemporaryFrameLimit()
|
||||||
|
|
||||||
private var coreErrorAlertResult = false
|
private var coreErrorAlertResult = false
|
||||||
private val coreErrorAlertLock = Object()
|
private val coreErrorAlertLock = Object()
|
||||||
|
|
||||||
|
@ -773,6 +777,7 @@ object NativeLibrary {
|
||||||
const val BUTTON_DEBUG = 781
|
const val BUTTON_DEBUG = 781
|
||||||
const val BUTTON_GPIO14 = 782
|
const val BUTTON_GPIO14 = 782
|
||||||
const val BUTTON_SWAP = 800
|
const val BUTTON_SWAP = 800
|
||||||
|
const val BUTTON_TURBO = 801
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import android.os.Bundle
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
@ -44,6 +45,7 @@ import org.citra.citra_emu.utils.FileBrowserHelper
|
||||||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||||
import org.citra.citra_emu.utils.ThemeUtil
|
import org.citra.citra_emu.utils.ThemeUtil
|
||||||
|
import org.citra.citra_emu.utils.TurboHelper
|
||||||
import org.citra.citra_emu.viewmodel.EmulationViewModel
|
import org.citra.citra_emu.viewmodel.EmulationViewModel
|
||||||
|
|
||||||
class EmulationActivity : AppCompatActivity() {
|
class EmulationActivity : AppCompatActivity() {
|
||||||
|
@ -51,7 +53,7 @@ class EmulationActivity : AppCompatActivity() {
|
||||||
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||||
var isActivityRecreated = false
|
var isActivityRecreated = false
|
||||||
private val emulationViewModel: EmulationViewModel by viewModels()
|
private val emulationViewModel: EmulationViewModel by viewModels()
|
||||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var binding: ActivityEmulationBinding
|
private lateinit var binding: ActivityEmulationBinding
|
||||||
private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil
|
private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil
|
||||||
|
@ -67,6 +69,8 @@ class EmulationActivity : AppCompatActivity() {
|
||||||
private var isEmulationRunning: Boolean = false
|
private var isEmulationRunning: Boolean = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
|
||||||
ThemeUtil.setTheme(this)
|
ThemeUtil.setTheme(this)
|
||||||
|
|
||||||
settingsViewModel.settings.loadSettings()
|
settingsViewModel.settings.loadSettings()
|
||||||
|
@ -192,9 +196,16 @@ class EmulationActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enableFullscreenImmersive() {
|
private fun enableFullscreenImmersive() {
|
||||||
// TODO: Remove this once we properly account for display insets in the input overlay
|
val attributes = window.attributes
|
||||||
window.attributes.layoutInDisplayCutoutMode =
|
|
||||||
|
attributes.layoutInDisplayCutoutMode =
|
||||||
|
if (BooleanSetting.EXPAND_TO_CUTOUT_AREA.boolean) {
|
||||||
|
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||||
|
} else {
|
||||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
||||||
|
}
|
||||||
|
|
||||||
|
window.attributes = attributes
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
package org.citra.citra_emu.adapters
|
package org.citra.citra_emu.adapters
|
||||||
|
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
@ -28,6 +29,7 @@ import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import android.widget.PopupMenu
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
|
@ -44,7 +46,9 @@ import org.citra.citra_emu.databinding.CardGameBinding
|
||||||
import org.citra.citra_emu.features.cheats.ui.CheatsFragmentDirections
|
import org.citra.citra_emu.features.cheats.ui.CheatsFragmentDirections
|
||||||
import org.citra.citra_emu.features.settings.ui.SettingsActivity
|
import org.citra.citra_emu.features.settings.ui.SettingsActivity
|
||||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||||
|
import org.citra.citra_emu.fragments.IndeterminateProgressDialogFragment
|
||||||
import org.citra.citra_emu.model.Game
|
import org.citra.citra_emu.model.Game
|
||||||
|
import org.citra.citra_emu.utils.FileUtil
|
||||||
import org.citra.citra_emu.utils.GameIconUtils
|
import org.citra.citra_emu.utils.GameIconUtils
|
||||||
import org.citra.citra_emu.viewmodel.GamesViewModel
|
import org.citra.citra_emu.viewmodel.GamesViewModel
|
||||||
|
|
||||||
|
@ -203,6 +207,117 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class GameDirectories(
|
||||||
|
val gameDir: String,
|
||||||
|
val saveDir: String,
|
||||||
|
val modsDir: String,
|
||||||
|
val texturesDir: String,
|
||||||
|
val appDir: String,
|
||||||
|
val dlcDir: String,
|
||||||
|
val updatesDir: String,
|
||||||
|
val extraDir: String
|
||||||
|
)
|
||||||
|
private fun getGameDirectories(game: Game): GameDirectories {
|
||||||
|
val basePath = "sdmc/Nintendo 3DS/00000000000000000000000000000000/00000000000000000000000000000000"
|
||||||
|
return GameDirectories(
|
||||||
|
gameDir = game.path.substringBeforeLast("/"),
|
||||||
|
saveDir = basePath + "/title/${String.format("%016x", game.titleId).lowercase().substring(0, 8)}/${String.format("%016x", game.titleId).lowercase().substring(8)}/data/00000001",
|
||||||
|
modsDir = "load/mods/${String.format("%016X", game.titleId)}",
|
||||||
|
texturesDir = "load/textures/${String.format("%016X", game.titleId)}",
|
||||||
|
appDir = game.path.substringBeforeLast("/").split("/").filter { it.isNotEmpty() }.joinToString("/"),
|
||||||
|
dlcDir = basePath + "/title/0004008c/${String.format("%016x", game.titleId).lowercase().substring(8)}/content",
|
||||||
|
updatesDir = basePath + "/title/0004000e/${String.format("%016x", game.titleId).lowercase().substring(8)}/content",
|
||||||
|
extraDir = basePath + "/extdata/00000000/${String.format("%016X", game.titleId).substring(8, 14).padStart(8, '0')}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showOpenContextMenu(view: View, game: Game) {
|
||||||
|
val dirs = getGameDirectories(game)
|
||||||
|
|
||||||
|
val popup = PopupMenu(view.context, view).apply {
|
||||||
|
menuInflater.inflate(R.menu.game_context_menu_open, menu)
|
||||||
|
listOf(
|
||||||
|
R.id.game_context_open_app to dirs.appDir,
|
||||||
|
R.id.game_context_open_save_dir to dirs.saveDir,
|
||||||
|
R.id.game_context_open_updates to dirs.updatesDir,
|
||||||
|
R.id.game_context_open_dlc to dirs.dlcDir,
|
||||||
|
R.id.game_context_open_extra to dirs.extraDir
|
||||||
|
).forEach { (id, dir) ->
|
||||||
|
menu.findItem(id)?.isEnabled =
|
||||||
|
CitraApplication.documentsTree.folderUriHelper(dir)?.let {
|
||||||
|
DocumentFile.fromTreeUri(view.context, it)?.exists()
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.setOnMenuItemClickListener { menuItem ->
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
.setType("*/*")
|
||||||
|
|
||||||
|
val uri = when (menuItem.itemId) {
|
||||||
|
R.id.game_context_open_app -> CitraApplication.documentsTree.folderUriHelper(dirs.appDir)
|
||||||
|
R.id.game_context_open_save_dir -> CitraApplication.documentsTree.folderUriHelper(dirs.saveDir)
|
||||||
|
R.id.game_context_open_updates -> CitraApplication.documentsTree.folderUriHelper(dirs.updatesDir)
|
||||||
|
R.id.game_context_open_dlc -> CitraApplication.documentsTree.folderUriHelper(dirs.dlcDir)
|
||||||
|
R.id.game_context_open_extra -> CitraApplication.documentsTree.folderUriHelper(dirs.extraDir)
|
||||||
|
R.id.game_context_open_textures -> CitraApplication.documentsTree.folderUriHelper(dirs.texturesDir, true)
|
||||||
|
R.id.game_context_open_mods -> CitraApplication.documentsTree.folderUriHelper(dirs.modsDir, true)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
uri?.let {
|
||||||
|
intent.data = it
|
||||||
|
view.context.startActivity(intent)
|
||||||
|
true
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUninstallContextMenu(view: View, game: Game, bottomSheetDialog: BottomSheetDialog) {
|
||||||
|
val dirs = getGameDirectories(game)
|
||||||
|
val popup = PopupMenu(view.context, view).apply {
|
||||||
|
menuInflater.inflate(R.menu.game_context_menu_uninstall, menu)
|
||||||
|
listOf(
|
||||||
|
R.id.game_context_uninstall to dirs.gameDir,
|
||||||
|
R.id.game_context_uninstall_dlc to dirs.dlcDir,
|
||||||
|
R.id.game_context_uninstall_updates to dirs.updatesDir
|
||||||
|
).forEach { (id, dir) ->
|
||||||
|
menu.findItem(id)?.isEnabled =
|
||||||
|
CitraApplication.documentsTree.folderUriHelper(dir)?.let {
|
||||||
|
DocumentFile.fromTreeUri(view.context, it)?.exists()
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.setOnMenuItemClickListener { menuItem ->
|
||||||
|
val uninstallAction: () -> Unit = {
|
||||||
|
when (menuItem.itemId) {
|
||||||
|
R.id.game_context_uninstall -> CitraApplication.documentsTree.deleteDocument(dirs.gameDir)
|
||||||
|
R.id.game_context_uninstall_dlc -> FileUtil.deleteDocument(CitraApplication.documentsTree.folderUriHelper(dirs.dlcDir)
|
||||||
|
.toString())
|
||||||
|
R.id.game_context_uninstall_updates -> FileUtil.deleteDocument(CitraApplication.documentsTree.folderUriHelper(dirs.updatesDir)
|
||||||
|
.toString())
|
||||||
|
}
|
||||||
|
ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true)
|
||||||
|
bottomSheetDialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menuItem.itemId in listOf(R.id.game_context_uninstall, R.id.game_context_uninstall_dlc, R.id.game_context_uninstall_updates)) {
|
||||||
|
IndeterminateProgressDialogFragment.newInstance(activity, R.string.uninstalling, false, uninstallAction)
|
||||||
|
.show(activity.supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
popup.show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun showAboutGameDialog(context: Context, game: Game, holder: GameViewHolder, view: View) {
|
private fun showAboutGameDialog(context: Context, game: Game, holder: GameViewHolder, view: View) {
|
||||||
val bottomSheetView = inflater.inflate(R.layout.dialog_about_game, null)
|
val bottomSheetView = inflater.inflate(R.layout.dialog_about_game, null)
|
||||||
|
|
||||||
|
@ -245,6 +360,14 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
|
||||||
bottomSheetDialog.dismiss()
|
bottomSheetDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bottomSheetView.findViewById<MaterialButton>(R.id.menu_button_open).setOnClickListener {
|
||||||
|
showOpenContextMenu(it, game)
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomSheetView.findViewById<MaterialButton>(R.id.menu_button_uninstall).setOnClickListener {
|
||||||
|
showUninstallContextMenu(it, game, bottomSheetDialog)
|
||||||
|
}
|
||||||
|
|
||||||
val bottomSheetBehavior = bottomSheetDialog.getBehavior()
|
val bottomSheetBehavior = bottomSheetDialog.getBehavior()
|
||||||
bottomSheetBehavior.skipCollapsed = true
|
bottomSheetBehavior.skipCollapsed = true
|
||||||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ enum class SmallScreenPosition(val int: Int) {
|
||||||
enum class PortraitScreenLayout(val int: Int) {
|
enum class PortraitScreenLayout(val int: Int) {
|
||||||
// These must match what is defined in src/common/settings.h
|
// These must match what is defined in src/common/settings.h
|
||||||
TOP_FULL_WIDTH(0),
|
TOP_FULL_WIDTH(0),
|
||||||
CUSTOM_PORTRAIT_LAYOUT(1);
|
CUSTOM_PORTRAIT_LAYOUT(1),
|
||||||
|
ORIGINAL(2);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun from(int: Int): PortraitScreenLayout {
|
fun from(int: Int): PortraitScreenLayout {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -10,5 +10,6 @@ enum class Hotkey(val button: Int) {
|
||||||
CLOSE_GAME(10003),
|
CLOSE_GAME(10003),
|
||||||
PAUSE_OR_RESUME(10004),
|
PAUSE_OR_RESUME(10004),
|
||||||
QUICKSAVE(10005),
|
QUICKSAVE(10005),
|
||||||
QUICKLOAD(10006);
|
QUICKLOAD(10006),
|
||||||
|
TURBO_LIMIT(10007);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -9,11 +9,14 @@ import android.widget.Toast
|
||||||
import org.citra.citra_emu.NativeLibrary
|
import org.citra.citra_emu.NativeLibrary
|
||||||
import org.citra.citra_emu.R
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||||
|
import org.citra.citra_emu.utils.TurboHelper
|
||||||
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
||||||
|
|
||||||
class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil, private val context: Context) {
|
class HotkeyUtility(
|
||||||
|
private val screenAdjustmentUtil: ScreenAdjustmentUtil,
|
||||||
|
private val context: Context) {
|
||||||
|
|
||||||
val hotkeyButtons = Hotkey.entries.map { it.button }
|
private val hotkeyButtons = Hotkey.entries.map { it.button }
|
||||||
|
|
||||||
fun handleHotkey(bindedButton: Int): Boolean {
|
fun handleHotkey(bindedButton: Int): Boolean {
|
||||||
if(hotkeyButtons.contains(bindedButton)) {
|
if(hotkeyButtons.contains(bindedButton)) {
|
||||||
|
@ -22,16 +25,17 @@ class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil, priv
|
||||||
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
||||||
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
||||||
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
||||||
|
Hotkey.TURBO_LIMIT.button -> TurboHelper.setTurboEnabled(!TurboHelper.isTurboSpeedEnabled())
|
||||||
Hotkey.QUICKSAVE.button -> {
|
Hotkey.QUICKSAVE.button -> {
|
||||||
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
||||||
Toast.makeText(context,
|
Toast.makeText(context,
|
||||||
context.getString(R.string.quicksave_saving),
|
context.getString(R.string.saving),
|
||||||
Toast.LENGTH_SHORT).show()
|
Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
Hotkey.QUICKLOAD.button -> {
|
Hotkey.QUICKLOAD.button -> {
|
||||||
val wasLoaded = NativeLibrary.loadStateIfAvailable(NativeLibrary.QUICKSAVE_SLOT)
|
val wasLoaded = NativeLibrary.loadStateIfAvailable(NativeLibrary.QUICKSAVE_SLOT)
|
||||||
val stringRes = if(wasLoaded) {
|
val stringRes = if(wasLoaded) {
|
||||||
R.string.quickload_loading
|
R.string.loading
|
||||||
} else {
|
} else {
|
||||||
R.string.quickload_not_found
|
R.string.quickload_not_found
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ enum class BooleanSetting(
|
||||||
override val section: String,
|
override val section: String,
|
||||||
override val defaultValue: Boolean
|
override val defaultValue: Boolean
|
||||||
) : AbstractBooleanSetting {
|
) : AbstractBooleanSetting {
|
||||||
|
EXPAND_TO_CUTOUT_AREA("expand_to_cutout_area", Settings.SECTION_LAYOUT, false),
|
||||||
SPIRV_SHADER_GEN("spirv_shader_gen", Settings.SECTION_RENDERER, true),
|
SPIRV_SHADER_GEN("spirv_shader_gen", Settings.SECTION_RENDERER, true),
|
||||||
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
|
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
|
||||||
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
||||||
|
|
|
@ -33,6 +33,7 @@ enum class IntSetting(
|
||||||
LANDSCAPE_BOTTOM_Y("custom_bottom_y",Settings.SECTION_LAYOUT,480),
|
LANDSCAPE_BOTTOM_Y("custom_bottom_y",Settings.SECTION_LAYOUT,480),
|
||||||
LANDSCAPE_BOTTOM_WIDTH("custom_bottom_width",Settings.SECTION_LAYOUT,640),
|
LANDSCAPE_BOTTOM_WIDTH("custom_bottom_width",Settings.SECTION_LAYOUT,640),
|
||||||
LANDSCAPE_BOTTOM_HEIGHT("custom_bottom_height",Settings.SECTION_LAYOUT,480),
|
LANDSCAPE_BOTTOM_HEIGHT("custom_bottom_height",Settings.SECTION_LAYOUT,480),
|
||||||
|
SCREEN_GAP("screen_gap",Settings.SECTION_LAYOUT,0),
|
||||||
PORTRAIT_SCREEN_LAYOUT("portrait_layout_option",Settings.SECTION_LAYOUT,0),
|
PORTRAIT_SCREEN_LAYOUT("portrait_layout_option",Settings.SECTION_LAYOUT,0),
|
||||||
PORTRAIT_TOP_X("custom_portrait_top_x",Settings.SECTION_LAYOUT,0),
|
PORTRAIT_TOP_X("custom_portrait_top_x",Settings.SECTION_LAYOUT,0),
|
||||||
PORTRAIT_TOP_Y("custom_portrait_top_y",Settings.SECTION_LAYOUT,0),
|
PORTRAIT_TOP_Y("custom_portrait_top_y",Settings.SECTION_LAYOUT,0),
|
||||||
|
@ -65,7 +66,9 @@ enum class IntSetting(
|
||||||
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
|
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
|
||||||
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0),
|
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0),
|
||||||
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
|
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
|
||||||
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0);
|
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0),
|
||||||
|
TURBO_LIMIT("turbo_limit", Settings.SECTION_CORE, 200);
|
||||||
|
|
||||||
override var int: Int = defaultValue
|
override var int: Int = defaultValue
|
||||||
|
|
||||||
override val valueAsString: String
|
override val valueAsString: String
|
||||||
|
@ -94,7 +97,7 @@ enum class IntSetting(
|
||||||
ASYNC_CUSTOM_LOADING,
|
ASYNC_CUSTOM_LOADING,
|
||||||
AUDIO_INPUT_TYPE,
|
AUDIO_INPUT_TYPE,
|
||||||
USE_ARTIC_BASE_CONTROLLER,
|
USE_ARTIC_BASE_CONTROLLER,
|
||||||
SHADERS_ACCURATE_MUL,
|
SHADERS_ACCURATE_MUL
|
||||||
)
|
)
|
||||||
|
|
||||||
fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
|
fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -139,6 +139,7 @@ class Settings {
|
||||||
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
||||||
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
||||||
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
||||||
|
const val HOTKEY_TURBO_LIMIT = "hotkey_turbo_limit"
|
||||||
|
|
||||||
val buttonKeys = listOf(
|
val buttonKeys = listOf(
|
||||||
KEY_BUTTON_A,
|
KEY_BUTTON_A,
|
||||||
|
@ -204,7 +205,8 @@ class Settings {
|
||||||
HOTKEY_CLOSE_GAME,
|
HOTKEY_CLOSE_GAME,
|
||||||
HOTKEY_PAUSE_OR_RESUME,
|
HOTKEY_PAUSE_OR_RESUME,
|
||||||
HOTKEY_QUICKSAVE,
|
HOTKEY_QUICKSAVE,
|
||||||
HOTKEY_QUICKlOAD
|
HOTKEY_QUICKlOAD,
|
||||||
|
HOTKEY_TURBO_LIMIT
|
||||||
)
|
)
|
||||||
val hotkeyTitles = listOf(
|
val hotkeyTitles = listOf(
|
||||||
R.string.emulation_swap_screens,
|
R.string.emulation_swap_screens,
|
||||||
|
@ -213,6 +215,7 @@ class Settings {
|
||||||
R.string.emulation_toggle_pause,
|
R.string.emulation_toggle_pause,
|
||||||
R.string.emulation_quicksave,
|
R.string.emulation_quicksave,
|
||||||
R.string.emulation_quickload,
|
R.string.emulation_quickload,
|
||||||
|
R.string.turbo_limit_hotkey
|
||||||
)
|
)
|
||||||
|
|
||||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||||
|
|
|
@ -12,7 +12,8 @@ class DateTimeSetting(
|
||||||
titleId: Int,
|
titleId: Int,
|
||||||
descriptionId: Int,
|
descriptionId: Int,
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
private val defaultValue: String? = null
|
private val defaultValue: String? = null,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_DATETIME_SETTING
|
override val type = TYPE_DATETIME_SETTING
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ class InputBindingSetting(
|
||||||
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
||||||
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
||||||
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
||||||
|
Settings.HOTKEY_TURBO_LIMIT -> Hotkey.TURBO_LIMIT.button
|
||||||
else -> -1
|
else -> -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -28,6 +28,13 @@ abstract class SettingsItem(
|
||||||
return setting?.isRuntimeEditable ?: false
|
return setting?.isRuntimeEditable ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open var isEnabled: Boolean = true
|
||||||
|
|
||||||
|
val isActive: Boolean
|
||||||
|
get() {
|
||||||
|
return this.isEditable && this.isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE_HEADER = 0
|
const val TYPE_HEADER = 0
|
||||||
const val TYPE_SWITCH = 1
|
const val TYPE_SWITCH = 1
|
||||||
|
|
|
@ -15,7 +15,8 @@ class SingleChoiceSetting(
|
||||||
val choicesId: Int,
|
val choicesId: Int,
|
||||||
val valuesId: Int,
|
val valuesId: Int,
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
val defaultValue: Int? = null
|
val defaultValue: Int? = null,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_SINGLE_CHOICE
|
override val type = TYPE_SINGLE_CHOICE
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ class SliderSetting(
|
||||||
val max: Int,
|
val max: Int,
|
||||||
val units: String,
|
val units: String,
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
val defaultValue: Float? = null
|
val defaultValue: Float? = null,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_SLIDER
|
override val type = TYPE_SLIDER
|
||||||
val selectedFloat: Float
|
val selectedFloat: Float
|
||||||
|
|
|
@ -12,7 +12,8 @@ class StringInputSetting(
|
||||||
titleId: Int,
|
titleId: Int,
|
||||||
descriptionId: Int,
|
descriptionId: Int,
|
||||||
val defaultValue: String,
|
val defaultValue: String,
|
||||||
val characterLimit: Int = 0
|
val characterLimit: Int = 0,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_STRING_INPUT
|
override val type = TYPE_STRING_INPUT
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ class StringSingleChoiceSetting(
|
||||||
val choices: Array<String>,
|
val choices: Array<String>,
|
||||||
val values: Array<String>?,
|
val values: Array<String>?,
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
private val defaultValue: String? = null
|
private val defaultValue: String? = null,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_STRING_SINGLE_CHOICE
|
override val type = TYPE_STRING_SINGLE_CHOICE
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ class SwitchSetting(
|
||||||
titleId: Int,
|
titleId: Int,
|
||||||
descriptionId: Int,
|
descriptionId: Int,
|
||||||
val key: String? = null,
|
val key: String? = null,
|
||||||
val defaultValue: Any? = null
|
val defaultValue: Any? = null,
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
) : SettingsItem(setting, titleId, descriptionId) {
|
) : SettingsItem(setting, titleId, descriptionId) {
|
||||||
override val type = TYPE_SWITCH
|
override val type = TYPE_SWITCH
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.citra.citra_emu.features.settings.model.Settings
|
||||||
import org.citra.citra_emu.utils.SystemSaveGame
|
import org.citra.citra_emu.utils.SystemSaveGame
|
||||||
import org.citra.citra_emu.utils.DirectoryInitialization
|
import org.citra.citra_emu.utils.DirectoryInitialization
|
||||||
import org.citra.citra_emu.utils.Log
|
import org.citra.citra_emu.utils.Log
|
||||||
|
import org.citra.citra_emu.utils.TurboHelper
|
||||||
|
|
||||||
class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
|
class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
|
||||||
val settings: Settings get() = activityView.settings
|
val settings: Settings get() = activityView.settings
|
||||||
|
@ -66,6 +67,7 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
|
||||||
//added to ensure that layout changes take effect as soon as settings window closes
|
//added to ensure that layout changes take effect as soon as settings window closes
|
||||||
NativeLibrary.reloadSettings()
|
NativeLibrary.reloadSettings()
|
||||||
NativeLibrary.updateFramebuffer(NativeLibrary.isPortraitMode)
|
NativeLibrary.updateFramebuffer(NativeLibrary.isPortraitMode)
|
||||||
|
TurboHelper.reloadTurbo() // TODO: Can this go someone else? -OS
|
||||||
}
|
}
|
||||||
NativeLibrary.reloadSettings()
|
NativeLibrary.reloadSettings()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ package org.citra.citra_emu.features.settings.ui
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.graphics.Color
|
|
||||||
import android.icu.util.Calendar
|
import android.icu.util.Calendar
|
||||||
import android.icu.util.TimeZone
|
import android.icu.util.TimeZone
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
|
@ -17,11 +16,11 @@ import android.text.TextWatcher
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker
|
import com.google.android.material.datepicker.MaterialDatePicker
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
@ -66,7 +65,6 @@ import org.citra.citra_emu.features.settings.ui.viewholder.SwitchSettingViewHold
|
||||||
import org.citra.citra_emu.fragments.MessageDialogFragment
|
import org.citra.citra_emu.fragments.MessageDialogFragment
|
||||||
import org.citra.citra_emu.fragments.MotionBottomSheetDialogFragment
|
import org.citra.citra_emu.fragments.MotionBottomSheetDialogFragment
|
||||||
import org.citra.citra_emu.utils.SystemSaveGame
|
import org.citra.citra_emu.utils.SystemSaveGame
|
||||||
import java.lang.IllegalStateException
|
|
||||||
import java.lang.NumberFormatException
|
import java.lang.NumberFormatException
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
@ -153,15 +151,71 @@ class SettingsAdapter(
|
||||||
return getItem(position)?.type ?: -1
|
return getItem(position)?.type ?: -1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSettingsList(settings: ArrayList<SettingsItem>?) {
|
fun setSettingsList(newSettings: ArrayList<SettingsItem>?) {
|
||||||
this.settings = settings ?: arrayListOf()
|
if (settings == null) {
|
||||||
|
settings = newSettings ?: arrayListOf()
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val oldSettings = settings
|
||||||
|
val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
|
||||||
|
override fun getOldListSize() = oldSettings?.size ?: 0
|
||||||
|
override fun getNewListSize() = newSettings?.size ?: 0
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||||
|
val oldItem = oldSettings?.get(oldItemPosition)?.setting
|
||||||
|
val newItem = newSettings?.get(newItemPosition)?.setting
|
||||||
|
return oldItem?.key == newItem?.key
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||||
|
val oldItem = oldSettings?.get(oldItemPosition)
|
||||||
|
val newItem = newSettings?.get(newItemPosition)
|
||||||
|
|
||||||
|
if (oldItem == null || newItem == null || oldItem.type != newItem.type) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (oldItem.type) {
|
||||||
|
SettingsItem.TYPE_SLIDER -> {
|
||||||
|
(oldItem as SliderSetting).isEnabled == (newItem as SliderSetting).isEnabled
|
||||||
|
}
|
||||||
|
SettingsItem.TYPE_SWITCH -> {
|
||||||
|
(oldItem as SwitchSetting).isEnabled == (newItem as SwitchSetting).isEnabled
|
||||||
|
}
|
||||||
|
SettingsItem.TYPE_SINGLE_CHOICE -> {
|
||||||
|
(oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled
|
||||||
|
}
|
||||||
|
SettingsItem.TYPE_DATETIME_SETTING -> {
|
||||||
|
(oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled
|
||||||
|
}
|
||||||
|
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
|
||||||
|
(oldItem as StringSingleChoiceSetting).isEnabled == (newItem as StringSingleChoiceSetting).isEnabled
|
||||||
|
}
|
||||||
|
SettingsItem.TYPE_STRING_INPUT -> {
|
||||||
|
(oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
oldItem == newItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
settings = newSettings ?: arrayListOf()
|
||||||
|
diffResult.dispatchUpdatesTo(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
|
fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
|
||||||
val setting = item.setChecked(checked)
|
val setting = item.setChecked(checked)
|
||||||
fragmentView.putSetting(setting)
|
fragmentView.putSetting(setting)
|
||||||
fragmentView.onSettingChanged()
|
fragmentView.onSettingChanged()
|
||||||
|
|
||||||
|
// If statement is required otherwise the app will crash on activity recreate ex. theme settings
|
||||||
|
if (fragmentView.activityView != null)
|
||||||
|
// Reload the settings list to update the UI
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSingleChoiceClick(item: SingleChoiceSetting) {
|
private fun onSingleChoiceClick(item: SingleChoiceSetting) {
|
||||||
|
@ -247,6 +301,7 @@ class SettingsAdapter(
|
||||||
notifyItemChanged(clickedPosition)
|
notifyItemChanged(clickedPosition)
|
||||||
val setting = item.setSelectedValue(rtcString)
|
val setting = item.setSelectedValue(rtcString)
|
||||||
fragmentView.putSetting(setting)
|
fragmentView.putSetting(setting)
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
clickedItem = null
|
clickedItem = null
|
||||||
}
|
}
|
||||||
datePicker.show(
|
datePicker.show(
|
||||||
|
@ -402,6 +457,7 @@ class SettingsAdapter(
|
||||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||||
}
|
}
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,6 +481,7 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,6 +504,7 @@ class SettingsAdapter(
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,6 +517,7 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
val setting = it.setSelectedValue(textInputValue ?: "")
|
val setting = it.setSelectedValue(textInputValue ?: "")
|
||||||
fragmentView?.putSetting(setting)
|
fragmentView?.putSetting(setting)
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
closeDialog()
|
closeDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,6 +547,7 @@ class SettingsAdapter(
|
||||||
}
|
}
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
fragmentView.onSettingChanged()
|
fragmentView.onSettingChanged()
|
||||||
|
fragmentView.loadSettingsList()
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.show()
|
.show()
|
||||||
|
@ -495,10 +555,19 @@ class SettingsAdapter(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onClickDisabledSetting() {
|
fun onClickDisabledSetting(isRuntimeDisabled: Boolean) {
|
||||||
MessageDialogFragment.newInstance(
|
val titleId = if (isRuntimeDisabled)
|
||||||
R.string.setting_not_editable,
|
R.string.setting_not_editable
|
||||||
|
else
|
||||||
|
R.string.setting_disabled
|
||||||
|
val messageId = if (isRuntimeDisabled)
|
||||||
R.string.setting_not_editable_description
|
R.string.setting_not_editable_description
|
||||||
|
else
|
||||||
|
R.string.setting_disabled_description
|
||||||
|
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId,
|
||||||
|
messageId
|
||||||
).show((fragmentView as SettingsFragment).childFragmentManager, MessageDialogFragment.TAG)
|
).show((fragmentView as SettingsFragment).childFragmentManager, MessageDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
IntSetting.FRAME_LIMIT.defaultValue.toFloat()
|
IntSetting.FRAME_LIMIT.defaultValue.toFloat()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SliderSetting(
|
||||||
|
IntSetting.TURBO_LIMIT,
|
||||||
|
R.string.turbo_limit,
|
||||||
|
R.string.turbo_limit_description,
|
||||||
|
100,
|
||||||
|
400,
|
||||||
|
"%",
|
||||||
|
IntSetting.TURBO_LIMIT.key,
|
||||||
|
IntSetting.TURBO_LIMIT.defaultValue.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +538,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
DateTimeSetting(
|
DateTimeSetting(
|
||||||
StringSetting.INIT_TIME,
|
StringSetting.INIT_TIME,
|
||||||
R.string.simulated_clock,
|
R.string.simulated_clock,
|
||||||
R.string.init_time_description,
|
R.string.simulated_clock_description,
|
||||||
StringSetting.INIT_TIME.key,
|
StringSetting.INIT_TIME.key,
|
||||||
StringSetting.INIT_TIME.defaultValue
|
StringSetting.INIT_TIME.defaultValue
|
||||||
)
|
)
|
||||||
|
@ -914,7 +926,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
R.string.factor3d,
|
R.string.factor3d,
|
||||||
R.string.factor3d_description,
|
R.string.factor3d_description,
|
||||||
0,
|
0,
|
||||||
100,
|
255,
|
||||||
"%",
|
"%",
|
||||||
IntSetting.STEREOSCOPIC_3D_DEPTH.key,
|
IntSetting.STEREOSCOPIC_3D_DEPTH.key,
|
||||||
IntSetting.STEREOSCOPIC_3D_DEPTH.defaultValue.toFloat()
|
IntSetting.STEREOSCOPIC_3D_DEPTH.defaultValue.toFloat()
|
||||||
|
@ -1038,6 +1050,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
IntSetting.ORIENTATION_OPTION.defaultValue
|
IntSetting.ORIENTATION_OPTION.defaultValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.EXPAND_TO_CUTOUT_AREA,
|
||||||
|
R.string.expand_to_cutout_area,
|
||||||
|
R.string.expand_to_cutout_area_description,
|
||||||
|
BooleanSetting.EXPAND_TO_CUTOUT_AREA.key,
|
||||||
|
BooleanSetting.EXPAND_TO_CUTOUT_AREA.defaultValue
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.SCREEN_LAYOUT,
|
IntSetting.SCREEN_LAYOUT,
|
||||||
|
@ -1071,6 +1092,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
IntSetting.SMALL_SCREEN_POSITION.defaultValue
|
IntSetting.SMALL_SCREEN_POSITION.defaultValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SliderSetting(
|
||||||
|
IntSetting.SCREEN_GAP,
|
||||||
|
R.string.screen_gap,
|
||||||
|
R.string.screen_gap_description,
|
||||||
|
0,
|
||||||
|
480,
|
||||||
|
"px",
|
||||||
|
IntSetting.SCREEN_GAP.key,
|
||||||
|
IntSetting.SCREEN_GAP.defaultValue.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
SliderSetting(
|
SliderSetting(
|
||||||
FloatSetting.LARGE_SCREEN_PROPORTION,
|
FloatSetting.LARGE_SCREEN_PROPORTION,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||||
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
||||||
|
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
binding.textSettingName.alpha = 1f
|
binding.textSettingName.alpha = 1f
|
||||||
binding.textSettingDescription.alpha = 1f
|
binding.textSettingDescription.alpha = 1f
|
||||||
binding.textSettingValue.alpha = 1f
|
binding.textSettingValue.alpha = 1f
|
||||||
|
@ -59,18 +59,18 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
adapter.onDateTimeClick(setting, bindingAdapterPosition)
|
adapter.onDateTimeClick(setting, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(clicked: View): Boolean {
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class InputBindingSettingViewHolder(val binding: ListItemSettingBinding, adapter
|
||||||
if (setting.isEditable) {
|
if (setting.isEditable) {
|
||||||
adapter.onInputBindingClick(setting, bindingAdapterPosition)
|
adapter.onInputBindingClick(setting, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class InputBindingSettingViewHolder(val binding: ListItemSettingBinding, adapter
|
||||||
if (setting.isEditable) {
|
if (setting.isEditable) {
|
||||||
adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (!setting.isRuntimeRunnable && EmulationActivity.isRunning()) {
|
if (!setting.isRuntimeRunnable && EmulationActivity.isRunning()) {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(true)
|
||||||
} else {
|
} else {
|
||||||
setting.runnable.invoke()
|
setting.runnable.invoke()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
binding.textSettingValue.visibility = View.VISIBLE
|
||||||
binding.textSettingValue.text = getTextSetting()
|
binding.textSettingValue.text = getTextSetting()
|
||||||
|
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
binding.textSettingName.alpha = 1f
|
binding.textSettingName.alpha = 1f
|
||||||
binding.textSettingDescription.alpha = 1f
|
binding.textSettingDescription.alpha = 1f
|
||||||
binding.textSettingValue.alpha = 1f
|
binding.textSettingValue.alpha = 1f
|
||||||
|
@ -65,8 +65,8 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (!setting.isEditable) {
|
if (!setting.isEditable || !setting.isEnabled) {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +84,10 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(clicked: View): Boolean {
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
||||||
else -> "${(setting.setting as AbstractIntSetting).int}${setting.units}"
|
else -> "${(setting.setting as AbstractIntSetting).int}${setting.units}"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
binding.textSettingName.alpha = 1f
|
binding.textSettingName.alpha = 1f
|
||||||
binding.textSettingDescription.alpha = 1f
|
binding.textSettingDescription.alpha = 1f
|
||||||
binding.textSettingValue.alpha = 1f
|
binding.textSettingValue.alpha = 1f
|
||||||
|
@ -47,18 +47,18 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
adapter.onSliderClick(setting, bindingAdapterPosition)
|
adapter.onSliderClick(setting, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(clicked: View): Boolean {
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -25,21 +25,31 @@ class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: Settin
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
binding.textSettingValue.visibility = View.VISIBLE
|
||||||
binding.textSettingValue.text = setting.setting?.valueAsString
|
binding.textSettingValue.text = setting.setting?.valueAsString
|
||||||
|
|
||||||
|
if (setting.isActive) {
|
||||||
|
binding.textSettingName.alpha = 1f
|
||||||
|
binding.textSettingDescription.alpha = 1f
|
||||||
|
binding.textSettingValue.alpha = 1f
|
||||||
|
} else {
|
||||||
|
binding.textSettingName.alpha = 0.5f
|
||||||
|
binding.textSettingDescription.alpha = 0.5f
|
||||||
|
binding.textSettingValue.alpha = 0.5f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (!setting.isEditable) {
|
if (!setting.isEditable || !setting.isEnabled) {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
adapter.onStringInputClick((setting as StringInputSetting), bindingAdapterPosition)
|
adapter.onStringInputClick((setting as StringInputSetting), bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(clicked: View): Boolean {
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -33,26 +33,26 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
|
||||||
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.switchWidget.isEnabled = setting.isEditable
|
binding.switchWidget.isEnabled = setting.isActive
|
||||||
|
|
||||||
val textAlpha = if (setting.isEditable) 1f else 0.5f
|
val textAlpha = if (setting.isActive) 1f else 0.5f
|
||||||
binding.textSettingName.alpha = textAlpha
|
binding.textSettingName.alpha = textAlpha
|
||||||
binding.textSettingDescription.alpha = textAlpha
|
binding.textSettingDescription.alpha = textAlpha
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
binding.switchWidget.toggle()
|
binding.switchWidget.toggle()
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(clicked: View): Boolean {
|
override fun onLongClick(clicked: View): Boolean {
|
||||||
if (setting.isEditable) {
|
if (setting.isActive) {
|
||||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||||
} else {
|
} else {
|
||||||
adapter.onClickDisabledSetting()
|
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import android.view.Surface
|
||||||
import android.view.SurfaceHolder
|
import android.view.SurfaceHolder
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
@ -232,8 +233,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
|
binding.inGameMenu.getHeaderView(0).apply {
|
||||||
game.title
|
val titleView = findViewById<TextView>(R.id.text_game_title)
|
||||||
|
val iconView = findViewById<ImageView>(R.id.game_icon)
|
||||||
|
|
||||||
|
titleView.text = game.title
|
||||||
|
|
||||||
|
GameIconUtils.loadGameIcon(requireActivity(), game, iconView)
|
||||||
|
}
|
||||||
|
|
||||||
binding.inGameMenu.setNavigationItemSelectedListener {
|
binding.inGameMenu.setNavigationItemSelectedListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.menu_emulation_pause -> {
|
R.id.menu_emulation_pause -> {
|
||||||
|
@ -447,6 +455,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
Choreographer.getInstance().postFrameCallback(this)
|
Choreographer.getInstance().postFrameCallback(this)
|
||||||
if (NativeLibrary.isRunning()) {
|
if (NativeLibrary.isRunning()) {
|
||||||
NativeLibrary.unPauseEmulation()
|
NativeLibrary.unPauseEmulation()
|
||||||
|
binding.inGameMenu.menu.findItem(R.id.menu_emulation_pause)?.let { menuItem ->
|
||||||
|
menuItem.title = resources.getString(R.string.pause_emulation)
|
||||||
|
menuItem.icon = ResourcesCompat.getDrawable(
|
||||||
|
resources,
|
||||||
|
R.drawable.ic_pause,
|
||||||
|
requireContext().theme
|
||||||
|
)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +549,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
val slot = i
|
val slot = i
|
||||||
var enableClick = isSaving
|
var enableClick = isSaving
|
||||||
val text = if (slot == NativeLibrary.QUICKSAVE_SLOT) {
|
val text = if (slot == NativeLibrary.QUICKSAVE_SLOT) {
|
||||||
enableClick = false
|
|
||||||
getString(R.string.emulation_quicksave_slot)
|
getString(R.string.emulation_quicksave_slot)
|
||||||
} else {
|
} else {
|
||||||
getString(R.string.emulation_empty_state_slot, slot)
|
getString(R.string.emulation_empty_state_slot, slot)
|
||||||
|
@ -542,11 +557,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
add(text).setEnabled(enableClick).setOnMenuItemClickListener {
|
add(text).setEnabled(enableClick).setOnMenuItemClickListener {
|
||||||
if(isSaving) {
|
if(isSaving) {
|
||||||
NativeLibrary.saveState(slot)
|
NativeLibrary.saveState(slot)
|
||||||
|
Toast.makeText(context,
|
||||||
|
getString(R.string.saving),
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
NativeLibrary.loadState(slot)
|
NativeLibrary.loadState(slot)
|
||||||
binding.drawerLayout.close()
|
binding.drawerLayout.close()
|
||||||
Toast.makeText(context,
|
Toast.makeText(context,
|
||||||
getString(R.string.quickload_loading),
|
getString(R.string.loading),
|
||||||
Toast.LENGTH_SHORT).show()
|
Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
@ -557,8 +575,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
savestates?.forEach {
|
savestates?.forEach {
|
||||||
var enableClick = true
|
var enableClick = true
|
||||||
val text = if(it.slot == NativeLibrary.QUICKSAVE_SLOT) {
|
val text = if(it.slot == NativeLibrary.QUICKSAVE_SLOT) {
|
||||||
// do not allow saving in quicksave slot
|
|
||||||
enableClick = !isSaving
|
|
||||||
getString(R.string.emulation_occupied_quicksave_slot, it.time)
|
getString(R.string.emulation_occupied_quicksave_slot, it.time)
|
||||||
} else{
|
} else{
|
||||||
getString(R.string.emulation_occupied_state_slot, it.slot, it.time)
|
getString(R.string.emulation_occupied_state_slot, it.slot, it.time)
|
||||||
|
@ -886,10 +902,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
val layoutOptionMenuItem = when (IntSetting.PORTRAIT_SCREEN_LAYOUT.int) {
|
val layoutOptionMenuItem = when (IntSetting.PORTRAIT_SCREEN_LAYOUT.int) {
|
||||||
PortraitScreenLayout.TOP_FULL_WIDTH.int ->
|
PortraitScreenLayout.TOP_FULL_WIDTH.int ->
|
||||||
R.id.menu_portrait_layout_top_full
|
R.id.menu_portrait_layout_top_full
|
||||||
|
PortraitScreenLayout.ORIGINAL.int ->
|
||||||
|
R.id.menu_portrait_layout_original
|
||||||
PortraitScreenLayout.CUSTOM_PORTRAIT_LAYOUT.int ->
|
PortraitScreenLayout.CUSTOM_PORTRAIT_LAYOUT.int ->
|
||||||
R.id.menu_portrait_layout_custom
|
R.id.menu_portrait_layout_custom
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
R.id.menu_portrait_layout_top_full
|
R.id.menu_portrait_layout_top_full
|
||||||
|
|
||||||
|
@ -904,6 +920,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.menu_portrait_layout_original -> {
|
||||||
|
screenAdjustmentUtil.changePortraitOrientation(PortraitScreenLayout.ORIGINAL.int)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
R.id.menu_portrait_layout_custom -> {
|
R.id.menu_portrait_layout_custom -> {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
|
@ -933,12 +954,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
|
|
||||||
private fun showToggleControlsDialog() {
|
private fun showToggleControlsDialog() {
|
||||||
val editor = preferences.edit()
|
val editor = preferences.edit()
|
||||||
val enabledButtons = BooleanArray(15)
|
val enabledButtons = BooleanArray(16)
|
||||||
enabledButtons.forEachIndexed { i: Int, _: Boolean ->
|
enabledButtons.forEachIndexed { i: Int, _: Boolean ->
|
||||||
// Buttons that are disabled by default
|
// Buttons that are disabled by default
|
||||||
var defaultValue = true
|
var defaultValue = true
|
||||||
when (i) {
|
when (i) {
|
||||||
6, 7, 12, 13, 14 -> defaultValue = false
|
6, 7, 12, 13, 14, 15 -> defaultValue = false
|
||||||
}
|
}
|
||||||
enabledButtons[i] = preferences.getBoolean("buttonToggle$i", defaultValue)
|
enabledButtons[i] = preferences.getBoolean("buttonToggle$i", defaultValue)
|
||||||
}
|
}
|
||||||
|
@ -1116,10 +1137,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||||
.apply()
|
.apply()
|
||||||
|
|
||||||
val editor = preferences.edit()
|
val editor = preferences.edit()
|
||||||
for (i in 0 until 15) {
|
for (i in 0 until 16) {
|
||||||
var defaultValue = true
|
var defaultValue = true
|
||||||
when (i) {
|
when (i) {
|
||||||
6, 7, 12, 13, 14 -> defaultValue = false
|
6, 7, 12, 13, 14, 15 -> defaultValue = false
|
||||||
}
|
}
|
||||||
editor.putBoolean("buttonToggle$i", defaultValue)
|
editor.putBoolean("buttonToggle$i", defaultValue)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -22,9 +22,10 @@ class SelectUserDirectoryDialogFragment : DialogFragment() {
|
||||||
mainActivity = requireActivity() as MainActivity
|
mainActivity = requireActivity() as MainActivity
|
||||||
|
|
||||||
isCancelable = false
|
isCancelable = false
|
||||||
|
|
||||||
return MaterialAlertDialogBuilder(requireContext())
|
return MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle(R.string.select_citra_user_folder)
|
.setTitle(R.string.select_citra_user_folder)
|
||||||
.setMessage(R.string.cannot_skip_directory_description)
|
.setMessage(R.string.selecting_user_directory_without_write_permissions)
|
||||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||||
mainActivity?.openCitraDirectory?.launch(null)
|
mainActivity?.openCitraDirectory?.launch(null)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
// 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.content.DialogInterface
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.RadioButton
|
||||||
|
import android.widget.RadioGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
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.ui.main.MainActivity
|
||||||
|
import org.citra.citra_emu.utils.CitraDirectoryUtils
|
||||||
|
import org.citra.citra_emu.utils.DirectoryInitialization
|
||||||
|
import org.citra.citra_emu.utils.PermissionsHandler
|
||||||
|
import org.citra.citra_emu.viewmodel.HomeViewModel
|
||||||
|
|
||||||
|
class UpdateUserDirectoryDialogFragment : DialogFragment() {
|
||||||
|
private lateinit var mainActivity: MainActivity
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
mainActivity = requireActivity() as MainActivity
|
||||||
|
|
||||||
|
isCancelable = false
|
||||||
|
val preferences: SharedPreferences =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||||
|
val ld = preferences.getString("LIME3DS_DIRECTORY","")
|
||||||
|
val cd = preferences.getString("CITRA_DIRECTORY","")
|
||||||
|
val dialogView = LayoutInflater.from(requireContext())
|
||||||
|
.inflate(R.layout.dialog_select_which_directory, null)
|
||||||
|
|
||||||
|
val radioGroup = dialogView.findViewById<RadioGroup>(R.id.radioGroup)
|
||||||
|
|
||||||
|
val choices = listOf(
|
||||||
|
getString(R.string.keep_current_azahar_directory) to Uri.parse(cd).path,
|
||||||
|
getString(R.string.use_prior_lime3ds_directory) to Uri.parse(ld).path
|
||||||
|
)
|
||||||
|
var selected = -1 // 0 = current, 1 = prior, -1 = no selection
|
||||||
|
|
||||||
|
choices.forEachIndexed { index, (label, subtext) ->
|
||||||
|
val container = LinearLayout(requireContext()).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
setPadding(0, 16, 0, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
val radioButton = RadioButton(requireContext()).apply {
|
||||||
|
text = label
|
||||||
|
id = View.generateViewId()
|
||||||
|
}
|
||||||
|
|
||||||
|
val subTextView = TextView(requireContext()).apply {
|
||||||
|
text = subtext
|
||||||
|
setPadding(64, 4, 0, 0) // indent for visual hierarchy
|
||||||
|
setTextAppearance(android.R.style.TextAppearance_Small)
|
||||||
|
}
|
||||||
|
|
||||||
|
container.addView(radioButton)
|
||||||
|
container.addView(subTextView)
|
||||||
|
radioGroup.addView(container)
|
||||||
|
|
||||||
|
// RadioGroup expects RadioButtons directly, so we need to manage selection ourselves
|
||||||
|
radioButton.setOnClickListener {
|
||||||
|
selected = index
|
||||||
|
// Manually uncheck others
|
||||||
|
for (i in 0 until radioGroup.childCount) {
|
||||||
|
val child = radioGroup.getChildAt(i) as LinearLayout
|
||||||
|
val rb = child.getChildAt(0) as RadioButton
|
||||||
|
rb.isChecked = i == index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle(R.string.select_citra_user_folder)
|
||||||
|
.setView(dialogView)
|
||||||
|
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||||
|
if (selected == 1) {
|
||||||
|
PermissionsHandler.setCitraDirectory(ld)
|
||||||
|
}
|
||||||
|
if (selected >= 0) {
|
||||||
|
CitraDirectoryUtils.removeLimeDirectoryPreference()
|
||||||
|
DirectoryInitialization.resetCitraDirectoryState()
|
||||||
|
DirectoryInitialization.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModelProvider(mainActivity)[HomeViewModel::class.java].setPickingUserDir(false)
|
||||||
|
ViewModelProvider(mainActivity)[HomeViewModel::class.java].setUserDir(this.requireActivity(),PermissionsHandler.citraDirectory.path!!)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "UpdateUserDirectoryDialogFragment"
|
||||||
|
|
||||||
|
fun newInstance(activity: FragmentActivity): UpdateUserDirectoryDialogFragment {
|
||||||
|
ViewModelProvider(activity)[HomeViewModel::class.java].setPickingUserDir(true)
|
||||||
|
return UpdateUserDirectoryDialogFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import org.citra.citra_emu.CitraApplication
|
||||||
import org.citra.citra_emu.NativeLibrary
|
import org.citra.citra_emu.NativeLibrary
|
||||||
import org.citra.citra_emu.R
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||||
|
import org.citra.citra_emu.utils.TurboHelper
|
||||||
import java.lang.NullPointerException
|
import java.lang.NullPointerException
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
private var buttonBeingConfigured: InputOverlayDrawableButton? = null
|
private var buttonBeingConfigured: InputOverlayDrawableButton? = null
|
||||||
private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
|
private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
|
||||||
private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
|
private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
|
||||||
|
private val settingsViewModel = NativeLibrary.sEmulationActivity.get()!!.settingsViewModel
|
||||||
|
|
||||||
// Stores the ID of the pointer that interacted with the 3DS touchscreen.
|
// Stores the ID of the pointer that interacted with the 3DS touchscreen.
|
||||||
private var touchscreenPointerId = -1
|
private var touchscreenPointerId = -1
|
||||||
|
@ -104,6 +106,10 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
swapScreen()
|
swapScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (button.id == NativeLibrary.ButtonType.BUTTON_TURBO && button.status == NativeLibrary.ButtonState.PRESSED) {
|
||||||
|
TurboHelper.setTurboEnabled((!TurboHelper.isTurboSpeedEnabled()))
|
||||||
|
}
|
||||||
|
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.id, button.status)
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.id, button.status)
|
||||||
shouldUpdateView = true
|
shouldUpdateView = true
|
||||||
}
|
}
|
||||||
|
@ -468,6 +474,18 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preferences.getBoolean("buttonToggle15", false)) {
|
||||||
|
overlayButtons.add(
|
||||||
|
initializeOverlayButton(
|
||||||
|
context,
|
||||||
|
R.drawable.button_turbo,
|
||||||
|
R.drawable.button_turbo_pressed,
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO,
|
||||||
|
orientation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshControls() {
|
fun refreshControls() {
|
||||||
|
@ -673,6 +691,14 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
NativeLibrary.ButtonType.BUTTON_SWAP.toString() + "-Y",
|
NativeLibrary.ButtonType.BUTTON_SWAP.toString() + "-Y",
|
||||||
resources.getInteger(R.integer.N3DS_BUTTON_SWAP_Y).toFloat() / 1000 * maxY
|
resources.getInteger(R.integer.N3DS_BUTTON_SWAP_Y).toFloat() / 1000 * maxY
|
||||||
)
|
)
|
||||||
|
.putFloat(
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO.toString() + "-X",
|
||||||
|
resources.getInteger(R.integer.N3DS_BUTTON_TURBO_X).toFloat() / 1000 * maxX
|
||||||
|
)
|
||||||
|
.putFloat(
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO.toString() + "-Y",
|
||||||
|
resources.getInteger(R.integer.N3DS_BUTTON_TURBO_Y).toFloat() / 1000 * maxY
|
||||||
|
)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,6 +842,14 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
NativeLibrary.ButtonType.BUTTON_SWAP.toString() + portrait + "-Y",
|
NativeLibrary.ButtonType.BUTTON_SWAP.toString() + portrait + "-Y",
|
||||||
resources.getInteger(R.integer.N3DS_BUTTON_SWAP_PORTRAIT_Y).toFloat() / 1000 * maxY
|
resources.getInteger(R.integer.N3DS_BUTTON_SWAP_PORTRAIT_Y).toFloat() / 1000 * maxY
|
||||||
)
|
)
|
||||||
|
.putFloat(
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO.toString() + portrait + "-X",
|
||||||
|
resources.getInteger(R.integer.N3DS_BUTTON_TURBO_PORTRAIT_X).toFloat() / 1000 * maxX
|
||||||
|
)
|
||||||
|
.putFloat(
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO.toString() + portrait + "-Y",
|
||||||
|
resources.getInteger(R.integer.N3DS_BUTTON_TURBO_PORTRAIT_Y).toFloat() / 1000 * maxY
|
||||||
|
)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,6 +962,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||||
NativeLibrary.ButtonType.BUTTON_START,
|
NativeLibrary.ButtonType.BUTTON_START,
|
||||||
NativeLibrary.ButtonType.BUTTON_SELECT,
|
NativeLibrary.ButtonType.BUTTON_SELECT,
|
||||||
NativeLibrary.ButtonType.BUTTON_SWAP -> 0.08f
|
NativeLibrary.ButtonType.BUTTON_SWAP -> 0.08f
|
||||||
|
NativeLibrary.ButtonType.BUTTON_TURBO -> 0.10f
|
||||||
|
|
||||||
NativeLibrary.ButtonType.TRIGGER_L,
|
NativeLibrary.ButtonType.TRIGGER_L,
|
||||||
NativeLibrary.ButtonType.TRIGGER_R,
|
NativeLibrary.ButtonType.TRIGGER_R,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -34,10 +34,8 @@ import androidx.work.OutOfQuotaPolicy
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.navigation.NavigationBarView
|
import com.google.android.material.navigation.NavigationBarView
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.citra.citra_emu.R
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.activities.EmulationActivity
|
|
||||||
import org.citra.citra_emu.contracts.OpenFileResultContract
|
import org.citra.citra_emu.contracts.OpenFileResultContract
|
||||||
import org.citra.citra_emu.databinding.ActivityMainBinding
|
import org.citra.citra_emu.databinding.ActivityMainBinding
|
||||||
import org.citra.citra_emu.features.settings.model.Settings
|
import org.citra.citra_emu.features.settings.model.Settings
|
||||||
|
@ -45,8 +43,10 @@ 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.ui.SettingsActivity
|
||||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||||
import org.citra.citra_emu.fragments.SelectUserDirectoryDialogFragment
|
import org.citra.citra_emu.fragments.SelectUserDirectoryDialogFragment
|
||||||
|
import org.citra.citra_emu.fragments.UpdateUserDirectoryDialogFragment
|
||||||
import org.citra.citra_emu.utils.CiaInstallWorker
|
import org.citra.citra_emu.utils.CiaInstallWorker
|
||||||
import org.citra.citra_emu.utils.CitraDirectoryHelper
|
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.DirectoryInitialization
|
||||||
import org.citra.citra_emu.utils.FileBrowserHelper
|
import org.citra.citra_emu.utils.FileBrowserHelper
|
||||||
import org.citra.citra_emu.utils.InsetsHelper
|
import org.citra.citra_emu.utils.InsetsHelper
|
||||||
|
@ -66,13 +66,17 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
val splashScreen = installSplashScreen()
|
val splashScreen = installSplashScreen()
|
||||||
|
CitraDirectoryUtils.attemptAutomaticUpdateDirectory()
|
||||||
splashScreen.setKeepOnScreenCondition {
|
splashScreen.setKeepOnScreenCondition {
|
||||||
!DirectoryInitialization.areCitraDirectoriesReady() &&
|
!DirectoryInitialization.areCitraDirectoriesReady() &&
|
||||||
PermissionsHandler.hasWriteAccess(this)
|
PermissionsHandler.hasWriteAccess(this) &&
|
||||||
|
!CitraDirectoryUtils.needToUpdateManually()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (PermissionsHandler.hasWriteAccess(applicationContext) &&
|
if (PermissionsHandler.hasWriteAccess(applicationContext) &&
|
||||||
DirectoryInitialization.areCitraDirectoriesReady()) {
|
DirectoryInitialization.areCitraDirectoriesReady() &&
|
||||||
|
!CitraDirectoryUtils.needToUpdateManually()) {
|
||||||
settingsViewModel.settings.loadSettings()
|
settingsViewModel.settings.loadSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +189,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||||
) {
|
) {
|
||||||
SelectUserDirectoryDialogFragment.newInstance(this)
|
SelectUserDirectoryDialogFragment.newInstance(this)
|
||||||
.show(supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
.show(supportFragmentManager, SelectUserDirectoryDialogFragment.TAG)
|
||||||
|
} else if (!firstTimeSetup && !homeViewModel.isPickingUserDir.value && CitraDirectoryUtils.needToUpdateManually()) {
|
||||||
|
UpdateUserDirectoryDialogFragment.newInstance(this)
|
||||||
|
.show(supportFragmentManager,UpdateUserDirectoryDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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.content.SharedPreferences
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import org.citra.citra_emu.CitraApplication
|
||||||
|
|
||||||
|
object CitraDirectoryUtils {
|
||||||
|
const val CITRA_DIRECTORY = "CITRA_DIRECTORY"
|
||||||
|
const val LIME3DS_DIRECTORY = "LIME3DS_DIRECTORY"
|
||||||
|
val preferences: SharedPreferences =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||||
|
|
||||||
|
fun needToUpdateManually(): Boolean {
|
||||||
|
val directoryString = preferences.getString(CITRA_DIRECTORY, "")
|
||||||
|
val limeDirectoryString = preferences.getString(LIME3DS_DIRECTORY,"")
|
||||||
|
return (directoryString != "" && limeDirectoryString != "" && directoryString != limeDirectoryString)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attemptAutomaticUpdateDirectory() {
|
||||||
|
val directoryString = preferences.getString(CITRA_DIRECTORY, "")
|
||||||
|
val limeDirectoryString = preferences.getString(LIME3DS_DIRECTORY,"")
|
||||||
|
if (needToUpdateManually()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (directoryString == "" && limeDirectoryString != "") {
|
||||||
|
// Upgrade from Lime3DS to Azahar
|
||||||
|
PermissionsHandler.setCitraDirectory(limeDirectoryString)
|
||||||
|
removeLimeDirectoryPreference()
|
||||||
|
DirectoryInitialization.resetCitraDirectoryState()
|
||||||
|
DirectoryInitialization.start()
|
||||||
|
|
||||||
|
} else if (directoryString != "" && directoryString == limeDirectoryString) {
|
||||||
|
// Both the Lime3DS and Azahar directories are the same,
|
||||||
|
// so delete the obsolete Lime3DS value.
|
||||||
|
removeLimeDirectoryPreference()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeLimeDirectoryPreference() {
|
||||||
|
preferences.edit().remove(LIME3DS_DIRECTORY).apply()
|
||||||
|
}
|
||||||
|
}
|
|
@ -106,6 +106,40 @@ class DocumentsTree {
|
||||||
return node.uri ?: return Uri.EMPTY
|
return node.uri ?: return Uri.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun folderUriHelper(path: String, createIfNotExists: Boolean = false): Uri? {
|
||||||
|
root ?: return null
|
||||||
|
val components = path.split(DELIMITER).filter { it.isNotEmpty() }
|
||||||
|
var current = root
|
||||||
|
|
||||||
|
for (component in components) {
|
||||||
|
if (!current!!.loaded) {
|
||||||
|
structTree(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
var child = current.findChild(component)
|
||||||
|
|
||||||
|
// Create directory if it doesn't exist and creation is enabled
|
||||||
|
if (child == null && createIfNotExists) {
|
||||||
|
try {
|
||||||
|
val createdDir = FileUtil.createDir(current.uri.toString(), component) ?: return null
|
||||||
|
child = DocumentsNode(createdDir, true).apply {
|
||||||
|
parent = current
|
||||||
|
}
|
||||||
|
current.addChild(child)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error("[DocumentsTree]: Cannot create directory, error: " + e.message)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} else if (child == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
current = child
|
||||||
|
}
|
||||||
|
return current?.uri
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun isDirectory(filepath: String): Boolean {
|
fun isDirectory(filepath: String): Boolean {
|
||||||
val node = resolvePath(filepath) ?: return false
|
val node = resolvePath(filepath) ?: return false
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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.widget.Toast
|
||||||
|
import org.citra.citra_emu.CitraApplication
|
||||||
|
import org.citra.citra_emu.NativeLibrary
|
||||||
|
import org.citra.citra_emu.R
|
||||||
|
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||||
|
|
||||||
|
object TurboHelper {
|
||||||
|
private var turboSpeedEnabled = false
|
||||||
|
|
||||||
|
fun isTurboSpeedEnabled(): Boolean {
|
||||||
|
return turboSpeedEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTurboEnabled(state: Boolean) {
|
||||||
|
turboSpeedEnabled = state
|
||||||
|
reloadTurbo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reloadTurbo() {
|
||||||
|
val context = CitraApplication.appContext
|
||||||
|
val toastMessage: String
|
||||||
|
|
||||||
|
if (turboSpeedEnabled) {
|
||||||
|
NativeLibrary.setTemporaryFrameLimit(IntSetting.TURBO_LIMIT.int.toDouble())
|
||||||
|
toastMessage = context.getString(R.string.turbo_enabled_toast)
|
||||||
|
} else {
|
||||||
|
NativeLibrary.disableTemporaryFrameLimit()
|
||||||
|
toastMessage = context.getString(R.string.turbo_disabled_toast)
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
|
@ -149,8 +149,8 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
||||||
ReadSetting("Renderer", Settings::values.texture_filter);
|
ReadSetting("Renderer", Settings::values.texture_filter);
|
||||||
ReadSetting("Renderer", Settings::values.texture_sampling);
|
ReadSetting("Renderer", Settings::values.texture_sampling);
|
||||||
|
ReadSetting("Renderer", Settings::values.turbo_limit);
|
||||||
// Work around to map Android setting for enabling the frame limiter to the format Citra expects
|
// Workaround to map Android setting for enabling the frame limiter to the format Citra expects
|
||||||
if (sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)) {
|
if (sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)) {
|
||||||
ReadSetting("Renderer", Settings::values.frame_limit);
|
ReadSetting("Renderer", Settings::values.frame_limit);
|
||||||
} else {
|
} else {
|
||||||
|
@ -183,11 +183,13 @@ void Config::ReadValues() {
|
||||||
layoutInt = static_cast<int>(Settings::LayoutOption::LargeScreen);
|
layoutInt = static_cast<int>(Settings::LayoutOption::LargeScreen);
|
||||||
}
|
}
|
||||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layoutInt);
|
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layoutInt);
|
||||||
|
Settings::values.screen_gap = static_cast<int>(sdl2_config->GetReal("Layout", "screen_gap", 0));
|
||||||
Settings::values.large_screen_proportion =
|
Settings::values.large_screen_proportion =
|
||||||
static_cast<float>(sdl2_config->GetReal("Layout", "large_screen_proportion", 2.25));
|
static_cast<float>(sdl2_config->GetReal("Layout", "large_screen_proportion", 2.25));
|
||||||
Settings::values.small_screen_position = static_cast<Settings::SmallScreenPosition>(
|
Settings::values.small_screen_position = static_cast<Settings::SmallScreenPosition>(
|
||||||
sdl2_config->GetInteger("Layout", "small_screen_position",
|
sdl2_config->GetInteger("Layout", "small_screen_position",
|
||||||
static_cast<int>(Settings::SmallScreenPosition::TopRight)));
|
static_cast<int>(Settings::SmallScreenPosition::TopRight)));
|
||||||
|
ReadSetting("Layout", Settings::values.screen_gap);
|
||||||
ReadSetting("Layout", Settings::values.custom_top_x);
|
ReadSetting("Layout", Settings::values.custom_top_x);
|
||||||
ReadSetting("Layout", Settings::values.custom_top_y);
|
ReadSetting("Layout", Settings::values.custom_top_y);
|
||||||
ReadSetting("Layout", Settings::values.custom_top_width);
|
ReadSetting("Layout", Settings::values.custom_top_width);
|
||||||
|
|
|
@ -156,6 +156,10 @@ use_frame_limit =
|
||||||
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
||||||
frame_limit =
|
frame_limit =
|
||||||
|
|
||||||
|
# Alternative frame limit which can be triggered by the user
|
||||||
|
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
|
||||||
|
turbo_limit =
|
||||||
|
|
||||||
# The clear color for the renderer. What shows up on the sides of the bottom screen.
|
# The clear color for the renderer. What shows up on the sides of the bottom screen.
|
||||||
# Must be in range of 0.0-1.0. Defaults to 0.0 for all.
|
# Must be in range of 0.0-1.0. Defaults to 0.0 for all.
|
||||||
bg_red =
|
bg_red =
|
||||||
|
@ -167,7 +171,7 @@ bg_green =
|
||||||
render_3d =
|
render_3d =
|
||||||
|
|
||||||
# Change 3D Intensity
|
# Change 3D Intensity
|
||||||
# 0 - 100: Intensity. 0 (default)
|
# 0 - 255: Intensity. 0 (default)
|
||||||
factor_3d =
|
factor_3d =
|
||||||
|
|
||||||
# The name of the post processing shader to apply.
|
# The name of the post processing shader to apply.
|
||||||
|
@ -202,6 +206,12 @@ disable_right_eye_render =
|
||||||
# 5: Custom Layout
|
# 5: Custom Layout
|
||||||
layout_option =
|
layout_option =
|
||||||
|
|
||||||
|
# Screen Gap - adds a gap between screens in all two-screen modes
|
||||||
|
# Measured in pixels relative to the 240px default height of the screens
|
||||||
|
# Scales with the larger screen (so 24 is 10% of the larger screen height)
|
||||||
|
# Default value is 0.0
|
||||||
|
screen_gap =
|
||||||
|
|
||||||
# Large Screen Proportion - Relative size of large:small in large screen mode
|
# Large Screen Proportion - Relative size of large:small in large screen mode
|
||||||
# Default value is 2.25
|
# Default value is 2.25
|
||||||
large_screen_proportion =
|
large_screen_proportion =
|
||||||
|
@ -256,6 +266,10 @@ custom_portrait_bottom_height =
|
||||||
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
|
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
|
||||||
swap_screen =
|
swap_screen =
|
||||||
|
|
||||||
|
# Expands the display area to include the cutout (or notch) area
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
expand_to_cutout_area =
|
||||||
|
|
||||||
# Screen placement settings when using Cardboard VR (render3d = 4)
|
# Screen placement settings when using Cardboard VR (render3d = 4)
|
||||||
# 30 - 100: Screen size as a percentage of the viewport. 85 (default)
|
# 30 - 100: Screen size as a percentage of the viewport. 85 (default)
|
||||||
cardboard_screen_size =
|
cardboard_screen_size =
|
||||||
|
|
|
@ -215,7 +215,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||||
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||||
|
|
||||||
std::unique_ptr<Frontend::GraphicsContext> cpu_context;
|
std::unique_ptr<Frontend::GraphicsContext> cpu_context;
|
||||||
system.GPU().Renderer().Rasterizer()->LoadDiskResources(stop_run, &LoadDiskCacheProgress);
|
system.GPU().Renderer().Rasterizer()->LoadDefaultDiskResources(stop_run,
|
||||||
|
&LoadDiskCacheProgress);
|
||||||
|
|
||||||
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
|
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
|
||||||
|
|
||||||
|
@ -781,4 +782,14 @@ void Java_org_citra_citra_1emu_NativeLibrary_unlinkConsole(JNIEnv* env, jobject
|
||||||
HW::UniqueData::UnlinkConsole();
|
HW::UniqueData::UnlinkConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Java_org_citra_citra_1emu_NativeLibrary_setTemporaryFrameLimit(JNIEnv* env, jobject obj,
|
||||||
|
jdouble speed) {
|
||||||
|
Settings::temporary_frame_limit = speed;
|
||||||
|
Settings::is_temporary_frame_limit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Java_org_citra_citra_1emu_NativeLibrary_disableTemporaryFrameLimit(JNIEnv* env, jobject obj) {
|
||||||
|
Settings::is_temporary_frame_limit = false;
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
BIN
src/android/app/src/main/res/drawable-hdpi/button_turbo.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.6 KiB |
BIN
src/android/app/src/main/res/drawable-xhdpi/button_turbo.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.5 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/button_turbo.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.9 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/button_turbo.png
Normal file
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.2 KiB |
10
src/android/app/src/main/res/drawable/ic_open.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="?attr/colorControlNormal"
|
||||||
|
android:pathData="M20,6h-8l-2,-2H4C2.89,4 2,4.89 2,6v12c0,1.1 0.89,2 2,2h16c1.1,0 2,-0.9 2,-2V8C22,6.89 21.1,6 20,6zM19,18H5V8h14v10zM12,9l-4,4h3v3h2v-3h3L12,9z"/>
|
||||||
|
</vector>
|
10
src/android/app/src/main/res/drawable/ic_uninstall.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="?attr/colorControlNormal"
|
||||||
|
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
||||||
|
</vector>
|
|
@ -110,6 +110,24 @@
|
||||||
android:text="@string/play"
|
android:text="@string/play"
|
||||||
app:icon="@drawable/ic_play" />
|
app:icon="@drawable/ic_play" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/menu_button_open"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:icon="@drawable/ic_open"
|
||||||
|
app:iconGravity="textStart" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/menu_button_uninstall"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:icon="@drawable/ic_uninstall"
|
||||||
|
app:iconGravity="textStart" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/game_shortcut"
|
android:id="@+id/game_shortcut"
|
||||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
@ -120,11 +138,6 @@
|
||||||
app:icon="@drawable/ic_shortcut"
|
app:icon="@drawable/ic_shortcut"
|
||||||
app:iconGravity="textStart" />
|
app:iconGravity="textStart" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -148,6 +161,7 @@
|
||||||
android:contentDescription="@string/cheats"
|
android:contentDescription="@string/cheats"
|
||||||
android:text="@string/cheats" />
|
android:text="@string/cheats" />
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?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:paddingTop="12dp"
|
||||||
|
android:paddingLeft="24dp"
|
||||||
|
android:paddingRight="24dp"
|
||||||
|
android:paddingBottom="0dp">
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fadeScrollbars="false"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
android:overScrollMode="ifContentScrolls">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/messageText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/select_which_user_directory_to_use"
|
||||||
|
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||||
|
android:paddingBottom="16dp" />
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/radioGroup"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation = "vertical" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -1,14 +1,26 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/game_icon"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginEnd="16dp"/>
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_game_title"
|
android:id="@+id/text_game_title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginEnd="24dp"
|
|
||||||
android:textAppearance="?attr/textAppearanceHeadlineMedium"
|
android:textAppearance="?attr/textAppearanceHeadlineMedium"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
tools:text="Super Mario 3D Land" />
|
tools:text="text_game_title" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
24
src/android/app/src/main/res/menu/game_context_menu_open.xml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_app"
|
||||||
|
android:title="@string/game_context_open_app" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_save_dir"
|
||||||
|
android:title="@string/game_context_open_save_dir" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_updates"
|
||||||
|
android:title="@string/game_context_open_updates" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_dlc"
|
||||||
|
android:title="@string/game_context_open_dlc" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_extra"
|
||||||
|
android:title="@string/game_context_open_extra" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_textures"
|
||||||
|
android:title="@string/game_context_open_textures" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_open_mods"
|
||||||
|
android:title="@string/game_context_open_mods" />
|
||||||
|
</menu>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_uninstall"
|
||||||
|
android:title="@string/uninstall_cia" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_uninstall_dlc"
|
||||||
|
android:title="@string/game_context_uninstall_dlc" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/game_context_uninstall_updates"
|
||||||
|
android:title="@string/game_context_uninstall_updates" />
|
||||||
|
</menu>
|
|
@ -7,6 +7,10 @@
|
||||||
android:id="@+id/menu_portrait_layout_top_full"
|
android:id="@+id/menu_portrait_layout_top_full"
|
||||||
android:title="@string/emulation_portrait_layout_top_full" />
|
android:title="@string/emulation_portrait_layout_top_full" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_portrait_layout_original"
|
||||||
|
android:title="@string/emulation_screen_layout_original" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_portrait_layout_custom"
|
android:id="@+id/menu_portrait_layout_custom"
|
||||||
android:title="@string/emulation_screen_layout_custom" />
|
android:title="@string/emulation_screen_layout_custom" />
|
||||||
|
|
|
@ -83,9 +83,13 @@
|
||||||
<string name="warning_cancel">Cancel·lar</string>
|
<string name="warning_cancel">Cancel·lar</string>
|
||||||
<string name="select_citra_user_folder">Seleccionar carpeta d\'usuari.</string>
|
<string name="select_citra_user_folder">Seleccionar carpeta d\'usuari.</string>
|
||||||
<string name="select_citra_user_folder_description"><![CDATA[Selecciona el vostre directori de <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">dades d\'usuari</a> amb el següent botó.]]></string>
|
<string name="select_citra_user_folder_description"><![CDATA[Selecciona el vostre directori de <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">dades d\'usuari</a> amb el següent botó.]]></string>
|
||||||
|
<string name="select_which_user_directory_to_use">Sembla que tens directoris d\'usuari configurats tant per a Lime3DS com per a Azahar. Probablement es deu al fet que vas actualitzar a Azahar i, quan se\'t va demanar, vas triar un directori d\'usuari diferent del qual usaves per a Lime3DS.\n\nAixó pot haver-te fet pensar que vas perdre partides guardades o altres configuracions; et demanem disculpes si això va ocórrer.\n\nPreferixes tornar a usar el teu directori d\'usuari original de Lime3DS, restaurant la configuració i les partides guardades de Lime3DS, o conservar el teu directori d\'usuari actual d\'Azahar?\n\nCap dels directoris s\'eliminarà, independentment de la teua elecció, i pots canviar lliurement entre ells usant l\'opció \"Seleccionar carpeta d\'usuari\".</string>
|
||||||
|
<string name="keep_current_azahar_directory">Mantindre el directori Azahar actual</string>
|
||||||
|
<string name="use_prior_lime3ds_directory">Usar el directori de Lime3DS anterior</string>
|
||||||
<string name="select">Seleccionar</string>
|
<string name="select">Seleccionar</string>
|
||||||
<string name="cannot_skip">No pots saltar aquest pas</string>
|
<string name="cannot_skip">No pots saltar aquest pas</string>
|
||||||
<string name="cannot_skip_directory_description">Aquest pas és necessari perquè Azahar funcione. Selecciona un directori i després podràs continuar.</string>
|
<string name="cannot_skip_directory_description">Aquest pas és necessari perquè Azahar funcione. Selecciona un directori i després podràs continuar.</string>
|
||||||
|
<string name="selecting_user_directory_without_write_permissions">Has perdut els permisos d\'escriptura en el teu <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">directori de dades d\'usuari</a>, on es guarden les partides guardades i altra informació. Això pot ocórrer després d\'algunes actualitzacions d\'aplicacions o d\'Android. Torna a seleccionar el directori per a recuperar els permisos i poder continuar.</string>
|
||||||
<string name="set_up_theme_settings">Configuració de tema</string>
|
<string name="set_up_theme_settings">Configuració de tema</string>
|
||||||
<string name="setup_theme_settings_description">Configura les teues preferències de temes per a Azahar.</string>
|
<string name="setup_theme_settings_description">Configura les teues preferències de temes per a Azahar.</string>
|
||||||
<string name="setup_set_theme">Establir tema</string>
|
<string name="setup_set_theme">Establir tema</string>
|
||||||
|
@ -122,6 +126,7 @@
|
||||||
<string name="input_binding_description_horizontal_axis">Mou el joystick a esquerra o dreta.</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_home">HOME</string>
|
||||||
<string name="button_swap">Intercanviar Pantalles</string>
|
<string name="button_swap">Intercanviar Pantalles</string>
|
||||||
|
<string name="button_turbo">Turbo</string>
|
||||||
<string name="input_message_analog_only">Aquest control s\'ha d\'assignar a un estic analògic del comandament o a un eix del Pad de Control!</string>
|
<string name="input_message_analog_only">Aquest control s\'ha d\'assignar a un estic analògic del comandament o a un eix del Pad de Control!</string>
|
||||||
<string name="input_message_button_only">Aquest control s\'ha d\'assignar a un botó del comandament!</string>
|
<string name="input_message_button_only">Aquest control s\'ha d\'assignar a un botó del comandament!</string>
|
||||||
|
|
||||||
|
@ -222,11 +227,17 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||||
<string name="asynchronous_gpu">Activar Emulació Asíncrona de la GPU</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="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">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.</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>
|
||||||
<string name="frame_limit_slider">Limitar percentatge de velocitat</string>
|
<string name="frame_limit_slider">Limitar percentatge de velocitat</string>
|
||||||
<string name="frame_limit_slider_description">Especifica el valor al qual es limita la velocitat d\'emulació. Amb el valor per defecte del 100%, l\'emulació es limitarà a la velocitat normal. Els valors alts o baixos incrementaran o reduiran el límit de velocitat.</string>
|
<string name="frame_limit_slider_description">Especifica el valor al qual es limita la velocitat d\'emulació. Amb el valor per defecte del 100%, l\'emulació es limitarà a la velocitat normal. Els valors alts o baixos incrementaran o reduiran el límit de velocitat.</string>
|
||||||
|
<string name="expand_to_cutout_area">Expandir a l\'àrea de retallada</string>
|
||||||
|
<string name="expand_to_cutout_area_description">Amplia l\'àrea de visualització per a incloure l\'àrea de retallada (o osca).</string>
|
||||||
|
<string name="emulation_toggle_turbo_speed">Velocitat Turbo</string>
|
||||||
|
<string name="turbo_speed">Velocitat Turbo</string>
|
||||||
|
<string name="turbo_speed_description">Límit de velocitat d\'emulació utilitzat mentres la tecla d\'accés ràpid turbo està activa.</string>
|
||||||
<string name="internal_resolution">Resolució interna</string>
|
<string name="internal_resolution">Resolució interna</string>
|
||||||
<string name="internal_resolution_description">Especifica la resolució utilitzada per a renderitzar. Una resolució alta millora considerablement la qualitat visual, però també afecta bastant al rendiment i pot causar problemes en unes certes aplicacions.</string>
|
<string name="internal_resolution_description">Especifica la resolució utilitzada per a renderitzar. Una resolució alta millora considerablement la qualitat visual, però també afecta bastant al rendiment i pot causar problemes en unes certes aplicacions.</string>
|
||||||
|
<string name="internal_resolution_setting_auto">Auto (Grandària Pantalla)</string>
|
||||||
<string name="internal_resolution_setting_1x">Nativa (400x240)</string>
|
<string name="internal_resolution_setting_1x">Nativa (400x240)</string>
|
||||||
<string name="internal_resolution_setting_2x">2x Nativa (800x480)</string>
|
<string name="internal_resolution_setting_2x">2x Nativa (800x480)</string>
|
||||||
<string name="internal_resolution_setting_3x">3x Nativa (1200x720)</string>
|
<string name="internal_resolution_setting_3x">3x Nativa (1200x720)</string>
|
||||||
|
@ -306,6 +317,8 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||||
<string name="select_rtc_time">Seleccionar hora RTC</string>
|
<string name="select_rtc_time">Seleccionar hora RTC</string>
|
||||||
<string name="reset_setting_confirmation">Vols reiniciar esta configuració al seu valor per defecte?</string>
|
<string name="reset_setting_confirmation">Vols reiniciar esta configuració al seu valor per defecte?</string>
|
||||||
<string name="setting_not_editable">No pots editar-ho ara</string>
|
<string name="setting_not_editable">No pots editar-ho ara</string>
|
||||||
|
<string name="setting_disabled">Configuració deshabilitada</string>
|
||||||
|
<string name="setting_disabled_description">Esta configuració està actualment deshabilitada perquè una altra configuració no té el valor apropiat.</string>
|
||||||
<string name="setting_not_editable_description">Esta opció no pot canviar-se mentres s\'està executant un joc.</string>
|
<string name="setting_not_editable_description">Esta opció no pot canviar-se mentres s\'està executant un joc.</string>
|
||||||
<string name="auto_select">Auto-elegir</string>
|
<string name="auto_select">Auto-elegir</string>
|
||||||
|
|
||||||
|
@ -463,6 +476,17 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||||
<!-- About Game Dialog -->
|
<!-- About Game Dialog -->
|
||||||
<string name="play">Jugar</string>
|
<string name="play">Jugar</string>
|
||||||
<string name="shortcut">Drecera</string>
|
<string name="shortcut">Drecera</string>
|
||||||
|
<string name="uninstall_cia">Desinstal·lar Aplicació</string>
|
||||||
|
<string name="uninstalling">Desinstal·lant...</string>
|
||||||
|
<string name="game_context_open_save_dir">Obrir Carpeta de Guardat</string>
|
||||||
|
<string name="game_context_open_app">Obrir Carpeta d\'Aplicació</string>
|
||||||
|
<string name="game_context_open_mods">Obrir Carpeta de Mods</string>
|
||||||
|
<string name="game_context_open_textures">Obrir Carpeta de Textures</string>
|
||||||
|
<string name="game_context_open_dlc">Obrir Carpeta de DLC</string>
|
||||||
|
<string name="game_context_open_updates">Obrir Carpeta d\'Actualitzacions</string>
|
||||||
|
<string name="game_context_open_extra">Obrir Carpeta Extra</string>
|
||||||
|
<string name="game_context_uninstall_dlc">Desinstal·lar DLC</string>
|
||||||
|
<string name="game_context_uninstall_updates">Desinstal·lar Actualitzacions</string>
|
||||||
|
|
||||||
<!-- Cheats -->
|
<!-- Cheats -->
|
||||||
<string name="cheats">Trucs</string>
|
<string name="cheats">Trucs</string>
|
||||||
|
@ -780,4 +804,5 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
|
||||||
<string name="mac_address">Adreça MAC</string>
|
<string name="mac_address">Adreça MAC</string>
|
||||||
<string name="regenerate_mac_address">Regenerar adreça MAC</string>
|
<string name="regenerate_mac_address">Regenerar adreça MAC</string>
|
||||||
<string name="regenerate_mac_address_description">Això reemplaçarà la teua adreça MAC actual per una nova. No es recomana fer-ho si vas obtindre la direcció MAC de la teua consola real amb la ferramenta de configuració. Continuar?</string>
|
<string name="regenerate_mac_address_description">Això reemplaçarà la teua adreça MAC actual per una nova. No es recomana fer-ho si vas obtindre la direcció MAC de la teua consola real amb la ferramenta de configuració. Continuar?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -129,7 +129,10 @@
|
||||||
<string name="setup_system_files">Systemfiler</string>
|
<string name="setup_system_files">Systemfiler</string>
|
||||||
<string name="setup_system_files_description">Udfør handlinger som installation af systemfiler eller opstart af startmenu</string>
|
<string name="setup_system_files_description">Udfør handlinger som installation af systemfiler eller opstart af startmenu</string>
|
||||||
<string name="setup_tool_connect">Opret forbindelse til Artic opsætningsværktøj</string>
|
<string name="setup_tool_connect">Opret forbindelse til Artic opsætningsværktøj</string>
|
||||||
|
<string name="setup_system_files_preamble"><![CDATA[Azahar har brug for unikke konsoldata og firmwarefiler fra en rigtig konsol for at kunne bruge nogle af dens funktioner. Disse filer og data kan sættes op med <a href=https://github.com/azahar-emu/ArticSetupTool>Azahar Artic Setup Tool</a>.<br>Bemærk:<ul><li><b>Denne handling vil installere unikke konsoldata til Azahar, del ikke dine bruger- eller nand-mapper efter at have udført opsætningsprocessen!</b></li><li>Mens du udfører opsætningsprocessen, vil Azahar forbinde til konsollen, der kører opsætningsværktøjet. Du kan fjerne forbindelsen til konsollen senere fra fanen Systemfiler i emulatorindstillingsmenuen.</li><li>Gå ikke online med både Azahar og din 3DS-konsol på samme tid efter opsætning af systemfiler, da dette kan medføre problemer.</li><li>Gammel 3DS-opsætning er nødvendig for at den nye 3DS-opsætning kan fungere (det anbefales at opsætte begge dele).</li><li>Begge opsætningstilstande fungerer uanset hvilken model af konsollen, der kører opsætningsværktøjet.</li></ul>]]></string>
|
||||||
<string name="setup_system_files_detect">Henter den aktuelle status for systemfiler, vent venligst...</string>
|
<string name="setup_system_files_detect">Henter den aktuelle status for systemfiler, vent venligst...</string>
|
||||||
|
<string name="delete_system_files">Fjern linket til de unikke konsoldata</string>
|
||||||
|
<string name="delete_system_files_description"><![CDATA[Denne handling vil fjerne forbindelsen mellem din rigtige konsol og Azahar, med følgende konsekvenser:<br><ul><li>Din OTP, SecureInfo og LocalFriendCodeSeed vil blive fjernet fra Azahar.</li><li>Din venneliste nulstilles, og du bliver logget ud af din NNID/PNID-konto.</li><li>Systemfiler og eshop-titler opnået gennem Azahar bliver utilgængelige, indtil den samme konsol er linket igen ved hjælp af opsætningsværktøjet (gemte data går ikke tabt).</li></ul><br>Fortsætte?]]></string>
|
||||||
<string name="setup_system_files_o3ds">Gammel 3DS opsætning</string>
|
<string name="setup_system_files_o3ds">Gammel 3DS opsætning</string>
|
||||||
<string name="setup_system_files_n3ds">Ny 3DS-opsætning</string>
|
<string name="setup_system_files_n3ds">Ny 3DS-opsætning</string>
|
||||||
<string name="setup_system_files_possible">Opsætning er mulig.</string>
|
<string name="setup_system_files_possible">Opsætning er mulig.</string>
|
||||||
|
@ -138,7 +141,7 @@
|
||||||
<string name="setup_system_files_enter_address">Indtast adressen til Artic opsætningsværktøj</string>
|
<string name="setup_system_files_enter_address">Indtast adressen til Artic opsætningsværktøj</string>
|
||||||
<string name="setup_system_files_preparing">Forbereder opsætning, vent venligst...</string>
|
<string name="setup_system_files_preparing">Forbereder opsætning, vent venligst...</string>
|
||||||
<string name="boot_home_menu">Start HOME-menuen</string>
|
<string name="boot_home_menu">Start HOME-menuen</string>
|
||||||
<string name="show_home_apps">Vi apps i HOME menu i listen over applikationer</string>
|
<string name="show_home_apps">Vi apps i HOME menu i applikationslisten</string>
|
||||||
<string name="run_system_setup">Kør systemopsætning, når HOME-menuen startes.</string>
|
<string name="run_system_setup">Kør systemopsætning, når HOME-menuen startes.</string>
|
||||||
<string name="home_menu">HOME menu</string>
|
<string name="home_menu">HOME menu</string>
|
||||||
|
|
||||||
|
@ -176,6 +179,10 @@
|
||||||
<string name="plugin_loader_description">Indlæser 3GX plugins fra det emulerede SD-kort, hvis de er tilgængelige.</string>
|
<string name="plugin_loader_description">Indlæser 3GX plugins fra det emulerede SD-kort, hvis de er tilgængelige.</string>
|
||||||
<string name="allow_plugin_loader">Tillad applikationer at ændre plugin-indlæserens tilstand</string>
|
<string name="allow_plugin_loader">Tillad applikationer at ændre plugin-indlæserens tilstand</string>
|
||||||
<string name="allow_plugin_loader_description">Tillader at homebrew applikationer kan aktivere plugin-indlæseren, selv når den er deaktiveret.</string>
|
<string name="allow_plugin_loader_description">Tillader at homebrew applikationer kan aktivere plugin-indlæseren, selv når den er deaktiveret.</string>
|
||||||
|
<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>
|
||||||
|
|
||||||
<!-- Camera settings strings -->
|
<!-- Camera settings strings -->
|
||||||
<string name="inner_camera">Indre kamera</string>
|
<string name="inner_camera">Indre kamera</string>
|
||||||
<string name="outer_left_camera">Ydre venstre kamera</string>
|
<string name="outer_left_camera">Ydre venstre kamera</string>
|
||||||
|
@ -204,6 +211,9 @@
|
||||||
<string name="linear_filtering_description">Aktiverer lineær filtrering, hvilket får spillets grafik til at se mere jævnt ud.</string>
|
<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_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="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="advanced">Avanceret\"</string>
|
||||||
|
<string name="texture_sampling_name">Tekstur sampling</string>
|
||||||
|
<string name="texture_sampling_description">Tilsidesætter det samplingsfilter, der bruges af spillene. Dette kan i nogle tilfælde være nyttigt for spil, der ikke håndterer opskalering godt. Hvis du er usikker, skal du indstille dette til Styret af spillene.</string>
|
||||||
<string name="hw_shaders">Aktiver hardware shader</string>
|
<string name="hw_shaders">Aktiver hardware shader</string>
|
||||||
<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="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="shaders_accurate_mul">Nøjagtig multiplikation</string>
|
<string name="shaders_accurate_mul">Nøjagtig multiplikation</string>
|
||||||
|
@ -211,9 +221,10 @@
|
||||||
<string name="asynchronous_gpu">Aktiver asynkron GPU-emulering</string>
|
<string name="asynchronous_gpu">Aktiver asynkron GPU-emulering</string>
|
||||||
<string name="asynchronous_gpu_description">Bruger en separat tråd til at emulere GPU\'en asynkront. Når den er aktiveret, vil ydeevnen blive forbedret.</string>
|
<string name="asynchronous_gpu_description">Bruger en separat tråd til at emulere GPU\'en asynkront. Når den er aktiveret, vil ydeevnen blive forbedret.</string>
|
||||||
<string name="frame_limit_enable">Begræns hastighed</string>
|
<string name="frame_limit_enable">Begræns hastighed</string>
|
||||||
<string name="frame_limit_enable_description">Når den er aktiveret, vil emuleringshastigheden være begrænset til en specificeret procentdel af normal hastighed.</string>
|
|
||||||
<string name="frame_limit_slider">Begræns hastighedsprocent</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="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="expand_to_cutout_area">Anvend området ved frontkamera</string>
|
||||||
|
<string name="expand_to_cutout_area_description">Udvider visningsområdet til at omfatte området ved frontkameraet (eller indhakket).</string>
|
||||||
<string name="internal_resolution">Intern opløsning</string>
|
<string name="internal_resolution">Intern opløsning</string>
|
||||||
<string name="internal_resolution_description">Angiver den opløsning, der bruges til renderingen. En høj opløsning vil forbedre den visuelle kvalitet meget, men kræver også stor ydelse og kan forårsage fejl i visse applikationer.</string>
|
<string name="internal_resolution_description">Angiver den opløsning, der bruges til renderingen. En høj opløsning vil forbedre den visuelle kvalitet meget, men kræver også stor ydelse og kan forårsage fejl i visse applikationer.</string>
|
||||||
<string name="internal_resolution_setting_1x">Indbygget (400x240)</string>
|
<string name="internal_resolution_setting_1x">Indbygget (400x240)</string>
|
||||||
|
@ -452,6 +463,16 @@
|
||||||
<!-- About Game Dialog -->
|
<!-- About Game Dialog -->
|
||||||
<string name="play">Spil</string>
|
<string name="play">Spil</string>
|
||||||
<string name="shortcut">Genvej</string>
|
<string name="shortcut">Genvej</string>
|
||||||
|
<string name="uninstalling">Afinstallerer...</string>
|
||||||
|
<string name="game_context_open_save_dir">Åbn mappen med gemt data</string>
|
||||||
|
<string name="game_context_open_app">Åbn applikationsmappe</string>
|
||||||
|
<string name="game_context_open_mods">Åbn mappen med Mods</string>
|
||||||
|
<string name="game_context_open_textures">Åbn mappen med teksturer</string>
|
||||||
|
<string name="game_context_open_dlc">Åbn mappen med DLC</string>
|
||||||
|
<string name="game_context_open_updates">Åbn mappen med opdateringer</string>
|
||||||
|
<string name="game_context_open_extra">Åbn mappen med ekstra</string>
|
||||||
|
<string name="game_context_uninstall_dlc">Afinstaller DLC</string>
|
||||||
|
<string name="game_context_uninstall_updates">Afinstaller opdateringer</string>
|
||||||
|
|
||||||
<!-- Cheats -->
|
<!-- Cheats -->
|
||||||
<string name="cheats">Snyd</string>
|
<string name="cheats">Snyd</string>
|
||||||
|
@ -575,7 +596,11 @@
|
||||||
<string name="xbrz">xBRZ</string>
|
<string name="xbrz">xBRZ</string>
|
||||||
<string name="mmpx">MMPX</string>
|
<string name="mmpx">MMPX</string>
|
||||||
|
|
||||||
|
<!-- Texture Sampling names -->
|
||||||
|
<string name="game_controlled">Styret af spillene</string>
|
||||||
<string name="nearest_neighbor">Nærmeste nabo</string>
|
<string name="nearest_neighbor">Nærmeste nabo</string>
|
||||||
|
<string name="linear">Lineær</string>
|
||||||
|
|
||||||
<!-- Sound output modes -->
|
<!-- Sound output modes -->
|
||||||
<string name="mono">Mono</string>
|
<string name="mono">Mono</string>
|
||||||
<string name="stereo">Stereo</string>
|
<string name="stereo">Stereo</string>
|
||||||
|
@ -765,4 +790,5 @@
|
||||||
<string name="mac_address">MAC-adresse</string>
|
<string name="mac_address">MAC-adresse</string>
|
||||||
<string name="regenerate_mac_address">Udtag ny MAC-adresse</string>
|
<string name="regenerate_mac_address">Udtag ny MAC-adresse</string>
|
||||||
<string name="regenerate_mac_address_description">Dette vil erstatte din nuværende MAC-adresse med en ny. Det anbefales ikke at gøre dette, hvis du har fået MAC-adressen fra din rigtige konsol ved hjælp af opsætningsværktøjet. Fortsætte?</string>
|
<string name="regenerate_mac_address_description">Dette vil erstatte din nuværende MAC-adresse med en ny. Det anbefales ikke at gøre dette, hvis du har fået MAC-adressen fra din rigtige konsol ved hjælp af opsætningsværktøjet. Fortsætte?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -83,9 +83,13 @@
|
||||||
<string name="warning_cancel">Cancelar</string>
|
<string name="warning_cancel">Cancelar</string>
|
||||||
<string name="select_citra_user_folder">Seleccionar Carpeta de Usuario</string>
|
<string name="select_citra_user_folder">Seleccionar Carpeta de Usuario</string>
|
||||||
<string name="select_citra_user_folder_description"><![CDATA[Selecciona tu directorio de <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">datos de usuario</a> con el botón de abajo.]]></string>
|
<string name="select_citra_user_folder_description"><![CDATA[Selecciona tu directorio de <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">datos de usuario</a> con el botón de abajo.]]></string>
|
||||||
|
<string name="select_which_user_directory_to_use">Parece que tienes directorios de usuario configurados tanto para Lime3DS como para Azahar. Probablemente se deba a que actualizaste a Azahar y, cuando se te pidió, elegiste un directorio de usuario diferente al que usabas para Lime3DS.\n\nEsto puede haberte hecho pensar que perdiste partidas guardadas u otras configuraciones; te pedimos disculpas si eso ocurrió.\n\n¿Prefieres volver a usar tu directorio de usuario original de Lime3DS, restaurando la configuración y las partidas guardadas de Lime3DS, o conservar tu directorio de usuario actual de Azahar?\n\nNinguno de los directorios se eliminará, independientemente de tu elección, y puedes cambiar libremente entre ellos usando la opción \"Seleccionar carpeta de usuario\".</string>
|
||||||
|
<string name="keep_current_azahar_directory">Mantener el directorio Azahar actual</string>
|
||||||
|
<string name="use_prior_lime3ds_directory">Usar el directorio de Lime3DS anterior</string>
|
||||||
<string name="select">Seleccionar</string>
|
<string name="select">Seleccionar</string>
|
||||||
<string name="cannot_skip">No puedes saltarte este paso</string>
|
<string name="cannot_skip">No puedes saltarte este paso</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="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="set_up_theme_settings">Configuración de tema</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_theme_settings_description">Configura tus preferencias de tema de Azahar.</string>
|
||||||
<string name="setup_set_theme">Establecer tema</string>
|
<string name="setup_set_theme">Establecer tema</string>
|
||||||
|
@ -122,6 +126,7 @@
|
||||||
<string name="input_binding_description_horizontal_axis">Mueve el joystick a izquierda o derecha.</string>
|
<string name="input_binding_description_horizontal_axis">Mueve el joystick a izquierda o derecha.</string>
|
||||||
<string name="button_home">HOME</string>
|
<string name="button_home">HOME</string>
|
||||||
<string name="button_swap">Intercambiar Pantallas</string>
|
<string name="button_swap">Intercambiar Pantallas</string>
|
||||||
|
<string name="button_turbo">Turbo</string>
|
||||||
<string name="input_message_analog_only">¡Este control debe asignarse a un stick analógico del mando o a un eje del Pad de Control!</string>
|
<string name="input_message_analog_only">¡Este control debe asignarse a un stick analógico del mando o a un eje del Pad de Control!</string>
|
||||||
<string name="input_message_button_only">¡Este control debe asignarse a un botón del mando!</string>
|
<string name="input_message_button_only">¡Este control debe asignarse a un botón del mando!</string>
|
||||||
|
|
||||||
|
@ -222,11 +227,17 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||||
<string name="asynchronous_gpu">Activar Emulación Asíncrona de la GPU</string>
|
<string name="asynchronous_gpu">Activar Emulación Asíncrona de la GPU</string>
|
||||||
<string name="asynchronous_gpu_description">Usa un hilo separado para emular la GPU de manera asíncrona. Cuando se active, el rendimiento mejorará.</string>
|
<string name="asynchronous_gpu_description">Usa un hilo separado para emular la GPU de manera asíncrona. Cuando se active, el rendimiento mejorará.</string>
|
||||||
<string name="frame_limit_enable">Límite de velocidad</string>
|
<string name="frame_limit_enable">Límite de velocidad</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.</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">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="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="expand_to_cutout_area">Expandir al área de recorte</string>
|
||||||
|
<string name="expand_to_cutout_area_description">Amplía el área de visualización para incluir el área de recorte (o muesca).</string>
|
||||||
|
<string name="emulation_toggle_turbo_speed">Velocidad Turbo</string>
|
||||||
|
<string name="turbo_speed">Velocidad Turbo</string>
|
||||||
|
<string name="turbo_speed_description">Límite de velocidad de emulación utilizado mientras la tecla de acceso rápido turbo está activa.</string>
|
||||||
<string name="internal_resolution">Resolución interna</string>
|
<string name="internal_resolution">Resolución interna</string>
|
||||||
<string name="internal_resolution_description">Especifica la resolución a la que se quiera renderizar. Una alta resolución mejorará la calidad visual un montón, pero también causará un gran impacto en el rendimiento y puede causar fallos en ciertas aplicaciones.</string>
|
<string name="internal_resolution_description">Especifica la resolución a la que se quiera renderizar. Una alta resolución mejorará la calidad visual un montón, pero también causará un gran impacto en el rendimiento y puede causar fallos en ciertas aplicaciones.</string>
|
||||||
|
<string name="internal_resolution_setting_auto">Auto (Tamaño Pantalla)</string>
|
||||||
<string name="internal_resolution_setting_1x">Nativa (400x240)</string>
|
<string name="internal_resolution_setting_1x">Nativa (400x240)</string>
|
||||||
<string name="internal_resolution_setting_2x">2x Nativa (800x480)</string>
|
<string name="internal_resolution_setting_2x">2x Nativa (800x480)</string>
|
||||||
<string name="internal_resolution_setting_3x">3x Nativa (1200x720)</string>
|
<string name="internal_resolution_setting_3x">3x Nativa (1200x720)</string>
|
||||||
|
@ -306,6 +317,8 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||||
<string name="select_rtc_time">Seleccionar hora RTC</string>
|
<string name="select_rtc_time">Seleccionar hora RTC</string>
|
||||||
<string name="reset_setting_confirmation">¿Quiere reiniciar esta configuración a su valor por defecto?</string>
|
<string name="reset_setting_confirmation">¿Quiere reiniciar esta configuración a su valor por defecto?</string>
|
||||||
<string name="setting_not_editable">No puedes editarlo ahora</string>
|
<string name="setting_not_editable">No puedes editarlo ahora</string>
|
||||||
|
<string name="setting_disabled">Configuración deshabilitada</string>
|
||||||
|
<string name="setting_disabled_description">Esta configuración está actualmente deshabilitada debido a que otra configuración no tiene el valor apropiado.</string>
|
||||||
<string name="setting_not_editable_description">Esta opción no puede cambiarse mientras se está ejecutando un juego.</string>
|
<string name="setting_not_editable_description">Esta opción no puede cambiarse mientras se está ejecutando un juego.</string>
|
||||||
<string name="auto_select">Auto-elegir</string>
|
<string name="auto_select">Auto-elegir</string>
|
||||||
|
|
||||||
|
@ -463,6 +476,17 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||||
<!-- About Game Dialog -->
|
<!-- About Game Dialog -->
|
||||||
<string name="play">Jugar</string>
|
<string name="play">Jugar</string>
|
||||||
<string name="shortcut">Atajo</string>
|
<string name="shortcut">Atajo</string>
|
||||||
|
<string name="uninstall_cia">Desinstalar Aplicación</string>
|
||||||
|
<string name="uninstalling">Desinstalando...</string>
|
||||||
|
<string name="game_context_open_save_dir">Abrir Carpeta de Guardado</string>
|
||||||
|
<string name="game_context_open_app">Abrir Carpeta de Aplicación</string>
|
||||||
|
<string name="game_context_open_mods">Abrir Carpeta de Mods</string>
|
||||||
|
<string name="game_context_open_textures">Abrir Carpeta de Texturas</string>
|
||||||
|
<string name="game_context_open_dlc">Abrir Carpeta de DLC</string>
|
||||||
|
<string name="game_context_open_updates">Abrir Carpeta de Actualizaciones</string>
|
||||||
|
<string name="game_context_open_extra">Abrir Carpeta Extra</string>
|
||||||
|
<string name="game_context_uninstall_dlc">Desinstalar DLC</string>
|
||||||
|
<string name="game_context_uninstall_updates">Desinstalar Actualizaciones</string>
|
||||||
|
|
||||||
<!-- Cheats -->
|
<!-- Cheats -->
|
||||||
<string name="cheats">Trucos</string>
|
<string name="cheats">Trucos</string>
|
||||||
|
@ -781,4 +805,5 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||||
<string name="mac_address">Dirección MAC</string>
|
<string name="mac_address">Dirección MAC</string>
|
||||||
<string name="regenerate_mac_address">Regenerar Dirección MAC</string>
|
<string name="regenerate_mac_address">Regenerar Dirección MAC</string>
|
||||||
<string name="regenerate_mac_address_description">Esto reemplazará tu dirección MAC actual por una nueva. No se recomienda hacerlo si obtuviste la dirección MAC de tu consola real con la herramienta de configuración. ¿Continuar?</string>
|
<string name="regenerate_mac_address_description">Esto reemplazará tu dirección MAC actual por una nueva. No se recomienda hacerlo si obtuviste la dirección MAC de tu consola real con la herramienta de configuración. ¿Continuar?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,4 +1,152 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
</resources>
|
<!-- Countries -->
|
||||||
|
<string name="japan">日本</string>
|
||||||
|
<string name="anguilla">アンゴラ</string>
|
||||||
|
<string name="antigua_and_barbuda">アンティグア・バーブーダ</string>
|
||||||
|
<string name="argentina">アルゼンチン</string>
|
||||||
|
<string name="aruba">アルバ</string>
|
||||||
|
<string name="bahamas">バハマ</string>
|
||||||
|
<string name="barbados">バルバドス</string>
|
||||||
|
<string name="belize">ベリーズ</string>
|
||||||
|
<string name="bolivia">ボリビア</string>
|
||||||
|
<string name="brazil">ブラジル</string>
|
||||||
|
<string name="british_virgin_islands">英領ヴァージン諸島</string>
|
||||||
|
<string name="canada">カナダ</string>
|
||||||
|
<string name="cayman_islands">ケイマン諸島</string>
|
||||||
|
<string name="chile">チリ</string>
|
||||||
|
<string name="colombia">コロンビア</string>
|
||||||
|
<string name="costa_rica">コスタリカ</string>
|
||||||
|
<string name="dominica">ドミニカ国</string>
|
||||||
|
<string name="dominican_republic">ドミニカ共和国</string>
|
||||||
|
<string name="ecuador">エクアドル</string>
|
||||||
|
<string name="el_salvador">エルサルバドル</string>
|
||||||
|
<string name="french_guiana">仏領ギアナ</string>
|
||||||
|
<string name="grenada">グレナダ</string>
|
||||||
|
<string name="guadeloupe">グアドループ</string>
|
||||||
|
<string name="guatemala">グアテマラ</string>
|
||||||
|
<string name="guyana">ガイアナ</string>
|
||||||
|
<string name="haiti">ハイチ</string>
|
||||||
|
<string name="honduras">ホンジュラス</string>
|
||||||
|
<string name="jamaica">ジャマイカ</string>
|
||||||
|
<string name="matinique">マルティニーク</string>
|
||||||
|
<string name="mexico">メキシコ</string>
|
||||||
|
<string name="monsterrat">モントセラト</string>
|
||||||
|
<string name="netherlands_antilles">オランダ領アンティル</string>
|
||||||
|
<string name="nicaragua">ニカラグア</string>
|
||||||
|
<string name="panama">パナマ</string>
|
||||||
|
<string name="paraguay">パラグアイ</string>
|
||||||
|
<string name="peru">ペルー</string>
|
||||||
|
<string name="saint_kittis_and_nevis">セントクリストファー・ネーヴィス</string>
|
||||||
|
<string name="saint_lucia">セントルシア</string>
|
||||||
|
<string name="saint_vincent_and_the_grenadines">セントビンセント及びグレナディーン諸島</string>
|
||||||
|
<string name="suriname">スリナム</string>
|
||||||
|
<string name="trinidad_and_tobago">トリニダード・トバゴ</string>
|
||||||
|
<string name="turks_and_caicos_islands">タークス・カイコス諸島</string>
|
||||||
|
<string name="united_states">アメリカ合衆国</string>
|
||||||
|
<string name="uruguay">ウルグアイ</string>
|
||||||
|
<string name="us_virgin_islands">米領ヴァージン諸島</string>
|
||||||
|
<string name="venezuela">ベネズエラ</string>
|
||||||
|
<string name="albania">アルバニア</string>
|
||||||
|
<string name="australia">Australia</string>
|
||||||
|
<string name="austria">オーストリア</string>
|
||||||
|
<string name="belgium">ベルギー</string>
|
||||||
|
<string name="bosnia_and_herzegovnia">ボスニア・ヘルツェゴビナ</string>
|
||||||
|
<string name="botswana">ボツワナ</string>
|
||||||
|
<string name="bulgaria">ブルガリア</string>
|
||||||
|
<string name="croatia">クロアチア</string>
|
||||||
|
<string name="cyprus">キプロス</string>
|
||||||
|
<string name="czech_republic">チェコ共和国</string>
|
||||||
|
<string name="denmark">デンマーク</string>
|
||||||
|
<string name="estonia">エストニア</string>
|
||||||
|
<string name="finland">フィンランド</string>
|
||||||
|
<string name="france">フランス</string>
|
||||||
|
<string name="germany">ドイツ</string>
|
||||||
|
<string name="greece">ギリシャ</string>
|
||||||
|
<string name="hungary">ハンガリー</string>
|
||||||
|
<string name="iceland">アイスランド</string>
|
||||||
|
<string name="ireland">アイルランド</string>
|
||||||
|
<string name="italy">イタリア</string>
|
||||||
|
<string name="latvia">ラトビア</string>
|
||||||
|
<string name="lesotho">レソト</string>
|
||||||
|
<string name="liechtenstein">リヒテンシュタイン</string>
|
||||||
|
<string name="lithuania">リトアニア</string>
|
||||||
|
<string name="luxembourg">ルクセンブルク</string>
|
||||||
|
<string name="macedonia">マケドニア</string>
|
||||||
|
<string name="malta">マルタ</string>
|
||||||
|
<string name="montenegro">モンテネグロ</string>
|
||||||
|
<string name="mozambique">モザンビーク</string>
|
||||||
|
<string name="namibia">ナミビア</string>
|
||||||
|
<string name="netherlands">オランダ</string>
|
||||||
|
<string name="new_zealand">ニュージーランド</string>
|
||||||
|
<string name="norway">ノルウェー</string>
|
||||||
|
<string name="poland">ポーランド</string>
|
||||||
|
<string name="portugal">ポルトガル</string>
|
||||||
|
<string name="romania">ルーマニア</string>
|
||||||
|
<string name="russia">ロシア</string>
|
||||||
|
<string name="serbia">セルビア</string>
|
||||||
|
<string name="slovakia">スロバキア</string>
|
||||||
|
<string name="slovenia">スロベニア</string>
|
||||||
|
<string name="south_africa">南アフリカ</string>
|
||||||
|
<string name="spain">スペイン</string>
|
||||||
|
<string name="swaziland">スワジランド</string>
|
||||||
|
<string name="sweden">スウェーデン</string>
|
||||||
|
<string name="switzerland">スイス</string>
|
||||||
|
<string name="turkey">トルコ</string>
|
||||||
|
<string name="united_kingdom">イギリス</string>
|
||||||
|
<string name="zambia">ザンビア</string>
|
||||||
|
<string name="zimbabwe">ジンバブエ</string>
|
||||||
|
<string name="azerbaijan">アゼルバイジャン</string>
|
||||||
|
<string name="mauritania">モーリタニア</string>
|
||||||
|
<string name="mali">マリ</string>
|
||||||
|
<string name="niger">ニジェール</string>
|
||||||
|
<string name="chad">チャド</string>
|
||||||
|
<string name="sudan">スーダン</string>
|
||||||
|
<string name="eritrea">エリトリア</string>
|
||||||
|
<string name="djibouti">ジブチ</string>
|
||||||
|
<string name="somalia">ソマリア</string>
|
||||||
|
<string name="andorra">アンドラ</string>
|
||||||
|
<string name="gibraltar">ジブラルタル</string>
|
||||||
|
<string name="guernsey">ガーンジー</string>
|
||||||
|
<string name="isle_of_man">マン島</string>
|
||||||
|
<string name="jersey">ジャージー</string>
|
||||||
|
<!-- Months -->
|
||||||
|
<string name="january">1月</string>
|
||||||
|
<string name="february">2月</string>
|
||||||
|
<string name="march">3月</string>
|
||||||
|
<string name="april">4月</string>
|
||||||
|
<string name="may">5月</string>
|
||||||
|
<string name="june">6月</string>
|
||||||
|
<string name="july">7月</string>
|
||||||
|
<string name="august">8月</string>
|
||||||
|
<string name="september">9月</string>
|
||||||
|
<string name="october">10月</string>
|
||||||
|
<string name="november">11月</string>
|
||||||
|
<string name="december">12月</string>
|
||||||
|
|
||||||
|
<string name="artic_base">Artic Base</string>
|
||||||
|
<string name="artic_base_connect_description">Artic Baseのサーバーを実行している実機に接続</string>
|
||||||
|
<string name="artic_base_connect">Artic Baseに接続</string>
|
||||||
|
<string name="artic_base_enter_address">Artic Baseのサーバーアドレスを入力してください</string>
|
||||||
|
<string name="delay_render_thread">描写スレッドを遅延する</string>
|
||||||
|
<string name="delay_render_thread_description">GPUにデータを送信する間、ゲームの描写スレッドを遅延します。動的フレームレートである(ほんの一部の)アプリケーションでのパフォーマンスが向上します。</string>
|
||||||
|
|
||||||
|
<!-- Quickload&Save-->
|
||||||
|
<string name="emulation_quicksave_slot">クイックセーブ</string>
|
||||||
|
<string name="emulation_quicksave">クイックセーブ</string>
|
||||||
|
<string name="emulation_quickload">クイックロード</string>
|
||||||
|
<string name="emulation_occupied_quicksave_slot">クイックセーブ-%1$tF%1$tR</string>
|
||||||
|
<string name="quicksave_saving">セーブ中...</string>
|
||||||
|
<string name="quickload_loading">ロード中...</string>
|
||||||
|
<string name="miscellaneous">その他</string>
|
||||||
|
<string name="instant_debug_log_description">デバッグログを即座にファイルに書き込みます。Azaharがクラッシュしてログが途切れるときに有効にしてください。</string>
|
||||||
|
<string name="enable_required_online_lle_modules">オンラインに必要なLLEモジュールを有効にする(インストール済みの場合)</string>
|
||||||
|
<string name="enable_required_online_lle_modules_desc">eShopやオンラインマルチプレイヤーなどに必要なLLEモジュールを有効にします。</string>
|
||||||
|
<string name="emulation_settings">エミュレーション設定</string>
|
||||||
|
<string name="profile_settings">プロファイル設定</string>
|
||||||
|
<string name="mac_address">MACアドレス</string>
|
||||||
|
<string name="regenerate_mac_address">MACアドレスを再生成</string>
|
||||||
|
<string name="regenerate_mac_address_description">これを行うと、今のMACアドレスを新しいもので置き換えます。セットアップツールで実機からMACアドレスを吸い出した場合、これをするのは推奨しません。続行しますか?</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
|
|
|
@ -2,18 +2,27 @@
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string name="app_notification_channel_description">Azahar 3DS emulatorius</string>
|
<string name="app_notification_channel_description">Azahar 3DS emulatorius</string>
|
||||||
|
<string name="app_notification_running">Azahar veikia</string>
|
||||||
<string name="start">Pradėti</string>
|
<string name="start">Pradėti</string>
|
||||||
<string name="cancelling">Atšaukiama...</string>
|
<string name="cancelling">Atšaukiama...</string>
|
||||||
|
<string name="important">Svarbu</string>
|
||||||
<string name="dont_show_again">Daugiau niekada nerodyti</string>
|
<string name="dont_show_again">Daugiau niekada nerodyti</string>
|
||||||
|
|
||||||
<!-- Home Strings -->
|
<!-- Home Strings -->
|
||||||
<string name="grid_menu_core_settings">Nustatymai</string>
|
<string name="grid_menu_core_settings">Nustatymai</string>
|
||||||
<string name="home_options">Pasirinkimai</string>
|
<string name="home_options">Pasirinkimai</string>
|
||||||
<string name="home_search">Paieška</string>
|
<string name="home_search">Paieška</string>
|
||||||
|
<string name="home_games">Aplikacijos</string>
|
||||||
<string name="share_log">Dalintis žurnalu</string>
|
<string name="share_log">Dalintis žurnalu</string>
|
||||||
|
<string name="share_log_not_found">Žurnalas nerastas</string>
|
||||||
<string name="about">Apie</string>
|
<string name="about">Apie</string>
|
||||||
|
<string name="citra_description">Atviro kodo 3DS emulatorius</string>
|
||||||
<string name="select_gpu_driver_install">Instaliuoti</string>
|
<string name="select_gpu_driver_install">Instaliuoti</string>
|
||||||
<string name="licenses">Licencijos</string>
|
<string name="licenses">Licencijos</string>
|
||||||
|
<!-- Setup strings -->
|
||||||
|
<string name="welcome">Sveiki!</string>
|
||||||
|
<string name="get_started">Pradėti</string>
|
||||||
|
<string name="step_complete">Baigta!</string>
|
||||||
<string name="done">Baigta</string>
|
<string name="done">Baigta</string>
|
||||||
<string name="text_continue">Tęsti</string>
|
<string name="text_continue">Tęsti</string>
|
||||||
<string name="notifications">Pranešimai</string>
|
<string name="notifications">Pranešimai</string>
|
||||||
|
@ -24,38 +33,51 @@
|
||||||
<string name="warning_help">Pagalba</string>
|
<string name="warning_help">Pagalba</string>
|
||||||
<string name="warning_skip">Praleisti</string>
|
<string name="warning_skip">Praleisti</string>
|
||||||
<string name="warning_cancel">Atšaukti</string>
|
<string name="warning_cancel">Atšaukti</string>
|
||||||
|
<string name="select_citra_user_folder">Pasirinkti vartotojo aplanką</string>
|
||||||
<string name="select">Pasirinkti</string>
|
<string name="select">Pasirinkti</string>
|
||||||
|
<string name="cannot_skip">Tu negali praleisti šio žingsnio</string>
|
||||||
|
<string name="search_recently_played">Nesenai žaista</string>
|
||||||
|
<string name="search_recently_added">Nesenai pridėta</string>
|
||||||
<string name="button_swap">Apkeisti ekranus</string>
|
<string name="button_swap">Apkeisti ekranus</string>
|
||||||
|
<!-- System files strings -->
|
||||||
|
<string name="setup_system_files">Sistemos failai</string>
|
||||||
<string name="init_clock">Laikrodis</string>
|
<string name="init_clock">Laikrodis</string>
|
||||||
<!-- System settings strings -->
|
<!-- System settings strings -->
|
||||||
<string name="username">Vartotojo vardas</string>
|
<string name="username">Vartotojo vardas</string>
|
||||||
<string name="clock">Laikrodis</string>
|
<string name="clock">Laikrodis</string>
|
||||||
<string name="emulated_region">Regionas</string>
|
<string name="emulated_region">Regionas</string>
|
||||||
<string name="emulated_language">Kalba</string>
|
<string name="emulated_language">Kalba</string>
|
||||||
|
<string name="birthday">Gimtadienis</string>
|
||||||
<string name="birthday_month">Mėnesis</string>
|
<string name="birthday_month">Mėnesis</string>
|
||||||
<string name="birthday_day">Diena</string>
|
<string name="birthday_day">Diena</string>
|
||||||
<string name="country">Šalis</string>
|
<string name="country">Šalis</string>
|
||||||
|
<string name="console_id">Konsolės ID</string>
|
||||||
<string name="camera_device">Kamera</string>
|
<string name="camera_device">Kamera</string>
|
||||||
<string name="camera_facing_front">Priekio</string>
|
<string name="camera_facing_front">Priekio</string>
|
||||||
<string name="camera_facing_back">Galo</string>
|
<string name="camera_facing_back">Galo</string>
|
||||||
<string name="camera_facing_external">Išorinė</string>
|
<string name="camera_facing_external">Išorinė</string>
|
||||||
<string name="image_flip">Apversti</string>
|
<string name="image_flip">Apversti</string>
|
||||||
|
|
||||||
<string name="shaders_accurate_mul">Tikslus atkurimas</string>
|
<string name="graphics_api">Grafikos API</string>
|
||||||
|
<string name="shaders_accurate_mul">Tikslus atkūrimas</string>
|
||||||
<string name="frame_limit_enable">Riboti greitį</string>
|
<string name="frame_limit_enable">Riboti greitį</string>
|
||||||
<string name="internal_resolution">Vidinė rezoliucija </string>
|
<string name="internal_resolution">Vidinė rezoliucija </string>
|
||||||
<string name="factor3d">Gylis</string>
|
<string name="factor3d">Gylis</string>
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_volume">Garsumas</string>
|
<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="realtime_audio">Įjungti realaus laiko garsą</string>
|
||||||
<string name="layout_screen_orientation_auto_sensor">Automatinis</string>
|
<string name="layout_screen_orientation_auto_sensor">Automatinis</string>
|
||||||
<string name="learn_more">Sužinoti daugiau</string>
|
<string name="learn_more">Sužinoti daugiau</string>
|
||||||
<string name="close">Uždaryti</string>
|
<string name="close">Uždaryti</string>
|
||||||
<string name="reset_all_settings">Atstatyti visus nustatymus?</string>
|
<string name="reset_all_settings">Atstatyti visus nustatymus?</string>
|
||||||
|
<!-- Preferences Screen -->
|
||||||
|
<string name="preferences_settings">Nustatymai</string>
|
||||||
<string name="preferences_system">Sistema</string>
|
<string name="preferences_system">Sistema</string>
|
||||||
<string name="preferences_camera">Kamera</string>
|
<string name="preferences_camera">Kamera</string>
|
||||||
<string name="preferences_graphics">Grafika</string>
|
<string name="preferences_graphics">Grafika</string>
|
||||||
<string name="preferences_audio">Garsas</string>
|
<string name="preferences_audio">Garsas</string>
|
||||||
|
<string name="preferences_theme">Tema ir Spalva</string>
|
||||||
<string name="preferences_layout">Išdėstymas</string>
|
<string name="preferences_layout">Išdėstymas</string>
|
||||||
|
|
||||||
<string name="emulation_show_fps">Rodyti FPS</string>
|
<string name="emulation_show_fps">Rodyti FPS</string>
|
||||||
|
@ -63,6 +85,8 @@
|
||||||
<string name="emulation_done">Baigta</string>
|
<string name="emulation_done">Baigta</string>
|
||||||
<string name="emulation_close_game">Uždaryti žaidimą</string>
|
<string name="emulation_close_game">Uždaryti žaidimą</string>
|
||||||
<string name="menu_emulation_amiibo_remove">Pašalinti</string>
|
<string name="menu_emulation_amiibo_remove">Pašalinti</string>
|
||||||
|
<string name="pause_emulation">Pristabdyti Emuliaciją</string>
|
||||||
|
<string name="resume_emulation">Atstabdyti Emuliaciją</string>
|
||||||
<string name="i_forgot">Aš pamiršau</string>
|
<string name="i_forgot">Aš pamiršau</string>
|
||||||
<string name="camera">Kamera</string>
|
<string name="camera">Kamera</string>
|
||||||
<!-- Microphone -->
|
<!-- Microphone -->
|
||||||
|
@ -70,12 +94,53 @@
|
||||||
<string name="continue_button">Tęsti</string>
|
<string name="continue_button">Tęsti</string>
|
||||||
<!-- About Game Dialog -->
|
<!-- About Game Dialog -->
|
||||||
<string name="play">Žaisti</string>
|
<string name="play">Žaisti</string>
|
||||||
|
<string name="cheats_name">Pavadinimas</string>
|
||||||
|
<string name="cheats_code">Kodas</string>
|
||||||
<string name="cheats_edit">Redaguoti</string>
|
<string name="cheats_edit">Redaguoti</string>
|
||||||
<string name="cheats_delete">Ištrinti</string>
|
<string name="cheats_delete">Ištrinti</string>
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Juodas fonas</string>
|
<string name="use_black_backgrounds">Juodas fonas</string>
|
||||||
<!-- Clock types -->
|
<!-- Clock types -->
|
||||||
<string name="device_clock">Įrenginio laikas</string>
|
<string name="device_clock">Įrenginio laikas</string>
|
||||||
|
<string name="simulated_clock">Netikras laikas</string>
|
||||||
|
|
||||||
|
<string name="language_english">Anglų</string>
|
||||||
|
<!-- Graphics API names -->
|
||||||
|
<string name="opengles">OpenGLES</string>
|
||||||
|
<string name="vulkan">Vulkan</string>
|
||||||
|
|
||||||
|
<!-- Sound output modes -->
|
||||||
|
<string name="mono">Mono</string>
|
||||||
|
<string name="stereo">Stereo</string>
|
||||||
|
<string name="surround">Erdvinis</string>
|
||||||
|
|
||||||
|
<!-- Countries -->
|
||||||
|
<string name="japan">Japonija</string>
|
||||||
|
<string name="anguilla">Angilija</string>
|
||||||
|
<string name="antigua_and_barbuda">Antigva ir Barbuda</string>
|
||||||
|
<string name="argentina">Argentina</string>
|
||||||
|
<string name="aruba">Aruba</string>
|
||||||
|
<string name="bahamas">Bahamos</string>
|
||||||
|
<string name="barbados">Barbadosas</string>
|
||||||
|
<string name="belize">Belizas</string>
|
||||||
|
<string name="bolivia">Bolivija</string>
|
||||||
|
<string name="brazil">Brazilija</string>
|
||||||
|
<string name="canada">Kanada</string>
|
||||||
|
<string name="chile">Čilė</string>
|
||||||
|
<string name="colombia">Kolumbija</string>
|
||||||
|
<string name="costa_rica">Kosta Rika</string>
|
||||||
|
<string name="dominica">Dominika</string>
|
||||||
|
<string name="dominican_republic">Dominikos respublika</string>
|
||||||
|
<string name="ecuador">Ekvadoras</string>
|
||||||
|
<string name="el_salvador">El Salvadoras</string>
|
||||||
|
<string name="french_guiana">Prancūzų Gviana</string>
|
||||||
|
<string name="grenada">Grenada</string>
|
||||||
|
<string name="guadeloupe">Gvadelupa</string>
|
||||||
|
<string name="jamaica">Jamaika</string>
|
||||||
|
<string name="mexico">Meksika</string>
|
||||||
|
<string name="peru">Peru</string>
|
||||||
|
<string name="united_states">Jungtinės Amerikos Valstijos</string>
|
||||||
|
<string name="venezuela">Venesuela</string>
|
||||||
<string name="albania">Albanija</string>
|
<string name="albania">Albanija</string>
|
||||||
<string name="australia">Australija</string>
|
<string name="australia">Australija</string>
|
||||||
<string name="austria">Austrija</string>
|
<string name="austria">Austrija</string>
|
||||||
|
@ -89,5 +154,69 @@
|
||||||
<string name="denmark">Danija</string>
|
<string name="denmark">Danija</string>
|
||||||
<string name="estonia">Estija</string>
|
<string name="estonia">Estija</string>
|
||||||
<string name="finland">Suomija</string>
|
<string name="finland">Suomija</string>
|
||||||
|
<string name="france">Prancūzija</string>
|
||||||
|
<string name="germany">Vokietija</string>
|
||||||
|
<string name="greece">Graikija</string>
|
||||||
|
<string name="hungary">Vengrija</string>
|
||||||
|
<string name="iceland">Islandija</string>
|
||||||
|
<string name="ireland">Airija</string>
|
||||||
|
<string name="italy">Italija</string>
|
||||||
|
<string name="latvia">Latvija</string>
|
||||||
|
<string name="lesotho">Lesotas</string>
|
||||||
|
<string name="liechtenstein">Lichtenšteinas</string>
|
||||||
<string name="lithuania">Lietuva</string>
|
<string name="lithuania">Lietuva</string>
|
||||||
|
<string name="luxembourg">Liuksemburgas</string>
|
||||||
|
<string name="macedonia">Makedonija</string>
|
||||||
|
<string name="malta">Malta</string>
|
||||||
|
<string name="montenegro">Juodkalnija</string>
|
||||||
|
<string name="mozambique">Mozambikas</string>
|
||||||
|
<string name="namibia">Namibija</string>
|
||||||
|
<string name="netherlands">Nyderlandai</string>
|
||||||
|
<string name="new_zealand">Naujoji Zelandija</string>
|
||||||
|
<string name="norway">Norvegija</string>
|
||||||
|
<string name="poland">Lenkija</string>
|
||||||
|
<string name="portugal">Portugalija</string>
|
||||||
|
<string name="romania">Rumunija</string>
|
||||||
|
<string name="russia">Rusija</string>
|
||||||
|
<string name="serbia">Serbija</string>
|
||||||
|
<string name="slovakia">Slovakija</string>
|
||||||
|
<string name="slovenia">Slovėnija</string>
|
||||||
|
<string name="south_africa">Pietų Afrika</string>
|
||||||
|
<string name="spain">Ispanija</string>
|
||||||
|
<string name="swaziland">Svazilandas</string>
|
||||||
|
<string name="sweden">Švedija</string>
|
||||||
|
<string name="switzerland">Šveicarija</string>
|
||||||
|
<string name="turkey">Turkija</string>
|
||||||
|
<string name="united_kingdom">Jungtinė Karalystė</string>
|
||||||
|
<string name="zambia">Zambija</string>
|
||||||
|
<string name="zimbabwe">Zimbabvė</string>
|
||||||
|
<string name="azerbaijan">Azerbaidžanas</string>
|
||||||
|
<string name="mauritania">Mauritanija</string>
|
||||||
|
<string name="mali">Malis</string>
|
||||||
|
<string name="niger">Nigeris</string>
|
||||||
|
<string name="chad">Čadas</string>
|
||||||
|
<string name="sudan">Sudanas</string>
|
||||||
|
<string name="andorra">Andora</string>
|
||||||
|
<string name="taiwan">Taivanas</string>
|
||||||
|
<string name="south_korea">Pietų Korėja</string>
|
||||||
|
<string name="hong_kong">Hong Kongas</string>
|
||||||
|
<string name="macau">Makao</string>
|
||||||
|
<string name="indonesia">Indonezija</string>
|
||||||
|
<string name="singapore">Singapūras</string>
|
||||||
|
<string name="thailand">Tailandas</string>
|
||||||
|
<string name="philippines">Filipinai</string>
|
||||||
|
<string name="malaysia">Malaizija</string>
|
||||||
|
<string name="china">Kinija</string>
|
||||||
|
<string name="united_arab_emirates">Jungtiniai Arabų Emyratai</string>
|
||||||
|
<string name="india">Indija</string>
|
||||||
|
<string name="egypt">Egiptas</string>
|
||||||
|
<string name="oman">Omanas</string>
|
||||||
|
<string name="san_marino">San Marinas</string>
|
||||||
|
<string name="vatican_city">Vatikanas</string>
|
||||||
|
<!-- Months -->
|
||||||
|
<string name="january">Sausis</string>
|
||||||
|
<string name="february">Vasaris</string>
|
||||||
|
<string name="march">Kovas</string>
|
||||||
|
<string name="april">Balandis</string>
|
||||||
|
<string name="may">Gegužė</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -122,6 +122,7 @@
|
||||||
<string name="input_binding_description_horizontal_axis">Przesuń analog w lewo lub w prawo.</string>
|
<string name="input_binding_description_horizontal_axis">Przesuń analog w lewo lub w prawo.</string>
|
||||||
<string name="button_home">HOME</string>
|
<string name="button_home">HOME</string>
|
||||||
<string name="button_swap">Zamień ekrany</string>
|
<string name="button_swap">Zamień ekrany</string>
|
||||||
|
<string name="button_turbo">Turbo</string>
|
||||||
<string name="input_message_analog_only">Ten kontroler musi być powiązany z drążkiem analogowym gamepada lub z krzyżakiem!</string>
|
<string name="input_message_analog_only">Ten kontroler musi być powiązany z drążkiem analogowym gamepada lub z krzyżakiem!</string>
|
||||||
<string name="input_message_button_only">Ten kontroler musi być powiązany z przyciskiem gamepada!</string>
|
<string name="input_message_button_only">Ten kontroler musi być powiązany z przyciskiem gamepada!</string>
|
||||||
|
|
||||||
|
@ -179,6 +180,10 @@
|
||||||
<string name="plugin_loader_description">Ładuje wtyczki 3GX z emulowanej karty SD, jeśli są dostępne.</string>
|
<string name="plugin_loader_description">Ładuje wtyczki 3GX z emulowanej karty SD, jeśli są dostępne.</string>
|
||||||
<string name="allow_plugin_loader">Zezwól aplikacjom na zmianę stanu programu ładującego wtyczki</string>
|
<string name="allow_plugin_loader">Zezwól aplikacjom na zmianę stanu programu ładującego wtyczki</string>
|
||||||
<string name="allow_plugin_loader_description">Umożliwia aplikacjom homebrew włączenie programu ładującego wtyczki, nawet jeśli jest on wyłączony.</string>
|
<string name="allow_plugin_loader_description">Umożliwia aplikacjom homebrew włączenie programu ładującego wtyczki, nawet jeśli jest on wyłączony.</string>
|
||||||
|
<string name="region_mismatch">Ostrzeżenie o niedopasowaniu regionów</string>
|
||||||
|
<string name="region_mismatch_emulated">Ustawienie kraju nie jest prawidłowe dla wybranego emulowanego regionu.</string>
|
||||||
|
<string name="region_mismatch_console">Ustawienie kraju nie jest prawidłowe dla aktualnie podłączonej konsoli.</string>
|
||||||
|
|
||||||
<!-- Camera settings strings -->
|
<!-- Camera settings strings -->
|
||||||
<string name="inner_camera">Kamera wewnętrzna</string>
|
<string name="inner_camera">Kamera wewnętrzna</string>
|
||||||
<string name="outer_left_camera">Lewa zewnętrzna kamera</string>
|
<string name="outer_left_camera">Lewa zewnętrzna kamera</string>
|
||||||
|
@ -217,11 +222,17 @@
|
||||||
<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="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">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.</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">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="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="expand_to_cutout_area">Rozszerz do obszaru wycięcia</string>
|
||||||
|
<string name="expand_to_cutout_area_description">Rozszerza obszar wyświetlania o obszar wycięcia.</string>
|
||||||
|
<string name="emulation_toggle_turbo_speed">Prędkość Turbo</string>
|
||||||
|
<string name="turbo_speed">Prędkość Turbo</string>
|
||||||
|
<string name="turbo_speed_description">Limit prędkości emulacji wykorzystywany, gdy aktywny jest klawisz skrótu turbo.</string>
|
||||||
<string name="internal_resolution">Rozdzielczość Wewnętrzna</string>
|
<string name="internal_resolution">Rozdzielczość Wewnętrzna</string>
|
||||||
<string name="internal_resolution_description">Określa rozdzielczość używaną do renderowania. Wysoka rozdzielczość znacznie poprawi jakość wizualną, ale jest również dość obciążająca dla wydajności i może powodować błędy w niektórych aplikacjach.</string>
|
<string name="internal_resolution_description">Określa rozdzielczość używaną do renderowania. Wysoka rozdzielczość znacznie poprawi jakość wizualną, ale jest również dość obciążająca dla wydajności i może powodować błędy w niektórych aplikacjach.</string>
|
||||||
|
<string name="internal_resolution_setting_auto">Automatyczne (Rozmiar ekranu)</string>
|
||||||
<string name="internal_resolution_setting_1x">Natywna (400x240)</string>
|
<string name="internal_resolution_setting_1x">Natywna (400x240)</string>
|
||||||
<string name="internal_resolution_setting_2x">2x Natywna (800x480)</string>
|
<string name="internal_resolution_setting_2x">2x Natywna (800x480)</string>
|
||||||
<string name="internal_resolution_setting_3x">3x Natywna (1200x720)</string>
|
<string name="internal_resolution_setting_3x">3x Natywna (1200x720)</string>
|
||||||
|
@ -301,6 +312,8 @@
|
||||||
<string name="select_rtc_time">Wybierz czas RTC</string>
|
<string name="select_rtc_time">Wybierz czas RTC</string>
|
||||||
<string name="reset_setting_confirmation">Czy chcesz przywrócić to ustawienie do domyślnej wartości?</string>
|
<string name="reset_setting_confirmation">Czy chcesz przywrócić to ustawienie do domyślnej wartości?</string>
|
||||||
<string name="setting_not_editable">Nie możesz teraz tego edytować</string>
|
<string name="setting_not_editable">Nie możesz teraz tego edytować</string>
|
||||||
|
<string name="setting_disabled">Ustawienie wyłączone</string>
|
||||||
|
<string name="setting_disabled_description">To ustawienie jest obecnie wyłączone, ponieważ inne ustawienie nie jest odpowiednią wartością.</string>
|
||||||
<string name="setting_not_editable_description">Tej opcji nie można zmienić podczas gry.</string>
|
<string name="setting_not_editable_description">Tej opcji nie można zmienić podczas gry.</string>
|
||||||
<string name="auto_select">Wybór automatyczny</string>
|
<string name="auto_select">Wybór automatyczny</string>
|
||||||
|
|
||||||
|
@ -458,6 +471,16 @@
|
||||||
<!-- About Game Dialog -->
|
<!-- About Game Dialog -->
|
||||||
<string name="play">Odtwórz</string>
|
<string name="play">Odtwórz</string>
|
||||||
<string name="shortcut">Skrót</string>
|
<string name="shortcut">Skrót</string>
|
||||||
|
<string name="uninstalling">Odinstalowywanie...</string>
|
||||||
|
<string name="game_context_open_save_dir">Otwórz folder zapisanych danych</string>
|
||||||
|
<string name="game_context_open_app">Otwórz folder aplikacji</string>
|
||||||
|
<string name="game_context_open_mods">Otwórz folder modów</string>
|
||||||
|
<string name="game_context_open_textures">Otwórz folder tekstur</string>
|
||||||
|
<string name="game_context_open_dlc">Otwórz folder z plikami DLC</string>
|
||||||
|
<string name="game_context_open_updates">Otwórz folder aktualizacji</string>
|
||||||
|
<string name="game_context_open_extra">Otwórz folder Extra</string>
|
||||||
|
<string name="game_context_uninstall_dlc">Odinstaluj DLC</string>
|
||||||
|
<string name="game_context_uninstall_updates">Odinstaluj aktualizacje</string>
|
||||||
|
|
||||||
<!-- Cheats -->
|
<!-- Cheats -->
|
||||||
<string name="cheats">Cheaty</string>
|
<string name="cheats">Cheaty</string>
|
||||||
|
@ -777,4 +800,5 @@
|
||||||
<string name="mac_address">Adres MAC</string>
|
<string name="mac_address">Adres MAC</string>
|
||||||
<string name="regenerate_mac_address">Wygeneruj adres MAC</string>
|
<string name="regenerate_mac_address">Wygeneruj adres MAC</string>
|
||||||
<string name="regenerate_mac_address_description">Spowoduje to zastąpienie bieżącego adresu MAC nowym. Nie zaleca się wykonywania tej czynności, jeśli adres MAC został uzyskany z rzeczywistej konsoli za pomocą narzędzia konfiguracyjnego. Kontynuować?</string>
|
<string name="regenerate_mac_address_description">Spowoduje to zastąpienie bieżącego adresu MAC nowym. Nie zaleca się wykonywania tej czynności, jeśli adres MAC został uzyskany z rzeczywistej konsoli za pomocą narzędzia konfiguracyjnego. Kontynuować?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|