Compare commits

...

107 Commits

Author SHA1 Message Date
OpenSauce
67f6735f02
qt: Add game launch stress test functionality behind new ENABLE_DEVELOPER_OPTIONS CMake option (#1442)
* qt: Implemented game launch stress test

* qt: Hide stress test behind ENABLE_DEVELOPER_OPTIONS CMake option
2025-10-21 16:29:15 +01:00
OpenSauce04
1f483e1d33 cmake: Fixed build issues on *nix introduced by Qt 6.10.0 2025-10-21 14:45:40 +00:00
OpenSauce04
068fec0d5f ci: Updated ARM64 and universal macOS runners to macOS 26 Tahoe 2025-10-03 17:35:02 +00:00
David Griswold
f309d4881a android: Add Display Listener methods for smoother secondary display updates 2025-10-03 17:04:57 +00:00
OpenSauce04
80ba2058a9 externals: Updated fmt to 12.0.0
This fixes a build failure with Clang 21
2025-10-03 16:28:01 +01:00
huesos_96
3716f6b9b6
Android: Dual screen fixes for Handhelds that have 2 screens like Ayaneo Pocket DS (#1341)
* Prevent SecondaryDisplay from stealing focus

The SecondaryDisplay Activity was stealing focus from the main
Activity when it was launched.

Set the `FLAG_NOT_FOCUSABLE` and `FLAG_NOT_TOUCH_MODAL` window flags
to prevent the SecondaryDisplay from gaining focus.

* Implement touch controls for secondary display

This commit introduces touch input handling for the secondary display.

The following changes were made:
- Added `onSecondaryTouchEvent` and `onSecondaryTouchMoved` to `NativeLibrary.kt` and `native.cpp` to process touch events on the secondary display.
- Implemented `onTouchListener` in `SecondaryDisplay.kt` to capture touch events and forward them to the native layer.
- Handles `ACTION_DOWN`, `ACTION_POINTER_DOWN`, `ACTION_MOVE`, `ACTION_UP`, `ACTION_POINTER_UP`, and `ACTION_CANCEL` motion events.
- Tracks the active pointer to ensure correct touch event handling.

* Refactor display logic for multi-display support

This commit introduces a `DisplayHelper` class to centralize display-related logic, particularly for handling scenarios where the application might be launched on an external display.

Key changes:
- Added `DisplayHelper.kt` to manage internal and external display identification based on launch conditions.
- `MainActivity` and `EmulationActivity` now use `DisplayHelper.checkLaunchDisplay()` to determine the initial display.
- `SecondaryDisplay` now uses `DisplayHelper.getExternalDisplay()` to correctly identify the target display for the secondary presentation.
- `InputOverlay` now queries `DisplayHelper.isBottomOnPrimary()` to determine if touch input should be processed for the primary display based on the current screen layout.
- `SecondaryDisplay` now queries `DisplayHelper.isBottomOnSecondary()` to conditionally pass touch events to the native layer based on which screen (primary or secondary) is currently displaying the 3DS bottom screen.

These changes ensure that the application behaves correctly when launched on either the internal or an external display, and that touch input is routed appropriately based on the user's chosen screen layout for the dual screens.

* Removed primary-screen checks so the input overlay always forwards touch events, ensuring all touches reach the native handler even when multiple displays are active

* Remove DisplayHelper class and adjust external display logic

* Formatting adjustments

---------

Co-authored-by: DavidRGriswold <novachild@gmail.com>
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-10-03 14:45:49 +01:00
OpenSauce04
3af2cd1227 ci: Update all macOS runners to macOS 15 Sequoia 2025-10-03 14:17:27 +01:00
lannoene
0be78e9550
Improve DLP and multiplayer compatability (#1375)
* Added NWM spectator mode (DLP now partially working), fixed debug assert, added applet utility cmd fallback

* Reverted AppletUtility command change

* Fixed inconsistent mac address

* Enabled DLP Child authorization

* Added the DLP module to recommended online modules

* Clean up

* Changed the returned number of words on GetProgramInfoFromCia to 7 insteead of 8, futher reverted AppletUtility function to match its original form
2025-09-20 19:59:54 +02:00
OpenSauce04
eb1197a65c cmake: Remove SYSTEM from target_link_libraries 2025-09-16 16:05:38 +01:00
OpenSauce04
a674eb8367 vk_pipeline_cache: Fix directory creation failure if shaders/vulkan/ is missing 2025-09-13 01:19:52 +01:00
OpenSauce04
118d124852 tools: Added Github cache purge script 2025-09-13 01:19:19 +01:00
OpenSauce04
34d46528eb Bump minimum Android version to Android 10 2025-09-11 01:08:32 +01:00
OpenSauce04
72c924a456 android: Rename performance overlay setting keys, strings and enums for clarity 2025-09-10 22:49:46 +01:00
OpenSauce04
f27490aeab android: Mark performance overlay toggle in settings as non-runtime-editable 2025-09-10 22:49:46 +01:00
OpenSauce04
ed451a72d9 android: Reimplemented performance overlay setting as a regular BooleanSetting 2025-09-10 22:49:46 +01:00
OpenSauce04
5c89977605 android: Removed hardcoded setting keys and default values for perf overlay 2025-09-10 22:49:46 +01:00
Briar
deda004227 renderer_opengl.cpp: Remove isPortrait check for second screen opacity 2025-09-10 18:43:44 +01:00
Briar
64f5277789 renderer_vulkan: Add second screen opacity support
& Update bottom screen opacity label in UI
2025-09-10 18:43:44 +01:00
marsia
5c5b1cdf45 android: Implement Hide All 3DS Images from Android setting
Co-Authored-By: Reg Tiangha <rtiangha@users.noreply.github.com>
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-10 18:28:37 +01:00
marsia
750286ae97 android: Add second screen opacity option
Co-authored-by: Reg Tiangha <rtiangha@users.noreply.github.com>
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-10 18:22:55 +01:00
Reg Tiangha
f35091eeb4 android: Implement Background Color settings UI
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-10 18:22:38 +01:00
OpenSauce04
8cd3bcc0e3 Updated compatibility list 2025-09-05 22:13:02 +01:00
OpenSauce04
e200bcbcbc tools: Updated guidance regarding translation updates 2025-09-05 21:56:02 +01:00
David Griswold
a2e6891f01 android: Re-fixed game termination bug (#1357)
* EmulationActivity and EmulationFragment clear only their own hooks

* EmulationLifecycleUtil: Rename `remove()` to `removeHook()`

* EmulationLifecycleUtil: Removed unused function `clear()`

* Corrected somewhat incorrect usage of the word "hook"

* Define `onShutdown` and `onPause` hook functions in constructors

* Formatting nitpicks

* Updated license header

* Re-added log messages for attempting to add duplicate hooks

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-05 21:36:01 +01:00
OpenSauce04
e0078b2407 Revert "Fix android termination bug (#1354)"
This reverts commit 70f9379eefc84b7651e3aababcce33987e073ed0.
2025-09-05 21:33:32 +01:00
OpenSauce04
1830290e55 SecondaryDisplay.kt: Remove redundant SurfaceTexture, preventing log spam 2025-09-05 16:44:48 +00:00
David Griswold
70f9379eef
Fix android termination bug (#1354)
* move hook additions to onCreateView

* Updated license header

* Formatting nitpick

* Added prefix to log messages

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-04 22:35:10 +01:00
OpenSauce04
b63d7841dd macos: Set UIDesignRequiresCompatibility to true 2025-09-03 23:02:08 +01:00
OpenSauce04
944cb7ab51 android: Bump Vulkan Validation Layers to SDK 1.4.313.0 2025-09-03 22:31:01 +01:00
DavidRGriswold
e5c3a0eef7 android: Prevent crash when editing a slider option with an out of bounds value
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-03 13:16:55 +01:00
OpenSauce04
16b8a78571 macos: Patch QMetalLayer.setNeedsDisplayInRect at runtime to avoid freezing on recent Qt 2025-09-03 03:15:14 +01:00
OpenSauce04
bf03cac9e1 cmake: On Windows, download MSVC 2022 Qt versions instead of MSVC 2019 2025-09-03 03:15:14 +01:00
OpenSauce04
b6be443069 cmake: Bump downloaded Qt version to 6.9.2
Also bumps aqtinstall to 3.3.0
2025-09-03 03:15:14 +01:00
OpenSauce04
10f6e1f6f7 cmake: Added check for minimum AppleClang version 2025-09-02 14:05:51 +01:00
RedBlackAka
6483b33ee1
Improve consistency of capitalization and colon usage in UI (#1306)
* frontend: Improve consistency of capitalization and : usage in UI

* Additional adjustments

* Further adjustments

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-09-01 01:43:54 +01:00
OpenSauce04
485db276e3 cmake: Corrected widespread incorrect usage of the SYSTEM property 2025-09-01 00:42:08 +01:00
OpenSauce04
20d577f9e3 Updated translations via Transifex 2025-08-20 13:58:33 +01:00
PabloMK7
48db1c1de5
am: fix save data being deleted on CIA install failure (#1319) 2025-08-20 14:48:34 +02:00
OpenSauce04
219b8dca2e Updated language translations via Transifex 2025-08-15 20:38:25 +01:00
OpenSauce
8fe05d5b74
ci: Don't cancel other builds in matrix if one fails 2025-08-11 12:33:52 +01:00
OpenSauce04
d79078c2d8 Updated language translations via Transifex 2025-08-11 12:04:03 +01:00
OpenSauce04
ff915b2fe1 Updated compatibility list 2025-08-11 12:02:01 +01:00
OpenSauce04
2f6e8b5756 android: Reimplement multitouch code correctly 2025-08-11 11:50:30 +01:00
OpenSauce04
a964e63722 Revert "android: Gross disgusting awful workaround for #1267"
This reverts commit 106e994dbf31bfae503551326a1a4b0c48647fab.
2025-08-11 11:50:30 +01:00
OpenSauce04
2087f96e90 qt: Prerelease builds now direct users to upgrade via GitHub rather than azahar-emu.org 2025-08-10 22:22:47 +01:00
OpenSauce04
68aab3e0e5 android: Fixed UI perf regression w/ OpenGL introduced by #617 2025-08-10 20:15:04 +01:00
OpenSauce04
c86830313e Updated language translations via Transifex 2025-08-08 23:19:15 +01:00
OpenSauce04
e3bfe497f2 Updated compatibility list 2025-08-08 22:58:41 +01:00
PabloMK7
dc2ab096cb loader: Fix compressed 3dsx icon reading 2025-08-08 22:46:17 +01:00
PabloMK7
4bf9161bcd android: Fix 3dsx listing 2025-08-08 22:46:17 +01:00
David Griswold
aca8b45664
android: Implement secondary display support (#617)
* Enable the SecondScreenPresentation class

* Update everything to enable second screen on android under GL and Vulkan. Still some issues!

* Some attempts to enable surface changes

* OpenGL is working on surface change, vulkan still no

* release surfaces (also fixed vulkan?)

* added and enabled layout setting

* resolve merge conflict

* rearrange switch cases to satisfy linux compiler

* openGL is working!

* several vk changes to try to fix crashes

* maybe vulkan is working?

* removing unnecessary code attempts

* Simplified secondscreen for better performance

* vk_platform.cpp: Fixed build failure caused by bad rebase

* vk_present_window.h: Removed stray newline

* Applied clang-format

* bug fix for odin 2

* Applied clang-format

* Updated license headers

* Moved SecondScreen class to org.citra.citra_emu.display

* Various formatting and readability improvements

* Added brackets where previously absent for readability

* Additional readability improvement

* RendererVulkan::NotifySurfaceChanged: Simplified condition checking

* change all references to "secondary screen" to "secondary display" to limit confusion with top screen / bottom screen

* rename main_window to main_present_window and second_window to secondary_present_window

* Reverted accidentally downgraded compatibility list submodule

* Removed unnecessary log message

* Applied clang-format

* Added a description to the Secondary Display Screen Layout setting

* Added `_ptr` suffix to `secondary_present_window`

This distinguishes it as a pointer, as `main_present_window` isn't a pointer, so there could be confusion on whether to use `.` or `->`

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-08-08 21:41:52 +01:00
OpenSauce04
2697526f34 android: Fixed new compressed format extensions not being handled correctly 2025-08-08 19:16:14 +01:00
Alex
e5838edf9f
MacOS: fix(network): fixes ArticBase UDP buffer handling on macOS (#1263)
* MacOS: fix(network): fixes ArticBase UDP buffer handling on macOS

- Set minimum 8KB UDP receive buffer size on macOS for reliable operation
- Add platform-specific buffer size handling with conditional compilation
- Enhance error logging with errno details and buffer size verification
- Maintain backward compatibility with existing buffer sizes on other platforms

Fixes ArticBase controller input reliability issues on macOS by ensuring
adequate UDP buffer capacity for real-time controller data transmission.

* Remove redundant log

---------

Co-authored-by: Alex Molina <alexmolina@MacBook-Air-de-Alex.local>
Co-authored-by: PabloMK7 <hackyglitch2@gmail.com>
2025-08-07 21:16:15 +02:00
OpenSauce04
1e9614fe4f cmake: Added SPIRV_HEADERS to LIB_VAR_LIST 2025-08-07 13:19:42 +01:00
OpenSauce
80f0c03e54 readme: Updated MacOS install instructions 2025-08-06 17:28:08 +01:00
RedBlackAka
cd333a619a ci: Distribute individual x86_64 and ARM64 macOS builds as well as universal 2025-08-06 17:22:02 +01:00
OpenSauce04
a660d9c04a cmake: Always use bundled spirv-tools, regardless of USE_SYSTEM_GLSLANG 2025-08-06 16:14:48 +01:00
OpenSauce04
f02a25f15f cmake: Added USE_SYSTEM_SPIRV_HEADERS option 2025-08-06 16:14:12 +01:00
RedBlackAka
05aa6af325
Installer: Further cleanups and high DPI support (#1234)
* Installer: Further cleanups and high DPI support

* Reverted removal of `(User)` suffix

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-08-04 13:59:00 +01:00
OpenSauce04
106e994dbf android: Gross disgusting awful workaround for #1267
Revert when no longer needed
2025-08-02 18:15:00 +00:00
OpenSauce04
2ce31e5507 Updated language translations via Transifex 2025-08-01 21:23:54 +01:00
OpenSauce04
bcf77a326b Updated compatibility list 2025-08-01 21:00:18 +01:00
OpenSauce04
efedbb16d0 ci: Dropped iOS build job 2025-08-01 16:09:32 +00:00
OpenSauce
885bb71da8
Use MacOS-specific refresh rate check to avoid SDL race condition (#1262)
* Use MacOS-specific refresh rate check to avoid SDL race condition

* IsLowRefreshRate: Change back to `SDL_Init` just to be safe
2025-08-01 16:45:07 +01:00
OpenSauce04
4b4d4f09da qt: Fixed Azahar icon being accessed incorrectly in about + window icon 2025-07-31 16:39:47 +00:00
David Griswold
36a0b7824d
desktop: Fix horizontal centering single window mode (#1211)
* fix horizontal centering single window mode

* Formatting adjustment

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-07-31 17:27:35 +01:00
RedBlackAka
3b0542f188 Capitalize first letter of builtin shaders 2025-07-31 16:12:49 +01:00
OpenSauce04
ce2bf584c2 android: Upgrade to AGP 8.11.1, Gradle 8.13 2025-07-30 01:13:20 +00:00
RedBlackAka
a5aecf91bb
Replace/remove leftover links for citra website and API #1236 (#1250)
* Replace/remove leftover links for citra website and web services #1236

* Fix license headers

* Restore web service settings
2025-07-28 19:33:53 +02:00
PabloMK7
25d7db7bbe
Z3DS: Mark compressed files in UI and other minor fixes (#1249) 2025-07-28 10:38:23 +02:00
toksn
c95b942ec2
android: Added button sliding to button overlay (#884)
* Added simple button sliding mode

* Added "keep first" button sliding mode

* directly pressed buttons stay active even when sliding off
* further buttons can be triggered via the simple sliding method

* Added button sliding configuration to overlay settings menu

* Updated licences

* Added button sliding activation to dpads and joysticks

* separated handling of buttons, dpads and joysticks needed since they can be activated by moving now

* Adjusted strings

* Changed ButtonSlidingMode values to mirror prior string name changes

* Reverted incorrectly applied language translation

* Nitpicky formatting adjustments

* Shortened string IDs

* hasActiveJoy --> hasActiveJoystick

* showButtonSlidingModeMenu --> showButtonSlidingMenu

* Updated outdated comment relating to `isMotionFirstButton`

Co-authored-by: toksn <toksn@yahoo.de>

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-07-28 02:15:26 +01:00
PabloMK7
00c0f01e73 Z3DS: Add title info and smdh to metadata 2025-07-27 17:13:32 +02:00
PabloMK7
db8aaacb35 Z3DS: Fix minor issues and add Android cia compress setting 2025-07-27 17:13:32 +02:00
PabloMK7
8dafecd528 loader: Add compressed ROM (Z3DS) support 2025-07-27 17:13:32 +02:00
kylon
fcdfe03674
renderer_vulkan: remove out of context SDL_Quit call (fixes #1220) (#1248)
* renderer_vulkan: remove out of context SDL_Quit call (fixes #1220)

SDL_Quit must not be called unless the application must exit or SDL is no longer needed

* comment: simplify, forgot init had ref-count
2025-07-27 13:01:06 +01:00
qr243vbi
687c4415be
Add missing find_package into CMakeLists.txt (#1165)
* Update CMakeLists.txt

* Add missing find_package directive

* Update CMakeLists.txt
2025-07-27 00:35:50 +01:00
OpenSauce04
f7361fdebb bootmanager.cpp: Disabled erroneous format checking for order-sensitive include 2025-07-23 18:34:03 +01:00
OpenSauce04
980f8e02e5 tools: Added delete-ignored-files.sh
This script deletes all files and directories which are ignored by
2025-07-17 22:41:54 +01:00
OpenSauce04
f326e39dba bootmanager.cpp: Removed seemingly unused include on MacOS 2025-07-13 12:25:52 +01:00
OpenSauce04
5937e0bf12 externals: Upgraded Vulkan dependencies to vulkan-sdk-1.4.313.0 2025-07-13 11:20:12 +01:00
OpenSauce04
c1761f87f9 gitmodules: Use tabs for indentation
This is the preferred indentation style of git, and it will use tabs by default when performing git operations which modify submodules
2025-07-12 13:07:08 +01:00
OpenSauce
7c278f9701
android: Implement play time tracking (#813)
* android: Implement play time tacking

Co-Authored-By: Reg Tiangha <rtiangha@users.noreply.github.com>

* Moved playtime manager from `citra_qt` to `common`

* Reimplemented Android play time to use existing logic from desktop

* Updated license headers

* When getting current game ID fails, silently error rather than crashing

* playTimeManagerStart: Check that `play_time_manager` is initialized before using it

---------

Co-authored-by: Kleidis <167202775+kleidis@users.noreply.github.com>
Co-authored-by: Reg Tiangha <rtiangha@users.noreply.github.com>
2025-07-12 13:01:46 +01:00
RedBlackAka
06ed6f3b6d Installer: cleanup NSIS, remove unused code, correct minimum version 2025-07-10 23:57:32 +01:00
Nikki
0453e4463a
GSP: correct MemoryFill interrupt signaling (#1218)
* GSP: correct MemoryFill interrupt signaling

---------

Co-authored-by: PabloMK7 <hackyglitch2@gmail.com>
2025-07-10 23:22:10 +01:00
PabloMK7
d8bef418a7
pica: Fix irq request register behaviour (#1216) 2025-07-10 23:01:53 +01:00
OpenSauce04
df134acefe math_util.cpp: Don't set GCC novector pragma when using GCC <14 2025-07-09 20:02:48 +01:00
Eric Warmenhoven
70314b9465 android: when cross-compiling from macos, don't include objcxx 2025-07-06 17:48:35 +01:00
PabloMK7
de7b457ee4
video_core: Remove assert in OpenGL LoadProgram and better logging (#1200) 2025-06-30 13:34:16 +02:00
OpenSauce04
f00d498f11 citra_sdl: Fixed compile failure due to use of removed function 2025-06-30 10:12:31 +01:00
OpenSauce
df3c0c18e4
renderer_vulkan: Disable FIFO when refresh rate is lower than ~60hz or Apple low power mode is enabled (#1193)
* renderer_vulkan: Disable FIFO when refresh rate is lower than ~60hz

Also disables FIFO when Apple low power mode is enabled, as it can limit the application framerate to 30fps

* renderer_vulkan.cpp: Put `IsLowRefreshRate` into anon namespace + make static
2025-06-29 21:06:44 +01:00
PabloMK7
a15af9b550
video_core: Fix LCD color fill (#1198) 2025-06-29 13:51:29 +02:00
Nikki
4447a5c9f2
[GSP] Set correct stop flag (#1199) 2025-06-29 13:09:03 +02:00
jbm11208
e24f8da113
Add per-title vulkan pipeline cache (#1118) 2025-06-23 20:51:25 +02:00
Qidi
680cbb559d
Fix aac_decoder memory leak (#1167)
* Fix aac_decoder memory leak

Only call NeAACDecInit on the first AAC frame and create new NeAACDecoder on DecoderCommand::Init request

* update license headers

* fix oversight

* reorganized code

-put open new FAAD2 AAC decoder code into a separate function
-removed LOG_INFO for open/close FAAD2 AAC decoder
-added LOG_ERROR when no decoder is created to handle decode request, either decoder creation failed or DecoderCommand::Init command not received

* Update aac_decoder.cpp

fix clang coding style check

* fix load savestate

Loading a savestate creates a situation where decode requests aren't preceded by an init request, so we open a new decoder by default in the constructor. A new AACDecoder instance is always constructed on load savestate.
2025-06-21 11:50:39 +01:00
OpenSauce04
9dc9bf3baf Updated language translations via Transifex 2025-06-20 23:24:51 +01:00
PabloMK7
5f81ac40c8
rasterizer: Increase uniform buffer size (#1174) 2025-06-20 22:10:04 +02:00
PabloMK7
0deb0f50b8
Add "SWP" frame time information (#1173) 2025-06-20 19:26:12 +02:00
kleidis
2b51691d57
android: Fix hotkey presses opening nav drawer even after being bound (#1122)
* android: Fix hotkey presses opening nav drawer even after being bound

* Removed unnecessary return

---------

Co-authored-by: Kleidis <167202775+kleidis@users.noreply.github.com>
Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-06-19 23:48:18 +01:00
marsia
11687fe32b android: Add landscape layout for setup pages 2025-06-19 21:14:26 +00:00
OpenSauce04
9d4d6c5fdc externals: Update libyuv to latest commit
Fixes an Android build failure while using CMake >=4.0
2025-06-19 21:06:10 +00:00
PabloMK7
f26b9b174a
cmake: Bump min version to 3.25 globally and to 3.30.3 for android (#1151)
* cmake: Bump min version to 3.25 and update android to 3.30.3

* app/build.gradle.kts: Set minimum CMake version rather than exact version

---------

Co-authored-by: OpenSauce <opensauce04@gmail.com>
2025-06-18 21:44:42 +02:00
qr243vbi
ce8798fffe
Replace deprecated and removed in boost 1.88 io_service to io_context (#1126)
* Replace deprecated and removed in boost 1.88 io_service for io_context

* More thoroughly replaced references to io_service with io_context

* Updated license header

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
2025-06-17 18:41:22 +00:00
PabloMK7
3c3dd2bd86
am: Improve cia encrypted content detection (#1152) 2025-06-17 14:17:01 +02:00
OpenSauce04
eec1466b7b Updated language translations via Transifex 2025-06-16 16:08:56 +01:00
OpenSauce04
5910edb9fa android: Fixed accurate multiplication setting using async shader value 2025-06-13 11:16:42 +01:00
OpenSauce04
63f52580ca qt: Renamed toggle console setting name to be more accurate 2025-06-09 20:19:40 +01:00
OpenSauce04
d1b80788f6 ci: Corrected Windows Vulkan SDK URL which was taken down by upstream 2025-06-09 19:29:08 +01:00
220 changed files with 14629 additions and 8303 deletions

View File

@ -17,7 +17,7 @@ puts 'done'
print 'Checking files...' print 'Checking files...'
issue_files = [] issue_files = []
branch_changed_files.each do |file_name| branch_changed_files.each do |file_name|
if file_name.end_with?('.cpp', '.h', '.kt', '.kts') and File.file?(file_name) if file_name.end_with?('.cpp', '.h', '.kt', '.kts', '.m', '.mm') and File.file?(file_name)
file_content = File.read(file_name, mode: 'r:bom|utf-8') file_content = File.read(file_name, mode: 'r:bom|utf-8')
if not file_content.start_with?(license_header) if not file_content.start_with?(license_header)
issue_files.push(file_name) issue_files.push(file_name)

View File

@ -25,6 +25,7 @@ jobs:
linux: linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
target: ["appimage", "fresh"] target: ["appimage", "fresh"]
container: container:
@ -61,8 +62,9 @@ jobs:
name: ${{ env.OS }}-${{ env.TARGET }} name: ${{ env.OS }}-${{ env.TARGET }}
path: artifacts/ path: artifacts/
macos: macos:
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-13') || 'macos-14' }} runs-on: ${{ (matrix.target == 'x86_64' && 'macos-15-intel') || 'macos-26' }}
strategy: strategy:
fail-fast: false
matrix: matrix:
target: ["x86_64", "arm64"] target: ["x86_64", "arm64"]
env: env:
@ -87,14 +89,21 @@ jobs:
- name: Build - name: Build
run: ./.ci/macos.sh run: ./.ci/macos.sh
- name: Prepare outputs for caching - name: Prepare outputs for caching
run: mv build/bundle $OS-$TARGET run: cp -R build/bundle $OS-$TARGET
- name: Cache outputs for universal build - name: Cache outputs for universal build
uses: actions/cache/save@v4 uses: actions/cache/save@v4
with: with:
path: ${{ env.OS }}-${{ env.TARGET }} path: ${{ env.OS }}-${{ env.TARGET }}
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }} key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
- name: Pack
run: ./.ci/pack.sh
- name: Upload
uses: actions/upload-artifact@v4
with:
name: ${{ env.OS }}-${{ env.TARGET }}
path: artifacts/
macos-universal: macos-universal:
runs-on: macos-14 runs-on: macos-26
needs: macos needs: macos
env: env:
OS: macos OS: macos
@ -127,6 +136,7 @@ jobs:
windows: windows:
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
target: ["msvc", "msys2"] target: ["msvc", "msys2"]
defaults: defaults:
@ -158,7 +168,7 @@ jobs:
- name: Install vulkan-sdk (MSVC) - name: Install vulkan-sdk (MSVC)
if: ${{ matrix.target == 'msvc' }} if: ${{ matrix.target == 'msvc' }}
run: | run: |
wget https://sdk.lunarg.com/sdk/download/1.4.304.1/windows/vulkansdk-windows-X64-1.4.304.1.exe -O D:/a/_temp/vulkan.exe wget https://sdk.lunarg.com/sdk/download/1.4.304.1/windows/VulkanSDK-1.4.304.1-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
- name: Set up MSYS2 - name: Set up MSYS2
if: ${{ matrix.target == 'msys2' }} if: ${{ matrix.target == 'msys2' }}
@ -232,6 +242,9 @@ jobs:
run: | run: |
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install ccache apksigner -y sudo apt-get install ccache apksigner -y
- name: Update Android SDK CMake version
run: |
echo "y" | ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "cmake;3.30.3"
- name: Build - name: Build
run: JAVA_HOME=$JAVA_HOME_17_X64 ./.ci/android.sh run: JAVA_HOME=$JAVA_HOME_17_X64 ./.ci/android.sh
env: env:
@ -248,28 +261,3 @@ jobs:
with: with:
name: ${{ env.OS }}-${{ env.TARGET }} name: ${{ env.OS }}-${{ env.TARGET }}
path: src/android/app/artifacts/ path: src/android/app/artifacts/
ios:
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
runs-on: macos-14
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_COMPILERCHECK: content
CCACHE_SLOPPINESS: time_macros
OS: ios
TARGET: arm64
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up cache
uses: actions/cache@v4
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-ios-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ios-
- name: Install tools
run: brew install ccache ninja
- name: Build
run: ./.ci/ios.sh

8
.gitmodules vendored
View File

@ -77,7 +77,7 @@
path = externals/vulkan-headers path = externals/vulkan-headers
url = https://github.com/KhronosGroup/Vulkan-Headers url = https://github.com/KhronosGroup/Vulkan-Headers
[submodule "sirit"] [submodule "sirit"]
path = externals/sirit path = externals/sirit/sirit
url = https://github.com/azahar-emu/sirit url = https://github.com/azahar-emu/sirit
[submodule "faad2"] [submodule "faad2"]
path = externals/faad2/faad2 path = externals/faad2/faad2
@ -94,3 +94,9 @@
[submodule "compatibility-list"] [submodule "compatibility-list"]
path = dist/compatibility_list path = dist/compatibility_list
url = https://github.com/azahar-emu/compatibility-list url = https://github.com/azahar-emu/compatibility-list
[submodule "spirv-tools"]
path = externals/spirv-tools
url = https://github.com/KhronosGroup/SPIRV-Tools
[submodule "spirv-headers"]
path = externals/spirv-headers
url = https://github.com/KhronosGroup/SPIRV-Headers

View File

@ -1,5 +1,6 @@
# CMake 3.12 required for 20 to be a valid value for CXX_STANDARD # CMake >=3.12 required for 20 to be a valid value for CXX_STANDARD,
cmake_minimum_required(VERSION 3.15) # and >=3.25 required to make LTO work on Android.
cmake_minimum_required(VERSION 3.25)
# Don't override the warning flags in MSVC: # Don't override the warning flags in MSVC:
cmake_policy(SET CMP0092 NEW) cmake_policy(SET CMP0092 NEW)
@ -16,8 +17,12 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
include(DownloadExternals) include(DownloadExternals)
include(CMakeDependentOption) include(CMakeDependentOption)
include(FindPkgConfig)
project(citra LANGUAGES C CXX ASM) project(citra LANGUAGES C CXX ASM)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
enable_language(OBJC OBJCXX)
endif()
# Some submodules like to pick their own default build type if not specified. # Some submodules like to pick their own default build type if not specified.
# Make sure we default to Release build type always, unless the generator has custom types. # Make sure we default to Release build type always, unless the generator has custom types.
@ -43,6 +48,15 @@ if (APPLE)
else() else()
# Minimum macOS 13 # Minimum macOS 13
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.4") set(CMAKE_OSX_DEPLOYMENT_TARGET "13.4")
# Catch compiler issue on AppleClang versions below 15.0
# TODO: Remove this check when we drop macOS 13 Ventura
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0)
message(FATAL_ERROR "AppleClang 15.0 or later is required due to a compiler bug in earlier versions.\n"
"Current version: ${CMAKE_CXX_COMPILER_VERSION}\n"
"After updating, delete 'CMakeCache.txt' in the build directory.")
endif()
endif() endif()
endif() endif()
@ -107,6 +121,8 @@ option(ENABLE_MICROPROFILE "Enables microprofile capabilities" OFF)
option(ENABLE_SSE42 "Enable SSE4.2 optimizations on x86_64" ON) option(ENABLE_SSE42 "Enable SSE4.2 optimizations on x86_64" ON)
option(ENABLE_DEVELOPER_OPTIONS "Enable functionality targeted at emulator developers" OFF)
# Compile options # Compile options
CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ${IS_DEBUG_BUILD} "MINGW" OFF) CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ${IS_DEBUG_BUILD} "MINGW" OFF)
option(ENABLE_LTO "Enable link time optimization" ${DEFAULT_ENABLE_LTO}) option(ENABLE_LTO "Enable link time optimization" ${DEFAULT_ENABLE_LTO})
@ -124,6 +140,9 @@ endif()
if (ENABLE_ROOM) if (ENABLE_ROOM)
add_definitions(-DENABLE_ROOM) add_definitions(-DENABLE_ROOM)
endif() endif()
if (ENABLE_SDL2)
add_definitions(-DENABLE_SDL2)
endif()
if (ENABLE_SDL2_FRONTEND) if (ENABLE_SDL2_FRONTEND)
add_definitions(-DENABLE_SDL2_FRONTEND) add_definitions(-DENABLE_SDL2_FRONTEND)
endif() endif()
@ -291,7 +310,7 @@ find_package(Threads REQUIRED)
if (ENABLE_QT) if (ENABLE_QT)
if (NOT USE_SYSTEM_QT) if (NOT USE_SYSTEM_QT)
download_qt(6.7.2) download_qt(6.9.2)
endif() endif()
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent) find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
@ -474,12 +493,10 @@ if (ENABLE_SDL2 AND USE_SYSTEM_SDL2)
endif() endif()
if (ENABLE_LIBUSB AND USE_SYSTEM_LIBUSB) if (ENABLE_LIBUSB AND USE_SYSTEM_LIBUSB)
include(FindPkgConfig)
find_package(LibUSB) find_package(LibUSB)
endif() endif()
if (USE_SYSTEM_SOUNDTOUCH) if (USE_SYSTEM_SOUNDTOUCH)
include(FindPkgConfig)
find_package(SoundTouch REQUIRED) find_package(SoundTouch REQUIRED)
add_library(SoundTouch INTERFACE) add_library(SoundTouch INTERFACE)
target_link_libraries(SoundTouch INTERFACE "${SOUNDTOUCH_LIBRARIES}") target_link_libraries(SoundTouch INTERFACE "${SOUNDTOUCH_LIBRARIES}")

View File

@ -20,9 +20,9 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out
set(arch_path "mingw_64") set(arch_path "mingw_64")
elseif (MSVC) elseif (MSVC)
if ("arm64" IN_LIST ARCHITECTURE) if ("arm64" IN_LIST ARCHITECTURE)
set(arch_path "msvc2019_arm64") set(arch_path "msvc2022_arm64")
elseif ("x86_64" IN_LIST ARCHITECTURE) elseif ("x86_64" IN_LIST ARCHITECTURE)
set(arch_path "msvc2019_64") set(arch_path "msvc2022_64")
else() else()
message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.") message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.")
endif() endif()
@ -30,12 +30,13 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out
# In case we're cross-compiling, prepare to also fetch the correct host Qt tools. # In case we're cross-compiling, prepare to also fetch the correct host Qt tools.
if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
set(host_arch_path "msvc2019_64") set(host_arch_path "msvc2022_64")
elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64") elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64")
# TODO: msvc2019_arm64 doesn't include some of the required tools for some reason, # TODO: msvc2019_arm64 doesn't include some of the required tools for some reason,
# TODO: so until it does, just use msvc2019_64 under x86_64 emulation. # TODO: so until it does, just use msvc2019_64 under x86_64 emulation.
# TODO: ^ Is this still true with msvc2022?
# set(host_arch_path "msvc2019_arm64") # set(host_arch_path "msvc2019_arm64")
set(host_arch_path "msvc2019_64") set(host_arch_path "msvc2022_64")
endif() endif()
set(host_arch "win64_${host_arch_path}") set(host_arch "win64_${host_arch_path}")
else() else()
@ -105,7 +106,7 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
if (NOT EXISTS "${prefix}") if (NOT EXISTS "${prefix}")
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}") message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.1.18") set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0")
if (WIN32) if (WIN32)
set(aqt_path "${base_path}/aqt.exe") set(aqt_path "${base_path}/aqt.exe")
if (NOT EXISTS "${aqt_path}") if (NOT EXISTS "${aqt_path}")

View File

@ -22,9 +22,12 @@ If you are unsure of whether you want to use MSYS2 or MSVC, use MSYS2.
### MacOS ### MacOS
Download the latest release from [Releases](https://github.com/azahar-emu/azahar/releases). To download a build that will work on all Macs, you can download the `macos-universal` build on the [Releases](https://github.com/azahar-emu/azahar/releases) page.
The `macos-universal` download will work on both Intel and Apple Silicon Macs. Alternatively, if you wish to download a build specifically for your Mac, you can choose either:
- `macos-arm64` for Apple Silicon Macs
- `macos-x86_64` for Intel Macs
--- ---
### Android ### Android

View File

@ -75,6 +75,9 @@
<true/> <true/>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<string>True</string> <string>True</string>
<key>UIDesignRequiresCompatibility</key>
<true/> <!-- Remove when Qt Liquid Glass issues are fixed upstream:
https://bugreports.qt.io/browse/QTBUG-138942 -->
<key>UIFileSharingEnabled</key> <key>UIFileSharingEnabled</key>
<true/> <true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>

@ -1 +1 @@
Subproject commit 31c12299126baf892b965defc6ba7810b9c42ccf Subproject commit a36decbe43d0e5a570ac3d3ba9a0b226dc832a17

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

862
dist/languages/de.ts vendored

File diff suppressed because it is too large Load Diff

676
dist/languages/el.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

690
dist/languages/fi.ts vendored

File diff suppressed because it is too large Load Diff

686
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

690
dist/languages/id.ts vendored

File diff suppressed because it is too large Load Diff

730
dist/languages/it.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

690
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load Diff

676
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

686
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,37 @@
# Definitions for all external bundled libraries # Definitions for all external bundled libraries
# Suppress warnings from external libraries # Suppress warnings from external libraries
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") if (MSVC)
add_compile_options(/W0) add_compile_options(/W0)
else() else()
add_compile_options(-w) add_compile_options(-w)
endif() endif()
function(target_disable_warnings target)
if (MSVC)
target_compile_options(${target} INTERFACE /W0)
else()
target_compile_options(${target} INTERFACE -w)
endif()
endfunction()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
include(DownloadExternals) include(DownloadExternals)
include(ExternalProject) include(ExternalProject)
# Boost # Boost
if (NOT USE_SYSTEM_BOOST) if (USE_SYSTEM_BOOST)
unset(BOOST_ROOT CACHE)
unset(Boost_INCLUDE_DIR CACHE)
set(Boost_NO_SYSTEM_PATHS OFF CACHE BOOL "" FORCE)
else()
message(STATUS "Including vendored Boost library") message(STATUS "Including vendored Boost library")
set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "") set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "")
add_library(boost INTERFACE) add_library(boost INTERFACE)
target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR}) target_include_directories(boost INTERFACE ${Boost_INCLUDE_DIR})
target_disable_warnings(boost)
# Boost::serialization # Boost::serialization
file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp") file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp")
@ -34,10 +47,6 @@ if (NOT USE_SYSTEM_BOOST)
) )
target_link_libraries(boost_iostreams PUBLIC boost) target_link_libraries(boost_iostreams PUBLIC boost)
# Add additional boost libs here; remember to ALIAS them in the root CMakeLists! # Add additional boost libs here; remember to ALIAS them in the root CMakeLists!
else()
unset(BOOST_ROOT CACHE)
unset(Boost_INCLUDE_DIR CACHE)
set(Boost_NO_SYSTEM_PATHS OFF CACHE BOOL "" FORCE)
endif() endif()
# Catch2 # Catch2
@ -73,6 +82,7 @@ endif()
# dds-ktx # dds-ktx
add_library(dds-ktx INTERFACE) add_library(dds-ktx INTERFACE)
target_include_directories(dds-ktx INTERFACE ./dds-ktx) target_include_directories(dds-ktx INTERFACE ./dds-ktx)
target_disable_warnings(dds-ktx)
# fmt and Xbyak need to be added before dynarmic # fmt and Xbyak need to be added before dynarmic
# libfmt # libfmt
@ -137,7 +147,8 @@ endif()
# MicroProfile # MicroProfile
add_library(microprofile INTERFACE) add_library(microprofile INTERFACE)
target_include_directories(microprofile SYSTEM INTERFACE ./microprofile) target_include_directories(microprofile INTERFACE ./microprofile)
target_disable_warnings(microprofile)
if (ENABLE_MICROPROFILE) if (ENABLE_MICROPROFILE)
target_compile_definitions(microprofile INTERFACE MICROPROFILE_ENABLED=1) target_compile_definitions(microprofile INTERFACE MICROPROFILE_ENABLED=1)
else() else()
@ -146,10 +157,11 @@ endif()
# Nihstro # Nihstro
add_library(nihstro-headers INTERFACE) add_library(nihstro-headers INTERFACE)
target_include_directories(nihstro-headers SYSTEM INTERFACE ./nihstro/include) target_include_directories(nihstro-headers INTERFACE ./nihstro/include)
if (MSVC) target_disable_warnings(nihstro-headers)
# TODO: For some reason MSVC still applies this warning even with /W0 for externals. if (NOT MSVC)
target_compile_options(nihstro-headers INTERFACE /wd4715) # TODO: For some reason MSYS2 still applied this warnin even with -w
target_compile_options(nihstro-headers INTERFACE -Wno-invalid-specialization)
endif() endif()
# Open Source Archives # Open Source Archives
@ -173,7 +185,8 @@ if (USE_SYSTEM_FFMPEG_HEADERS)
endif() endif()
if (NOT FOUND_FFMPEG_HEADERS) if (NOT FOUND_FFMPEG_HEADERS)
message(STATUS "Using bundled ffmpeg headers.") message(STATUS "Using bundled ffmpeg headers.")
target_include_directories(library-headers SYSTEM INTERFACE ./library-headers/ffmpeg/include) target_include_directories(library-headers INTERFACE ./library-headers/ffmpeg/include)
target_disable_warnings(library-headers)
endif() endif()
# SoundTouch # SoundTouch
@ -214,8 +227,29 @@ else()
set(ZSTD_BUILD_PROGRAMS OFF) set(ZSTD_BUILD_PROGRAMS OFF)
set(ZSTD_BUILD_SHARED OFF) set(ZSTD_BUILD_SHARED OFF)
add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL) add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL)
target_include_directories(libzstd_static INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/externals/zstd/lib>)
target_include_directories(libzstd_static INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/externals/zstd/lib>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/externals/zstd/lib/common>
)
add_library(zstd_seekable STATIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zstd/contrib/seekable_format/zstdseek_compress.c>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zstd/contrib/seekable_format/zstdseek_decompress.c>
)
target_include_directories(zstd_seekable PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zstd/contrib/seekable_format>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/zstd/lib/common>
)
target_link_libraries(zstd_seekable PUBLIC libzstd_static)
target_link_libraries(libzstd_static INTERFACE zstd_seekable)
add_library(zstd ALIAS libzstd_static) add_library(zstd ALIAS libzstd_static)
install(TARGETS zstd_seekable
EXPORT zstdExports
)
endif() endif()
# ENet # ENet
@ -273,7 +307,8 @@ if (USE_SYSTEM_JSON)
# Citra uses "#include <json.hpp>" so we have to add this manually # Citra uses "#include <json.hpp>" so we have to add this manually
target_include_directories(json-headers SYSTEM INTERFACE "${NLOHMANN_PREFIX}/nlohmann") target_include_directories(json-headers SYSTEM INTERFACE "${NLOHMANN_PREFIX}/nlohmann")
else() else()
target_include_directories(json-headers SYSTEM INTERFACE ./json) target_include_directories(json-headers INTERFACE ./json)
target_disable_warnings(json-headers)
endif() endif()
# OpenSSL # OpenSSL
@ -289,7 +324,8 @@ if (NOT OPENSSL_FOUND)
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/") set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL) add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl SYSTEM INTERFACE ./libressl/include) target_include_directories(ssl INTERFACE ./libressl/include)
target_disable_warnings(ssl)
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP) target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
get_directory_property(OPENSSL_LIBRARIES get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl DIRECTORY libressl
@ -306,17 +342,20 @@ if(USE_SYSTEM_CPP_HTTPLIB)
get_target_property(HTTP_LIBS httplib::httplib INTERFACE_LINK_LIBRARIES) get_target_property(HTTP_LIBS httplib::httplib INTERFACE_LINK_LIBRARIES)
if(HTTP_LIBS) if(HTTP_LIBS)
message(WARNING "Shared cpp-http (${HTTP_LIBS}) not supported. Falling back to bundled...") message(WARNING "Shared cpp-http (${HTTP_LIBS}) not supported. Falling back to bundled...")
target_include_directories(httplib SYSTEM INTERFACE ./httplib) target_include_directories(httplib INTERFACE ./httplib)
target_disable_warnings(httplib)
else() else()
if(CppHttp_FOUND) if(CppHttp_FOUND)
target_link_libraries(httplib INTERFACE httplib::httplib) target_link_libraries(httplib INTERFACE httplib::httplib)
else() else()
message(STATUS "Cpp-httplib not found or not suitable version! Falling back to bundled...") message(STATUS "Cpp-httplib not found or not suitable version! Falling back to bundled...")
target_include_directories(httplib SYSTEM INTERFACE ./httplib) target_include_directories(httplib INTERFACE ./httplib)
target_disable_warnings(httplib)
endif() endif()
endif() endif()
else() else()
target_include_directories(httplib SYSTEM INTERFACE ./httplib) target_include_directories(httplib INTERFACE ./httplib)
target_disable_warnings(httplib)
endif() endif()
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT) target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES}) target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
@ -333,7 +372,8 @@ if (ENABLE_WEB_SERVICE)
target_link_libraries(cpp-jwt INTERFACE cpp-jwt::cpp-jwt) target_link_libraries(cpp-jwt INTERFACE cpp-jwt::cpp-jwt)
else() else()
add_library(cpp-jwt INTERFACE) add_library(cpp-jwt INTERFACE)
target_include_directories(cpp-jwt SYSTEM INTERFACE ./cpp-jwt/include) target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
target_disable_warnings(cpp-jwt)
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON) target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
endif() endif()
endif() endif()
@ -381,6 +421,24 @@ endif()
# Vulkan dependencies # Vulkan dependencies
if (ENABLE_VULKAN) if (ENABLE_VULKAN)
# spirv-headers
if(USE_SYSTEM_SPIRV_HEADERS)
find_package(SPIRV-Headers REQUIRED)
if(TARGET SPIRV-Headers::SPIRV-Headers)
message(STATUS "Found SPIRV headers")
get_target_property(SPIRV-Headers_SOURCE_DIR SPIRV-Headers::SPIRV-Headers INTERFACE_INCLUDE_DIRECTORIES)
set(SPIRV-Headers_SOURCE_DIR "${SPIRV-Headers_SOURCE_DIR}/../") # Not sure why this is necessary
endif()
else()
set(SPIRV-Headers_SOURCE_DIR "${CMAKE_SOURCE_DIR}/externals/spirv-headers")
add_subdirectory(spirv-headers EXCLUDE_FROM_ALL)
endif()
# spirv-tools
# TODO: Implement USE_SYSTEM_SPIRV_TOOLS -OS
set(SPIRV_SKIP_EXECUTABLES ON)
add_subdirectory(spirv-tools EXCLUDE_FROM_ALL)
# glslang # glslang
if(USE_SYSTEM_GLSLANG) if(USE_SYSTEM_GLSLANG)
find_package(glslang REQUIRED) find_package(glslang REQUIRED)
@ -398,7 +456,6 @@ if (ENABLE_VULKAN)
set(ENABLE_CTEST OFF CACHE BOOL "") set(ENABLE_CTEST OFF CACHE BOOL "")
set(ENABLE_HLSL OFF CACHE BOOL "") set(ENABLE_HLSL OFF CACHE BOOL "")
set(BUILD_EXTERNAL OFF CACHE BOOL "") set(BUILD_EXTERNAL OFF CACHE BOOL "")
set(ALLOW_EXTERNAL_SPIRV_TOOLS ON)
add_subdirectory(glslang) add_subdirectory(glslang)
endif() endif()
@ -415,7 +472,8 @@ if (ENABLE_VULKAN)
endif() endif()
else() else()
add_library(vma INTERFACE) add_library(vma INTERFACE)
target_include_directories(vma SYSTEM INTERFACE ./vma/include) target_include_directories(vma INTERFACE ./vma/include)
target_disable_warnings(vma)
endif() endif()
# vulkan-headers # vulkan-headers
@ -427,7 +485,8 @@ if (ENABLE_VULKAN)
target_link_libraries(vulkan-headers INTERFACE Vulkan::Headers) target_link_libraries(vulkan-headers INTERFACE Vulkan::Headers)
endif() endif()
else() else()
target_include_directories(vulkan-headers SYSTEM INTERFACE ./vulkan-headers/include) target_include_directories(vulkan-headers INTERFACE ./vulkan-headers/include)
target_disable_warnings(vulkan-headers)
endif() endif()
# adrenotools # adrenotools

View File

@ -25,6 +25,7 @@ option(USE_SYSTEM_LODEPNG "Use the system lodepng (instead of the bundled one)"
option(USE_SYSTEM_OPENAL "Use the system OpenAL (instead of the bundled one)" OFF) option(USE_SYSTEM_OPENAL "Use the system OpenAL (instead of the bundled one)" OFF)
option(USE_SYSTEM_VMA "Use the system VulkanMemoryAllocator (instead of the bundled one)" OFF) option(USE_SYSTEM_VMA "Use the system VulkanMemoryAllocator (instead of the bundled one)" OFF)
option(USE_SYSTEM_VULKAN_HEADERS "Use the system Vulkan headers (instead of the bundled ones)" OFF) option(USE_SYSTEM_VULKAN_HEADERS "Use the system Vulkan headers (instead of the bundled ones)" OFF)
option(USE_SYSTEM_SPIRV_HEADERS "Use the system SPIRV headers (instead of the bundled ones)" OFF)
option(USE_SYSTEM_CATCH2 "Use the system Catch2 (instead of the bundled one)" OFF) option(USE_SYSTEM_CATCH2 "Use the system Catch2 (instead of the bundled one)" OFF)
# Qt and MoltenVK are handled separately # Qt and MoltenVK are handled separately
@ -50,6 +51,7 @@ CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_LODEPNG "Disable system lodepng" OFF "USE_
CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_OPENAL "Disable system OpenAL" OFF "USE_SYSTEM_LIBS" OFF) CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_OPENAL "Disable system OpenAL" OFF "USE_SYSTEM_LIBS" OFF)
CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_VMA "Disable system VulkanMemoryAllocator" OFF "USE_SYSTEM_LIBS" OFF) CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_VMA "Disable system VulkanMemoryAllocator" OFF "USE_SYSTEM_LIBS" OFF)
CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_VULKAN_HEADERS "Disable system Vulkan headers" OFF "USE_SYSTEM_LIBS" OFF) CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_VULKAN_HEADERS "Disable system Vulkan headers" OFF "USE_SYSTEM_LIBS" OFF)
CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_SPIRV_HEADERS "Disable system SPIRV headers" OFF "USE_SYSTEM_LIBS" OFF)
CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_CATCH2 "Disable system Catch2" OFF "USE_SYSTEM_LIBS" OFF) CMAKE_DEPENDENT_OPTION(DISABLE_SYSTEM_CATCH2 "Disable system Catch2" OFF "USE_SYSTEM_LIBS" OFF)
set(LIB_VAR_LIST set(LIB_VAR_LIST
@ -75,6 +77,7 @@ set(LIB_VAR_LIST
OPENAL OPENAL
VMA VMA
VULKAN_HEADERS VULKAN_HEADERS
SPIRV_HEADERS
CATCH2 CATCH2
) )

2
externals/fmt vendored

@ -1 +1 @@
Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a Subproject commit e424e3f2e607da02742f73db84873b8084fc714c

2
externals/glslang vendored

@ -1 +1 @@
Subproject commit b3a6aa7b03c51ba976e4f4e96b1e31f77f43f312 Subproject commit fc9889c889561c5882e83819dcaffef5ed45529b

2
externals/libyuv vendored

@ -1 +1 @@
Subproject commit c060118bea3f28ceb837d3c85e479d3bb4c21726 Subproject commit 6f729fbe658a40dfd993fa8b22bd612bb17cde5c

91
externals/sirit/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,91 @@
# This file has been adapted from dynarmic
cmake_minimum_required(VERSION 3.8)
project(sirit CXX)
# Determine if we're built as a subproject (using add_subdirectory)
# or if this is the master project.
set(MASTER_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
endif()
# Sirit project options
option(SIRIT_TESTS "Build tests" OFF)
option(SIRIT_USE_SYSTEM_SPIRV_HEADERS "Use system SPIR-V headers" OFF)
# Default to a Release build
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
message(STATUS "Defaulting to a Release build")
endif()
# Set hard requirements for C++
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Warn on CMake API deprecations
set(CMAKE_WARN_DEPRECATED ON)
# Disable in-source builds
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(SEND_ERROR "In-source builds are not allowed.")
endif()
# Add the module directory to the list of paths
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules")
# Compiler flags
if (MSVC)
set(SIRIT_CXX_FLAGS
/std:c++latest # CMAKE_CXX_STANDARD as no effect on MSVC until CMake 3.10.
/W4
/w34263 # Non-virtual member function hides base class virtual function
/w44265 # Class has virtual functions, but destructor is not virtual
/w34456 # Declaration of 'var' hides previous local declaration
/w34457 # Declaration of 'var' hides function parameter
/w34458 # Declaration of 'var' hides class member
/w34459 # Declaration of 'var' hides global definition
/w34946 # Reinterpret-cast between related types
/wd4592 # Symbol will be dynamically initialized (implementation limitation)
/permissive- # Stricter C++ standards conformance
/MP
/Zi
/Zo
/EHsc
/Zc:throwingNew # Assumes new never returns null
/Zc:inline # Omits inline functions from object-file output
/DNOMINMAX
/WX)
if (CMAKE_VS_PLATFORM_TOOLSET MATCHES "LLVM-vs[0-9]+")
list(APPEND SIRIT_CXX_FLAGS
-Qunused-arguments
-Wno-missing-braces)
endif()
else()
set(SIRIT_CXX_FLAGS
-Wall
-Wextra
-Wcast-qual
-pedantic
-pedantic-errors
-Wfatal-errors
-Wno-missing-braces
-Wconversion
-Wsign-conversion
-Wshadow
-Werror)
endif()
# Enable unit-testing.
enable_testing(true)
# Sirit project files
add_subdirectory(sirit/src)
if (SIRIT_TESTS)
add_subdirectory(sirit/tests)
endif()

1
externals/spirv-headers vendored Submodule

@ -0,0 +1 @@
Subproject commit aa6cef192b8e693916eb713e7a9ccadf06062ceb

1
externals/spirv-tools vendored Submodule

@ -0,0 +1 @@
Subproject commit a62abcb402009b9ca5975e6167c09f237f630e0e

@ -1 +1 @@
Subproject commit d4a196d8c84e032d27f999adcea3075517c1c97f Subproject commit 409c16be502e39fe70dd6fe2d9ad4842ef2c9a53

View File

@ -174,6 +174,9 @@ endif()
if(ENABLE_VULKAN) if(ENABLE_VULKAN)
add_compile_definitions(ENABLE_VULKAN) add_compile_definitions(ENABLE_VULKAN)
endif() endif()
if(ENABLE_DEVELOPER_OPTIONS)
add_compile_definitions(ENABLE_DEVELOPER_OPTIONS)
endif()
add_subdirectory(common) add_subdirectory(common)
add_subdirectory(core) add_subdirectory(core)

View File

@ -64,7 +64,7 @@ android {
// The application ID refers to Lime3DS to allow for // The application ID refers to Lime3DS to allow for
// the Play Store listing, which was originally set up for Lime3DS, to still be used. // the Play Store listing, which was originally set up for Lime3DS, to still be used.
applicationId = "io.github.lime3ds.android" applicationId = "io.github.lime3ds.android"
minSdk = 28 minSdk = 29
targetSdk = 35 targetSdk = 35
versionCode = autoVersion versionCode = autoVersion
versionName = getGitVersion() versionName = getGitVersion()
@ -150,7 +150,7 @@ android {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
version = "3.22.1" version = "3.25.0+"
path = file("../../../CMakeLists.txt") path = file("../../../CMakeLists.txt")
} }
} }
@ -186,7 +186,7 @@ dependencies {
// Download Vulkan Validation Layers from the KhronosGroup GitHub. // Download Vulkan Validation Layers from the KhronosGroup GitHub.
val downloadVulkanValidationLayers = tasks.register<Download>("downloadVulkanValidationLayers") { val downloadVulkanValidationLayers = tasks.register<Download>("downloadVulkanValidationLayers") {
src("https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download/vulkan-sdk-1.4.304.1/android-binaries-1.4.304.1.zip") src("https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download/vulkan-sdk-1.4.313.0/android-binaries-1.4.313.0.zip")
dest(file("${layout.buildDirectory.get().asFile.path}/tmp/Vulkan-ValidationLayers.zip")) dest(file("${layout.buildDirectory.get().asFile.path}/tmp/Vulkan-ValidationLayers.zip"))
onlyIfModified(true) onlyIfModified(true)
} }

View File

@ -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.
@ -58,6 +58,7 @@ class CitraApplication : Application() {
NativeLibrary.logDeviceInfo() NativeLibrary.logDeviceInfo()
logDeviceInfo() logDeviceInfo()
createNotificationChannel() createNotificationChannel()
NativeLibrary.playTimeManagerInit()
} }
fun logDeviceInfo() { fun logDeviceInfo() {

View File

@ -21,7 +21,6 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.citra.citra_emu.activities.EmulationActivity import org.citra.citra_emu.activities.EmulationActivity
import org.citra.citra_emu.utils.EmulationMenuSettings
import org.citra.citra_emu.utils.FileUtil import org.citra.citra_emu.utils.FileUtil
import org.citra.citra_emu.utils.Log import org.citra.citra_emu.utils.Log
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -97,6 +96,24 @@ object NativeLibrary {
*/ */
external fun onTouchMoved(xAxis: Float, yAxis: Float) external fun onTouchMoved(xAxis: Float, yAxis: Float)
/**
* Handles touch events on the secondary display.
*
* @param xAxis The value of the x-axis.
* @param yAxis The value of the y-axis.
* @param pressed To identify if the touch held down or released.
* @return true if the pointer is within the touchscreen
*/
external fun onSecondaryTouchEvent(xAxis: Float, yAxis: Float, pressed: Boolean): Boolean
/**
* Handles touch movement on the secondary display.
*
* @param xAxis The value of the instantaneous x-axis.
* @param yAxis The value of the instantaneous y-axis.
*/
external fun onSecondaryTouchMoved(xAxis: Float, yAxis: Float)
external fun reloadSettings() external fun reloadSettings()
external fun getTitleId(filename: String): Long external fun getTitleId(filename: String): Long
@ -125,6 +142,10 @@ object NativeLibrary {
external fun surfaceDestroyed() external fun surfaceDestroyed()
external fun doFrame() external fun doFrame()
// Second window
external fun secondarySurfaceChanged(secondary_surface: Surface)
external fun secondarySurfaceDestroyed()
/** /**
* Unpauses emulation from a paused state. * Unpauses emulation from a paused state.
*/ */
@ -190,6 +211,12 @@ object NativeLibrary {
external fun disableTemporaryFrameLimit() external fun disableTemporaryFrameLimit()
external fun playTimeManagerInit()
external fun playTimeManagerStart(titleId: Long)
external fun playTimeManagerStop()
external fun playTimeManagerGetPlayTime(titleId: Long): Long
external fun playTimeManagerGetCurrentTitleId(): Long
private var coreErrorAlertResult = false private var coreErrorAlertResult = false
private val coreErrorAlertLock = Object() private val coreErrorAlertLock = Object()

View File

@ -6,7 +6,6 @@ package org.citra.citra_emu.activities
import android.Manifest.permission import android.Manifest.permission
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
@ -21,6 +20,7 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.BundleCompat
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
@ -33,6 +33,7 @@ import org.citra.citra_emu.camera.StillImageCameraHelper.OnFilePickerResult
import org.citra.citra_emu.contracts.OpenFileResultContract import org.citra.citra_emu.contracts.OpenFileResultContract
import org.citra.citra_emu.databinding.ActivityEmulationBinding import org.citra.citra_emu.databinding.ActivityEmulationBinding
import org.citra.citra_emu.display.ScreenAdjustmentUtil import org.citra.citra_emu.display.ScreenAdjustmentUtil
import org.citra.citra_emu.display.SecondaryDisplay
import org.citra.citra_emu.features.hotkeys.HotkeyUtility import org.citra.citra_emu.features.hotkeys.HotkeyUtility
import org.citra.citra_emu.features.settings.model.BooleanSetting import org.citra.citra_emu.features.settings.model.BooleanSetting
import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.IntSetting
@ -40,12 +41,13 @@ import org.citra.citra_emu.features.settings.model.SettingsViewModel
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
import org.citra.citra_emu.fragments.EmulationFragment import org.citra.citra_emu.fragments.EmulationFragment
import org.citra.citra_emu.fragments.MessageDialogFragment import org.citra.citra_emu.fragments.MessageDialogFragment
import org.citra.citra_emu.model.Game
import org.citra.citra_emu.utils.ControllerMappingHelper import org.citra.citra_emu.utils.ControllerMappingHelper
import org.citra.citra_emu.utils.FileBrowserHelper 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.Log
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() {
@ -58,6 +60,15 @@ class EmulationActivity : AppCompatActivity() {
private lateinit var binding: ActivityEmulationBinding private lateinit var binding: ActivityEmulationBinding
private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil
private lateinit var hotkeyUtility: HotkeyUtility private lateinit var hotkeyUtility: HotkeyUtility
private lateinit var secondaryDisplay: SecondaryDisplay
private val onShutdown = Runnable {
if (intent.getBooleanExtra("launched_from_shortcut", false)) {
finishAffinity()
} else {
this.finish()
}
}
private val emulationFragment: EmulationFragment private val emulationFragment: EmulationFragment
get() { get() {
@ -72,10 +83,10 @@ class EmulationActivity : AppCompatActivity() {
requestWindowFeature(Window.FEATURE_NO_TITLE) requestWindowFeature(Window.FEATURE_NO_TITLE)
ThemeUtil.setTheme(this) ThemeUtil.setTheme(this)
settingsViewModel.settings.loadSettings() settingsViewModel.settings.loadSettings()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
secondaryDisplay = SecondaryDisplay(this)
secondaryDisplay.updateDisplay()
binding = ActivityEmulationBinding.inflate(layoutInflater) binding = ActivityEmulationBinding.inflate(layoutInflater)
screenAdjustmentUtil = ScreenAdjustmentUtil(this, windowManager, settingsViewModel.settings) screenAdjustmentUtil = ScreenAdjustmentUtil(this, windowManager, settingsViewModel.settings)
@ -98,18 +109,26 @@ class EmulationActivity : AppCompatActivity() {
windowManager.defaultDisplay.rotation windowManager.defaultDisplay.rotation
) )
EmulationLifecycleUtil.addShutdownHook(hook = { EmulationLifecycleUtil.addShutdownHook(onShutdown)
if (intent.getBooleanExtra("launched_from_shortcut", false)) {
finishAffinity()
} else {
this.finish()
}
})
isEmulationRunning = true isEmulationRunning = true
instance = this instance = this
applyOrientationSettings() // Check for orientation settings at startup applyOrientationSettings() // Check for orientation settings at startup
val game = try {
intent.extras?.let { extras ->
BundleCompat.getParcelable(extras, "game", Game::class.java)
} ?: run {
Log.error("[EmulationActivity] Missing game data in intent extras")
return
}
} catch (e: Exception) {
Log.error("[EmulationActivity] Failed to retrieve game data: ${e.message}")
return
}
NativeLibrary.playTimeManagerStart(game.titleId)
} }
// On some devices, the system bars will not disappear on first boot or after some // On some devices, the system bars will not disappear on first boot or after some
@ -121,6 +140,11 @@ class EmulationActivity : AppCompatActivity() {
applyOrientationSettings() // Check for orientation settings changes on runtime applyOrientationSettings() // Check for orientation settings changes on runtime
} }
override fun onStop() {
secondaryDisplay.releasePresentation()
super.onStop()
}
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus) super.onWindowFocusChanged(hasFocus)
enableFullscreenImmersive() enableFullscreenImmersive()
@ -128,6 +152,7 @@ class EmulationActivity : AppCompatActivity() {
public override fun onRestart() { public override fun onRestart() {
super.onRestart() super.onRestart()
secondaryDisplay.updateDisplay()
NativeLibrary.reloadCameraDevices() NativeLibrary.reloadCameraDevices()
} }
@ -142,9 +167,13 @@ class EmulationActivity : AppCompatActivity() {
} }
override fun onDestroy() { override fun onDestroy() {
EmulationLifecycleUtil.clear() EmulationLifecycleUtil.removeHook(onShutdown)
NativeLibrary.playTimeManagerStop()
isEmulationRunning = false isEmulationRunning = false
instance = null instance = null
secondaryDisplay.releasePresentation()
secondaryDisplay.releaseVD()
super.onDestroy() super.onDestroy()
} }
@ -238,20 +267,26 @@ class EmulationActivity : AppCompatActivity() {
preferences.getInt(InputBindingSetting.getInputButtonKey(event.keyCode), event.keyCode) preferences.getInt(InputBindingSetting.getInputButtonKey(event.keyCode), event.keyCode)
val action: Int = when (event.action) { val action: Int = when (event.action) {
KeyEvent.ACTION_DOWN -> { KeyEvent.ACTION_DOWN -> {
hotkeyUtility.handleHotkey(button)
// On some devices, the back gesture / button press is not intercepted by androidx // On some devices, the back gesture / button press is not intercepted by androidx
// and fails to open the emulation menu. So we're stuck running deprecated code to // and fails to open the emulation menu. So we're stuck running deprecated code to
// cover for either a fault on androidx's side or in OEM skins (MIUI at least) // cover for either a fault on androidx's side or in OEM skins (MIUI at least)
if (event.keyCode == KeyEvent.KEYCODE_BACK) { if (event.keyCode == KeyEvent.KEYCODE_BACK) {
// If the hotkey is pressed, we don't want to open the drawer
if (!hotkeyUtility.HotkeyIsPressed) {
onBackPressed() onBackPressed()
} }
}
hotkeyUtility.handleHotkey(button)
// Normal key events. // Normal key events.
NativeLibrary.ButtonState.PRESSED NativeLibrary.ButtonState.PRESSED
} }
KeyEvent.ACTION_UP -> NativeLibrary.ButtonState.RELEASED KeyEvent.ACTION_UP -> {
hotkeyUtility.HotkeyIsPressed = false
NativeLibrary.ButtonState.RELEASED
}
else -> return false else -> return false
} }
val input = event.device val input = event.device

View File

@ -45,6 +45,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import org.citra.citra_emu.HomeNavigationDirections import org.citra.citra_emu.HomeNavigationDirections
import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.R import org.citra.citra_emu.R
import org.citra.citra_emu.adapters.GameAdapter.GameViewHolder import org.citra.citra_emu.adapters.GameAdapter.GameViewHolder
import org.citra.citra_emu.databinding.CardGameBinding import org.citra.citra_emu.databinding.CardGameBinding
@ -342,8 +343,9 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
bottomSheetView.findViewById<TextView>(R.id.about_game_title).text = game.title bottomSheetView.findViewById<TextView>(R.id.about_game_title).text = game.title
bottomSheetView.findViewById<TextView>(R.id.about_game_company).text = game.company bottomSheetView.findViewById<TextView>(R.id.about_game_company).text = game.company
bottomSheetView.findViewById<TextView>(R.id.about_game_region).text = game.regions bottomSheetView.findViewById<TextView>(R.id.about_game_region).text = game.regions
bottomSheetView.findViewById<TextView>(R.id.about_game_id).text = "ID: " + String.format("%016X", game.titleId) bottomSheetView.findViewById<TextView>(R.id.about_game_id).text = context.getString(R.string.game_context_id) + " " + String.format("%016X", game.titleId)
bottomSheetView.findViewById<TextView>(R.id.about_game_filename).text = "File: " + game.filename bottomSheetView.findViewById<TextView>(R.id.about_game_filename).text = context.getString(R.string.game_context_file) + " " + game.filename
bottomSheetView.findViewById<TextView>(R.id.about_game_filetype).text = context.getString(R.string.game_context_type) + " " + game.fileType
GameIconUtils.loadGameIcon(activity, game, bottomSheetView.findViewById(R.id.game_icon)) GameIconUtils.loadGameIcon(activity, game, bottomSheetView.findViewById(R.id.game_icon))
bottomSheetView.findViewById<MaterialButton>(R.id.about_game_play).setOnClickListener { bottomSheetView.findViewById<MaterialButton>(R.id.about_game_play).setOnClickListener {
@ -351,6 +353,24 @@ class GameAdapter(private val activity: AppCompatActivity, private val inflater:
view.findNavController().navigate(action) view.findNavController().navigate(action)
} }
bottomSheetView.findViewById<TextView>(R.id.about_game_playtime).text =
buildString {
val playTimeSeconds = NativeLibrary.playTimeManagerGetPlayTime(game.titleId)
val hours = playTimeSeconds / 3600
val minutes = (playTimeSeconds % 3600) / 60
val seconds = playTimeSeconds % 60
val readablePlayTime = when {
hours > 0 -> "${hours}h ${minutes}m ${seconds}s"
minutes > 0 -> "${minutes}m ${seconds}s"
else -> "${seconds}s"
}
append("Playtime: ")
append(readablePlayTime)
}
bottomSheetView.findViewById<MaterialButton>(R.id.game_shortcut).setOnClickListener { bottomSheetView.findViewById<MaterialButton>(R.id.game_shortcut).setOnClickListener {
val preferences = PreferenceManager.getDefaultSharedPreferences(context) val preferences = PreferenceManager.getDefaultSharedPreferences(context)

View File

@ -50,3 +50,17 @@ enum class PortraitScreenLayout(val int: Int) {
} }
} }
} }
enum class SecondaryDisplayLayout(val int: Int) {
// These must match what is defined in src/common/settings.h
NONE(0),
TOP_SCREEN(1),
BOTTOM_SCREEN(2),
SIDE_BY_SIDE(3);
companion object {
fun from(int: Int): SecondaryDisplayLayout {
return entries.firstOrNull { it.int == int } ?: NONE
}
}
}

View File

@ -0,0 +1,169 @@
// 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.display
import android.app.Presentation
import android.content.Context
import android.graphics.SurfaceTexture
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.os.Bundle
import android.view.Display
import android.view.MotionEvent
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.WindowManager
import org.citra.citra_emu.features.settings.model.IntSetting
import org.citra.citra_emu.display.SecondaryDisplayLayout
import org.citra.citra_emu.NativeLibrary
class SecondaryDisplay(val context: Context) : DisplayManager.DisplayListener {
private var pres: SecondaryDisplayPresentation? = null
private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
private val vd: VirtualDisplay
init {
vd = displayManager.createVirtualDisplay(
"HiddenDisplay",
1920,
1080,
320,
null,
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION
)
displayManager.registerDisplayListener(this, null)
}
fun updateSurface() {
NativeLibrary.secondarySurfaceChanged(pres!!.getSurfaceHolder().surface)
}
fun destroySurface() {
NativeLibrary.secondarySurfaceDestroyed()
}
private fun getExternalDisplay(context: Context): Display? {
val dm = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val internalId = context.display.displayId ?: Display.DEFAULT_DISPLAY
val displays = dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)
return displays.firstOrNull { it.displayId != internalId && it.name != "HiddenDisplay" }
}
fun updateDisplay() {
// decide if we are going to the external display or the internal one
var display = getExternalDisplay(context)
if (display == null ||
IntSetting.SECONDARY_DISPLAY_LAYOUT.int == SecondaryDisplayLayout.NONE.int) {
display = vd.display
}
// if our presentation is already on the right display, ignore
if (pres?.display == display) return
// otherwise, make a new presentation
releasePresentation()
pres = SecondaryDisplayPresentation(context, display!!, this)
pres?.show()
}
fun releasePresentation() {
pres?.dismiss()
pres = null
}
fun releaseVD() {
displayManager.unregisterDisplayListener(this)
vd.release()
}
override fun onDisplayAdded(displayId: Int) {
updateDisplay()
}
override fun onDisplayRemoved(displayId: Int) {
updateDisplay()
}
override fun onDisplayChanged(displayId: Int) {
updateDisplay()
}
}
class SecondaryDisplayPresentation(
context: Context, display: Display, val parent: SecondaryDisplay
) : Presentation(context, display) {
private lateinit var surfaceView: SurfaceView
private var touchscreenPointerId = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window?.setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
)
// Initialize SurfaceView
surfaceView = SurfaceView(context)
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
}
override fun surfaceChanged(
holder: SurfaceHolder, format: Int, width: Int, height: Int
) {
parent.updateSurface()
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
parent.destroySurface()
}
})
this.surfaceView.setOnTouchListener { _, event ->
val pointerIndex = event.actionIndex
val pointerId = event.getPointerId(pointerIndex)
when (event.actionMasked) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
if (touchscreenPointerId == -1) {
touchscreenPointerId = pointerId
NativeLibrary.onSecondaryTouchEvent(
event.getX(pointerIndex),
event.getY(pointerIndex),
true
)
}
}
MotionEvent.ACTION_MOVE -> {
val index = event.findPointerIndex(touchscreenPointerId)
if (index != -1) {
NativeLibrary.onSecondaryTouchMoved(
event.getX(index),
event.getY(index)
)
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP, MotionEvent.ACTION_CANCEL -> {
if (pointerId == touchscreenPointerId) {
NativeLibrary.onSecondaryTouchEvent(0f, 0f, false)
touchscreenPointerId = -1
}
}
}
true
}
setContentView(surfaceView) // Set SurfaceView as content
}
// Publicly accessible method to get the SurfaceHolder
fun getSurfaceHolder(): SurfaceHolder {
return surfaceView.holder
}
}

View File

@ -17,6 +17,7 @@ class HotkeyUtility(
private val context: Context) { private val context: Context) {
private val hotkeyButtons = Hotkey.entries.map { it.button } private val hotkeyButtons = Hotkey.entries.map { it.button }
var HotkeyIsPressed = false
fun handleHotkey(bindedButton: Int): Boolean { fun handleHotkey(bindedButton: Int): Boolean {
if(hotkeyButtons.contains(bindedButton)) { if(hotkeyButtons.contains(bindedButton)) {
@ -45,6 +46,7 @@ class HotkeyUtility(
} }
else -> {} else -> {}
} }
HotkeyIsPressed = true
return true return true
} }
return false return false

View File

@ -19,13 +19,14 @@ enum class BooleanSetting(
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false), INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false),
ENABLE_RPC_SERVER("enable_rpc_server", Settings.SECTION_DEBUG, false), ENABLE_RPC_SERVER("enable_rpc_server", Settings.SECTION_DEBUG, false),
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false), CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
OVERLAY_SHOW_FPS("overlay_show_fps", Settings.SECTION_LAYOUT, true), PERF_OVERLAY_ENABLE("performance_overlay_enable", Settings.SECTION_LAYOUT, false),
OVERLAY_SHOW_FRAMETIME("overlay_show_frame_time", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_FPS("performance_overlay_show_fps", Settings.SECTION_LAYOUT, true),
OVERLAY_SHOW_SPEED("overlay_show_speed", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_FRAMETIME("performance_overlay_show_frame_time", Settings.SECTION_LAYOUT, false),
OVERLAY_SHOW_APP_RAM_USAGE("overlay_show_app_ram_usage", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_SPEED("performance_overlay_show_speed", Settings.SECTION_LAYOUT, false),
OVERLAY_SHOW_AVAILABLE_RAM("overlay_show_available_ram", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_APP_RAM_USAGE("performance_overlay_show_app_ram_usage", Settings.SECTION_LAYOUT, false),
OVERLAY_SHOW_BATTERY_TEMP("overlay_show_battery_temp", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_AVAILABLE_RAM("performance_overlay_show_available_ram", Settings.SECTION_LAYOUT, false),
OVERLAY_BACKGROUND("overlay_background", Settings.SECTION_LAYOUT, false), PERF_OVERLAY_SHOW_BATTERY_TEMP("performance_overlay_show_battery_temp", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_BACKGROUND("performance_overlay_background", Settings.SECTION_LAYOUT, false),
DELAY_START_LLE_MODULES("delay_start_for_lle_modules", Settings.SECTION_DEBUG, true), DELAY_START_LLE_MODULES("delay_start_for_lle_modules", Settings.SECTION_DEBUG, true),
DETERMINISTIC_ASYNC_OPERATIONS("deterministic_async_operations", Settings.SECTION_DEBUG, false), DETERMINISTIC_ASYNC_OPERATIONS("deterministic_async_operations", Settings.SECTION_DEBUG, false),
REQUIRED_ONLINE_LLE_MODULES("enable_required_online_lle_modules", Settings.SECTION_SYSTEM, false), REQUIRED_ONLINE_LLE_MODULES("enable_required_online_lle_modules", Settings.SECTION_SYSTEM, false),
@ -48,7 +49,9 @@ enum class BooleanSetting(
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false), DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false),
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false), DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false),
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false), USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false),
UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false); UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false),
COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false),
ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false);
override var boolean: Boolean = defaultValue override var boolean: Boolean = defaultValue
@ -80,7 +83,10 @@ enum class BooleanSetting(
CPU_JIT, CPU_JIT,
ASYNC_CUSTOM_LOADING, ASYNC_CUSTOM_LOADING,
SHADERS_ACCURATE_MUL, SHADERS_ACCURATE_MUL,
USE_ARTIC_BASE_CONTROLLER USE_ARTIC_BASE_CONTROLLER,
COMPRESS_INSTALLED_CIA_CONTENT,
ANDROID_HIDE_IMAGES,
PERF_OVERLAY_ENABLE // Works in overlay options, but not from the settings menu
) )
fun from(key: String): BooleanSetting? = fun from(key: String): BooleanSetting? =

View File

@ -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.
@ -10,6 +10,10 @@ enum class FloatSetting(
override val defaultValue: Float override val defaultValue: Float
) : AbstractFloatSetting { ) : AbstractFloatSetting {
LARGE_SCREEN_PROPORTION("large_screen_proportion",Settings.SECTION_LAYOUT,2.25f), LARGE_SCREEN_PROPORTION("large_screen_proportion",Settings.SECTION_LAYOUT,2.25f),
SECOND_SCREEN_OPACITY("custom_second_layer_opacity", Settings.SECTION_RENDERER, 100f),
BACKGROUND_RED("bg_red", Settings.SECTION_RENDERER, 0f),
BACKGROUND_BLUE("bg_blue", Settings.SECTION_RENDERER, 0f),
BACKGROUND_GREEN("bg_green", Settings.SECTION_RENDERER, 0f),
EMPTY_SETTING("", "", 0.0f); EMPTY_SETTING("", "", 0.0f);
override var float: Float = defaultValue override var float: Float = defaultValue

View File

@ -35,6 +35,7 @@ enum class IntSetting(
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), 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),
SECONDARY_DISPLAY_LAYOUT("secondary_display_layout",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),
PORTRAIT_TOP_WIDTH("custom_portrait_top_width",Settings.SECTION_LAYOUT,800), PORTRAIT_TOP_WIDTH("custom_portrait_top_width",Settings.SECTION_LAYOUT,800),

View File

@ -112,6 +112,7 @@ class Settings {
const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout" const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout"
const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout"
const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay" const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay"
const val SECTION_STORAGE = "Storage"
const val KEY_BUTTON_A = "button_a" const val KEY_BUTTON_A = "button_a"
const val KEY_BUTTON_B = "button_b" const val KEY_BUTTON_B = "button_b"
@ -237,6 +238,7 @@ class Settings {
SECTION_CONTROLS, SECTION_CONTROLS,
SECTION_RENDERER, SECTION_RENDERER,
SECTION_LAYOUT, SECTION_LAYOUT,
SECTION_STORAGE,
SECTION_UTILITY, SECTION_UTILITY,
SECTION_AUDIO, SECTION_AUDIO,
SECTION_DEBUG SECTION_DEBUG

View File

@ -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.
@ -10,7 +10,6 @@ import org.citra.citra_emu.features.settings.model.AbstractSetting
import org.citra.citra_emu.features.settings.model.FloatSetting import org.citra.citra_emu.features.settings.model.FloatSetting
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
import org.citra.citra_emu.utils.Log import org.citra.citra_emu.utils.Log
import kotlin.math.roundToInt
class SliderSetting( class SliderSetting(
setting: AbstractSetting?, setting: AbstractSetting?,
@ -27,7 +26,8 @@ class SliderSetting(
val selectedFloat: Float val selectedFloat: Float
get() { get() {
val setting = setting ?: return defaultValue!!.toFloat() val setting = setting ?: return defaultValue!!.toFloat()
return when (setting) {
val ret = when (setting) {
is AbstractIntSetting -> setting.int.toFloat() is AbstractIntSetting -> setting.int.toFloat()
is FloatSetting -> setting.float is FloatSetting -> setting.float
is ScaledFloatSetting -> setting.float is ScaledFloatSetting -> setting.float
@ -36,8 +36,8 @@ class SliderSetting(
-1f -1f
} }
} }
return ret.coerceIn(min.toFloat(), max.toFloat())
} }
/** /**
* Write a value to the backing int. If that int was previously null, * Write a value to the backing int. If that int was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap. * initializes a new one and returns it, so it can be added to the Hashmap.

View File

@ -4,14 +4,19 @@
package org.citra.citra_emu.features.settings.ui package org.citra.citra_emu.features.settings.ui
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.BooleanSetting
import org.citra.citra_emu.features.settings.model.Settings 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.FileUtil
import org.citra.citra_emu.utils.Log import org.citra.citra_emu.utils.Log
import org.citra.citra_emu.utils.PermissionsHandler
import org.citra.citra_emu.utils.TurboHelper import org.citra.citra_emu.utils.TurboHelper
class SettingsActivityPresenter(private val activityView: SettingsActivityView) { class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
@ -60,6 +65,32 @@ class SettingsActivityPresenter(private val activityView: SettingsActivityView)
loadSettingsUI() loadSettingsUI()
} }
private fun updateAndroidImageVisibility() {
val dataDirTreeUri: Uri
val dataDirDocument: DocumentFile
val nomediaFileDocument: DocumentFile?
val nomediaFileExists: Boolean
try {
dataDirTreeUri = PermissionsHandler.citraDirectory
dataDirDocument = DocumentFile.fromTreeUri(CitraApplication.appContext, dataDirTreeUri)!!
nomediaFileDocument = dataDirDocument.findFile(".nomedia")
nomediaFileExists = (nomediaFileDocument != null)
} catch (e: Exception) {
Log.error("[SettingsActivity]: Error occurred while trying to find .nomedia, error: " + e.message)
return
}
if (BooleanSetting.ANDROID_HIDE_IMAGES.boolean) {
if (!nomediaFileExists) {
Log.info("[SettingsActivity]: Attempting to create .nomedia in user data directory")
FileUtil.createFile(dataDirTreeUri.toString(), ".nomedia")
}
} else if (nomediaFileExists) {
Log.info("[SettingsActivity]: Attempting to delete .nomedia in user data directory")
nomediaFileDocument!!.delete()
}
}
fun onStop(finishing: Boolean) { fun onStop(finishing: Boolean) {
if (finishing && shouldSave) { if (finishing && shouldSave) {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
@ -67,6 +98,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)
updateAndroidImageVisibility()
TurboHelper.reloadTurbo(false) // TODO: Can this go somewhere else? -OS TurboHelper.reloadTurbo(false) // TODO: Can this go somewhere else? -OS
} }
NativeLibrary.reloadSettings() NativeLibrary.reloadSettings()

View File

@ -14,11 +14,8 @@ import android.os.Build
import android.text.TextUtils import android.text.TextUtils
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlin.math.min
import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.R import org.citra.citra_emu.R
import org.citra.citra_emu.display.PortraitScreenLayout
import org.citra.citra_emu.display.ScreenLayout
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
import org.citra.citra_emu.features.settings.model.AbstractIntSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting
import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractSetting
@ -251,6 +248,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
IntSetting.TURBO_LIMIT.defaultValue.toFloat() IntSetting.TURBO_LIMIT.defaultValue.toFloat()
) )
) )
add(
SwitchSetting(
BooleanSetting.ANDROID_HIDE_IMAGES,
R.string.android_hide_images,
R.string.android_hide_images_description,
BooleanSetting.ANDROID_HIDE_IMAGES.key,
BooleanSetting.ANDROID_HIDE_IMAGES.defaultValue
)
)
} }
} }
@ -565,6 +571,16 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
BooleanSetting.ALLOW_PLUGIN_LOADER.defaultValue BooleanSetting.ALLOW_PLUGIN_LOADER.defaultValue
) )
) )
add(HeaderSetting(R.string.storage))
add(
SwitchSetting(
BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT,
R.string.compress_cia_installs,
R.string.compress_cia_installs_description,
BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT.key,
BooleanSetting.COMPRESS_INSTALLED_CIA_CONTENT.defaultValue
)
)
} }
} }
@ -879,7 +895,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.ASYNC_SHADERS, BooleanSetting.SHADERS_ACCURATE_MUL,
R.string.shaders_accurate_mul, R.string.shaders_accurate_mul,
R.string.shaders_accurate_mul_description, R.string.shaders_accurate_mul_description,
BooleanSetting.SHADERS_ACCURATE_MUL.key, BooleanSetting.SHADERS_ACCURATE_MUL.key,
@ -1101,6 +1117,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
IntSetting.PORTRAIT_SCREEN_LAYOUT.defaultValue IntSetting.PORTRAIT_SCREEN_LAYOUT.defaultValue
) )
) )
add(
SingleChoiceSetting(
IntSetting.SECONDARY_DISPLAY_LAYOUT,
R.string.emulation_switch_secondary_layout,
R.string.emulation_switch_secondary_layout_description,
R.array.secondaryLayouts,
R.array.secondaryLayoutValues,
IntSetting.SECONDARY_DISPLAY_LAYOUT.key,
IntSetting.SECONDARY_DISPLAY_LAYOUT.defaultValue
)
)
add( add(
SingleChoiceSetting( SingleChoiceSetting(
IntSetting.ASPECT_RATIO, IntSetting.ASPECT_RATIO,
@ -1148,6 +1175,89 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
FloatSetting.LARGE_SCREEN_PROPORTION.defaultValue FloatSetting.LARGE_SCREEN_PROPORTION.defaultValue
) )
) )
add(
SliderSetting(
FloatSetting.SECOND_SCREEN_OPACITY,
R.string.second_screen_opacity,
R.string.second_screen_opacity_description,
0,
100,
"%",
FloatSetting.SECOND_SCREEN_OPACITY.key,
FloatSetting.SECOND_SCREEN_OPACITY.defaultValue,
isEnabled = IntSetting.SCREEN_LAYOUT.int == 5
)
)
add(HeaderSetting(R.string.bg_color, R.string.bg_color_description))
val bgRedSetting = object : AbstractIntSetting {
override var int: Int
get() = (FloatSetting.BACKGROUND_RED.float * 255).toInt()
set(value) {
FloatSetting.BACKGROUND_RED.float = value.toFloat() / 255
settings.saveSetting(FloatSetting.BACKGROUND_RED, SettingsFile.FILE_NAME_CONFIG)
}
override val key = null
override val section = null
override val isRuntimeEditable = false
override val valueAsString = int.toString()
override val defaultValue = FloatSetting.BACKGROUND_RED.defaultValue
}
add(
SliderSetting(
bgRedSetting,
R.string.bg_red,
0,
0,
255,
""
)
)
val bgGreenSetting = object : AbstractIntSetting {
override var int: Int
get() = (FloatSetting.BACKGROUND_GREEN.float * 255).toInt()
set(value) {
FloatSetting.BACKGROUND_GREEN.float = value.toFloat() / 255
settings.saveSetting(FloatSetting.BACKGROUND_GREEN, SettingsFile.FILE_NAME_CONFIG)
}
override val key = null
override val section = null
override val isRuntimeEditable = false
override val valueAsString = int.toString()
override val defaultValue = FloatSetting.BACKGROUND_GREEN.defaultValue
}
add(
SliderSetting(
bgGreenSetting,
R.string.bg_green,
0,
0,
255,
""
)
)
val bgBlueSetting = object : AbstractIntSetting {
override var int: Int
get() = (FloatSetting.BACKGROUND_BLUE.float * 255).toInt()
set(value) {
FloatSetting.BACKGROUND_BLUE.float = value.toFloat() / 255
settings.saveSetting(FloatSetting.BACKGROUND_BLUE, SettingsFile.FILE_NAME_CONFIG)
}
override val key = null
override val section = null
override val isRuntimeEditable = false
override val valueAsString = int.toString()
override val defaultValue = FloatSetting.BACKGROUND_BLUE.defaultValue
}
add(
SliderSetting(
bgBlueSetting,
R.string.bg_blue,
0,
0,
255,
""
)
)
add( add(
SubmenuSetting( SubmenuSetting(
R.string.performance_overlay_options, R.string.performance_overlay_options,
@ -1183,38 +1293,29 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
add( add(
SwitchSetting( SwitchSetting(
object : AbstractBooleanSetting { BooleanSetting.PERF_OVERLAY_ENABLE,
override val key = "EmulationMenuSettings_showPerfPerformanceOverlay"
override val section = Settings.SECTION_LAYOUT
override val defaultValue = false
override var boolean: Boolean
get() = EmulationMenuSettings.showPerformanceOverlay
set(value) { EmulationMenuSettings.showPerformanceOverlay = value }
override val isRuntimeEditable = true
override val valueAsString: String get() = boolean.toString()
},
R.string.performance_overlay_enable, R.string.performance_overlay_enable,
0, 0,
"EmulationMenuSettings_showPerfPerformanceOverlay", BooleanSetting.PERF_OVERLAY_ENABLE.key,
false BooleanSetting.PERF_OVERLAY_ENABLE.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_BACKGROUND, BooleanSetting.PERF_OVERLAY_BACKGROUND,
R.string.overlay_background, R.string.performance_overlay_background,
R.string.overlay_background_description, R.string.performance_overlay_background_description,
"overlay_background", BooleanSetting.PERF_OVERLAY_BACKGROUND.key,
false BooleanSetting.PERF_OVERLAY_BACKGROUND.defaultValue
) )
) )
add( add(
SingleChoiceSetting( SingleChoiceSetting(
IntSetting.PERFORMANCE_OVERLAY_POSITION, IntSetting.PERFORMANCE_OVERLAY_POSITION,
R.string.overlay_position, R.string.performance_overlay_position,
R.string.overlay_position_description, R.string.performance_overlay_position_description,
R.array.statsPosition, R.array.statsPosition,
R.array.statsPositionValues, R.array.statsPositionValues,
) )
@ -1225,61 +1326,61 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_FPS, BooleanSetting.PERF_OVERLAY_SHOW_FPS,
R.string.overlay_show_fps, R.string.performance_overlay_show_fps,
R.string.overlay_show_fps_description, R.string.performance_overlay_show_fps_description,
"overlay_show_fps", BooleanSetting.PERF_OVERLAY_SHOW_FPS.key,
true BooleanSetting.PERF_OVERLAY_SHOW_FPS.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_FRAMETIME, BooleanSetting.PERF_OVERLAY_SHOW_FRAMETIME,
R.string.overlay_show_frametime, R.string.performance_overlay_show_frametime,
R.string.overlay_show_frametime_description, R.string.performance_overlay_show_frametime_description,
"overlay_show_frame_time", BooleanSetting.PERF_OVERLAY_SHOW_FRAMETIME.key,
true BooleanSetting.PERF_OVERLAY_SHOW_FRAMETIME.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_SPEED, BooleanSetting.PERF_OVERLAY_SHOW_SPEED,
R.string.overlay_show_speed, R.string.performance_overlay_show_speed,
R.string.overlay_show_speed_description, R.string.performance_overlay_show_speed_description,
"overlay_show_speed", BooleanSetting.PERF_OVERLAY_SHOW_SPEED.key,
false BooleanSetting.PERF_OVERLAY_SHOW_SPEED.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_APP_RAM_USAGE, BooleanSetting.PERF_OVERLAY_SHOW_APP_RAM_USAGE,
R.string.overlay_show_app_ram_usage, R.string.performance_overlay_show_app_ram_usage,
R.string.overlay_show_app_ram_usage_description, R.string.performance_overlay_show_app_ram_usage_description,
"overlay_show_app_ram_usage", BooleanSetting.PERF_OVERLAY_SHOW_APP_RAM_USAGE.key,
false BooleanSetting.PERF_OVERLAY_SHOW_APP_RAM_USAGE.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_AVAILABLE_RAM, BooleanSetting.PERF_OVERLAY_SHOW_AVAILABLE_RAM,
R.string.overlay_show_available_ram, R.string.performance_overlay_show_available_ram,
R.string.overlay_show_available_ram_description, R.string.performance_overlay_show_available_ram_description,
"overlay_show_available_ram", BooleanSetting.PERF_OVERLAY_SHOW_AVAILABLE_RAM.key,
false BooleanSetting.PERF_OVERLAY_SHOW_AVAILABLE_RAM.defaultValue
) )
) )
add( add(
SwitchSetting( SwitchSetting(
BooleanSetting.OVERLAY_SHOW_BATTERY_TEMP, BooleanSetting.PERF_OVERLAY_SHOW_BATTERY_TEMP,
R.string.overlay_show_battery_temp, R.string.performance_overlay_show_battery_temp,
R.string.overlay_show_battery_temp_description, R.string.performance_overlay_show_battery_temp_description,
"overlay_show_battery_temp", BooleanSetting.PERF_OVERLAY_SHOW_BATTERY_TEMP.key,
false BooleanSetting.PERF_OVERLAY_SHOW_BATTERY_TEMP.defaultValue
) )
) )
} }

View File

@ -66,6 +66,7 @@ import org.citra.citra_emu.display.ScreenAdjustmentUtil
import org.citra.citra_emu.display.ScreenLayout import org.citra.citra_emu.display.ScreenLayout
import org.citra.citra_emu.features.settings.model.BooleanSetting import org.citra.citra_emu.features.settings.model.BooleanSetting
import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.IntSetting
import org.citra.citra_emu.features.settings.model.Settings
import org.citra.citra_emu.features.settings.model.SettingsViewModel import org.citra.citra_emu.features.settings.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
@ -100,6 +101,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
private val emulationViewModel: EmulationViewModel by activityViewModels() private val emulationViewModel: EmulationViewModel by activityViewModels()
private val settingsViewModel: SettingsViewModel by viewModels() private val settingsViewModel: SettingsViewModel by viewModels()
private val settings get() = settingsViewModel.settings
private val onPause = Runnable{ togglePause() }
private val onShutdown = Runnable{ emulationState.stop() }
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
@ -155,9 +160,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
retainInstance = true retainInstance = true
emulationState = EmulationState(game.path) emulationState = EmulationState(game.path)
emulationActivity = requireActivity() as EmulationActivity emulationActivity = requireActivity() as EmulationActivity
screenAdjustmentUtil = ScreenAdjustmentUtil(requireContext(), requireActivity().windowManager, settingsViewModel.settings) screenAdjustmentUtil = ScreenAdjustmentUtil(requireContext(), requireActivity().windowManager, settings)
EmulationLifecycleUtil.addShutdownHook(hook = { emulationState.stop() }) EmulationLifecycleUtil.addPauseResumeHook(onPause)
EmulationLifecycleUtil.addPauseResumeHook(hook = { togglePause() }) EmulationLifecycleUtil.addShutdownHook(onShutdown)
} }
override fun onCreateView( override fun onCreateView(
@ -355,7 +360,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
} }
R.id.menu_exit -> { R.id.menu_exit -> {
NativeLibrary.pauseEmulation() emulationState.pause()
MaterialAlertDialogBuilder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.emulation_close_game) .setTitle(R.string.emulation_close_game)
.setMessage(R.string.emulation_close_game_message) .setMessage(R.string.emulation_close_game_message)
@ -363,9 +368,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
EmulationLifecycleUtil.closeGame() EmulationLifecycleUtil.closeGame()
} }
.setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int -> .setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int ->
NativeLibrary.unPauseEmulation() emulationState.unpause()
} }
.setOnCancelListener { NativeLibrary.unPauseEmulation() } .setOnCancelListener { emulationState.unpause() }
.show() .show()
true true
} }
@ -470,7 +475,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
super.onResume() super.onResume()
Choreographer.getInstance().postFrameCallback(this) Choreographer.getInstance().postFrameCallback(this)
if (NativeLibrary.isRunning()) { if (NativeLibrary.isRunning()) {
NativeLibrary.unPauseEmulation() emulationState.pause()
// If the overlay is enabled, we need to update the position if changed // If the overlay is enabled, we need to update the position if changed
val position = IntSetting.PERFORMANCE_OVERLAY_POSITION.int val position = IntSetting.PERFORMANCE_OVERLAY_POSITION.int
@ -507,6 +512,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
super.onDetach() super.onDetach()
} }
override fun onDestroy() {
EmulationLifecycleUtil.removeHook(onPause)
EmulationLifecycleUtil.removeHook(onShutdown)
super.onDestroy()
}
private fun setupCitraDirectoriesThenStartEmulation() { private fun setupCitraDirectoriesThenStartEmulation() {
val directoryInitializationState = DirectoryInitialization.start() val directoryInitializationState = DirectoryInitialization.start()
if (directoryInitializationState === if (directoryInitializationState ===
@ -662,7 +673,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
popupMenu.menu.apply { popupMenu.menu.apply {
findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay
findItem(R.id.menu_performance_overlay_show).isChecked = findItem(R.id.menu_performance_overlay_show).isChecked =
EmulationMenuSettings.showPerformanceOverlay BooleanSetting.PERF_OVERLAY_ENABLE.boolean
findItem(R.id.menu_haptic_feedback).isChecked = EmulationMenuSettings.hapticFeedback findItem(R.id.menu_haptic_feedback).isChecked = EmulationMenuSettings.hapticFeedback
findItem(R.id.menu_emulation_joystick_rel_center).isChecked = findItem(R.id.menu_emulation_joystick_rel_center).isChecked =
EmulationMenuSettings.joystickRelCenter EmulationMenuSettings.joystickRelCenter
@ -679,7 +690,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
} }
R.id.menu_performance_overlay_show -> { R.id.menu_performance_overlay_show -> {
EmulationMenuSettings.showPerformanceOverlay = !EmulationMenuSettings.showPerformanceOverlay BooleanSetting.PERF_OVERLAY_ENABLE.boolean = !BooleanSetting.PERF_OVERLAY_ENABLE.boolean
settings.saveSetting(BooleanSetting.PERF_OVERLAY_ENABLE, SettingsFile.FILE_NAME_CONFIG)
updateShowPerformanceOverlay() updateShowPerformanceOverlay()
true true
} }
@ -796,6 +808,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
true true
} }
R.id.menu_emulation_button_sliding -> {
showButtonSlidingMenu()
true
}
R.id.menu_emulation_dpad_slide_enable -> { R.id.menu_emulation_dpad_slide_enable -> {
EmulationMenuSettings.dpadSlide = !EmulationMenuSettings.dpadSlide EmulationMenuSettings.dpadSlide = !EmulationMenuSettings.dpadSlide
true true
@ -840,6 +857,28 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
popupMenu.show() popupMenu.show()
} }
private fun showButtonSlidingMenu() {
val editor = preferences.edit()
val buttonSlidingModes = mutableListOf<String>()
buttonSlidingModes.add(getString(R.string.emulation_button_sliding_disabled))
buttonSlidingModes.add(getString(R.string.emulation_button_sliding_enabled))
buttonSlidingModes.add(getString(R.string.emulation_button_sliding_alternative))
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.emulation_button_sliding)
.setSingleChoiceItems(
buttonSlidingModes.toTypedArray(),
EmulationMenuSettings.buttonSlide
) { _: DialogInterface?, which: Int ->
EmulationMenuSettings.buttonSlide = which
}
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
editor.apply()
}
.show()
}
private fun showLandscapeScreenLayoutMenu() { private fun showLandscapeScreenLayoutMenu() {
val popupMenu = PopupMenu( val popupMenu = PopupMenu(
requireContext(), requireContext(),
@ -1175,7 +1214,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!) perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
} }
if (EmulationMenuSettings.showPerformanceOverlay) { if (BooleanSetting.PERF_OVERLAY_ENABLE.boolean) {
val SYSTEM_FPS = 0 val SYSTEM_FPS = 0
val FPS = 1 val FPS = 1
val SPEED = 2 val SPEED = 2
@ -1183,23 +1222,25 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
val TIME_SVC = 4 val TIME_SVC = 4
val TIME_IPC = 5 val TIME_IPC = 5
val TIME_GPU = 6 val TIME_GPU = 6
val TIME_REM = 7 val TIME_SWAP = 7
val TIME_REM = 8
perfStatsUpdater = Runnable { perfStatsUpdater = Runnable {
val sb = StringBuilder() val sb = StringBuilder()
val perfStats = NativeLibrary.getPerfStats() val perfStats = NativeLibrary.getPerfStats()
val dividerString = "\u00A0\u2502 " val dividerString = "\u00A0\u2502 "
if (perfStats[FPS] > 0) { if (perfStats[FPS] > 0) {
if (BooleanSetting.OVERLAY_SHOW_FPS.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_FPS.boolean) {
sb.append(String.format("FPS:\u00A0%d", (perfStats[FPS] + 0.5).toInt())) sb.append(String.format("FPS:\u00A0%d", (perfStats[FPS] + 0.5).toInt()))
} }
if (BooleanSetting.OVERLAY_SHOW_FRAMETIME.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_FRAMETIME.boolean) {
if (sb.isNotEmpty()) sb.append(dividerString) if (sb.isNotEmpty()) sb.append(dividerString)
sb.append( sb.append(
String.format( String.format(
"Frame:\u00A0%.1fms (GPU:\u00A0%.1fms IPC:\u00A0%.1fms SVC:\u00A0%.1fms Rem:\u00A0%.1fms)", "Frame:\u00A0%.1fms (GPU: [CMD:\u00A0%.1fms SWP:\u00A0%.1fms] IPC:\u00A0%.1fms SVC:\u00A0%.1fms Rem:\u00A0%.1fms)",
(perfStats[FRAMETIME] * 1000.0f).toFloat(), (perfStats[FRAMETIME] * 1000.0f).toFloat(),
(perfStats[TIME_GPU] * 1000.0f).toFloat(), (perfStats[TIME_GPU] * 1000.0f).toFloat(),
(perfStats[TIME_SWAP] * 1000.0f).toFloat(),
(perfStats[TIME_IPC] * 1000.0f).toFloat(), (perfStats[TIME_IPC] * 1000.0f).toFloat(),
(perfStats[TIME_SVC] * 1000.0f).toFloat(), (perfStats[TIME_SVC] * 1000.0f).toFloat(),
(perfStats[TIME_REM] * 1000.0f).toFloat(), (perfStats[TIME_REM] * 1000.0f).toFloat(),
@ -1207,7 +1248,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
) )
} }
if (BooleanSetting.OVERLAY_SHOW_SPEED.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_SPEED.boolean) {
if (sb.isNotEmpty()) sb.append(dividerString) if (sb.isNotEmpty()) sb.append(dividerString)
sb.append( sb.append(
String.format( String.format(
@ -1217,14 +1258,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
) )
} }
if (BooleanSetting.OVERLAY_SHOW_APP_RAM_USAGE.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_APP_RAM_USAGE.boolean) {
if (sb.isNotEmpty()) sb.append(dividerString) if (sb.isNotEmpty()) sb.append(dividerString)
val appRamUsage = val appRamUsage =
File("/proc/self/statm").readLines()[0].split(' ')[1].toLong() * 4096 / 1000000 File("/proc/self/statm").readLines()[0].split(' ')[1].toLong() * 4096 / 1000000
sb.append("Process\u00A0RAM:\u00A0$appRamUsage\u00A0MB") sb.append("Process\u00A0RAM:\u00A0$appRamUsage\u00A0MB")
} }
if (BooleanSetting.OVERLAY_SHOW_AVAILABLE_RAM.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_AVAILABLE_RAM.boolean) {
if (sb.isNotEmpty()) sb.append(dividerString) if (sb.isNotEmpty()) sb.append(dividerString)
context?.let { ctx -> context?.let { ctx ->
val activityManager = val activityManager =
@ -1237,14 +1278,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
} }
} }
if (BooleanSetting.OVERLAY_SHOW_BATTERY_TEMP.boolean) { if (BooleanSetting.PERF_OVERLAY_SHOW_BATTERY_TEMP.boolean) {
if (sb.isNotEmpty()) sb.append(dividerString) if (sb.isNotEmpty()) sb.append(dividerString)
val batteryTemp = getBatteryTemperature() val batteryTemp = getBatteryTemperature()
val tempF = celsiusToFahrenheit(batteryTemp) val tempF = celsiusToFahrenheit(batteryTemp)
sb.append(String.format("%.1f°C/%.1f°F", batteryTemp, tempF)) sb.append(String.format("%.1f°C/%.1f°F", batteryTemp, tempF))
} }
if (BooleanSetting.OVERLAY_BACKGROUND.boolean) { if (BooleanSetting.PERF_OVERLAY_BACKGROUND.boolean) {
binding.performanceOverlayShowText.setBackgroundResource(R.color.citra_transparent_black) binding.performanceOverlayShowText.setBackgroundResource(R.color.citra_transparent_black)
} else { } else {
binding.performanceOverlayShowText.setBackgroundResource(0) binding.performanceOverlayShowText.setBackgroundResource(0)
@ -1393,6 +1434,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
// Release the surface before pausing, since emulation has to be running for that. // Release the surface before pausing, since emulation has to be running for that.
NativeLibrary.surfaceDestroyed() NativeLibrary.surfaceDestroyed()
NativeLibrary.pauseEmulation() NativeLibrary.pauseEmulation()
NativeLibrary.playTimeManagerStop()
} else { } else {
Log.warning("[EmulationFragment] Pause called while already paused.") Log.warning("[EmulationFragment] Pause called while already paused.")
} }
@ -1405,6 +1447,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
Log.debug("[EmulationFragment] Unpausing emulation.") Log.debug("[EmulationFragment] Unpausing emulation.")
NativeLibrary.unPauseEmulation() NativeLibrary.unPauseEmulation()
NativeLibrary.playTimeManagerStart(NativeLibrary.playTimeManagerGetCurrentTitleId())
} else { } else {
Log.warning("[EmulationFragment] Unpause called while already running.") Log.warning("[EmulationFragment] Unpause called while already running.")
} }
@ -1471,7 +1514,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
State.PAUSED -> { State.PAUSED -> {
Log.debug("[EmulationFragment] Resuming emulation.") Log.debug("[EmulationFragment] Resuming emulation.")
NativeLibrary.unPauseEmulation() unpause()
} }
else -> { else -> {

View File

@ -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.
@ -26,7 +26,8 @@ class Game(
val isSystemTitle: Boolean = false, val isSystemTitle: Boolean = false,
val isVisibleSystemTitle: Boolean = false, val isVisibleSystemTitle: Boolean = false,
val icon: IntArray? = null, val icon: IntArray? = null,
val filename: String val fileType: String = "",
val filename: String,
) : Parcelable { ) : Parcelable {
val keyAddedToLibraryTime get() = "${filename}_AddedToLibraryTime" val keyAddedToLibraryTime get() = "${filename}_AddedToLibraryTime"
val keyLastPlayedTime get() = "${filename}_LastPlayed" val keyLastPlayedTime get() = "${filename}_LastPlayed"
@ -63,7 +64,7 @@ class Game(
val allExtensions: Set<String> get() = extensions + badExtensions val allExtensions: Set<String> get() = extensions + badExtensions
val extensions: Set<String> = HashSet( val extensions: Set<String> = HashSet(
listOf("3dsx", "elf", "axf", "cci", "cxi", "app") listOf("3dsx", "app", "axf", "cci", "cxi", "elf", "z3dsx", "zcci", "zcxi")
) )
val badExtensions: Set<String> = HashSet( val badExtensions: Set<String> = HashSet(

View File

@ -13,25 +13,30 @@ class GameInfo(path: String) {
init { init {
pointer = initialize(path) pointer = initialize(path)
if (pointer == 0L) {
throw IOException()
}
} }
protected external fun finalize() protected external fun finalize()
external fun getTitle(): String external fun getTitle(): String
external fun isValid(): Boolean
external fun isEncrypted(): Boolean external fun isEncrypted(): Boolean
external fun getTitleID(): Long
external fun getRegions(): String external fun getRegions(): String
external fun getCompany(): String external fun getCompany(): String
external fun getIcon(): IntArray? external fun getIcon(): IntArray?
external fun isSystemTitle(): Boolean
external fun getIsVisibleSystemTitle(): Boolean external fun getIsVisibleSystemTitle(): Boolean
external fun getFileType(): String
companion object { companion object {
@JvmStatic @JvmStatic
private external fun initialize(path: String): Long private external fun initialize(path: String): Long

View File

@ -96,28 +96,115 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
if (isInEditMode) { if (isInEditMode) {
return onTouchWhileEditing(event) return onTouchWhileEditing(event)
} }
var shouldUpdateView = false
val motionEvent = event.action and MotionEvent.ACTION_MASK
val isActionDown =
motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN
val isActionMove = motionEvent == MotionEvent.ACTION_MOVE
val isActionUp =
motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP
val pointerList = (0 until event.pointerCount).toMutableList()
// Move the pointer that triggered the most recent event to the front
// of the list so that it is processed first
val currentActionPointer = event.actionIndex
pointerList.remove(pointerList.indexOf(currentActionPointer))
pointerList.add(0, currentActionPointer)
// Set up a loop for if we need to check touches other than the most recent one
// (Only happens if we're dragging the touch)
for (pointerIndex in pointerList) {
val pointerId = event.getPointerId(pointerIndex)
val xPosition = event.getX(pointerIndex).toInt()
val yPosition = event.getY(pointerIndex).toInt()
var hasActiveButtons = false
for (button in overlayButtons) { for (button in overlayButtons) {
if (!button.updateStatus(event, this)) { if (button.trackId == pointerId) {
hasActiveButtons = true
break
}
}
var hasActiveDpad = false
if (!hasActiveButtons) {
for (dpad in overlayDpads) {
if (dpad.trackId == pointerId) {
hasActiveDpad = true
break
}
}
}
var hasActiveJoystick = false
if(!hasActiveButtons && !hasActiveDpad){
for (joystick in overlayJoysticks) {
if (joystick.trackId == pointerId) {
hasActiveJoystick = true
break
}
}
}
val hasActiveOverlay = hasActiveButtons || hasActiveDpad || hasActiveJoystick
if (preferences.getBoolean("isTouchEnabled", true) && !hasActiveOverlay) {
if (isActionMove) {
NativeLibrary.onTouchMoved(xPosition.toFloat(), yPosition.toFloat())
continue
} else if (isActionUp) {
NativeLibrary.onTouchEvent(0f, 0f, false)
break // Up and down actions shouldn't loop
}
}
var anyOverlayStateChanged = false
var shouldUpdateView = false
if(!hasActiveDpad && !hasActiveJoystick) {
for (button in overlayButtons) {
val stateChanged = button.updateStatus(event, pointerIndex, hasActiveButtons, this)
if (!stateChanged) {
continue continue
} }
anyOverlayStateChanged = true
if (button.id == NativeLibrary.ButtonType.BUTTON_SWAP && button.status == NativeLibrary.ButtonState.PRESSED) { if (button.id == NativeLibrary.ButtonType.BUTTON_SWAP && button.status == NativeLibrary.ButtonState.PRESSED) {
swapScreen() swapScreen()
} }
else if (button.id == NativeLibrary.ButtonType.BUTTON_TURBO && button.status == NativeLibrary.ButtonState.PRESSED) {
if (button.id == NativeLibrary.ButtonType.BUTTON_TURBO && button.status == NativeLibrary.ButtonState.PRESSED) {
TurboHelper.toggleTurbo(true) TurboHelper.toggleTurbo(true)
} }
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.id, button.status) NativeLibrary.onGamePadEvent(
NativeLibrary.TouchScreenDevice,
button.id,
button.status
)
shouldUpdateView = true shouldUpdateView = true
} }
}
if(!hasActiveButtons && !hasActiveJoystick) {
for (dpad in overlayDpads) { for (dpad in overlayDpads) {
if (!dpad.updateStatus(event, EmulationMenuSettings.dpadSlide, this)) { val stateChanged = dpad.updateStatus(
event,
pointerIndex,
hasActiveDpad,
EmulationMenuSettings.dpadSlide,
this
)
if (!stateChanged) {
continue continue
} }
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.upId, dpad.upStatus) anyOverlayStateChanged = true
NativeLibrary.onGamePadEvent(
NativeLibrary.TouchScreenDevice,
dpad.upId,
dpad.upStatus
)
NativeLibrary.onGamePadEvent( NativeLibrary.onGamePadEvent(
NativeLibrary.TouchScreenDevice, NativeLibrary.TouchScreenDevice,
dpad.downId, dpad.downId,
@ -133,12 +220,19 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
dpad.rightId, dpad.rightId,
dpad.rightStatus dpad.rightStatus
) )
shouldUpdateView = true shouldUpdateView = true
} }
}
if(!hasActiveDpad && !hasActiveButtons) {
for (joystick in overlayJoysticks) { for (joystick in overlayJoysticks) {
if (!joystick.updateStatus(event, this)) { val stateChanged = joystick.updateStatus(event, pointerIndex, hasActiveJoystick, this)
if (!stateChanged) {
continue continue
} }
anyOverlayStateChanged = true
val axisID = joystick.joystickId val axisID = joystick.joystickId
NativeLibrary.onGamePadMoveEvent( NativeLibrary.onGamePadMoveEvent(
NativeLibrary.TouchScreenDevice, NativeLibrary.TouchScreenDevice,
@ -146,63 +240,51 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
joystick.xAxis, joystick.xAxis,
joystick.yAxis joystick.yAxis
) )
shouldUpdateView = true shouldUpdateView = true
} }
}
if (shouldUpdateView) { if (shouldUpdateView) {
invalidate() invalidate()
} }
if (!preferences.getBoolean("isTouchEnabled", true)) { if (preferences.getBoolean("isTouchEnabled", true) &&
return true isActionDown &&
!anyOverlayStateChanged
) {
// These need to be recalculated because touching the area
// right in the middle of the dpad (between the "buttons") or
// tapping a joystick in a certain way both don't cause
// `anyOverlayStateChanged` to be set to true
var isDpadPressed = false
for (dpad in overlayDpads) {
if (dpad.trackId == pointerId) {
isDpadPressed = true
break
}
}
var isJoystickPressed = false
for (joystick in overlayJoysticks) {
if (joystick.trackId == pointerId) {
isJoystickPressed = true
break
}
} }
val pointerIndex = event.actionIndex if (!isDpadPressed && !isJoystickPressed) {
val xPosition = event.getX(pointerIndex).toInt()
val yPosition = event.getY(pointerIndex).toInt()
val pointerId = event.getPointerId(pointerIndex)
val motionEvent = event.action and MotionEvent.ACTION_MASK
val isActionDown =
motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN
val isActionMove = motionEvent == MotionEvent.ACTION_MOVE
val isActionUp =
motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP
if (isActionDown && !isTouchInputConsumed(pointerId)) {
NativeLibrary.onTouchEvent(xPosition.toFloat(), yPosition.toFloat(), true) NativeLibrary.onTouchEvent(xPosition.toFloat(), yPosition.toFloat(), true)
} }
if (isActionMove) {
for (i in 0 until event.pointerCount) {
val fingerId = event.getPointerId(i)
if (isTouchInputConsumed(fingerId)) {
continue
}
NativeLibrary.onTouchMoved(xPosition.toFloat(), yPosition.toFloat())
}
}
if (isActionUp && !isTouchInputConsumed(pointerId)) {
NativeLibrary.onTouchEvent(0f, 0f, false)
}
return true
} }
private fun isTouchInputConsumed(trackId: Int): Boolean { // We should only loop here if touch is being dragged
overlayButtons.forEach { if (!isActionMove) {
if (it.trackId == trackId) { break
}
}
return true return true
} }
}
overlayDpads.forEach {
if (it.trackId == trackId) {
return true
}
}
overlayJoysticks.forEach {
if (it.trackId == trackId) {
return true
}
}
return false
}
fun onTouchWhileEditing(event: MotionEvent): Boolean { fun onTouchWhileEditing(event: MotionEvent): Boolean {
val pointerIndex = event.actionIndex val pointerIndex = event.actionIndex

View File

@ -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.
@ -12,6 +12,20 @@ import android.graphics.drawable.BitmapDrawable
import android.view.HapticFeedbackConstants import android.view.HapticFeedbackConstants
import android.view.MotionEvent import android.view.MotionEvent
import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.utils.EmulationMenuSettings
enum class ButtonSlidingMode(val int: Int) {
// Disabled, buttons can only be triggered by pressing them directly.
Disabled(0),
// Additionally to pressing buttons directly, they can be activated and released by sliding into
// and out of their area.
Enabled(1),
// The first button is kept activated until released, further buttons use the simple button
// sliding method.
Alternative(2)
}
/** /**
* Custom [BitmapDrawable] that is capable * Custom [BitmapDrawable] that is capable
@ -30,6 +44,9 @@ class InputOverlayDrawableButton(
val opacity: Int val opacity: Int
) { ) {
var trackId: Int var trackId: Int
private var isMotionFirstButton = false // mark the first activated button with the current motion
private var previousTouchX = 0 private var previousTouchX = 0
private var previousTouchY = 0 private var previousTouchY = 0
private var controlPositionX = 0 private var controlPositionX = 0
@ -53,8 +70,8 @@ class InputOverlayDrawableButton(
* *
* @return true if value was changed * @return true if value was changed
*/ */
fun updateStatus(event: MotionEvent, overlay:InputOverlay): Boolean { fun updateStatus(event: MotionEvent, pointerIndex: Int, hasActiveButtons: Boolean, overlay: InputOverlay): Boolean {
val pointerIndex = event.actionIndex val buttonSliding = EmulationMenuSettings.buttonSlide
val xPosition = event.getX(pointerIndex).toInt() val xPosition = event.getX(pointerIndex).toInt()
val yPosition = event.getY(pointerIndex).toInt() val yPosition = event.getY(pointerIndex).toInt()
val pointerId = event.getPointerId(pointerIndex) val pointerId = event.getPointerId(pointerIndex)
@ -67,23 +84,65 @@ class InputOverlayDrawableButton(
if (!bounds.contains(xPosition, yPosition)) { if (!bounds.contains(xPosition, yPosition)) {
return false return false
} }
pressedState = true buttonDown(true, pointerId, overlay)
trackId = pointerId
overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
return true return true
} }
if (isActionUp) { if (isActionUp) {
if (trackId != pointerId) { if (trackId != pointerId) {
return false return false
} }
pressedState = false buttonUp(overlay, false)
trackId = -1
overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE)
return true return true
} }
val isActionMoving = motionEvent == MotionEvent.ACTION_MOVE
if (buttonSliding != ButtonSlidingMode.Disabled.int && isActionMoving) {
val inside = bounds.contains(xPosition, yPosition)
if (pressedState) {
// button is already pressed
// check whether we moved out of the button area to update the state
if (inside || trackId != pointerId) {
return false return false
} }
// prevent the first (directly pressed) button to deactivate when sliding off
if (buttonSliding == ButtonSlidingMode.Alternative.int && isMotionFirstButton) {
return false
}
val preserveTrackId = (buttonSliding != ButtonSlidingMode.Disabled.int)
buttonUp(overlay, preserveTrackId)
return true
} else {
// button was not yet pressed
// check whether we moved into the button area to update the state
if (!inside) {
return false
}
buttonDown(!hasActiveButtons, pointerId, overlay)
return true
}
}
return false
}
private fun buttonDown(firstBtn: Boolean, pointerId: Int, overlay: InputOverlay) {
pressedState = true
isMotionFirstButton = firstBtn
trackId = pointerId
overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
}
private fun buttonUp(overlay: InputOverlay, preserveTrackId: Boolean) {
pressedState = false
isMotionFirstButton = false
if (!preserveTrackId) {
trackId = -1
}
overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE)
}
fun onConfigureTouch(event: MotionEvent): Boolean { fun onConfigureTouch(event: MotionEvent): Boolean {
val pointerIndex = event.actionIndex val pointerIndex = event.actionIndex
val fingerPositionX = event.getX(pointerIndex).toInt() val fingerPositionX = event.getX(pointerIndex).toInt()

View File

@ -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.
@ -12,6 +12,7 @@ import android.graphics.drawable.BitmapDrawable
import android.view.HapticFeedbackConstants import android.view.HapticFeedbackConstants
import android.view.MotionEvent import android.view.MotionEvent
import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.utils.EmulationMenuSettings
/** /**
* Custom [BitmapDrawable] that is capable * Custom [BitmapDrawable] that is capable
@ -62,15 +63,18 @@ class InputOverlayDrawableDpad(
trackId = -1 trackId = -1
} }
fun updateStatus(event: MotionEvent, dpadSlide: Boolean, overlay:InputOverlay): Boolean { fun updateStatus(event: MotionEvent, pointerIndex: Int, hasActiveButtons: Boolean, dpadSlide: Boolean, overlay: InputOverlay): Boolean {
var isDown = false var isDown = false
val pointerIndex = event.actionIndex
val xPosition = event.getX(pointerIndex).toInt() val xPosition = event.getX(pointerIndex).toInt()
val yPosition = event.getY(pointerIndex).toInt() val yPosition = event.getY(pointerIndex).toInt()
val pointerId = event.getPointerId(pointerIndex) val pointerId = event.getPointerId(pointerIndex)
val motionEvent = event.action and MotionEvent.ACTION_MASK val motionEvent = event.action and MotionEvent.ACTION_MASK
val isActionDown = var isActionDown =
motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN
if (!isActionDown && EmulationMenuSettings.buttonSlide != ButtonSlidingMode.Disabled.int) {
isActionDown = motionEvent == MotionEvent.ACTION_MOVE && !hasActiveButtons
}
val isActionUp = val isActionUp =
motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP
if (isActionDown) { if (isActionDown) {

View File

@ -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.
@ -93,14 +93,17 @@ class InputOverlayDrawableJoystick(
currentStateBitmapDrawable.draw(canvas) currentStateBitmapDrawable.draw(canvas)
} }
fun updateStatus(event: MotionEvent, overlay:InputOverlay): Boolean { fun updateStatus(event: MotionEvent, pointerIndex: Int, hasActiveButtons: Boolean, overlay: InputOverlay): Boolean {
val pointerIndex = event.actionIndex
val xPosition = event.getX(pointerIndex).toInt() val xPosition = event.getX(pointerIndex).toInt()
val yPosition = event.getY(pointerIndex).toInt() val yPosition = event.getY(pointerIndex).toInt()
val pointerId = event.getPointerId(pointerIndex) val pointerId = event.getPointerId(pointerIndex)
val motionEvent = event.action and MotionEvent.ACTION_MASK val motionEvent = event.action and MotionEvent.ACTION_MASK
val isActionDown = var isActionDown =
motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN
if (!isActionDown && EmulationMenuSettings.buttonSlide != ButtonSlidingMode.Disabled.int) {
isActionDown = motionEvent == MotionEvent.ACTION_MOVE && !hasActiveButtons
}
val isActionUp = val isActionUp =
motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP
if (isActionDown) { if (isActionDown) {

View File

@ -332,7 +332,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
} }
val selectedFiles = val selectedFiles =
FileBrowserHelper.getSelectedFiles(result, applicationContext, listOf("cia")) FileBrowserHelper.getSelectedFiles(result, applicationContext, listOf("cia", "zcia"))
if (selectedFiles == null) { if (selectedFiles == null) {
Toast.makeText(applicationContext, R.string.cia_file_not_found, Toast.LENGTH_LONG) Toast.makeText(applicationContext, R.string.cia_file_not_found, Toast.LENGTH_LONG)
.show() .show()

View File

@ -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.
@ -18,15 +18,27 @@ object EmulationLifecycleUtil {
} }
fun addShutdownHook(hook: Runnable) { fun addShutdownHook(hook: Runnable) {
if (shutdownHooks.contains(hook)) {
Log.warning("[EmulationLifecycleUtil] Tried to add shutdown hook for function that already existed. Skipping.")
} else {
shutdownHooks.add(hook) shutdownHooks.add(hook)
} }
}
fun addPauseResumeHook(hook: Runnable) { fun addPauseResumeHook(hook: Runnable) {
if (pauseResumeHooks.contains(hook)) {
Log.warning("[EmulationLifecycleUtil] Tried to add pause resume hook for function that already existed. Skipping.")
} else {
pauseResumeHooks.add(hook) pauseResumeHooks.add(hook)
} }
}
fun clear() { fun removeHook(hook: Runnable) {
pauseResumeHooks.clear() if (pauseResumeHooks.contains(hook)) {
shutdownHooks.clear() pauseResumeHooks.remove(hook)
}
if (shutdownHooks.contains(hook)) {
shutdownHooks.remove(hook)
}
} }
} }

View File

@ -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.
@ -7,6 +7,7 @@ package org.citra.citra_emu.utils
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.overlay.ButtonSlidingMode
object EmulationMenuSettings { object EmulationMenuSettings {
private val preferences = private val preferences =
@ -26,14 +27,14 @@ object EmulationMenuSettings {
.putBoolean("EmulationMenuSettings_DpadSlideEnable", value) .putBoolean("EmulationMenuSettings_DpadSlideEnable", value)
.apply() .apply()
} }
var buttonSlide: Int
var showPerformanceOverlay: Boolean get() = preferences.getInt("EmulationMenuSettings_ButtonSlideMode", ButtonSlidingMode.Disabled.int)
get() = preferences.getBoolean("EmulationMenuSettings_showPerformanceOverlay", false)
set(value) { set(value) {
preferences.edit() preferences.edit()
.putBoolean("EmulationMenuSettings_showPerformanceOverlay", value) .putInt("EmulationMenuSettings_ButtonSlideMode", value)
.apply() .apply()
} }
var hapticFeedback: Boolean var hapticFeedback: Boolean
get() = preferences.getBoolean("EmulationMenuSettings_HapticFeedback", true) get() = preferences.getBoolean("EmulationMenuSettings_HapticFeedback", true)
set(value) { set(value) {

View File

@ -70,29 +70,26 @@ object GameHelper {
fun getGame(uri: Uri, isInstalled: Boolean, addedToLibrary: Boolean): Game { fun getGame(uri: Uri, isInstalled: Boolean, addedToLibrary: Boolean): Game {
val filePath = uri.toString() val filePath = uri.toString()
var gameInfo: GameInfo? = try { var gameInfo: GameInfo? = GameInfo(filePath)
GameInfo(filePath)
} catch (e: IOException) { if (gameInfo?.isValid() == false) {
null gameInfo = null
} }
var isEncrypted = false val isEncrypted = gameInfo?.isEncrypted() == true
if (gameInfo?.isEncrypted() == true) {
gameInfo = null
isEncrypted = true
}
val newGame = Game( val newGame = Game(
(gameInfo?.getTitle() ?: FileUtil.getFilename(uri)).replace("[\\t\\n\\r]+".toRegex(), " "), (gameInfo?.getTitle() ?: FileUtil.getFilename(uri)).replace("[\\t\\n\\r]+".toRegex(), " "),
filePath.replace("\n", " "), filePath.replace("\n", " "),
filePath, filePath,
NativeLibrary.getTitleId(filePath), gameInfo?.getTitleID() ?: 0,
gameInfo?.getCompany() ?: "", gameInfo?.getCompany() ?: "",
gameInfo?.getRegions() ?: (if (isEncrypted) { CitraApplication.appContext.getString(R.string.unsupported_encrypted) } else { CitraApplication.appContext.getString(R.string.invalid_region) }), if (isEncrypted) { CitraApplication.appContext.getString(R.string.unsupported_encrypted) } else { gameInfo?.getRegions() ?: "" },
isInstalled, isInstalled,
NativeLibrary.getIsSystemTitle(filePath), gameInfo?.isSystemTitle() ?: false,
gameInfo?.getIsVisibleSystemTitle() ?: false, gameInfo?.getIsVisibleSystemTitle() ?: false,
gameInfo?.getIcon(), gameInfo?.getIcon(),
gameInfo?.getFileType() ?: "",
if (FileUtil.isNativePath(filePath)) { if (FileUtil.isNativePath(filePath)) {
CitraApplication.documentsTree.getFilename(filePath) CitraApplication.documentsTree.getFilename(filePath)
} else { } else {

View File

@ -160,11 +160,11 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.render_3d); ReadSetting("Renderer", Settings::values.render_3d);
ReadSetting("Renderer", Settings::values.factor_3d); ReadSetting("Renderer", Settings::values.factor_3d);
std::string default_shader = "none (builtin)"; std::string default_shader = "None (builtin)";
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph)
default_shader = "dubois (builtin)"; default_shader = "Dubois (builtin)";
else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced) else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced)
default_shader = "horizontal (builtin)"; default_shader = "Horizontal (builtin)";
Settings::values.pp_shader_name = Settings::values.pp_shader_name =
sdl2_config->GetString("Renderer", "pp_shader_name", default_shader); sdl2_config->GetString("Renderer", "pp_shader_name", default_shader);
ReadSetting("Renderer", Settings::values.filter_mode); ReadSetting("Renderer", Settings::values.filter_mode);
@ -172,6 +172,7 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.bg_red); ReadSetting("Renderer", Settings::values.bg_red);
ReadSetting("Renderer", Settings::values.bg_green); ReadSetting("Renderer", Settings::values.bg_green);
ReadSetting("Renderer", Settings::values.bg_blue); ReadSetting("Renderer", Settings::values.bg_blue);
ReadSetting("Renderer", Settings::values.custom_second_layer_opacity);
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us); ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
ReadSetting("Renderer", Settings::values.disable_right_eye_render); ReadSetting("Renderer", Settings::values.disable_right_eye_render);
@ -209,6 +210,9 @@ void Config::ReadValues() {
static_cast<Settings::PortraitLayoutOption>(sdl2_config->GetInteger( static_cast<Settings::PortraitLayoutOption>(sdl2_config->GetInteger(
"Layout", "portrait_layout_option", "Layout", "portrait_layout_option",
static_cast<int>(Settings::PortraitLayoutOption::PortraitTopFullWidth))); static_cast<int>(Settings::PortraitLayoutOption::PortraitTopFullWidth)));
Settings::values.secondary_display_layout = static_cast<Settings::SecondaryDisplayLayout>(
sdl2_config->GetInteger("Layout", "secondary_display_layout",
static_cast<int>(Settings::SecondaryDisplayLayout::None)));
ReadSetting("Layout", Settings::values.custom_portrait_top_x); ReadSetting("Layout", Settings::values.custom_portrait_top_x);
ReadSetting("Layout", Settings::values.custom_portrait_top_y); ReadSetting("Layout", Settings::values.custom_portrait_top_y);
ReadSetting("Layout", Settings::values.custom_portrait_top_width); ReadSetting("Layout", Settings::values.custom_portrait_top_width);
@ -218,6 +222,9 @@ void Config::ReadValues() {
ReadSetting("Layout", Settings::values.custom_portrait_bottom_width); ReadSetting("Layout", Settings::values.custom_portrait_bottom_width);
ReadSetting("Layout", Settings::values.custom_portrait_bottom_height); ReadSetting("Layout", Settings::values.custom_portrait_bottom_height);
// Storage
ReadSetting("Storage", Settings::values.compress_cia_installs);
// Utility // Utility
ReadSetting("Utility", Settings::values.dump_textures); ReadSetting("Utility", Settings::values.dump_textures);
ReadSetting("Utility", Settings::values.custom_textures); ReadSetting("Utility", Settings::values.custom_textures);

View File

@ -170,6 +170,9 @@ bg_red =
bg_blue = bg_blue =
bg_green = bg_green =
# Opacity of second layer when using custom layout option (bottom screen unless swapped). Useful if positioning on top of the first layer.
custom_second_layer_opacity =
# Whether and how Stereoscopic 3D should be rendered # Whether and how Stereoscopic 3D should be rendered
# 0 (default): Off, 1: Side by Side, 2: Reverse Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR # 0 (default): Off, 1: Side by Side, 2: Reverse Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
render_3d = render_3d =
@ -210,6 +213,11 @@ disable_right_eye_render =
# 5: Custom Layout # 5: Custom Layout
layout_option = layout_option =
[Storage]
# Whether to compress the installed CIA contents
# 0 (default): Do not compress, 1: Compress
compress_cia_installs =
# Position of the performance overlay # Position of the performance overlay
# 0: Top Left # 0: Top Left
# 1: Center Top # 1: Center Top
@ -283,6 +291,15 @@ swap_screen =
# 0 (default): Off, 1: On # 0 (default): Off, 1: On
expand_to_cutout_area = expand_to_cutout_area =
# Secondary Display Layout
# What the game should do if a secondary display is connected physically or using
# Miracast / Chromecast screen mirroring
# 0 (default) - Use System Default (mirror)
# 1 - Show Top Screen Only
# 2 - Show Bottom Screen Only
# 3 - Show both screens side by side
secondary_display_layout =
# 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 =
@ -466,9 +483,8 @@ deterministic_async_operations =
[WebService] [WebService]
# URL for Web API # URL for Web API
web_api_url = https://api.citra-emu.org web_api_url =
# Username and token for Citra Web Service # Username and token for Citra Web Service
# See https://profile.citra-emu.org/ for more info
citra_username = citra_username =
citra_token = citra_token =
)"; )";

View File

@ -1,4 +1,4 @@
// Copyright 2019 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.
@ -49,16 +49,16 @@ void EmuWindow_Android::OnFramebufferSizeChanged() {
const int bigger{window_width > window_height ? window_width : window_height}; const int bigger{window_width > window_height ? window_width : window_height};
const int smaller{window_width < window_height ? window_width : window_height}; const int smaller{window_width < window_height ? window_width : window_height};
if (is_portrait_mode) { if (is_portrait_mode && !is_secondary) {
UpdateCurrentFramebufferLayout(smaller, bigger, is_portrait_mode); UpdateCurrentFramebufferLayout(smaller, bigger, is_portrait_mode);
} else { } else {
UpdateCurrentFramebufferLayout(bigger, smaller, is_portrait_mode); UpdateCurrentFramebufferLayout(bigger, smaller, is_portrait_mode);
} }
} }
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface) : host_window{surface} { EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface, bool is_secondary)
: EmuWindow{is_secondary}, host_window(surface) {
LOG_DEBUG(Frontend, "Initializing EmuWindow_Android"); LOG_DEBUG(Frontend, "Initializing EmuWindow_Android");
if (!surface) { if (!surface) {
LOG_CRITICAL(Frontend, "surface is nullptr"); LOG_CRITICAL(Frontend, "surface is nullptr");
return; return;

View File

@ -1,10 +1,11 @@
// Copyright 2019 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.
#pragma once #pragma once
#include <vector> #include <vector>
#include <EGL/egl.h>
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
namespace Core { namespace Core {
@ -13,7 +14,7 @@ class System;
class EmuWindow_Android : public Frontend::EmuWindow { class EmuWindow_Android : public Frontend::EmuWindow {
public: public:
EmuWindow_Android(ANativeWindow* surface); EmuWindow_Android(ANativeWindow* surface, bool is_secondary = false);
~EmuWindow_Android(); ~EmuWindow_Android();
/// Called by the onSurfaceChanges() method to change the surface /// Called by the onSurfaceChanges() method to change the surface
@ -30,7 +31,12 @@ public:
void DoneCurrent() override; void DoneCurrent() override;
virtual void TryPresenting() {} virtual void TryPresenting() {}
// EGL Context must be shared
// could probably use the existing
// SharedContext for this instead, this is maybe temporary
virtual EGLContext* GetEGLContext() {
return nullptr;
}
virtual void StopPresenting() {} virtual void StopPresenting() {}
protected: protected:

View File

@ -1,4 +1,4 @@
// Copyright 2019 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.
@ -72,8 +72,9 @@ private:
EGLContext egl_context{}; EGLContext egl_context{};
}; };
EmuWindow_Android_OpenGL::EmuWindow_Android_OpenGL(Core::System& system_, ANativeWindow* surface) EmuWindow_Android_OpenGL::EmuWindow_Android_OpenGL(Core::System& system_, ANativeWindow* surface,
: EmuWindow_Android{surface}, system{system_} { bool is_secondary, EGLContext* sharedContext)
: EmuWindow_Android{surface, is_secondary}, system{system_} {
if (egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); egl_display == EGL_NO_DISPLAY) { if (egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); egl_display == EGL_NO_DISPLAY) {
LOG_CRITICAL(Frontend, "eglGetDisplay() failed"); LOG_CRITICAL(Frontend, "eglGetDisplay() failed");
return; return;
@ -96,8 +97,10 @@ EmuWindow_Android_OpenGL::EmuWindow_Android_OpenGL(Core::System& system_, ANativ
if (eglQuerySurface(egl_display, egl_surface, EGL_HEIGHT, &window_height) != EGL_TRUE) { if (eglQuerySurface(egl_display, egl_surface, EGL_HEIGHT, &window_height) != EGL_TRUE) {
return; return;
} }
if (sharedContext) {
if (egl_context = eglCreateContext(egl_display, egl_config, 0, egl_context_attribs.data()); egl_context = *sharedContext;
} else if (egl_context =
eglCreateContext(egl_display, egl_config, 0, egl_context_attribs.data());
egl_context == EGL_NO_CONTEXT) { egl_context == EGL_NO_CONTEXT) {
LOG_CRITICAL(Frontend, "eglCreateContext() failed"); LOG_CRITICAL(Frontend, "eglCreateContext() failed");
return; return;
@ -127,6 +130,10 @@ EmuWindow_Android_OpenGL::EmuWindow_Android_OpenGL(Core::System& system_, ANativ
OnFramebufferSizeChanged(); OnFramebufferSizeChanged();
} }
EGLContext* EmuWindow_Android_OpenGL::GetEGLContext() {
return &egl_context;
}
bool EmuWindow_Android_OpenGL::CreateWindowSurface() { bool EmuWindow_Android_OpenGL::CreateWindowSurface() {
if (!host_window) { if (!host_window) {
return true; return true;
@ -204,14 +211,14 @@ void EmuWindow_Android_OpenGL::TryPresenting() {
return; return;
} }
if (presenting_state == PresentingState::Initial) [[unlikely]] { if (presenting_state == PresentingState::Initial) [[unlikely]] {
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
presenting_state = PresentingState::Running; presenting_state = PresentingState::Running;
} }
if (presenting_state != PresentingState::Running) [[unlikely]] { if (presenting_state != PresentingState::Running) [[unlikely]] {
return; return;
} }
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0); eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
system.GPU().Renderer().TryPresent(0); system.GPU().Renderer().TryPresent(0, is_secondary);
eglSwapBuffers(egl_display, egl_surface); eglSwapBuffers(egl_display, egl_surface);
} }

View File

@ -1,4 +1,4 @@
// Copyright 2019 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.
@ -19,13 +19,14 @@ struct ANativeWindow;
class EmuWindow_Android_OpenGL : public EmuWindow_Android { class EmuWindow_Android_OpenGL : public EmuWindow_Android {
public: public:
EmuWindow_Android_OpenGL(Core::System& system, ANativeWindow* surface); EmuWindow_Android_OpenGL(Core::System& system, ANativeWindow* surface, bool is_secondary,
EGLContext* sharedContext = NULL);
~EmuWindow_Android_OpenGL() override = default; ~EmuWindow_Android_OpenGL() override = default;
void TryPresenting() override; void TryPresenting() override;
void StopPresenting() override; void StopPresenting() override;
void PollEvents() override; void PollEvents() override;
EGLContext* GetEGLContext() override;
std::unique_ptr<GraphicsContext> CreateSharedContext() const override; std::unique_ptr<GraphicsContext> CreateSharedContext() const override;
private: private:

View File

@ -1,4 +1,4 @@
// Copyright 2019 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.
@ -24,8 +24,9 @@ private:
}; };
EmuWindow_Android_Vulkan::EmuWindow_Android_Vulkan( EmuWindow_Android_Vulkan::EmuWindow_Android_Vulkan(
ANativeWindow* surface, std::shared_ptr<Common::DynamicLibrary> driver_library_) ANativeWindow* surface, std::shared_ptr<Common::DynamicLibrary> driver_library_,
: EmuWindow_Android{surface}, driver_library{driver_library_} { bool is_secondary)
: EmuWindow_Android{surface, is_secondary}, driver_library{driver_library_} {
CreateWindowSurface(); CreateWindowSurface();
if (core_context = CreateSharedContext(); !core_context) { if (core_context = CreateSharedContext(); !core_context) {

View File

@ -1,4 +1,4 @@
// Copyright 2022 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.
@ -11,7 +11,8 @@ struct ANativeWindow;
class EmuWindow_Android_Vulkan : public EmuWindow_Android { class EmuWindow_Android_Vulkan : public EmuWindow_Android {
public: public:
EmuWindow_Android_Vulkan(ANativeWindow* surface, EmuWindow_Android_Vulkan(ANativeWindow* surface,
std::shared_ptr<Common::DynamicLibrary> driver_library); std::shared_ptr<Common::DynamicLibrary> driver_library,
bool is_secondary);
~EmuWindow_Android_Vulkan() override = default; ~EmuWindow_Android_Vulkan() override = default;
void PollEvents() override {} void PollEvents() override {}

View File

@ -17,28 +17,50 @@
namespace { namespace {
std::vector<u8> GetSMDHData(const std::string& path, bool& is_encrypted) { static constexpr u64 UPDATE_TID_HIGH = 0x0004000e00000000;
struct GameInfoData {
Loader::SMDH smdh;
u64 title_id = 0;
bool loaded = false;
bool is_encrypted = false;
std::string file_type = "";
};
GameInfoData* GetNewGameInfoData(const std::string& path) {
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(path); std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(path);
if (!loader) { u64 program_id = 0;
return {}; bool is_encrypted = false;
Loader::ResultStatus result{};
if (loader) {
result = loader->ReadProgramId(program_id);
if (result == Loader::ResultStatus::ErrorNotImplemented) {
// This can happen for 3DSX and ELF files.
program_id = 0;
result = Loader::ResultStatus::Success;
}
} }
u64 program_id = 0; if (!loader || result != Loader::ResultStatus::Success) {
loader->ReadProgramId(program_id); GameInfoData* gid = new GameInfoData();
memset(&gid->smdh, 0, sizeof(Loader::SMDH));
return gid;
}
std::vector<u8> smdh = [program_id, &loader, &is_encrypted]() -> std::vector<u8> { std::vector<u8> smdh = [program_id, &loader, &is_encrypted]() -> std::vector<u8> {
std::vector<u8> original_smdh; std::vector<u8> original_smdh;
auto result = loader->ReadIcon(original_smdh); auto result = loader->ReadIcon(original_smdh);
if (result == Loader::ResultStatus::ErrorEncrypted) { if (result != Loader::ResultStatus::Success) {
is_encrypted = true; is_encrypted = result == Loader::ResultStatus::ErrorEncrypted;
return original_smdh; return {};
} }
if (program_id < 0x00040000'00000000 || program_id > 0x00040000'FFFFFFFF) if (program_id < 0x00040000'00000000 || program_id > 0x00040000'FFFFFFFF)
return original_smdh; return original_smdh;
std::string update_path = Service::AM::GetTitleContentPath( u64 update_tid = (program_id & 0xFFFFFFFFULL) | UPDATE_TID_HIGH;
Service::FS::MediaType::SDMC, program_id + 0x0000000E'00000000); std::string update_path =
Service::AM::GetTitleContentPath(Service::FS::MediaType::SDMC, update_tid);
if (!FileUtil::Exists(update_path)) if (!FileUtil::Exists(update_path))
return original_smdh; return original_smdh;
@ -49,41 +71,50 @@ std::vector<u8> GetSMDHData(const std::string& path, bool& is_encrypted) {
return original_smdh; return original_smdh;
std::vector<u8> update_smdh; std::vector<u8> update_smdh;
update_loader->ReadIcon(update_smdh); result = update_loader->ReadIcon(update_smdh);
if (result != Loader::ResultStatus::Success) {
is_encrypted = result == Loader::ResultStatus::ErrorEncrypted;
return {};
}
return update_smdh; return update_smdh;
}(); }();
return smdh; GameInfoData* gid = new GameInfoData();
if (smdh.empty()) {
std::memset(&gid->smdh, 0, sizeof(Loader::SMDH));
} else {
std::memcpy(&gid->smdh, smdh.data(), smdh.size());
}
gid->loaded = true;
gid->is_encrypted = is_encrypted;
gid->title_id = program_id;
gid->file_type = Loader::GetFileTypeString(loader->GetFileType(), loader->IsFileCompressed());
return gid;
} }
} // namespace } // namespace
extern "C" { extern "C" {
static Loader::SMDH* GetPointer(JNIEnv* env, jobject obj) { static GameInfoData* GetPointer(JNIEnv* env, jobject obj) {
return reinterpret_cast<Loader::SMDH*>(env->GetLongField(obj, IDCache::GetGameInfoPointer())); return reinterpret_cast<GameInfoData*>(env->GetLongField(obj, IDCache::GetGameInfoPointer()));
} }
JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_model_GameInfo_initialize(JNIEnv* env, jclass, JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_model_GameInfo_initialize(JNIEnv* env, jclass,
jstring j_path) { jstring j_path) {
bool is_encrypted = false; GameInfoData* game_info_data = GetNewGameInfoData(GetJString(env, j_path));
std::vector<u8> smdh_data = GetSMDHData(GetJString(env, j_path), is_encrypted); return reinterpret_cast<jlong>(game_info_data);
Loader::SMDH* smdh = nullptr;
if (is_encrypted) {
smdh = new Loader::SMDH;
smdh->magic = 0xDEADDEAD;
} else if (Loader::IsValidSMDH(smdh_data)) {
smdh = new Loader::SMDH;
std::memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH));
} }
return reinterpret_cast<jlong>(smdh);
JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_model_GameInfo_isValid(JNIEnv* env,
jobject obj) {
return GetPointer(env, obj)->loaded;
} }
JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_model_GameInfo_isEncrypted(JNIEnv* env, JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_model_GameInfo_isEncrypted(JNIEnv* env,
jobject obj) { jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); return GetPointer(env, obj)->is_encrypted;
return smdh->magic == 0xDEADDEAD;
} }
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_model_GameInfo_finalize(JNIEnv* env, jobject obj) { JNIEXPORT void JNICALL Java_org_citra_citra_1emu_model_GameInfo_finalize(JNIEnv* env, jobject obj) {
@ -91,7 +122,11 @@ JNIEXPORT void JNICALL Java_org_citra_citra_1emu_model_GameInfo_finalize(JNIEnv*
} }
jstring Java_org_citra_citra_1emu_model_GameInfo_getTitle(JNIEnv* env, jobject obj) { jstring Java_org_citra_citra_1emu_model_GameInfo_getTitle(JNIEnv* env, jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); Loader::SMDH* smdh = &GetPointer(env, obj)->smdh;
if (!smdh->IsValid()) {
return ToJString(env, "");
}
Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English; Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English;
// Get the title from SMDH in UTF-16 format // Get the title from SMDH in UTF-16 format
@ -102,7 +137,11 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getTitle(JNIEnv* env, jobject o
} }
jstring Java_org_citra_citra_1emu_model_GameInfo_getCompany(JNIEnv* env, jobject obj) { jstring Java_org_citra_citra_1emu_model_GameInfo_getCompany(JNIEnv* env, jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); Loader::SMDH* smdh = &GetPointer(env, obj)->smdh;
if (!smdh->IsValid()) {
return ToJString(env, "");
}
Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English; Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English;
// Get the Publisher's name from SMDH in UTF-16 format // Get the Publisher's name from SMDH in UTF-16 format
@ -113,8 +152,15 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getCompany(JNIEnv* env, jobject
return ToJString(env, Common::UTF16ToUTF8(publisher).data()); return ToJString(env, Common::UTF16ToUTF8(publisher).data());
} }
jlong Java_org_citra_citra_1emu_model_GameInfo_getTitleID(JNIEnv* env, jobject obj) {
return static_cast<jlong>(GetPointer(env, obj)->title_id);
}
jstring Java_org_citra_citra_1emu_model_GameInfo_getRegions(JNIEnv* env, jobject obj) { jstring Java_org_citra_citra_1emu_model_GameInfo_getRegions(JNIEnv* env, jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); Loader::SMDH* smdh = &GetPointer(env, obj)->smdh;
if (!smdh->IsValid()) {
return ToJString(env, "");
}
using GameRegion = Loader::SMDH::GameRegion; using GameRegion = Loader::SMDH::GameRegion;
static const std::map<GameRegion, const char*> regions_map = { static const std::map<GameRegion, const char*> regions_map = {
@ -147,7 +193,10 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getRegions(JNIEnv* env, jobject
} }
jintArray Java_org_citra_citra_1emu_model_GameInfo_getIcon(JNIEnv* env, jobject obj) { jintArray Java_org_citra_citra_1emu_model_GameInfo_getIcon(JNIEnv* env, jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); Loader::SMDH* smdh = &GetPointer(env, obj)->smdh;
if (!smdh->IsValid()) {
return nullptr;
}
// Always get a 48x48(large) icon // Always get a 48x48(large) icon
std::vector<u16> icon_data = smdh->GetIcon(true); std::vector<u16> icon_data = smdh->GetIcon(true);
@ -162,12 +211,23 @@ jintArray Java_org_citra_citra_1emu_model_GameInfo_getIcon(JNIEnv* env, jobject
return icon; return icon;
} }
jboolean Java_org_citra_citra_1emu_model_GameInfo_isSystemTitle(JNIEnv* env, jobject obj) {
return ((GetPointer(env, obj)->title_id >> 32) & 0xFFFFFFFF) == 0x00040010;
}
jboolean Java_org_citra_citra_1emu_model_GameInfo_getIsVisibleSystemTitle(JNIEnv* env, jboolean Java_org_citra_citra_1emu_model_GameInfo_getIsVisibleSystemTitle(JNIEnv* env,
jobject obj) { jobject obj) {
Loader::SMDH* smdh = GetPointer(env, obj); Loader::SMDH* smdh = &GetPointer(env, obj)->smdh;
if (smdh == nullptr) { if (!smdh->IsValid()) {
return false; return false;
} }
return smdh->flags & Loader::SMDH::Flags::Visible; return smdh->flags & Loader::SMDH::Flags::Visible;
} }
jstring Java_org_citra_citra_1emu_model_GameInfo_getFileType(JNIEnv* env, jobject obj) {
std::string& file_type = GetPointer(env, obj)->file_type;
return ToJString(env, file_type);
}
} }

View File

@ -16,17 +16,20 @@
#include <core/hle/service/cfg/cfg.h> #include <core/hle/service/cfg/cfg.h>
#include "audio_core/dsp_interface.h" #include "audio_core/dsp_interface.h"
#include "common/arch.h" #include "common/arch.h"
#if CITRA_ARCH(arm64) #if CITRA_ARCH(arm64)
#include "common/aarch64/cpu_detect.h" #include "common/aarch64/cpu_detect.h"
#elif CITRA_ARCH(x86_64) #elif CITRA_ARCH(x86_64)
#include "common/x64/cpu_detect.h" #include "common/x64/cpu_detect.h"
#endif #endif
#include "common/common_paths.h" #include "common/common_paths.h"
#include "common/dynamic_library/dynamic_library.h" #include "common/dynamic_library/dynamic_library.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/microprofile.h" #include "common/microprofile.h"
#include "common/play_time_manager.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
@ -46,12 +49,18 @@
#include "jni/camera/ndk_camera.h" #include "jni/camera/ndk_camera.h"
#include "jni/camera/still_image_camera.h" #include "jni/camera/still_image_camera.h"
#include "jni/config.h" #include "jni/config.h"
#ifdef ENABLE_OPENGL #ifdef ENABLE_OPENGL
#include "jni/emu_window/emu_window_gl.h" #include "jni/emu_window/emu_window_gl.h"
#endif #endif
#ifdef ENABLE_VULKAN #ifdef ENABLE_VULKAN
#include "jni/emu_window/emu_window_vk.h" #include "jni/emu_window/emu_window_vk.h"
#if CITRA_ARCH(arm64)
#include <adrenotools/driver.h>
#endif #endif
#endif
#include "jni/id_cache.h" #include "jni/id_cache.h"
#include "jni/input_manager.h" #include "jni/input_manager.h"
#include "jni/ndk_motion.h" #include "jni/ndk_motion.h"
@ -60,16 +69,17 @@
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
#if defined(ENABLE_VULKAN) && CITRA_ARCH(arm64)
#include <adrenotools/driver.h>
#endif
namespace { namespace {
ANativeWindow* s_surf; ANativeWindow* s_surface;
ANativeWindow* s_secondary_surface;
std::shared_ptr<Common::DynamicLibrary> vulkan_library{}; std::shared_ptr<Common::DynamicLibrary> vulkan_library{};
std::unique_ptr<EmuWindow_Android> window; std::unique_ptr<EmuWindow_Android> window;
std::unique_ptr<EmuWindow_Android> secondary_window;
std::unique_ptr<PlayTime::PlayTimeManager> play_time_manager;
jlong ptm_current_title_id = std::numeric_limits<jlong>::max(); // Arbitrary default value
std::atomic<bool> stop_run{true}; std::atomic<bool> stop_run{true};
std::atomic<bool> pause_emulation{false}; std::atomic<bool> pause_emulation{false};
@ -120,8 +130,17 @@ static void TryShutdown() {
} }
window->DoneCurrent(); window->DoneCurrent();
if (secondary_window) {
secondary_window->DoneCurrent();
}
Core::System::GetInstance().Shutdown(); Core::System::GetInstance().Shutdown();
window.reset(); window.reset();
if (secondary_window) {
secondary_window.reset();
}
InputManager::Shutdown(); InputManager::Shutdown();
MicroProfileShutdown(); MicroProfileShutdown();
} }
@ -147,15 +166,21 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
Core::System& system{Core::System::GetInstance()}; Core::System& system{Core::System::GetInstance()};
const auto graphics_api = Settings::values.graphics_api.GetValue(); const auto graphics_api = Settings::values.graphics_api.GetValue();
EGLContext* shared_context;
switch (graphics_api) { switch (graphics_api) {
#ifdef ENABLE_OPENGL #ifdef ENABLE_OPENGL
case Settings::GraphicsAPI::OpenGL: case Settings::GraphicsAPI::OpenGL:
window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_surf); window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_surface, false);
shared_context = window->GetEGLContext();
secondary_window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_secondary_surface,
true, shared_context);
break; break;
#endif #endif
#ifdef ENABLE_VULKAN #ifdef ENABLE_VULKAN
case Settings::GraphicsAPI::Vulkan: case Settings::GraphicsAPI::Vulkan:
window = std::make_unique<EmuWindow_Android_Vulkan>(s_surf, vulkan_library); window = std::make_unique<EmuWindow_Android_Vulkan>(s_surface, vulkan_library, false);
secondary_window =
std::make_unique<EmuWindow_Android_Vulkan>(s_secondary_surface, vulkan_library, true);
break; break;
#endif #endif
default: default:
@ -163,9 +188,15 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
"Unknown or unsupported graphics API {}, falling back to available default", "Unknown or unsupported graphics API {}, falling back to available default",
graphics_api); graphics_api);
#ifdef ENABLE_OPENGL #ifdef ENABLE_OPENGL
window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_surf); window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_surface, false);
shared_context = window->GetEGLContext();
secondary_window = std::make_unique<EmuWindow_Android_OpenGL>(system, s_secondary_surface,
true, shared_context);
#elif ENABLE_VULKAN #elif ENABLE_VULKAN
window = std::make_unique<EmuWindow_Android_Vulkan>(s_surf, vulkan_library); window = std::make_unique<EmuWindow_Android_Vulkan>(s_surface, vulkan_library);
secondary_window =
std::make_unique<EmuWindow_Android_Vulkan>(s_secondary_surface, vulkan_library, true);
#else #else
// TODO: Add a null renderer backend for this, perhaps. // TODO: Add a null renderer backend for this, perhaps.
#error "At least one renderer must be enabled." #error "At least one renderer must be enabled."
@ -204,7 +235,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
InputManager::Init(); InputManager::Init();
window->MakeCurrent(); window->MakeCurrent();
const Core::System::ResultStatus load_result{system.Load(*window, filepath)}; const Core::System::ResultStatus load_result{
system.Load(*window, filepath, secondary_window.get())};
if (load_result != Core::System::ResultStatus::Success) { if (load_result != Core::System::ResultStatus::Success) {
return load_result; return load_result;
} }
@ -300,28 +332,68 @@ extern "C" {
void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
[[maybe_unused]] jobject obj, [[maybe_unused]] jobject obj,
jobject surf) { jobject surf) {
s_surf = ANativeWindow_fromSurface(env, surf); s_surface = ANativeWindow_fromSurface(env, surf);
bool notify = false; bool notify = false;
if (window) { if (window) {
notify = window->OnSurfaceChanged(s_surf); notify = window->OnSurfaceChanged(s_surface);
} }
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
if (notify && system.IsPoweredOn()) { if (notify && system.IsPoweredOn()) {
system.GPU().Renderer().NotifySurfaceChanged(); system.GPU().Renderer().NotifySurfaceChanged(false);
} }
LOG_INFO(Frontend, "Surface changed"); LOG_INFO(Frontend, "Surface changed");
} }
void Java_org_citra_citra_1emu_NativeLibrary_secondarySurfaceChanged(JNIEnv* env,
[[maybe_unused]] jobject obj,
jobject surf) {
auto& system = Core::System::GetInstance();
if (s_secondary_surface) {
ANativeWindow_release(s_secondary_surface);
s_secondary_surface = nullptr;
}
s_secondary_surface = ANativeWindow_fromSurface(env, surf);
if (!s_secondary_surface) {
return;
}
bool notify = false;
if (secondary_window) {
// Second window already created, so update it
notify = secondary_window->OnSurfaceChanged(s_secondary_surface);
} else {
LOG_WARNING(Frontend,
"Second Window does not exist in native.cpp but surface changed. Ignoring.");
}
if (notify && system.IsPoweredOn()) {
system.GPU().Renderer().NotifySurfaceChanged(true);
}
LOG_INFO(Frontend, "Secondary Surface changed");
}
void Java_org_citra_citra_1emu_NativeLibrary_secondarySurfaceDestroyed(
JNIEnv* env, [[maybe_unused]] jobject obj) {
if (s_secondary_surface != nullptr) {
ANativeWindow_release(s_secondary_surface);
s_secondary_surface = nullptr;
}
LOG_INFO(Frontend, "Secondary Surface Destroyed");
}
void Java_org_citra_citra_1emu_NativeLibrary_surfaceDestroyed([[maybe_unused]] JNIEnv* env, void Java_org_citra_citra_1emu_NativeLibrary_surfaceDestroyed([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jobject obj) { [[maybe_unused]] jobject obj) {
if (s_surf != nullptr) { if (s_surface != nullptr) {
ANativeWindow_release(s_surf); ANativeWindow_release(s_surface);
s_surf = nullptr; s_surface = nullptr;
if (window) { if (window) {
window->OnSurfaceChanged(s_surf); window->OnSurfaceChanged(s_surface);
} }
} }
} }
@ -334,6 +406,9 @@ void Java_org_citra_citra_1emu_NativeLibrary_doFrame([[maybe_unused]] JNIEnv* en
if (window) { if (window) {
window->TryPresenting(); window->TryPresenting();
} }
if (secondary_window) {
secondary_window->TryPresenting();
}
} }
void JNICALL Java_org_citra_citra_1emu_NativeLibrary_initializeGpuDriver( void JNICALL Java_org_citra_citra_1emu_NativeLibrary_initializeGpuDriver(
@ -510,6 +585,9 @@ void Java_org_citra_citra_1emu_NativeLibrary_stopEmulation([[maybe_unused]] JNIE
stop_run = true; stop_run = true;
pause_emulation = false; pause_emulation = false;
window->StopPresenting(); window->StopPresenting();
if (secondary_window) {
secondary_window->StopPresenting();
}
running_cv.notify_all(); running_cv.notify_all();
} }
@ -579,6 +657,25 @@ void Java_org_citra_citra_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEn
window->OnTouchMoved((int)x, (int)y); window->OnTouchMoved((int)x, (int)y);
} }
jboolean Java_org_citra_citra_1emu_NativeLibrary_onSecondaryTouchEvent([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jobject obj,
jfloat x, jfloat y,
jboolean pressed) {
if (!secondary_window) {
return JNI_FALSE;
}
return static_cast<jboolean>(secondary_window->OnTouchEvent(
static_cast<int>(x + 0.5), static_cast<int>(y + 0.5), pressed));
}
void Java_org_citra_citra_1emu_NativeLibrary_onSecondaryTouchMoved([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jobject obj,
jfloat x, jfloat y) {
if (secondary_window) {
secondary_window->OnTouchMoved((int)x, (int)y);
}
}
jlong Java_org_citra_citra_1emu_NativeLibrary_getTitleId(JNIEnv* env, [[maybe_unused]] jobject obj, jlong Java_org_citra_citra_1emu_NativeLibrary_getTitleId(JNIEnv* env, [[maybe_unused]] jobject obj,
jstring j_filename) { jstring j_filename) {
std::string filepath = GetJString(env, j_filename); std::string filepath = GetJString(env, j_filename);
@ -644,18 +741,19 @@ void Java_org_citra_citra_1emu_NativeLibrary_reloadSettings([[maybe_unused]] JNI
jdoubleArray Java_org_citra_citra_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jdoubleArray Java_org_citra_citra_1emu_NativeLibrary_getPerfStats(JNIEnv* env,
[[maybe_unused]] jobject obj) { [[maybe_unused]] jobject obj) {
auto& core = Core::System::GetInstance(); auto& core = Core::System::GetInstance();
jdoubleArray j_stats = env->NewDoubleArray(8); jdoubleArray j_stats = env->NewDoubleArray(9);
if (core.IsPoweredOn()) { if (core.IsPoweredOn()) {
auto results = core.GetAndResetPerfStats(); auto results = core.GetAndResetPerfStats();
// Converting the structure into an array makes it easier to pass it to the frontend // Converting the structure into an array makes it easier to pass it to the frontend
double stats[8] = {results.system_fps, results.game_fps, double stats[9] = {results.system_fps, results.game_fps,
results.emulation_speed, results.time_vblank_interval, results.emulation_speed, results.time_vblank_interval,
results.time_hle_svc, results.time_hle_ipc, results.time_hle_svc, results.time_hle_ipc,
results.time_gpu, results.time_remaining}; results.time_gpu, results.time_swap,
results.time_remaining};
env->SetDoubleArrayRegion(j_stats, 0, 8, stats); env->SetDoubleArrayRegion(j_stats, 0, 9, stats);
} }
return j_stats; return j_stats;
@ -794,4 +892,31 @@ void Java_org_citra_citra_1emu_NativeLibrary_disableTemporaryFrameLimit(JNIEnv*
Settings::is_temporary_frame_limit = false; Settings::is_temporary_frame_limit = false;
} }
void Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerInit(JNIEnv* env, jobject obj) {
play_time_manager = std::make_unique<PlayTime::PlayTimeManager>();
}
void Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerStart(JNIEnv* env, jobject obj,
jlong title_id) {
ptm_current_title_id = title_id;
if (play_time_manager) {
play_time_manager->SetProgramId(static_cast<u64>(title_id));
play_time_manager->Start();
}
}
void Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerStop(JNIEnv* env, jobject obj) {
play_time_manager->Stop();
}
jlong Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerGetPlayTime(JNIEnv* env, jobject obj,
jlong title_id) {
return static_cast<jlong>(play_time_manager->GetPlayTime(title_id));
}
jlong Java_org_citra_citra_1emu_NativeLibrary_playTimeManagerGetCurrentTitleId(JNIEnv* env,
jobject obj) {
return ptm_current_title_id;
}
} // extern "C" } // extern "C"

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/right_content"
app:layout_constraintHorizontal_weight="2">
<ImageView
android:id="@+id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="32dp"
app:layout_constraintBottom_toTopOf="@+id/text_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_max="160dp"
app:layout_constraintHeight_min="80dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="160dp"
app:layout_constraintWidth_min="80dp"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_weight="3"
tools:src="@drawable/ic_notification" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text_title"
style="@style/TextAppearance.Material3.DisplaySmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="?attr/colorOnSurface"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/text_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/icon"
tools:text="@string/welcome" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text_description"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@+id/text_confirmation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_title"
app:lineHeight="30sp"
tools:text="@string/welcome_description" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text_confirmation"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:text="@string/step_complete"
android:textAlignment="center"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_description"
app:lineHeight="30sp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/left_content"
app:layout_constraintHorizontal_weight="1">
<LinearLayout
android:id="@+id/page_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -44,8 +44,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textSize="20sp" android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="Application Title" /> tools:text="Application Title" />
@ -85,6 +85,24 @@
app:layout_constraintTop_toBottomOf="@+id/about_game_id" app:layout_constraintTop_toBottomOf="@+id/about_game_id"
tools:text="Application Filename" /> tools:text="Application Filename" />
<TextView
android:id="@+id/about_game_filetype"
style="?attr/textAppearanceBodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@id/about_game_title"
app:layout_constraintTop_toBottomOf="@+id/about_game_filename"
tools:text="Game Filetype" />
<TextView
android:id="@+id/about_game_playtime"
style="?attr/textAppearanceBodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@id/about_game_title"
app:layout_constraintTop_toBottomOf="@+id/about_game_filetype"
tools:text="Game Playtime" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout <LinearLayout

View File

@ -86,6 +86,10 @@
android:id="@+id/menu_emulation_adjust_opacity" android:id="@+id/menu_emulation_adjust_opacity"
android:title="@string/emulation_control_opacity" /> android:title="@string/emulation_control_opacity" />
<item
android:id="@+id/menu_emulation_button_sliding"
android:title="@string/emulation_button_sliding">
</item>
<group android:checkableBehavior="all"> <group android:checkableBehavior="all">
<item <item
android:id="@+id/menu_emulation_joystick_rel_center" android:id="@+id/menu_emulation_joystick_rel_center"

View File

@ -193,6 +193,9 @@
<string name="region_mismatch">Advertiment Regió No Vàlida</string> <string name="region_mismatch">Advertiment Regió No Vàlida</string>
<string name="region_mismatch_emulated">La configuració del país no és vàlida per a la regió emulada seleccionada.</string> <string name="region_mismatch_emulated">La configuració del país no és vàlida per a la regió emulada seleccionada.</string>
<string name="region_mismatch_console">La configuració del país no és vàlida per a la consola vinculada actual.</string> <string name="region_mismatch_console">La configuració del país no és vàlida per a la consola vinculada actual.</string>
<string name="storage">Emmagatzematge</string>
<string name="compress_cia_installs">Comprimir el contingut de CIAs instal·lats</string>
<string name="compress_cia_installs_description">Comprimix el contingut de fitxers CIA quan són instal·lats a la SD emulada. Només afecta contingut CIA instal·lat amb esta opció activada.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Càmera interior</string> <string name="inner_camera">Càmera interior</string>
@ -398,6 +401,10 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
<string name="emulation_configure_controls">Configurar Controls</string> <string name="emulation_configure_controls">Configurar Controls</string>
<string name="emulation_edit_layout">Editar Estil</string> <string name="emulation_edit_layout">Editar Estil</string>
<string name="emulation_done">Fet</string> <string name="emulation_done">Fet</string>
<string name="emulation_button_sliding">Lliscament de botons</string>
<string name="emulation_button_sliding_disabled">Mantindre el botó pressionat originalment</string>
<string name="emulation_button_sliding_enabled">Mantindre el botó pressionat actualment</string>
<string name="emulation_button_sliding_alternative">Mantindre el botó original i actualment pressionat</string>
<string name="emulation_toggle_controls">Activar Controls</string> <string name="emulation_toggle_controls">Activar Controls</string>
<string name="emulation_control_scale">Ajustar Escala</string> <string name="emulation_control_scale">Ajustar Escala</string>
<string name="emulation_control_scale_global">Escala Global</string> <string name="emulation_control_scale_global">Escala Global</string>
@ -410,6 +417,8 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
<string name="emulation_aspect_ratio">Relació d\'Aspecte</string> <string name="emulation_aspect_ratio">Relació d\'Aspecte</string>
<string name="emulation_switch_screen_layout">Estil de Pantalla Apaïsada</string> <string name="emulation_switch_screen_layout">Estil de Pantalla Apaïsada</string>
<string name="emulation_switch_portrait_layout">Estil de Pantalla de Perfil</string> <string name="emulation_switch_portrait_layout">Estil de Pantalla de Perfil</string>
<string name="emulation_switch_secondary_layout">Estil de Pantalla Secundària</string>
<string name="emulation_switch_secondary_layout_description">La disposició de la pantalla secundària connectada, amb cable o sense fil (Chromecast, Miracast)</string>
<string name="emulation_screen_layout_largescreen">Pantalla amplia</string> <string name="emulation_screen_layout_largescreen">Pantalla amplia</string>
<string name="emulation_screen_layout_portrait">Vertical</string> <string name="emulation_screen_layout_portrait">Vertical</string>
<string name="emulation_screen_layout_single">Pantalla Única</string> <string name="emulation_screen_layout_single">Pantalla Única</string>
@ -417,6 +426,7 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
<string name="emulation_screen_layout_hybrid">Pantalles híbrides</string> <string name="emulation_screen_layout_hybrid">Pantalles híbrides</string>
<string name="emulation_screen_layout_original">Original</string> <string name="emulation_screen_layout_original">Original</string>
<string name="emulation_portrait_layout_top_full">Per omissió</string> <string name="emulation_portrait_layout_top_full">Per omissió</string>
<string name="emulation_secondary_display_default">Per defecte del sistema (espill)</string>
<string name="emulation_screen_layout_custom">Estil Personalitzat</string> <string name="emulation_screen_layout_custom">Estil Personalitzat</string>
<string name="emulation_small_screen_position">Posició de Pantalla Xicoteta</string> <string name="emulation_small_screen_position">Posició de Pantalla Xicoteta</string>
<string name="small_screen_position_description">On hauria d\'aparéixer la pantalla xicoteta en relació amb la gran en Proporció de Pantalla Gran?</string> <string name="small_screen_position_description">On hauria d\'aparéixer la pantalla xicoteta en relació amb la gran en Proporció de Pantalla Gran?</string>
@ -512,7 +522,6 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
<string name="save_load_error">Error de guardat/càrrega</string> <string name="save_load_error">Error de guardat/càrrega</string>
<string name="fatal_error">Error Fatal</string> <string name="fatal_error">Error Fatal</string>
<string name="fatal_error_message">Ha ocorregut un error fatal. Mira el registre per a més detalls.\nSeguir amb l\'emulació podria resultar en diversos penges i problemes.</string> <string name="fatal_error_message">Ha ocorregut un error fatal. Mira el registre per a més detalls.\nSeguir amb l\'emulació podria resultar en diversos penges i problemes.</string>
<string name="invalid_region">Regió no vàlida</string>
<string name="unsupported_encrypted">Aplicació cifrada no suportada</string> <string name="unsupported_encrypted">Aplicació cifrada no suportada</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -538,6 +547,9 @@ S\'esperen errors gràfics temporals quan estigue activat.</string>
<string name="create_shortcut">Crear drecera</string> <string name="create_shortcut">Crear drecera</string>
<string name="shortcut_name_empty">El nom de la drecera no pot estar buit</string> <string name="shortcut_name_empty">El nom de la drecera no pot estar buit</string>
<string name="shortcut_image_stretch_toggle">Allargar per a ajustar la imatge</string> <string name="shortcut_image_stretch_toggle">Allargar per a ajustar la imatge</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">Fitxer:</string>
<string name="game_context_type">Tipus:</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Mostrar informació de rendiment</string> <string name="performance_overlay_show">Mostrar informació de rendiment</string>

View File

@ -74,6 +74,10 @@
<string name="permission_denied">Tilladelse nægtet</string> <string name="permission_denied">Tilladelse nægtet</string>
<string name="add_games_warning">Vil du droppe at vælge applikationsmappen?</string> <string name="add_games_warning">Vil du droppe at vælge applikationsmappen?</string>
<string name="add_games_warning_description">Software vil ikke blive vist på applikationslisten, hvis en mappe ikke er valgt.</string> <string name="add_games_warning_description">Software vil ikke blive vist på applikationslisten, hvis en mappe ikke er valgt.</string>
<string name="permissions">Tilladelser</string>
<string name="select_emulator_data_folders">Datamapper</string>
<string name="select_emulator_data_folders_description"><![CDATA[Vælg datamapper<br/>(Brugermappe er påkrævet)]]></string>
<string name="permissions_description">Giv valgfrie tilladelser til at bruge specifikke funktioner i emulatoren</string>
<string name="warning_help">Hjælp</string> <string name="warning_help">Hjælp</string>
<string name="warning_skip">Spring over</string> <string name="warning_skip">Spring over</string>
<string name="warning_cancel">Annuller</string> <string name="warning_cancel">Annuller</string>
@ -83,6 +87,7 @@
<string name="keep_current_azahar_directory">Behold den aktuelle Azahar-mappe</string> <string name="keep_current_azahar_directory">Behold den aktuelle Azahar-mappe</string>
<string name="use_prior_lime3ds_directory">Brug tidligere Lime3DS mappe</string> <string name="use_prior_lime3ds_directory">Brug tidligere Lime3DS mappe</string>
<string name="select">Vælg</string> <string name="select">Vælg</string>
<string name="cannot_skip">Du kan ikke springe opsætningen af brugermappen over </string>
<string name="cannot_skip_directory_description">Dette trin er påkrævet for at Azahar kan fungere. Vælg en mappe og så kan du fortsætte.</string> <string name="cannot_skip_directory_description">Dette trin er påkrævet for at Azahar kan fungere. Vælg en mappe og så kan du fortsætte.</string>
<string name="selecting_user_directory_without_write_permissions">Du har mistet skrivetilladelse i din <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">brugerdata</a> mappe, hvor gemte tilstande og anden information er gemt. Dette kan ske efter en app- eller Android-opdatering. Vælg venligst mappen for at give tilladelse igen, så du kan fortsætte.</string> <string name="selecting_user_directory_without_write_permissions">Du har mistet skrivetilladelse i din <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">brugerdata</a> mappe, hvor gemte tilstande og anden information er gemt. Dette kan ske efter en app- eller Android-opdatering. Vælg venligst mappen for at give tilladelse igen, så du kan fortsætte.</string>
<string name="set_up_theme_settings">Temaindstillinger</string> <string name="set_up_theme_settings">Temaindstillinger</string>
@ -188,7 +193,6 @@
<string name="region_mismatch">Advarsel om uoverensstemmelse i region</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_emulated">Landeindstillingen er ikke gyldig for det valgte emulerede område.</string>
<string name="region_mismatch_console">Landeindstillingen er ikke gyldig for den aktuelle forbundne konsol.</string> <string name="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>
@ -207,6 +211,8 @@
<string name="graphics_api">Grafik API</string> <string name="graphics_api">Grafik API</string>
<string name="spirv_shader_gen">Aktiver generering af SPIR-V shader</string> <string name="spirv_shader_gen">Aktiver generering af SPIR-V shader</string>
<string name="spirv_shader_gen_description">Udsender den fragment shader, der bruges til at emulere PICA med SPIR-V i stedet for GLSL</string> <string name="spirv_shader_gen_description">Udsender den fragment shader, der bruges til at emulere PICA med SPIR-V i stedet for GLSL</string>
<string name="disable_spirv_optimizer">Deaktiver SPIR-V Optimeringsværktøj</string>
<string name="disable_spirv_optimizer_description">Deaktiverer SPIR-V-optimeringspasset, hvilket reducerer hakken betydeligt, mens ydeevnen næsten ikke påvirkes.</string>
<string name="async_shaders">Aktiver asynkron shader kompilering</string> <string name="async_shaders">Aktiver asynkron shader kompilering</string>
<string name="async_shaders_description">Kompilerer shaders i baggrunden for at reducere hakken under spilet. Når det er aktiveret, skal du forvente tilfældige grafiske fejl</string> <string name="async_shaders_description">Kompilerer shaders i baggrunden for at reducere hakken under spilet. Når det er aktiveret, skal du forvente tilfældige grafiske fejl</string>
<string name="linear_filtering">Lineær filtrering</string> <string name="linear_filtering">Lineær filtrering</string>
@ -215,6 +221,7 @@
<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="delay_render_thread">Forsinket spillets renderingstråd</string> <string name="delay_render_thread">Forsinket spillets renderingstråd</string>
<string name="delay_render_thread_description">Forsink spillets remderingstråd, når den sender data til GPU\'en. Hjælper med ydeevneproblemer i de (meget få) applikationer med dynamiske framerates.</string> <string name="delay_render_thread_description">Forsink spillets remderingstråd, når den sender data til GPU\'en. Hjælper med ydeevneproblemer i de (meget få) applikationer med dynamiske framerates.</string>
<string name="advanced">Avanceret</string>
<string name="texture_sampling_name">Tekstur sampling</string> <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="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="shaders_accurate_mul">Nøjagtig multiplikation</string> <string name="shaders_accurate_mul">Nøjagtig multiplikation</string>
@ -297,6 +304,9 @@
<string name="deterministic_async_operations_description">Gør asynkrone operationer deterministiske for fejlretning. Aktivering af dette kan forårsage at programmet fryser fast.</string> <string name="deterministic_async_operations_description">Gør asynkrone operationer deterministiske for fejlretning. Aktivering af dette kan forårsage at programmet fryser fast.</string>
<string name="enable_rpc_server">Aktivér RPC-server</string> <string name="enable_rpc_server">Aktivér RPC-server</string>
<string name="enable_rpc_server_desc">Aktiverer RPC-serveren på port 45987. Dette tillader fjernlæsning/skrivning af gæstehukommelse.</string> <string name="enable_rpc_server_desc">Aktiverer RPC-serveren på port 45987. Dette tillader fjernlæsning/skrivning af gæstehukommelse.</string>
<string name="shader_jit">Aktiver shader-JIT</string>
<string name="shader_jit_description">Brug JIT-motoren i stedet for fortolkeren til software-shader-emulering.</string>
<!-- Layout settings strings --> <!-- Layout settings strings -->
<string name="layout_screen_orientation">Skærmorientering</string> <string name="layout_screen_orientation">Skærmorientering</string>
<string name="layout_screen_orientation_auto_sensor">Automatisk</string> <string name="layout_screen_orientation_auto_sensor">Automatisk</string>
@ -431,6 +441,7 @@
<string name="emulation_custom_layout_height">Højde</string> <string name="emulation_custom_layout_height">Højde</string>
<string name="emulation_cycle_landscape_layouts">Skift layout</string> <string name="emulation_cycle_landscape_layouts">Skift layout</string>
<string name="emulation_swap_screens">Byt skærme</string> <string name="emulation_swap_screens">Byt skærme</string>
<string name="emulation_rotate_upright">Roter skærmen oprejst</string>
<string name="emulation_touch_overlay_reset">Nulstil overlejring</string> <string name="emulation_touch_overlay_reset">Nulstil overlejring</string>
<string name="emulation_show_controller_overlay">Vis controller-overlejring</string> <string name="emulation_show_controller_overlay">Vis controller-overlejring</string>
<string name="emulation_close_game">Luk spil</string> <string name="emulation_close_game">Luk spil</string>
@ -499,7 +510,6 @@
<string name="save_load_error">Gem/indlæs fejl</string> <string name="save_load_error">Gem/indlæs fejl</string>
<string name="fatal_error">Fatal fejl</string> <string name="fatal_error">Fatal fejl</string>
<string name="fatal_error_message">Der opstod en fatal fejl. Kontroller loggen for detaljer.\nFortsat emulering kan resultere i nedbrud og fejl.</string> <string name="fatal_error_message">Der opstod en fatal fejl. Kontroller loggen for detaljer.\nFortsat emulering kan resultere i nedbrud og fejl.</string>
<string name="invalid_region">Ugyldig region</string>
<string name="unsupported_encrypted">Ikke understøttet krypteret applikation</string> <string name="unsupported_encrypted">Ikke understøttet krypteret applikation</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -520,6 +530,11 @@
<string name="game_context_uninstall_dlc">Afinstaller DLC</string> <string name="game_context_uninstall_dlc">Afinstaller DLC</string>
<string name="game_context_uninstall_updates">Afinstaller opdateringer</string> <string name="game_context_uninstall_updates">Afinstaller opdateringer</string>
<string name="shortcut">Genvej</string> <string name="shortcut">Genvej</string>
<string name="shortcut_name">Genvejsnavn</string>
<string name="edit_icon">Rediger ikon</string>
<string name="create_shortcut">Opret genvej</string>
<string name="shortcut_name_empty">Genvejsnavnet må ikke være tomt</string>
<string name="shortcut_image_stretch_toggle">Stræk for at tilpasse billedet</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Vis ydelsesoverlejring</string> <string name="performance_overlay_show">Vis ydelsesoverlejring</string>
<string name="performance_overlay_options">Ydelsesoverlejring</string> <string name="performance_overlay_options">Ydelsesoverlejring</string>

View File

@ -193,6 +193,9 @@
<string name="region_mismatch">Advertencia Región No Válida</string> <string name="region_mismatch">Advertencia Región No Válida</string>
<string name="region_mismatch_emulated">La configuración del país no es válida para la región emulada seleccionada.</string> <string name="region_mismatch_emulated">La configuración del país no es válida para la región emulada seleccionada.</string>
<string name="region_mismatch_console">La configuración del país no es válida para la consola vinculada actual.</string> <string name="region_mismatch_console">La configuración del país no es válida para la consola vinculada actual.</string>
<string name="storage">Almacenamiento</string>
<string name="compress_cia_installs">Comprimir el contenido de CIAs instalados</string>
<string name="compress_cia_installs_description">Comprime el contenido de archivos CIA cuando son instalados a la SD emulada. Solo afecta contenido CIA instalado con esta opción activada.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Cámara interior</string> <string name="inner_camera">Cámara interior</string>
@ -398,6 +401,10 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
<string name="emulation_configure_controls">Configurar Controles</string> <string name="emulation_configure_controls">Configurar Controles</string>
<string name="emulation_edit_layout">Editar Estilo</string> <string name="emulation_edit_layout">Editar Estilo</string>
<string name="emulation_done">Hecho</string> <string name="emulation_done">Hecho</string>
<string name="emulation_button_sliding">Deslizamiento de botones</string>
<string name="emulation_button_sliding_disabled">Mantener el botón presionado originalmente</string>
<string name="emulation_button_sliding_enabled">Mantener el botón presionado actualmente</string>
<string name="emulation_button_sliding_alternative">Mantener el botón original y actualmente presionado</string>
<string name="emulation_toggle_controls">Activar Controles</string> <string name="emulation_toggle_controls">Activar Controles</string>
<string name="emulation_control_scale">Ajustar Escala</string> <string name="emulation_control_scale">Ajustar Escala</string>
<string name="emulation_control_scale_global">Escala Global</string> <string name="emulation_control_scale_global">Escala Global</string>
@ -410,6 +417,8 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
<string name="emulation_aspect_ratio">Relación de Aspecto</string> <string name="emulation_aspect_ratio">Relación de Aspecto</string>
<string name="emulation_switch_screen_layout">Estilo de Pantalla Apaisada</string> <string name="emulation_switch_screen_layout">Estilo de Pantalla Apaisada</string>
<string name="emulation_switch_portrait_layout">Estilo de Pantalla de Perfil</string> <string name="emulation_switch_portrait_layout">Estilo de Pantalla de Perfil</string>
<string name="emulation_switch_secondary_layout">Estilo de Pantalla Secundaria</string>
<string name="emulation_switch_secondary_layout_description">El estilo de la pantalla secundaria conectada, con cable o inalámbrica (Chromecast, Miracast)</string>
<string name="emulation_screen_layout_largescreen">Pantalla amplia</string> <string name="emulation_screen_layout_largescreen">Pantalla amplia</string>
<string name="emulation_screen_layout_portrait">Retrato</string> <string name="emulation_screen_layout_portrait">Retrato</string>
<string name="emulation_screen_layout_single">Pantalla Única</string> <string name="emulation_screen_layout_single">Pantalla Única</string>
@ -417,6 +426,7 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
<string name="emulation_screen_layout_hybrid">Pantallas híbridas</string> <string name="emulation_screen_layout_hybrid">Pantallas híbridas</string>
<string name="emulation_screen_layout_original">Original</string> <string name="emulation_screen_layout_original">Original</string>
<string name="emulation_portrait_layout_top_full">Por defecto</string> <string name="emulation_portrait_layout_top_full">Por defecto</string>
<string name="emulation_secondary_display_default">Por defecto del sistema (espejo)</string>
<string name="emulation_screen_layout_custom">Estilo personalizado</string> <string name="emulation_screen_layout_custom">Estilo personalizado</string>
<string name="emulation_small_screen_position">Posición Pantalla Pequeña</string> <string name="emulation_small_screen_position">Posición Pantalla Pequeña</string>
<string name="small_screen_position_description">¿Dónde debería aparecer la pantalla pequeña en relación con la grande en Disposicion de Pantalla Grande?</string> <string name="small_screen_position_description">¿Dónde debería aparecer la pantalla pequeña en relación con la grande en Disposicion de Pantalla Grande?</string>
@ -512,7 +522,6 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
<string name="save_load_error">Error de guardado/carga</string> <string name="save_load_error">Error de guardado/carga</string>
<string name="fatal_error">Error Fatal</string> <string name="fatal_error">Error Fatal</string>
<string name="fatal_error_message">Ha ocurrido un error fatal. Mira el registro para más detalles.\nSeguir con la emulación podría resultar en diversos cuelgues y bugs.</string> <string name="fatal_error_message">Ha ocurrido un error fatal. Mira el registro para más detalles.\nSeguir con la emulación podría resultar en diversos cuelgues y bugs.</string>
<string name="invalid_region">Región no válida</string>
<string name="unsupported_encrypted">Aplicación encriptada no soportada</string> <string name="unsupported_encrypted">Aplicación encriptada no soportada</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -538,6 +547,9 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
<string name="create_shortcut">Crear atajo</string> <string name="create_shortcut">Crear atajo</string>
<string name="shortcut_name_empty">El nombre del atajo no puede estar vacío</string> <string name="shortcut_name_empty">El nombre del atajo no puede estar vacío</string>
<string name="shortcut_image_stretch_toggle">Alargar para ajustar la imagen</string> <string name="shortcut_image_stretch_toggle">Alargar para ajustar la imagen</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">Archivo:</string>
<string name="game_context_type">Tipo:</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Mostrar información de rendimiento</string> <string name="performance_overlay_show">Mostrar información de rendimiento</string>

View File

@ -193,6 +193,9 @@
<string name="region_mismatch">Ostrzeżenie o niedopasowaniu regionów</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_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> <string name="region_mismatch_console">Ustawienie kraju nie jest prawidłowe dla aktualnie podłączonej konsoli.</string>
<string name="storage">Miejsce</string>
<string name="compress_cia_installs">Kompresuj zainstalowaną zawartość CIA</string>
<string name="compress_cia_installs_description">Kompresuje zawartość plików CIA zainstalowanych na emulowanej karcie SD. Ma wpływ tylko na zawartość CIA, która jest instalowana, gdy ustawienie jest włączone.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Kamera wewnętrzna</string> <string name="inner_camera">Kamera wewnętrzna</string>
@ -397,6 +400,10 @@
<string name="emulation_configure_controls">Konfiguracja sterowania</string> <string name="emulation_configure_controls">Konfiguracja sterowania</string>
<string name="emulation_edit_layout">Edytuj układ</string> <string name="emulation_edit_layout">Edytuj układ</string>
<string name="emulation_done">Gotowe</string> <string name="emulation_done">Gotowe</string>
<string name="emulation_button_sliding">Przesuwanie przycisków</string>
<string name="emulation_button_sliding_disabled">Przytrzymuje pierwotnie naciśnięty przycisk</string>
<string name="emulation_button_sliding_enabled">przytrzymuje aktualnie naciśnięty przycisk</string>
<string name="emulation_button_sliding_alternative">Przytrzymuje oryginalny i aktualnie naciśnięty przycisk</string>
<string name="emulation_toggle_controls">Przełącz sterowanie</string> <string name="emulation_toggle_controls">Przełącz sterowanie</string>
<string name="emulation_control_scale">Dostosuj Skalę</string> <string name="emulation_control_scale">Dostosuj Skalę</string>
<string name="emulation_control_scale_global">Ogólna Skala</string> <string name="emulation_control_scale_global">Ogólna Skala</string>
@ -409,6 +416,8 @@
<string name="emulation_aspect_ratio">Proporcje obrazu</string> <string name="emulation_aspect_ratio">Proporcje obrazu</string>
<string name="emulation_switch_screen_layout">Geometryczny Układ Ekranu</string> <string name="emulation_switch_screen_layout">Geometryczny Układ Ekranu</string>
<string name="emulation_switch_portrait_layout">Pionowy Układ Ekranu</string> <string name="emulation_switch_portrait_layout">Pionowy Układ Ekranu</string>
<string name="emulation_switch_secondary_layout">Układ ekranu wyświetlacza dodatkowego</string>
<string name="emulation_switch_secondary_layout_description">Układ używany przez podłączony dodatkowy ekran, przewodowy lub bezprzewodowy (Chromecast, Miracast)</string>
<string name="emulation_screen_layout_largescreen">Duży Ekran</string> <string name="emulation_screen_layout_largescreen">Duży Ekran</string>
<string name="emulation_screen_layout_portrait">Ekran</string> <string name="emulation_screen_layout_portrait">Ekran</string>
<string name="emulation_screen_layout_single">Pojedynczy ekran</string> <string name="emulation_screen_layout_single">Pojedynczy ekran</string>
@ -416,6 +425,7 @@
<string name="emulation_screen_layout_hybrid">Hybrydowy Ekran</string> <string name="emulation_screen_layout_hybrid">Hybrydowy Ekran</string>
<string name="emulation_screen_layout_original">Oryginalny</string> <string name="emulation_screen_layout_original">Oryginalny</string>
<string name="emulation_portrait_layout_top_full">Domyślny</string> <string name="emulation_portrait_layout_top_full">Domyślny</string>
<string name="emulation_secondary_display_default">Ustawienia domyślne systemu (mirror)</string>
<string name="emulation_screen_layout_custom">Niestandardowy Układ</string> <string name="emulation_screen_layout_custom">Niestandardowy Układ</string>
<string name="emulation_small_screen_position">Pozycja małego ekranu</string> <string name="emulation_small_screen_position">Pozycja małego ekranu</string>
<string name="small_screen_position_description">Gdzie powinien być wyświetlany mały ekran względem dużego w układzie dużego ekranu?</string> <string name="small_screen_position_description">Gdzie powinien być wyświetlany mały ekran względem dużego w układzie dużego ekranu?</string>
@ -511,7 +521,6 @@
<string name="save_load_error">Błąd zapisywania/wczytywania</string> <string name="save_load_error">Błąd zapisywania/wczytywania</string>
<string name="fatal_error">Krytyczny Błąd</string> <string name="fatal_error">Krytyczny Błąd</string>
<string name="fatal_error_message">Wystąpił błąd krytyczny. Kontynuowanie emulacji może spowodować awarie i błędy.</string> <string name="fatal_error_message">Wystąpił błąd krytyczny. Kontynuowanie emulacji może spowodować awarie i błędy.</string>
<string name="invalid_region">Nieprawidłowy region</string>
<string name="unsupported_encrypted">Nieobsługiwana zaszyfrowana aplikacja</string> <string name="unsupported_encrypted">Nieobsługiwana zaszyfrowana aplikacja</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -537,6 +546,9 @@
<string name="create_shortcut">Utwórz skrót</string> <string name="create_shortcut">Utwórz skrót</string>
<string name="shortcut_name_empty">Nazwa skrótu nie może być pusta</string> <string name="shortcut_name_empty">Nazwa skrótu nie może być pusta</string>
<string name="shortcut_image_stretch_toggle">Rozciągnij, aby dopasować obraz</string> <string name="shortcut_image_stretch_toggle">Rozciągnij, aby dopasować obraz</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">Plik:</string>
<string name="game_context_type">Typ:</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Wyświetl nakładkę wydajności</string> <string name="performance_overlay_show">Wyświetl nakładkę wydajności</string>

View File

@ -11,13 +11,13 @@
<string name="home_options">Opções</string> <string name="home_options">Opções</string>
<string name="home_search">Procurar</string> <string name="home_search">Procurar</string>
<string name="home_games">Aplicativos</string> <string name="home_games">Aplicativos</string>
<string name="settings_description">Definir configurações do emulador</string> <string name="settings_description">Definir as configurações do emulador</string>
<string name="install_game_content">Instale o arquivo CIA</string> <string name="install_game_content">Instalar arquivo CIA</string>
<string name="install_game_content_description">Instalar aplicativos, atualizações ou DLC</string> <string name="install_game_content_description">Instalar aplicativos, atualizações ou DLC</string>
<string name="share_log">Compartilhar registro</string> <string name="share_log">Compartilhar Registro</string>
<string name="share_log_description">Compartilhe o arquivo de log do Azahar para depurar problemas</string> <string name="share_log_description">Compartilhe o arquivo de log do Azahar para depurar problemas</string>
<string name="gpu_driver_manager">Gerenciador de driver da GPU</string> <string name="gpu_driver_manager">Gerenciador de Driver da GPU</string>
<string name="install_gpu_driver">Instale o driver da GPU</string> <string name="install_gpu_driver">Instalar driver da GPU</string>
<string name="install_gpu_driver_description">Instale drivers alternativos para poder obter desempenho ou precisão</string> <string name="install_gpu_driver_description">Instale drivers alternativos para poder obter desempenho ou precisão</string>
<string name="driver_already_installed">Driver já instalado</string> <string name="driver_already_installed">Driver já instalado</string>
<string name="custom_driver_not_supported">Drivers personalizados não suportados</string> <string name="custom_driver_not_supported">Drivers personalizados não suportados</string>
@ -27,15 +27,15 @@
<string name="select_games_folder_description">Permitir que o Azahar preencha a lista de aplicativos</string> <string name="select_games_folder_description">Permitir que o Azahar preencha a lista de aplicativos</string>
<string name="about">Sobre</string> <string name="about">Sobre</string>
<string name="citra_description">Um emulador de 3DS de código aberto</string> <string name="citra_description">Um emulador de 3DS de código aberto</string>
<string name="about_description">Versão de compilação, créditos e mais</string> <string name="about_description">Versão da compilação, créditos e mais</string>
<string name="games_dir_selected">Diretório de aplicativos selecionado</string> <string name="games_dir_selected">Diretório do aplicativo selecionado</string>
<string name="select_citra_user_folder_home_description">Altera os arquivos que o Azahar usa para carregar aplicativos</string> <string name="select_citra_user_folder_home_description">Altera os arquivos que o Azahar usa para carregar aplicativos</string>
<string name="theme_and_color_description">Modificar a aparência do aplicativo</string> <string name="theme_and_color_description">Modificar a aparência do aplicativo</string>
<string name="install_cia_title">Instale a CIA</string> <string name="install_cia_title">Instalar arquivo CIA</string>
<string name="warning_3ds_files"><![CDATA[Arquivos criptografados e arquivos .3ds não são mais suportados. Talvez seja necessário descriptografá-los e/ou renomeá-los para .cci. <a href=\"https://azahar-emu.org/blog/game-loading-changes/\">Saiba mais.</a>]]></string> <string name="warning_3ds_files"><![CDATA[Arquivos criptografados e arquivos .3ds não são mais suportados. Talvez seja necessário descriptografá-los e/ou renomeá-los para .cci. <a href=\"https://azahar-emu.org/blog/game-loading-changes/\">Saiba mais.</a>]]></string>
<!-- GPU driver installation --> <!-- GPU driver installation -->
<string name="select_gpu_driver">Selecione o driver GPU</string> <string name="select_gpu_driver">Selecionar driver da GPU</string>
<string name="select_gpu_driver_title">Você quer substituir seu driver de GPU atual?</string> <string name="select_gpu_driver_title">Você quer substituir seu driver de GPU atual?</string>
<string name="select_gpu_driver_install">Instalar</string> <string name="select_gpu_driver_install">Instalar</string>
<string name="select_gpu_driver_default">Padrão</string> <string name="select_gpu_driver_default">Padrão</string>
@ -74,6 +74,10 @@
<string name="permission_denied">Permissão negada</string> <string name="permission_denied">Permissão negada</string>
<string name="add_games_warning">Pular a seleção da pasta de aplicativos?</string> <string name="add_games_warning">Pular a seleção da pasta de aplicativos?</string>
<string name="add_games_warning_description">Os softwares não serão exibidos na lista de Aplicativos se uma pasta não for selecionada.</string> <string name="add_games_warning_description">Os softwares não serão exibidos na lista de Aplicativos se uma pasta não for selecionada.</string>
<string name="permissions">Premissões</string>
<string name="select_emulator_data_folders">Pastas de Dados</string>
<string name="select_emulator_data_folders_description"><![CDATA[Selecione pastas de dados<br/>(Pasta de usuário é necessária)]]></string>
<string name="permissions_description">Conceda permissões opcionais para usar recursos específicos do emulador.</string>
<string name="warning_help">Ajuda</string> <string name="warning_help">Ajuda</string>
<string name="warning_skip">Pular</string> <string name="warning_skip">Pular</string>
<string name="warning_cancel">Cancelar</string> <string name="warning_cancel">Cancelar</string>
@ -83,6 +87,7 @@
<string name="keep_current_azahar_directory">Manter diretório atual do Azahar</string> <string name="keep_current_azahar_directory">Manter diretório atual do Azahar</string>
<string name="use_prior_lime3ds_directory">Usar o diretório antigo do Lime3DS</string> <string name="use_prior_lime3ds_directory">Usar o diretório antigo do Lime3DS</string>
<string name="select">Selecionar</string> <string name="select">Selecionar</string>
<string name="cannot_skip">Você não pode pular a configuração da pasta do usuário.</string>
<string name="cannot_skip_directory_description">Este passo é necessário para permitir que o Azahar funcione. Selecione um diretório para continuar.</string> <string name="cannot_skip_directory_description">Este passo é necessário para permitir que o Azahar funcione. Selecione um diretório para continuar.</string>
<string name="selecting_user_directory_without_write_permissions">Você perdeu suas permissões de escrita no seu diretório de <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">dados de usuário</a>, onde dados salvos e outras informações são guardadas. Isso pode acontecer depois que algum app ou Android atualiza. Re-selecione o diretório para reobter as permissões para que você possa continuar.</string> <string name="selecting_user_directory_without_write_permissions">Você perdeu suas permissões de escrita no seu diretório de <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">dados de usuário</a>, onde dados salvos e outras informações são guardadas. Isso pode acontecer depois que algum app ou Android atualiza. Re-selecione o diretório para reobter as permissões para que você possa continuar.</string>
<string name="set_up_theme_settings">Configurações de Tema</string> <string name="set_up_theme_settings">Configurações de Tema</string>
@ -124,6 +129,10 @@
<string name="button_turbo">Turbo</string> <string name="button_turbo">Turbo</string>
<string name="input_message_analog_only">Este controle tem de ser mapeado a um eixo analógico do gamepad ou um eixo de D-pad!</string> <string name="input_message_analog_only">Este controle tem de ser mapeado a um eixo analógico do gamepad ou um eixo de D-pad!</string>
<string name="input_message_button_only">Este controle tem de ser mapeado a um botão do gamepad!</string> <string name="input_message_button_only">Este controle tem de ser mapeado a um botão do gamepad!</string>
<string name="turbo_limit_hotkey">Velocidade Turbo</string>
<string name="turbo_enabled_toast">Velocidade Turbo Ativada</string>
<string name="turbo_disabled_toast">Velocidade Turbo Desativada</string>
<!-- System files strings --> <!-- System files strings -->
<string name="setup_system_files">Arquivos do Sistema</string> <string name="setup_system_files">Arquivos do Sistema</string>
<string name="setup_system_files_description">Executar operações de arquivos do sistema, como instalar arquivos do sistema ou iniciar o Menu Principal.</string> <string name="setup_system_files_description">Executar operações de arquivos do sistema, como instalar arquivos do sistema ou iniciar o Menu Principal.</string>
@ -160,6 +169,7 @@
<string name="init_clock_description">Configura o relógio emulado do 3DS para refletir o do seu dispositivo ou para começar numa data e hora simulados.</string> <string name="init_clock_description">Configura o relógio emulado do 3DS para refletir o do seu dispositivo ou para começar numa data e hora simulados.</string>
<string name="device_clock">Clock do Dispositivo</string> <string name="device_clock">Clock do Dispositivo</string>
<string name="simulated_clock">Clock Simulado</string> <string name="simulated_clock">Clock Simulado</string>
<string name="simulated_clock_description">Se o relógio estiver definido como \'Relógio simulado\', isso altera a data e hora fixas de início.</string>
<string name="profile_settings">Configurações de Perfil</string> <string name="profile_settings">Configurações de Perfil</string>
<string name="emulated_region">Região</string> <string name="emulated_region">Região</string>
<string name="emulated_language">Linguagem</string> <string name="emulated_language">Linguagem</string>
@ -183,7 +193,6 @@
<string name="region_mismatch">Aviso de inconsistência de região</string> <string name="region_mismatch">Aviso de inconsistência de região</string>
<string name="region_mismatch_emulated">O país configurado não é válido para a região emulada selecionada.</string> <string name="region_mismatch_emulated">O país configurado não é válido para a região emulada selecionada.</string>
<string name="region_mismatch_console">O país configurado não é válido para o console vinculado atual.</string> <string name="region_mismatch_console">O país configurado não é válido para o console vinculado atual.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Câmera frontal</string> <string name="inner_camera">Câmera frontal</string>
<string name="outer_left_camera">Câmera traseira esquerda</string> <string name="outer_left_camera">Câmera traseira esquerda</string>
@ -202,6 +211,8 @@
<string name="graphics_api">API de gráficos</string> <string name="graphics_api">API de gráficos</string>
<string name="spirv_shader_gen">Ativar geração de shaders SPIR-V</string> <string name="spirv_shader_gen">Ativar geração de shaders SPIR-V</string>
<string name="spirv_shader_gen_description">Emite o fragment shader usado para emular PICA usando SPIR-V em vez de GLSL</string> <string name="spirv_shader_gen_description">Emite o fragment shader usado para emular PICA usando SPIR-V em vez de GLSL</string>
<string name="disable_spirv_optimizer">Desativar otimizador SPIR-V</string>
<string name="disable_spirv_optimizer_description">Desativa a etapa de otimização SPIR-V, reduzindo consideravelmente os travamentos, com impacto mínimo no desempenho.</string>
<string name="async_shaders">Ativar a compilação assíncrona de shaders</string> <string name="async_shaders">Ativar a compilação assíncrona de shaders</string>
<string name="async_shaders_description">Compila shaders em segundo plano para reduzir travamentos durante o jogo. Quando ativado, espere falhas gráficas temporárias</string> <string name="async_shaders_description">Compila shaders em segundo plano para reduzir travamentos durante o jogo. Quando ativado, espere falhas gráficas temporárias</string>
<string name="linear_filtering">Filtragem Linear</string> <string name="linear_filtering">Filtragem Linear</string>
@ -210,6 +221,7 @@
<string name="texture_filter_description">Aprimora o visual dos aplicativos ao aplicar filtros às texturas. Os filtros compatíveis são: Anime4K Ultrafast, Bicúbico, ScaleForce, xBRZ Freescale e MMPX.</string> <string name="texture_filter_description">Aprimora o visual dos aplicativos ao aplicar filtros às texturas. Os filtros compatíveis são: Anime4K Ultrafast, Bicúbico, ScaleForce, xBRZ Freescale e MMPX.</string>
<string name="delay_render_thread">Atrasar thread de renderização do aplicativo</string> <string name="delay_render_thread">Atrasar thread de renderização do aplicativo</string>
<string name="delay_render_thread_description">Atrasar thread de renderização do aplicativo quando for enviado dados para a GPU. Ajuda com problemas de desempenho em (muito poucos) aplicativos com taxa de quadros dinâmica.</string> <string name="delay_render_thread_description">Atrasar thread de renderização do aplicativo quando for enviado dados para a GPU. Ajuda com problemas de desempenho em (muito poucos) aplicativos com taxa de quadros dinâmica.</string>
<string name="advanced">Avançado</string>
<string name="texture_sampling_name">Amostragem de Texturas</string> <string name="texture_sampling_name">Amostragem de Texturas</string>
<string name="texture_sampling_description">Substitui o filtro de amostragem usado pelos jogos. Isso pode ser útil em certos casos com jogos que se comportem mal durante o upscaling. Em caso de dúvidas, defina como Controlado pelo Jogo.</string> <string name="texture_sampling_description">Substitui o filtro de amostragem usado pelos jogos. Isso pode ser útil em certos casos com jogos que se comportem mal durante o upscaling. Em caso de dúvidas, defina como Controlado pelo Jogo.</string>
<string name="shaders_accurate_mul">Multiplicação precisa</string> <string name="shaders_accurate_mul">Multiplicação precisa</string>
@ -220,6 +232,8 @@
<string name="frame_limit_enable_description">Quando ativo, a velocidade de emulação será limitada à uma porcentagem especificada da velocidade normal. Se desativado, a velocidade de emulação será destravada e a tecla de atalho do turbo não irá funcionar.</string> <string name="frame_limit_enable_description">Quando ativo, a velocidade de emulação será limitada à uma porcentagem especificada da velocidade normal. Se desativado, a velocidade de emulação será destravada e a tecla de atalho do turbo não irá funcionar.</string>
<string name="frame_limit_slider">Limite de velocidade percentual</string> <string name="frame_limit_slider">Limite de velocidade percentual</string>
<string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade. Com o padrão de 100% a emulação será limitada a velocidade normal. Valores maiores ou menores vão aumentar ou reduzir o limite de velocidade.</string> <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade. Com o padrão de 100% a emulação será limitada a velocidade normal. Valores maiores ou menores vão aumentar ou reduzir o limite de velocidade.</string>
<string name="turbo_limit">Limite da Velocidade Turbo:</string>
<string name="turbo_limit_description">Limite de velocidade da emulação usado enquanto a tecla de atalho turbo está ativa.</string>
<string name="expand_to_cutout_area">Expandir para a área recortada</string> <string name="expand_to_cutout_area">Expandir para a área recortada</string>
<string name="expand_to_cutout_area_description">Expande a área da tela para incluir a área recortada (ou notch).</string> <string name="expand_to_cutout_area_description">Expande a área da tela para incluir a área recortada (ou notch).</string>
<string name="internal_resolution">Resolução Interna</string> <string name="internal_resolution">Resolução Interna</string>
@ -288,6 +302,11 @@
<string name="delay_start_lle_modules_description">Atrasa a inicialização do aplicativo quando os módulos LLE estão ativados.</string> <string name="delay_start_lle_modules_description">Atrasa a inicialização do aplicativo quando os módulos LLE estão ativados.</string>
<string name="deterministic_async_operations">Operações Assíncronas Determinísticas</string> <string name="deterministic_async_operations">Operações Assíncronas Determinísticas</string>
<string name="deterministic_async_operations_description">Torna as operações assíncronas determinísticas para depuração. Ativar essa opção pode causar congelamentos.</string> <string name="deterministic_async_operations_description">Torna as operações assíncronas determinísticas para depuração. Ativar essa opção pode causar congelamentos.</string>
<string name="enable_rpc_server">Ativar servidor RPC</string>
<string name="enable_rpc_server_desc">Ativa o servidor RPC na porta 45987. Isso permite ler e escrever remotamente a memória do sistema emulado.</string>
<string name="shader_jit">Ativar Shader JIT</string>
<string name="shader_jit_description">Usa o mecanismo JIT em vez do interpretador para a emulação de shaders por software.</string>
<!-- Layout settings strings --> <!-- Layout settings strings -->
<string name="layout_screen_orientation">Orientação da Tela</string> <string name="layout_screen_orientation">Orientação da Tela</string>
<string name="layout_screen_orientation_auto_sensor">Automático</string> <string name="layout_screen_orientation_auto_sensor">Automático</string>
@ -295,12 +314,20 @@
<string name="layout_screen_orientation_landscape_reverse">Paisagem Reversa</string> <string name="layout_screen_orientation_landscape_reverse">Paisagem Reversa</string>
<string name="layout_screen_orientation_portrait">Retrato</string> <string name="layout_screen_orientation_portrait">Retrato</string>
<string name="layout_screen_orientation_portrait_reverse">Retrato Reverso</string> <string name="layout_screen_orientation_portrait_reverse">Retrato Reverso</string>
<string name="aspect_ratio_default">Padrão</string>
<string name="aspect_ratio_16_9">16:9</string>
<string name="aspect_ratio_4_3">4:3</string>
<string name="aspect_ratio_21_9_fullscreen">21:9</string>
<string name="aspect_ratio_16_10_fullscreen_stretched">16:10</string>
<string name="aspect_ratio_stretch">Esticar</string>
<!-- Miscellaneous --> <!-- Miscellaneous -->
<string name="clear">Limpar</string> <string name="clear">Limpar</string>
<string name="slider_default">Padrão</string> <string name="slider_default">Padrão</string>
<string name="ini_saved">As configurações foram salvas</string> <string name="ini_saved">As configurações foram salvas</string>
<string name="gameid_saved">As configurações de %1$s foram salvas</string> <string name="gameid_saved">As configurações de %1$s foram salvas</string>
<string name="error_saving">Erro ao salvar %1$s.ini: %2$s</string> <string name="error_saving">Erro ao salvar %1$s.ini: %2$s</string>
<string name="saving">Salvando...</string>
<string name="loading">Carregando…</string> <string name="loading">Carregando…</string>
<string name="next">Próximo</string> <string name="next">Próximo</string>
<string name="back">Voltar</string> <string name="back">Voltar</string>
@ -329,6 +356,9 @@
<string name="cancelling">Cancelando...</string> <string name="cancelling">Cancelando...</string>
<string name="important">Importante</string> <string name="important">Importante</string>
<string name="dont_show_again">Não mostrar novamente</string> <string name="dont_show_again">Não mostrar novamente</string>
<string name="visibility">Visibilidade</string>
<string name="information">Informação</string>
<!-- Add Directory Screen--> <!-- Add Directory Screen-->
<string name="select_game_folder">Escolher pasta de jogos</string> <string name="select_game_folder">Escolher pasta de jogos</string>
@ -375,6 +405,7 @@
<string name="emulation_control_dpad_slide_enable">Deslize do D-Pad</string> <string name="emulation_control_dpad_slide_enable">Deslize do D-Pad</string>
<string name="emulation_open_settings">Abrir configurações</string> <string name="emulation_open_settings">Abrir configurações</string>
<string name="emulation_open_cheats">Mostrar Trapaças</string> <string name="emulation_open_cheats">Mostrar Trapaças</string>
<string name="emulation_aspect_ratio">Proporção da Tela</string>
<string name="emulation_switch_screen_layout">Disposição de tela em paisagem</string> <string name="emulation_switch_screen_layout">Disposição de tela em paisagem</string>
<string name="emulation_switch_portrait_layout">Disposição da tela em retrato</string> <string name="emulation_switch_portrait_layout">Disposição da tela em retrato</string>
<string name="emulation_screen_layout_largescreen">Tela Grande</string> <string name="emulation_screen_layout_largescreen">Tela Grande</string>
@ -395,6 +426,8 @@
<string name="small_screen_position_bottom_left">Inferior Esquerda</string> <string name="small_screen_position_bottom_left">Inferior Esquerda</string>
<string name="small_screen_position_above">Acima</string> <string name="small_screen_position_above">Acima</string>
<string name="small_screen_position_below">Abaixo</string> <string name="small_screen_position_below">Abaixo</string>
<string name="screen_gap">Espaço entre Telas</string>
<string name="screen_gap_description">Espaço entre as telas em todos os modos de duas telas. Medido em pixels em relação à altura de 240 pixels da tela maior.</string>
<string name="large_screen_proportion">Proporção de Tela Grande</string> <string name="large_screen_proportion">Proporção de Tela Grande</string>
<string name="large_screen_proportion_description">Quantas vezes maior é a tela grande em relação à tela pequena no Layout de Tela Grande?</string> <string name="large_screen_proportion_description">Quantas vezes maior é a tela grande em relação à tela pequena no Layout de Tela Grande?</string>
<string name="emulation_adjust_custom_layout">Ajuste a Disposição Personalizada nas Configurações</string> <string name="emulation_adjust_custom_layout">Ajuste a Disposição Personalizada nas Configurações</string>
@ -408,7 +441,9 @@
<string name="emulation_custom_layout_height">Altura</string> <string name="emulation_custom_layout_height">Altura</string>
<string name="emulation_cycle_landscape_layouts">Trocar Disposições</string> <string name="emulation_cycle_landscape_layouts">Trocar Disposições</string>
<string name="emulation_swap_screens">Trocar telas</string> <string name="emulation_swap_screens">Trocar telas</string>
<string name="emulation_rotate_upright">Girar Tela para Posição Vertical</string>
<string name="emulation_touch_overlay_reset">Redefinir sobreposição</string> <string name="emulation_touch_overlay_reset">Redefinir sobreposição</string>
<string name="emulation_show_controller_overlay">Mostrar Sobreposição do Controle</string>
<string name="emulation_close_game">Fechar jogo</string> <string name="emulation_close_game">Fechar jogo</string>
<string name="emulation_toggle_pause">Alternar Pausa</string> <string name="emulation_toggle_pause">Alternar Pausa</string>
<string name="miscellaneous">Diversos</string> <string name="miscellaneous">Diversos</string>
@ -475,7 +510,6 @@
<string name="save_load_error">Erro ao Salvar/Carregar</string> <string name="save_load_error">Erro ao Salvar/Carregar</string>
<string name="fatal_error">Erro Fatal</string> <string name="fatal_error">Erro Fatal</string>
<string name="fatal_error_message">Ocorreu um erro fatal. Verifique o registro para obter detalhes.\nContinuar a emulação pode resultar em falhas e bugs.</string> <string name="fatal_error_message">Ocorreu um erro fatal. Verifique o registro para obter detalhes.\nContinuar a emulação pode resultar em falhas e bugs.</string>
<string name="invalid_region">Região inválida</string>
<string name="unsupported_encrypted">Aplicativo criptografado não suportado</string> <string name="unsupported_encrypted">Aplicativo criptografado não suportado</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -496,6 +530,39 @@
<string name="game_context_uninstall_dlc">Desinstalar DLC</string> <string name="game_context_uninstall_dlc">Desinstalar DLC</string>
<string name="game_context_uninstall_updates">Desinstalar atualizações</string> <string name="game_context_uninstall_updates">Desinstalar atualizações</string>
<string name="shortcut">Atalho</string> <string name="shortcut">Atalho</string>
<string name="shortcut_name">Nome do Atalho</string>
<string name="edit_icon">Editar ícone</string>
<string name="create_shortcut">Criar Atalho</string>
<string name="shortcut_name_empty">O nome do atalho não pode ficar vazio</string>
<string name="shortcut_image_stretch_toggle">Esticar para ajustar à imagem</string>
<!-- Performance Overlay settings -->
<string name="performance_overlay_show">Mostrar Sobreposição de Desempenho</string>
<string name="performance_overlay_options">Sobreposição de Desempenho</string>
<string name="performance_overlay_enable">Ativa a Sobreposição de Desempenho</string>
<string name="performance_overlay_options_description">Configure se a sobreposição de desempenho será exibida e quais informações serão mostradas.</string>
<string name="overlay_show_fps">Mostrar FPS</string>
<string name="overlay_show_fps_description">Exibe a taxa de quadros atual por segundo.</string>
<string name="overlay_show_frametime">Mostrar Tempo de Quadro</string>
<string name="overlay_show_frametime_description">Exibe o tempo de quadro atual.</string>
<string name="overlay_show_speed">Mostrar Velocidade</string>
<string name="overlay_show_speed_description">Exibe a porcentagem atual da velocidade da emulação.</string>
<string name="overlay_show_app_ram_usage">Mostrar o Uso de Memória do Aplicativo</string>
<string name="overlay_show_app_ram_usage_description">Exibe a quantidade de RAM utilizada pelo emulador.</string>
<string name="overlay_show_available_ram">Mostrar Memória Disponível</string>
<string name="overlay_show_available_ram_description">Exibe a quantidade de RAM disponível.</string>
<string name="overlay_show_battery_temp">Mostrar a Temperatura da Bateria</string>
<string name="overlay_show_battery_temp_description">Exibe a temperatura atual da Bateria em Celsius e Fahrenheit.</string>
<string name="overlay_position">Posição da Sobreposição</string>
<string name="overlay_position_description">Escolha onde a sobreposição de desempenho será exibida na tela.</string>
<string name="overlay_position_top_left">Superior Esquerdo</string>
<string name="overlay_position_top_right">Superior Direito</string>
<string name="overlay_position_bottom_left">Inferior Esquerdo</string>
<string name="overlay_position_bottom_right">Inferior Direito</string>
<string name="overlay_position_center_top">Centro Superior</string>
<string name="overlay_position_center_bottom">Centro Inferior</string>
<string name="overlay_background">Plano de Fundo da Sobreposição</string>
<string name="overlay_background_description">Adiciona um plano de fundo atrás da sobreposição para facilitar a leitura.</string>
<!-- Cheats --> <!-- Cheats -->
<string name="cheats">Truques</string> <string name="cheats">Truques</string>
<string name="cheats_add">Adicionar Trapaça</string> <string name="cheats_add">Adicionar Trapaça</string>

View File

@ -185,7 +185,6 @@
<string name="region_mismatch">Bölge Uyuşmazlık Uyarısı</string> <string name="region_mismatch">Bölge Uyuşmazlık Uyarısı</string>
<string name="region_mismatch_emulated">Ülke ayarı emülasyon bölgesi için geçerli değil.</string> <string name="region_mismatch_emulated">Ülke ayarı emülasyon bölgesi için geçerli değil.</string>
<string name="region_mismatch_console">Ülke ayarı bağlı olan konsol için geçerli değil.</string> <string name="region_mismatch_console">Ülke ayarı bağlı olan konsol için geçerli değil.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">  <string name="inner_camera"> 
İç Kamera</string> İç Kamera</string>
@ -462,7 +461,6 @@
<string name="save_load_error">Kaydetme/yükleme Hatası</string> <string name="save_load_error">Kaydetme/yükleme Hatası</string>
<string name="fatal_error">Ölümcül Hata</string> <string name="fatal_error">Ölümcül Hata</string>
<string name="fatal_error_message">Ölümcül bir hata oluştu. Ayrıntılar için log\'u kontrol edin.\nEmülasyona devam etmek çökmelere ve hatalara neden olabilir.</string> <string name="fatal_error_message">Ölümcül bir hata oluştu. Ayrıntılar için log\'u kontrol edin.\nEmülasyona devam etmek çökmelere ve hatalara neden olabilir.</string>
<string name="invalid_region">Geçersiz bölge</string>
<string name="unsupported_encrypted">Desteklenmeyen şifreli uygulama</string> <string name="unsupported_encrypted">Desteklenmeyen şifreli uygulama</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->

View File

@ -193,6 +193,9 @@
<string name="region_mismatch">区域不匹配警告</string> <string name="region_mismatch">区域不匹配警告</string>
<string name="region_mismatch_emulated">此国家/地区设置对于所选择的模拟区域无效。</string> <string name="region_mismatch_emulated">此国家/地区设置对于所选择的模拟区域无效。</string>
<string name="region_mismatch_console">此国家/地区设置对于当前关联的掌机无效。</string> <string name="region_mismatch_console">此国家/地区设置对于当前关联的掌机无效。</string>
<string name="storage">存储</string>
<string name="compress_cia_installs">压缩已安装的 CIA 内容</string>
<string name="compress_cia_installs_description">安装到模拟 SD 卡时,压缩 CIA 文件的内容。仅影响启用此设置时安装的 CIA 内容。</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">内置摄像头</string> <string name="inner_camera">内置摄像头</string>
@ -397,18 +400,24 @@
<string name="emulation_configure_controls">控制设置</string> <string name="emulation_configure_controls">控制设置</string>
<string name="emulation_edit_layout">编辑布局</string> <string name="emulation_edit_layout">编辑布局</string>
<string name="emulation_done">完成</string> <string name="emulation_done">完成</string>
<string name="emulation_button_sliding">按键滑行</string>
<string name="emulation_button_sliding_disabled">按住起始按下的按键</string>
<string name="emulation_button_sliding_enabled">按住当前按下的按键</string>
<string name="emulation_button_sliding_alternative">按住起始和当前按下的按键</string>
<string name="emulation_toggle_controls">切换控制</string> <string name="emulation_toggle_controls">切换控制</string>
<string name="emulation_control_scale">调整大小</string> <string name="emulation_control_scale">调整大小</string>
<string name="emulation_control_scale_global">全局缩放</string> <string name="emulation_control_scale_global">全局缩放</string>
<string name="emulation_control_scale_reset_all">重置全部</string> <string name="emulation_control_scale_reset_all">重置全部</string>
<string name="emulation_control_opacity">调整透明度</string> <string name="emulation_control_opacity">调整透明度</string>
<string name="emulation_control_joystick_rel_center">相对摇杆中心</string> <string name="emulation_control_joystick_rel_center">相对摇杆中心</string>
<string name="emulation_control_dpad_slide_enable">十字方向键滑动</string> <string name="emulation_control_dpad_slide_enable">十字键滑行</string>
<string name="emulation_open_settings">打开设置项</string> <string name="emulation_open_settings">打开设置项</string>
<string name="emulation_open_cheats">开启金手指</string> <string name="emulation_open_cheats">开启金手指</string>
<string name="emulation_aspect_ratio">宽高比</string> <string name="emulation_aspect_ratio">宽高比</string>
<string name="emulation_switch_screen_layout">屏幕布局</string> <string name="emulation_switch_screen_layout">屏幕布局</string>
<string name="emulation_switch_portrait_layout">纵向屏幕布局</string> <string name="emulation_switch_portrait_layout">纵向屏幕布局</string>
<string name="emulation_switch_secondary_layout">副屏幕布局</string>
<string name="emulation_switch_secondary_layout_description">有线或无线连接的辅助屏幕使用布局Chromecast, Miracast</string>
<string name="emulation_screen_layout_largescreen">大屏幕</string> <string name="emulation_screen_layout_largescreen">大屏幕</string>
<string name="emulation_screen_layout_portrait">纵向</string> <string name="emulation_screen_layout_portrait">纵向</string>
<string name="emulation_screen_layout_single">单个屏幕</string> <string name="emulation_screen_layout_single">单个屏幕</string>
@ -416,6 +425,7 @@
<string name="emulation_screen_layout_hybrid">混合式屏幕</string> <string name="emulation_screen_layout_hybrid">混合式屏幕</string>
<string name="emulation_screen_layout_original">原始</string> <string name="emulation_screen_layout_original">原始</string>
<string name="emulation_portrait_layout_top_full">默认</string> <string name="emulation_portrait_layout_top_full">默认</string>
<string name="emulation_secondary_display_default">系统默认(镜像)</string>
<string name="emulation_screen_layout_custom">自定义布局</string> <string name="emulation_screen_layout_custom">自定义布局</string>
<string name="emulation_small_screen_position">小屏幕位置</string> <string name="emulation_small_screen_position">小屏幕位置</string>
<string name="small_screen_position_description">在“大屏幕”布局中,小屏幕相对于大屏幕应该出现的位置?</string> <string name="small_screen_position_description">在“大屏幕”布局中,小屏幕相对于大屏幕应该出现的位置?</string>
@ -513,7 +523,6 @@
<string name="save_load_error">保存/读取出现错误</string> <string name="save_load_error">保存/读取出现错误</string>
<string name="fatal_error">致命错误</string> <string name="fatal_error">致命错误</string>
<string name="fatal_error_message">发生致命错误。请查阅日志获取相关信息。\n继续模拟可能会导致错误和崩溃。</string> <string name="fatal_error_message">发生致命错误。请查阅日志获取相关信息。\n继续模拟可能会导致错误和崩溃。</string>
<string name="invalid_region">无效的地区</string>
<string name="unsupported_encrypted">不支持的加密应用</string> <string name="unsupported_encrypted">不支持的加密应用</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -539,6 +548,9 @@
<string name="create_shortcut">创建快捷方式</string> <string name="create_shortcut">创建快捷方式</string>
<string name="shortcut_name_empty">快捷方式名称不能为空</string> <string name="shortcut_name_empty">快捷方式名称不能为空</string>
<string name="shortcut_image_stretch_toggle">拉伸以适合图像</string> <string name="shortcut_image_stretch_toggle">拉伸以适合图像</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">文件:</string>
<string name="game_context_type">类型:</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">显示性能参数</string> <string name="performance_overlay_show">显示性能参数</string>

View File

@ -74,6 +74,10 @@
<string name="permission_denied">Berechtigung verweigert</string> <string name="permission_denied">Berechtigung verweigert</string>
<string name="add_games_warning">Auswahl des Anwendungs Ordner überspringen?</string> <string name="add_games_warning">Auswahl des Anwendungs Ordner überspringen?</string>
<string name="add_games_warning_description">Software wird nicht in der Anwendungs Liste angezeigt, wenn kein Ordner ausgewählt ist.</string> <string name="add_games_warning_description">Software wird nicht in der Anwendungs Liste angezeigt, wenn kein Ordner ausgewählt ist.</string>
<string name="permissions">Berechtigungen</string>
<string name="select_emulator_data_folders">Daten Ordner</string>
<string name="select_emulator_data_folders_description"><![CDATA[Daten Ordner auswählen<br/>(Nutzer Ordner ist obligatorisch)]]></string>
<string name="permissions_description">Optionale Berechtigungen erteilen um spezifische Funktionen des Emulators zu verwenden</string>
<string name="warning_help">Hilfe</string> <string name="warning_help">Hilfe</string>
<string name="warning_skip">Überspringen</string> <string name="warning_skip">Überspringen</string>
<string name="warning_cancel">Abbrechen</string> <string name="warning_cancel">Abbrechen</string>
@ -83,6 +87,7 @@
<string name="keep_current_azahar_directory">Aktuelles Azahar-Verzeichnis behalten</string> <string name="keep_current_azahar_directory">Aktuelles Azahar-Verzeichnis behalten</string>
<string name="use_prior_lime3ds_directory">Vorheriges Lime3DS-Verzeichnis nutzen</string> <string name="use_prior_lime3ds_directory">Vorheriges Lime3DS-Verzeichnis nutzen</string>
<string name="select">Auswählen</string> <string name="select">Auswählen</string>
<string name="cannot_skip">Der Nutzer Ordner muss gesetzt sein</string>
<string name="cannot_skip_directory_description">Dieser Schritt ist nötig, damit Azahar funktionieren kann. Bitte wähle ein Verzeichnis aus, damit du fortfahren kannst.</string> <string name="cannot_skip_directory_description">Dieser Schritt ist nötig, damit Azahar funktionieren kann. Bitte wähle ein Verzeichnis aus, damit du fortfahren kannst.</string>
<string name="selecting_user_directory_without_write_permissions">Die Schreibrechte auf dein <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">Nutzerdaten</a>-Verzeichnis, wo deine Speicherstände und andere Informationen gespeichert sind, fehlen. Dies kann durch ein Anwendungsupdate, oder ein Androidupdate passiert sein. Bitte wähle das Verzeichnis erneut aus, damit die Berechtigungen wiederhergestellt werden können.</string> <string name="selecting_user_directory_without_write_permissions">Die Schreibrechte auf dein <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">Nutzerdaten</a>-Verzeichnis, wo deine Speicherstände und andere Informationen gespeichert sind, fehlen. Dies kann durch ein Anwendungsupdate, oder ein Androidupdate passiert sein. Bitte wähle das Verzeichnis erneut aus, damit die Berechtigungen wiederhergestellt werden können.</string>
<string name="set_up_theme_settings">Design-Einstellung</string> <string name="set_up_theme_settings">Design-Einstellung</string>
@ -188,7 +193,6 @@
<string name="region_mismatch">Region passt nicht überein</string> <string name="region_mismatch">Region passt nicht überein</string>
<string name="region_mismatch_emulated">Die Ländereinstellung ist für die ausgewählte emulierte Region nicht gültig.</string> <string name="region_mismatch_emulated">Die Ländereinstellung ist für die ausgewählte emulierte Region nicht gültig.</string>
<string name="region_mismatch_console">Die Ländereinstellung ist für die gekoppelte Konsole ungültig.</string> <string name="region_mismatch_console">Die Ländereinstellung ist für die gekoppelte Konsole ungültig.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Innenkamera</string> <string name="inner_camera">Innenkamera</string>
<string name="outer_left_camera">Außenkamera Links</string> <string name="outer_left_camera">Außenkamera Links</string>
@ -207,6 +211,8 @@
<string name="graphics_api">Grafik API</string> <string name="graphics_api">Grafik API</string>
<string name="spirv_shader_gen">SPIR-V-Shader-Generierung aktivieren</string> <string name="spirv_shader_gen">SPIR-V-Shader-Generierung aktivieren</string>
<string name="spirv_shader_gen_description">Gibt den Fragment-Shader aus, der zur Emulation von PICA unter Verwendung von SPIR-V statt GLSL verwendet wird.</string> <string name="spirv_shader_gen_description">Gibt den Fragment-Shader aus, der zur Emulation von PICA unter Verwendung von SPIR-V statt GLSL verwendet wird.</string>
<string name="disable_spirv_optimizer">SPIR-V Optimierer deaktivieren</string>
<string name="disable_spirv_optimizer_description">Deaktiviert den SPIR-V Optimierungsschritt, was stottern reduziert und die Leistung nur geringfügig beeinflusst.</string>
<string name="async_shaders">Asynchrone GPU-Emulation aktivieren</string> <string name="async_shaders">Asynchrone GPU-Emulation aktivieren</string>
<string name="async_shaders_description">Kompiliere Shader im Hintergrund, um das Stottern des Spiels zu reduzieren. Dadurch kann es zu temporären grafischen Fehlern während des Spielens kommen.</string> <string name="async_shaders_description">Kompiliere Shader im Hintergrund, um das Stottern des Spiels zu reduzieren. Dadurch kann es zu temporären grafischen Fehlern während des Spielens kommen.</string>
<string name="linear_filtering">Lineare Filterung</string> <string name="linear_filtering">Lineare Filterung</string>
@ -215,6 +221,7 @@
<string name="texture_filter_description">Verbessert die Optik von Anwendungen durch Anwenden eines Filters auf Texturen. Die unterstützten Filter sind Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale und MMPX.</string> <string name="texture_filter_description">Verbessert die Optik von Anwendungen durch Anwenden eines Filters auf Texturen. Die unterstützten Filter sind Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale und MMPX.</string>
<string name="delay_render_thread">Game-Render-Thread verzögern</string> <string name="delay_render_thread">Game-Render-Thread verzögern</string>
<string name="delay_render_thread_description">Verzögert den Render-Thread des Spiels, wenn er Daten an die GPU sendet. Hilft bei Leistungsproblemen in den (sehr wenigen) Anwendungen mit dynamischen Frameraten.</string> <string name="delay_render_thread_description">Verzögert den Render-Thread des Spiels, wenn er Daten an die GPU sendet. Hilft bei Leistungsproblemen in den (sehr wenigen) Anwendungen mit dynamischen Frameraten.</string>
<string name="advanced">Erweitert</string>
<string name="texture_sampling_name">Textur-Sampling</string> <string name="texture_sampling_name">Textur-Sampling</string>
<string name="texture_sampling_description">Setzt den von Spielen verwendeten Sampling-Filter außer Kraft. Dies kann in bestimmten Fällen nützlich sein, wenn sich die Spiele beim Hochskalieren schlecht verhalten. Wenn du dir unsicher bist, setze diese Einstellung auf „Spielgesteuert“</string> <string name="texture_sampling_description">Setzt den von Spielen verwendeten Sampling-Filter außer Kraft. Dies kann in bestimmten Fällen nützlich sein, wenn sich die Spiele beim Hochskalieren schlecht verhalten. Wenn du dir unsicher bist, setze diese Einstellung auf „Spielgesteuert“</string>
<string name="shaders_accurate_mul">Genaue Multiplikation</string> <string name="shaders_accurate_mul">Genaue Multiplikation</string>
@ -295,6 +302,11 @@
<string name="delay_start_lle_modules_description">Verzögert den Start der App, wenn die LLE-Module aktiviert sind.</string> <string name="delay_start_lle_modules_description">Verzögert den Start der App, wenn die LLE-Module aktiviert sind.</string>
<string name="deterministic_async_operations">Deterministische asynchrone Operationen</string> <string name="deterministic_async_operations">Deterministische asynchrone Operationen</string>
<string name="deterministic_async_operations_description">Asynchrone Operationen werden für Debug-Zwecke deterministisch. Die Aktivierung dieser Funktion kann zum Einfrieren führen.</string> <string name="deterministic_async_operations_description">Asynchrone Operationen werden für Debug-Zwecke deterministisch. Die Aktivierung dieser Funktion kann zum Einfrieren führen.</string>
<string name="enable_rpc_server">RPC Server aktivieren</string>
<string name="enable_rpc_server_desc">Aktiviert den RPC Server auf Port 45987. Dadurch können Programme im emulierten RAM lesen und schreiben.</string>
<string name="shader_jit">Shader JIT aktivieren</string>
<string name="shader_jit_description">Verwendet die JIT Engine anstatt des Interpreters für Software Shader Emulation.</string>
<!-- Layout settings strings --> <!-- Layout settings strings -->
<string name="layout_screen_orientation">Bildschirmausrichtung</string> <string name="layout_screen_orientation">Bildschirmausrichtung</string>
<string name="layout_screen_orientation_auto_sensor">Automatisch</string> <string name="layout_screen_orientation_auto_sensor">Automatisch</string>
@ -302,6 +314,13 @@
<string name="layout_screen_orientation_landscape_reverse">Umgekehrtes Querformat</string> <string name="layout_screen_orientation_landscape_reverse">Umgekehrtes Querformat</string>
<string name="layout_screen_orientation_portrait">Hochformat</string> <string name="layout_screen_orientation_portrait">Hochformat</string>
<string name="layout_screen_orientation_portrait_reverse">Umgekehrtes Hochformat</string> <string name="layout_screen_orientation_portrait_reverse">Umgekehrtes Hochformat</string>
<string name="aspect_ratio_default">Standard</string>
<string name="aspect_ratio_16_9">16:9</string>
<string name="aspect_ratio_4_3">4:3</string>
<string name="aspect_ratio_21_9_fullscreen">21:9</string>
<string name="aspect_ratio_16_10_fullscreen_stretched">16:10</string>
<string name="aspect_ratio_stretch">Gestreckt</string>
<!-- Miscellaneous --> <!-- Miscellaneous -->
<string name="clear">Zurücksetzen</string> <string name="clear">Zurücksetzen</string>
<string name="slider_default">Standard</string> <string name="slider_default">Standard</string>
@ -337,6 +356,9 @@
<string name="cancelling">Wird abgebrochen...</string> <string name="cancelling">Wird abgebrochen...</string>
<string name="important">Wichtig</string> <string name="important">Wichtig</string>
<string name="dont_show_again">Nicht noch einmal anzeigen</string> <string name="dont_show_again">Nicht noch einmal anzeigen</string>
<string name="visibility">Sichtbarkeit</string>
<string name="information">Information</string>
<!-- Add Directory Screen--> <!-- Add Directory Screen-->
<string name="select_game_folder">Spieleordner auswählen</string> <string name="select_game_folder">Spieleordner auswählen</string>
@ -383,6 +405,7 @@
<string name="emulation_control_dpad_slide_enable">Steuerkreuz-Gleiten</string> <string name="emulation_control_dpad_slide_enable">Steuerkreuz-Gleiten</string>
<string name="emulation_open_settings">Einstellungen öffnen</string> <string name="emulation_open_settings">Einstellungen öffnen</string>
<string name="emulation_open_cheats">Cheats öffnen</string> <string name="emulation_open_cheats">Cheats öffnen</string>
<string name="emulation_aspect_ratio">Seitenverhältnis</string>
<string name="emulation_switch_screen_layout">Querformat-Bildschirmanordnung</string> <string name="emulation_switch_screen_layout">Querformat-Bildschirmanordnung</string>
<string name="emulation_switch_portrait_layout">Hochformat-Bildschirmanordnung</string> <string name="emulation_switch_portrait_layout">Hochformat-Bildschirmanordnung</string>
<string name="emulation_screen_layout_largescreen">Großer Bildschirm</string> <string name="emulation_screen_layout_largescreen">Großer Bildschirm</string>
@ -418,7 +441,9 @@
<string name="emulation_custom_layout_height">Höhe</string> <string name="emulation_custom_layout_height">Höhe</string>
<string name="emulation_cycle_landscape_layouts">Anordnung wechseln</string> <string name="emulation_cycle_landscape_layouts">Anordnung wechseln</string>
<string name="emulation_swap_screens">Bildschirme tauschen</string> <string name="emulation_swap_screens">Bildschirme tauschen</string>
<string name="emulation_rotate_upright">Bildschirm aufrecht rotieren</string>
<string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string> <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string>
<string name="emulation_show_controller_overlay">Controller Overlay anzeigen</string>
<string name="emulation_close_game">Spiel schließen</string> <string name="emulation_close_game">Spiel schließen</string>
<string name="emulation_toggle_pause">Pause umschalten</string> <string name="emulation_toggle_pause">Pause umschalten</string>
<string name="miscellaneous">Weiteres</string> <string name="miscellaneous">Weiteres</string>
@ -485,7 +510,6 @@
<string name="save_load_error">Fehler beim Speichern/Laden</string> <string name="save_load_error">Fehler beim Speichern/Laden</string>
<string name="fatal_error">Schwerwiegender Fehler</string> <string name="fatal_error">Schwerwiegender Fehler</string>
<string name="fatal_error_message">Es ist ein schwerwiegender Fehler aufgetreten. Weitere Informationen findest du in der Protokolldatei.\nDas Fortfahren könnte zu ungewollten Abstürzen oder Problemen führen.</string> <string name="fatal_error_message">Es ist ein schwerwiegender Fehler aufgetreten. Weitere Informationen findest du in der Protokolldatei.\nDas Fortfahren könnte zu ungewollten Abstürzen oder Problemen führen.</string>
<string name="invalid_region">Ungültige Region</string>
<string name="unsupported_encrypted">Nicht unterstützte verschlüsselte Anwendung</string> <string name="unsupported_encrypted">Nicht unterstützte verschlüsselte Anwendung</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -506,6 +530,39 @@
<string name="game_context_uninstall_dlc">DLC deinstallieren</string> <string name="game_context_uninstall_dlc">DLC deinstallieren</string>
<string name="game_context_uninstall_updates">Updates deinstallieren</string> <string name="game_context_uninstall_updates">Updates deinstallieren</string>
<string name="shortcut">Verknüpfung</string> <string name="shortcut">Verknüpfung</string>
<string name="shortcut_name">Verknüpfungsname</string>
<string name="edit_icon">Symbol bearbeiten</string>
<string name="create_shortcut">Verknüpfung erstellen</string>
<string name="shortcut_name_empty">Verknüpfungsname darf nicht leer sein</string>
<string name="shortcut_image_stretch_toggle">Bildgröße anpassen</string>
<!-- Performance Overlay settings -->
<string name="performance_overlay_show">Leistungs-Overlay anzeigen</string>
<string name="performance_overlay_options">Leistungs-Overlay</string>
<string name="performance_overlay_enable">Leistungsoverlay aktivieren</string>
<string name="performance_overlay_options_description">Konfigurieren Sie, ob das Leistungs-Overlay angezeigt wird und welche Informationen angezeigt werden.</string>
<string name="overlay_show_fps">FPS anzeigen</string>
<string name="overlay_show_fps_description">Aktuelle Bilder pro Sekunde anzeigen.</string>
<string name="overlay_show_frametime">Frametime anzeigen</string>
<string name="overlay_show_frametime_description">Aktuelle Frametime anzeigen.</string>
<string name="overlay_show_speed">Geschwindigkeit anzeigen</string>
<string name="overlay_show_speed_description">Zeigt die aktuelle Emulationsgeschwindigkeit in Prozent an.</string>
<string name="overlay_show_app_ram_usage">App-Speichernutzung anzeigen</string>
<string name="overlay_show_app_ram_usage_description">Zeigt die vom Emulator verwendete RAM-Menge an.</string>
<string name="overlay_show_available_ram">Verfügbaren Speicher anzeigen</string>
<string name="overlay_show_available_ram_description">Zeigt die verfügbare RAM-Menge an.</string>
<string name="overlay_show_battery_temp">Batterietemperatur anzeigen</string>
<string name="overlay_show_battery_temp_description">Zeigt die aktuelle Batterietemperatur in Celsius und Fahrenheit an.</string>
<string name="overlay_position">Overlay-Position</string>
<string name="overlay_position_description">Wählen Sie, wo das Leistungs-Overlay auf dem Bildschirm angezeigt wird</string>
<string name="overlay_position_top_left">Links Oben</string>
<string name="overlay_position_top_right">Rechts Oben</string>
<string name="overlay_position_bottom_left">Links Unten</string>
<string name="overlay_position_bottom_right">Rechts Unten</string>
<string name="overlay_position_center_top">Oben Mittig</string>
<string name="overlay_position_center_bottom">Unten Mittig</string>
<string name="overlay_background">Overlay Hintergrund</string>
<string name="overlay_background_description">Fügt einen Hintergrund hinter dem Overlay hinzu für bessere Lesbarkeit.</string>
<!-- Cheats --> <!-- Cheats -->
<string name="cheats">Cheats</string> <string name="cheats">Cheats</string>
<string name="cheats_add">Cheat hinzufügen</string> <string name="cheats_add">Cheat hinzufügen</string>

View File

@ -193,6 +193,9 @@
<string name="region_mismatch">Avertissement d\'incompatibilité de région</string> <string name="region_mismatch">Avertissement d\'incompatibilité de région</string>
<string name="region_mismatch_emulated">Le paramètre de pays n\'est pas valide pour la région émulée sélectionnée.</string> <string name="region_mismatch_emulated">Le paramètre de pays n\'est pas valide pour la région émulée sélectionnée.</string>
<string name="region_mismatch_console">Le paramètre de pays n\'est pas valide pour la console actuellement connectée.</string> <string name="region_mismatch_console">Le paramètre de pays n\'est pas valide pour la console actuellement connectée.</string>
<string name="storage">Stockage</string>
<string name="compress_cia_installs">Compresser le contenu CIA installé</string>
<string name="compress_cia_installs_description">Compresse le contenu des fichiers CIA lorsqu\'ils sont installés sur la carte SD émulée. N\'affecte que le contenu CIA installé lorsque le paramètre est activé.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Caméra intérieure</string> <string name="inner_camera">Caméra intérieure</string>
@ -397,6 +400,10 @@
<string name="emulation_configure_controls">Configurer les commandes</string> <string name="emulation_configure_controls">Configurer les commandes</string>
<string name="emulation_edit_layout">Modifier la disposition</string> <string name="emulation_edit_layout">Modifier la disposition</string>
<string name="emulation_done">Terminé</string> <string name="emulation_done">Terminé</string>
<string name="emulation_button_sliding">Bouton coulissant</string>
<string name="emulation_button_sliding_disabled">Maintenez le bouton initialement enfoncé</string>
<string name="emulation_button_sliding_enabled">Maintenez le bouton enfoncé</string>
<string name="emulation_button_sliding_alternative">Maintenez enfoncé le bouton d\'origine et celui qui est actuellement enfoncé</string>
<string name="emulation_toggle_controls">Alterner les commandes</string> <string name="emulation_toggle_controls">Alterner les commandes</string>
<string name="emulation_control_scale">Ajuster la taille</string> <string name="emulation_control_scale">Ajuster la taille</string>
<string name="emulation_control_scale_global">Taille globale</string> <string name="emulation_control_scale_global">Taille globale</string>
@ -511,7 +518,6 @@
<string name="save_load_error">Erreur de sauvegarde/chargement</string> <string name="save_load_error">Erreur de sauvegarde/chargement</string>
<string name="fatal_error">Erreur fatale</string> <string name="fatal_error">Erreur fatale</string>
<string name="fatal_error_message">Une erreur fatale s\'est produite. Veuillez consulter les logs pour plus de détails.\nPoursuivre l\'émulation peut entraîner des plantages et des bugs.</string> <string name="fatal_error_message">Une erreur fatale s\'est produite. Veuillez consulter les logs pour plus de détails.\nPoursuivre l\'émulation peut entraîner des plantages et des bugs.</string>
<string name="invalid_region">Région invalide</string>
<string name="unsupported_encrypted">Application encryptée non supportée</string> <string name="unsupported_encrypted">Application encryptée non supportée</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -537,6 +543,9 @@
<string name="create_shortcut">Créer un raccourci</string> <string name="create_shortcut">Créer un raccourci</string>
<string name="shortcut_name_empty">Le nom du raccourci ne peut pas être vide</string> <string name="shortcut_name_empty">Le nom du raccourci ne peut pas être vide</string>
<string name="shortcut_image_stretch_toggle">Étirer pour ajuster l\'image</string> <string name="shortcut_image_stretch_toggle">Étirer pour ajuster l\'image</string>
<string name="game_context_id">ID :</string>
<string name="game_context_file">Fichier :</string>
<string name="game_context_type">Type :</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Afficher l\'overlay des performances</string> <string name="performance_overlay_show">Afficher l\'overlay des performances</string>

View File

@ -18,7 +18,7 @@ Cos\'è questo:
<string name="install_game_content">Installa file CIA</string> <string name="install_game_content">Installa file CIA</string>
<string name="install_game_content_description">Installa applicazioni, aggiornamenti o DLC</string> <string name="install_game_content_description">Installa applicazioni, aggiornamenti o DLC</string>
<string name="share_log">Condividi Log</string> <string name="share_log">Condividi Log</string>
<string name="share_log_description">Condividi il file di log di Azahar per il debug</string> <string name="share_log_description">Condividi il file di log di Azahar per il debug di problemi</string>
<string name="gpu_driver_manager">Gestione driver GPU</string> <string name="gpu_driver_manager">Gestione driver GPU</string>
<string name="install_gpu_driver">Installa driver GPU</string> <string name="install_gpu_driver">Installa driver GPU</string>
<string name="install_gpu_driver_description">Installa driver alternativi per possibili miglioramenti nelle performance o nell\'accuratezza</string> <string name="install_gpu_driver_description">Installa driver alternativi per possibili miglioramenti nelle performance o nell\'accuratezza</string>
@ -79,13 +79,22 @@ Divertiti usando l\'emulatore!</string>
<string name="permission_denied">Permesso negato</string> <string name="permission_denied">Permesso negato</string>
<string name="add_games_warning">Saltare la selezione della cartella applicazioni?</string> <string name="add_games_warning">Saltare la selezione della cartella applicazioni?</string>
<string name="add_games_warning_description">Non verrà mostrato alcun software nella lista applicazioni se non viene selezionata alcuna cartella.</string> <string name="add_games_warning_description">Non verrà mostrato alcun software nella lista applicazioni se non viene selezionata alcuna cartella.</string>
<string name="permissions">Permessi</string>
<string name="select_emulator_data_folders">Cartella dati</string>
<string name="select_emulator_data_folders_description"><![CDATA[Seleziona la cartella dati<br/>(La cartella utente è richiesta)]]></string>
<string name="permissions_description">Concedere autorizzazioni opzionali per utilizzare specifiche funzionalità dell\'emulatore</string>
<string name="warning_help">Aiuto</string> <string name="warning_help">Aiuto</string>
<string name="warning_skip">Salta</string> <string name="warning_skip">Salta</string>
<string name="warning_cancel">Indietro</string> <string name="warning_cancel">Indietro</string>
<string name="select_citra_user_folder">Seleziona cartella utente</string> <string name="select_citra_user_folder">Seleziona cartella utente</string>
<string name="select_citra_user_folder_description"><![CDATA[Seleziona la tua cartella <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">utente</a> usando il bottone sottostante.]]></string> <string name="select_citra_user_folder_description"><![CDATA[Seleziona la tua cartella <a href=\"https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage\">utente</a> usando il bottone sottostante.]]></string>
<string name="select_which_user_directory_to_use">Sembra che tu abbia impostato la cartella utente sia per Lime3DS che per Azahar. Questo probabilmente è dovuto al fatto che hai eseguito l\'aggiornamento ad Azahar e, al momento della richiesta, hai scelto una directory utente diversa da quella utilizzata per Lime3DS.\n\nQuesto potrebbe averti fatto pensare di aver perso salvataggi o altre impostazioni - ci scusiamo se è successo.\n\nDesideri tornare a utilizzare la tua cartella utente originale di Lime3DS, ripristinando impostazioni e salvataggi da Lime3DS, oppure preferisci mantenere la cartella utente attuale di Azahar?\n\nNessuna delle cartelle verrà eliminata, indipendentemente dalla tua scelta, e potrai passare liberamente da una all\'altra utilizzando l\'opzione \"Seleziona Cartella Utente\".</string>
<string name="keep_current_azahar_directory">Mantieni la cartella di Azahar attuale</string>
<string name="use_prior_lime3ds_directory">Usa la cartella precedente di Lime3DS</string>
<string name="select">Seleziona</string> <string name="select">Seleziona</string>
<string name="cannot_skip">Non puoi saltare la configurazione della cartella utente</string>
<string name="cannot_skip_directory_description">Questo passaggio è richiesto per permettere che Azahar funzioni. Quando la cartella verrà selezionata potrai continuare.</string> <string name="cannot_skip_directory_description">Questo passaggio è richiesto per permettere che Azahar funzioni. Quando la cartella verrà selezionata potrai continuare.</string>
<string name="selecting_user_directory_without_write_permissions">Hai perso i permessi di scrittura sulla tua <a href="https://web.archive.org/web/20240304193549/https://github.com/citra-emu/citra/wiki/Citra-Android-user-data-and-storage">cartella dei dati utente</a>, dove sono memorizzati i salvataggi e altre informazioni. Questo può accadere dopo alcuni aggiornamenti app o Android. Ri-seleziona la cartella per recuperare le autorizzazioni in modo da poter continuare.</string>
<string name="set_up_theme_settings">Impostazioni tema</string> <string name="set_up_theme_settings">Impostazioni tema</string>
<string name="setup_theme_settings_description">Configura le impostazioni del tema di Azahar.</string> <string name="setup_theme_settings_description">Configura le impostazioni del tema di Azahar.</string>
<string name="setup_set_theme">Imposta tema</string> <string name="setup_set_theme">Imposta tema</string>
@ -122,13 +131,21 @@ Divertiti usando l\'emulatore!</string>
<string name="input_binding_description_horizontal_axis">Muovi il joystick a sinistra o a destra.</string> <string name="input_binding_description_horizontal_axis">Muovi il joystick a sinistra o a destra.</string>
<string name="button_home">Home</string> <string name="button_home">Home</string>
<string name="button_swap">Inverti Schermi</string> <string name="button_swap">Inverti Schermi</string>
<string name="button_turbo">Turbo</string>
<string name="input_message_analog_only">Questo controllo dev\'essere assegnato ad uno stick analogico di un gamepad o ad un asse del Pad Direzionale!</string> <string name="input_message_analog_only">Questo controllo dev\'essere assegnato ad uno stick analogico di un gamepad o ad un asse del Pad Direzionale!</string>
<string name="input_message_button_only">Questo controllo dev\'essere assegnato a un pulsante del gamepad!</string> <string name="input_message_button_only">Questo controllo dev\'essere assegnato a un pulsante del gamepad!</string>
<string name="turbo_limit_hotkey">Turbo speed</string>
<string name="turbo_enabled_toast">\"Turbo speed\" abilitato</string>
<string name="turbo_disabled_toast">\"Turbo speed\" disabilitato</string>
<!-- System files strings --> <!-- System files strings -->
<string name="setup_system_files">File di Sistema</string> <string name="setup_system_files">File di Sistema</string>
<string name="setup_system_files_description">Esegui operazioni sui file di sistema come installare file di sistema o avviare il Menu Home</string> <string name="setup_system_files_description">Esegui operazioni sui file di sistema come installare file di sistema o avviare il Menu Home</string>
<string name="setup_tool_connect">Connettiti a Artic Setup Tool </string> <string name="setup_tool_connect">Connettiti a Artic Setup Tool </string>
<string name="setup_system_files_detect">Ottenendo lo stato attuale dei file di sistema, per favore attendi...</string> <string name="setup_system_files_preamble"><![CDATA[Azahar necessita di dati unici della console e file firmware provenienti da una console reale per poter utilizzare alcune delle sue funzionalità. Questi file e dati possono essere configurati con <a href=https://github.com/azahar-emu/ArticSetupTool>Azahar Artic Setup Tool</a>.<br>Note: <ul><li><b>Questa operazione installerà dati unici della console su Azahar, non condividere le tue cartelle utente o NAND dopo aver completato il processo di configurazione!</b></li><li>Durante il processo di configurazione, Azahar si collegherà alla console che sta eseguendo lo strumento di configurazione. Puoi scollegare la console in seguito dalla scheda \"File di sistema\" nel menu delle opzioni dell\'emulatore.</li><li>Non andare online contemporaneamente con Azahar e la tua console 3DS dopo aver configurato i file di sistema, poiché ciò potrebbe causare problemi.</li><li>La configurazione del vecchio 3DS è necessaria affinché la configurazione del nuovo 3DS funzioni (si consiglia di configurare entrambi).</li><li>Entrambe le modalità di configurazione funzioneranno indipendentemente dal modello della console che esegue lo strumento di configurazione.</li></ul>]]></string>
<string name="setup_system_files_detect">Recupero dello stato attuale dei file di sistema, per favore attendi...</string>
<string name="delete_system_files">Scollega i dati univoci della console</string>
<string name="delete_system_files_description"><![CDATA[Questa azione scollegherà la tua console reale da Azahar, con le seguenti conseguenze:<br><ul><li>il tuo OTP, SecureInfo e LocalFriendCodeSeed verranno rimossi da Azahar.</li><li>La tua lista amici verrà reimpostata e verrai disconnesso dal tuo account NNID/PNID.</li><li>I file di sistema e i titoli eshop ottenuti tramite Azahar diventeranno inaccessibili finché la stessa console non verrà nuovamente collegata tramite lo strumento di configurazione (i dati di salvataggio non andranno persi).</li></ul><br>Continuare?]]></string>
<string name="setup_system_files_o3ds">Setup Old 3DS</string> <string name="setup_system_files_o3ds">Setup Old 3DS</string>
<string name="setup_system_files_n3ds">Setup New 3DS</string> <string name="setup_system_files_n3ds">Setup New 3DS</string>
<string name="setup_system_files_possible">Il setup è possibile.</string> <string name="setup_system_files_possible">Il setup è possibile.</string>
@ -157,6 +174,7 @@ Divertiti usando l\'emulatore!</string>
<string name="init_clock_description">Scegli se l\'orologio di sistema del 3DS emulato dovrà rispecchiare l\'orario del tuo dispositivo o se dovrà indicare una data e ora in particolare.</string> <string name="init_clock_description">Scegli se l\'orologio di sistema del 3DS emulato dovrà rispecchiare l\'orario del tuo dispositivo o se dovrà indicare una data e ora in particolare.</string>
<string name="device_clock">Orologio del dispositivo</string> <string name="device_clock">Orologio del dispositivo</string>
<string name="simulated_clock">Orologio simulato</string> <string name="simulated_clock">Orologio simulato</string>
<string name="simulated_clock_description">Se l\'orologio è impostato su \"Orologio simulato\", questo cambia la data e l\'ora di inizio.</string>
<string name="profile_settings">Impostazioni profilo</string> <string name="profile_settings">Impostazioni profilo</string>
<string name="emulated_region">Regione</string> <string name="emulated_region">Regione</string>
<string name="emulated_language">Lingua</string> <string name="emulated_language">Lingua</string>
@ -177,6 +195,13 @@ Divertiti usando l\'emulatore!</string>
<string name="plugin_loader_description">Carica i plugin 3GX dalla scheda SD emulata, se disponibili.</string> <string name="plugin_loader_description">Carica i plugin 3GX dalla scheda SD emulata, se disponibili.</string>
<string name="allow_plugin_loader">Consenti alle applicazioni di cambiare lo stato del Plugin Loader</string> <string name="allow_plugin_loader">Consenti alle applicazioni di cambiare lo stato del Plugin Loader</string>
<string name="allow_plugin_loader_description">Permetti alle app homebrew di abilitare il Plugin Loader anche quando è disabilitato.</string> <string name="allow_plugin_loader_description">Permetti alle app homebrew di abilitare il Plugin Loader anche quando è disabilitato.</string>
<string name="region_mismatch">Mancata corrispondenza della regione</string>
<string name="region_mismatch_emulated">L\'impostazione del paese non è valida per la regione emulata selezionata.</string>
<string name="region_mismatch_console">L\'impostazione del paese non è valida per la console attualmente collegata.</string>
<string name="storage">Archiviazione</string>
<string name="compress_cia_installs">Comprimi i contenuti CIA installati</string>
<string name="compress_cia_installs_description">Comprime il contenuto dei file CIA quando installati sulla scheda SD emulata. Riguarda solo i contenuti CIA installati mentre l\'impostazione è abilitata.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Fotocamera Interna</string> <string name="inner_camera">Fotocamera Interna</string>
<string name="outer_left_camera">Fotocamera Esterna di Sinistra</string> <string name="outer_left_camera">Fotocamera Esterna di Sinistra</string>
@ -195,23 +220,34 @@ Divertiti usando l\'emulatore!</string>
<string name="graphics_api">API grafiche</string> <string name="graphics_api">API grafiche</string>
<string name="spirv_shader_gen">Abilita la generazione di shader SPIR-V</string> <string name="spirv_shader_gen">Abilita la generazione di shader SPIR-V</string>
<string name="spirv_shader_gen_description">Crea le fragments shader usate per emulare PICA tramite SPIR-V, invece di GLSL</string> <string name="spirv_shader_gen_description">Crea le fragments shader usate per emulare PICA tramite SPIR-V, invece di GLSL</string>
<string name="disable_spirv_optimizer">Disabilita SPIR-V Optimizer</string>
<string name="disable_spirv_optimizer_description">Disabilita il passaggio di ottimizzazione SPIR-V, riducendo considerevolmente gli stutter e influendo appena sulle prestazioni.</string>
<string name="async_shaders">Abilita la compilazione asincrona delle shader</string> <string name="async_shaders">Abilita la compilazione asincrona delle shader</string>
<string name="async_shaders_description">Compila le shader in background per ridurre lo stuttering durante il gameplay. Quando abilitato, potrebbero verificarsi dei glitch grafici.</string> <string name="async_shaders_description">Compila le shader in background per ridurre lo stuttering durante il gioco. Quando abilitato, potrebbero verificarsi dei glitch grafici.</string>
<string name="linear_filtering">Filtering Lineare</string> <string name="linear_filtering">Filtering Lineare</string>
<string name="linear_filtering_description">Abilita il filtro lineare, che fa sembrare più smussata la grafica dei giochi.</string> <string name="linear_filtering_description">Abilita il filtraggio lineare, che fa sembrare più smussata la grafica dei giochi.</string>
<string name="texture_filter_name">Filtro Texture</string> <string name="texture_filter_name">Filtro Texture</string>
<string name="texture_filter_description">Migliora la grafica delle applicazioni applicando un filtro alle texture. I filtri supportati sono Anime4k Ultrafast, Bicubic, ScaleForce, xBRZ freescale e MMPX.</string> <string name="texture_filter_description">Migliora la grafica delle applicazioni applicando un filtro alle texture. I filtri supportati sono Anime4k Ultrafast, Bicubic, ScaleForce, xBRZ freescale e MMPX.</string>
<string name="delay_render_thread">Ritarda il thread di rendering del gioco</string> <string name="delay_render_thread">Ritarda il thread di rendering del gioco</string>
<string name="delay_render_thread_description">Ritarda il thread di rendering del gioco quando invia dati alla GPU. Aiuta con i problemi di prestazioni nelle (poche) applicazioni con frame rate dinamici.</string> <string name="delay_render_thread_description">Ritarda il thread di rendering del gioco quando invia dati alla GPU. Aiuta con i problemi di prestazioni nelle (poche) applicazioni con frame rate dinamici.</string>
<string name="advanced">Avanzato</string>
<string name="texture_sampling_name">Campionamento texture</string>
<string name="texture_sampling_description">Sovrascrive il filtro di campionamento utilizzato dai giochi. Questo può essere utile in alcuni casi con giochi che gestiscono male l\'upscaling. Se hai dubbi, imposta questa opzione su \"Gestito dal gioco\".</string>
<string name="shaders_accurate_mul">Moltiplicazione Accurata</string> <string name="shaders_accurate_mul">Moltiplicazione Accurata</string>
<string name="shaders_accurate_mul_description">Utilizza una moltiplicazione più accurata degli shader hardware, che potrebbe correggere alcuni bug grafici. Se abilitato, le prestazioni saranno ridotte.</string> <string name="shaders_accurate_mul_description">Utilizza una moltiplicazione più accurata degli shader hardware, che potrebbe correggere alcuni bug grafici. Se abilitato, le prestazioni saranno ridotte.</string>
<string name="asynchronous_gpu">Abilita emulazione GPU asincrona</string> <string name="asynchronous_gpu">Abilita l\'emulazione GPU asincrona</string>
<string name="asynchronous_gpu_description">Utilizza un thread separato per emulare la GPU in differita. Se abilitato, le prestazioni miglioreranno.</string> <string name="asynchronous_gpu_description">Usa un thread separato per l\'emulazione asincrona della GPU. Quando è abilitato le prestazioni saranno migliori.</string>
<string name="frame_limit_enable">Limita Velocità</string> <string name="frame_limit_enable">Limita Velocità</string>
<string name="frame_limit_enable_description">Quando abilitata, la velocità di emulazione sarà limitata a una percentuale specificata della velocità normale. Se disabilitato, la velocità di emulazione non sarà limitata e tasto di scelta rapida per \"Turbo speed\" non funzionerà.</string>
<string name="frame_limit_slider">Limita Velocità tramite Percentuale</string> <string name="frame_limit_slider">Limita Velocità tramite Percentuale</string>
<string name="frame_limit_slider_description">Specifica a quale percentuale limitare la velocità d\'emulazione. Utilizzando l\'impostazione predefinita di 100% l\'emulazione sarà limitata alla velocità normale. Valori superiori o inferiori aumenteranno o diminuiranno il limite di velocità.</string> <string name="frame_limit_slider_description">Specifica a quale percentuale limitare la velocità d\'emulazione. Utilizzando l\'impostazione predefinita di 100% l\'emulazione sarà limitata alla velocità normale. Valori superiori o inferiori aumenteranno o diminuiranno il limite di velocità.</string>
<string name="turbo_limit">Limite \"Turbo speed\"</string>
<string name="turbo_limit_description">Limite di velocità dell\'emulazione usato quando il tasto di scelta rapida del turbo è attivo.</string>
<string name="expand_to_cutout_area">Espandi all\'area di ritaglio</string>
<string name="expand_to_cutout_area_description">Espande l\'area di visualizzazione per includere l\'area di ritaglio (o notch).</string>
<string name="internal_resolution">Risoluzione Interna</string> <string name="internal_resolution">Risoluzione Interna</string>
<string name="internal_resolution_description">Specifica la risoluzione a cui renderizzare. Una risoluzioe alta migliorerà la qualità visiva ma avrà un grande effetto sulle performance e potrebbe causare glitch in alcune applicazioni.</string> <string name="internal_resolution_description">Specifica la risoluzione a cui renderizzare. Una risoluzione alta migliorerà la qualità visiva ma avrà un grande effetto sulle prestazioni e potrebbe causare glitch in alcune applicazioni.</string>
<string name="internal_resolution_setting_auto">Auto (dimensione dello schermo)</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>
@ -222,20 +258,21 @@ Divertiti usando l\'emulatore!</string>
<string name="internal_resolution_setting_8x">8x Nativa (3200x1920)</string> <string name="internal_resolution_setting_8x">8x Nativa (3200x1920)</string>
<string name="internal_resolution_setting_9x">9x Nativa (3600x2160)</string> <string name="internal_resolution_setting_9x">9x Nativa (3600x2160)</string>
<string name="internal_resolution_setting_10x">10x Nativa (4000x2400)</string> <string name="internal_resolution_setting_10x">10x Nativa (4000x2400)</string>
<string name="performance_warning">Disabilitare questa impostazione riducerà significativamente le performance dell\'emulazione! Per un\'esperienza migliore, è consigliato lasciare questa impostazione abilitata.</string> <string name="performance_warning">Disabilitare questa impostazione riducerà significativamente le prestazioni dell\'emulazione! Per un\'esperienza migliore, è consigliato lasciare questa impostazione abilitata.</string>
<string name="debug_warning">Attenzione: Modificare queste impostazioni rallenterà l\'emulazione</string> <string name="debug_warning">Attenzione: Modificare queste impostazioni rallenterà l\'emulazione</string>
<string name="stereoscopy">Stereoscopia</string> <string name="stereoscopy">Stereoscopia</string>
<string name="render3d">Modalità Stereoscopia 3D</string> <string name="render3d">Modalità Stereoscopia 3D</string>
<string name="factor3d">Profondità</string> <string name="factor3d">Profondità</string>
<string name="factor3d_description">Specifica il valore del regolatore di profindità 3D. Questo valore deve essere impostato su un valore superiore allo 0% quando è abilitato il \"3D stereoscopico\".\nNote: Valori di profondità superiori al 100% non sono possibili su hardware reale e possono causare problemi grafici</string>
<string name="disable_right_eye_render">Disabilita il rendering dell\'occhio destro</string> <string name="disable_right_eye_render">Disabilita il rendering dell\'occhio destro</string>
<string name="disable_right_eye_render_description">Migliora notevolmente le prestazioni in alcune applicazioni, ma può causare flickering in altre.</string> <string name="disable_right_eye_render_description">Migliora notevolmente le prestazioni in alcune applicazioni, ma può causare flickering in altre.</string>
<string name="cardboard_vr">Cardboard VR</string> <string name="cardboard_vr">Cardboard VR</string>
<string name="cardboard_screen_size">Grandezza Cardboard</string> <string name="cardboard_screen_size">Grandezza Cardboard</string>
<string name="cardboard_screen_size_description">Scala lo schermo ad una percentuale fissata della sua grandezza originale</string> <string name="cardboard_screen_size_description">Scala lo schermo ad una percentuale fissata della sua grandezza originale</string>
<string name="cardboard_x_shift">Spostamento in Orizzontale</string> <string name="cardboard_x_shift">Spostamento in Orizzontale</string>
<string name="cardboard_x_shift_description">Specifica la percentuale dello schermo che contiene uno spazio vuoto per shiftare lo schermo orizzontalmente. Valori positivi muoveranno i due occhi al centro dello schermo, mentre i negativi faranno il contrario</string> <string name="cardboard_x_shift_description">Specifica la percentuale di spazio vuoto per spostare gli schermi orizzontalmente. Valori positivi muoveranno i due schermi al centro dello schermo, mentre i negativi faranno il contrario.</string>
<string name="cardboard_y_shift">Spostamento Verticale</string> <string name="cardboard_y_shift">Spostamento Verticale</string>
<string name="cardboard_y_shift_description">Specifica la percentuale dello schermo che contiene uno spazio vuoto per spostare lo schermo in verticale. Valori positivi muoveranno alla parte bassa dello schermo, mentre i negativi faranno il contrario.</string> <string name="cardboard_y_shift_description">Specifica la percentuale di spazio vuoto per spostare gli schermi verticalmente. Valori positivi muoveranno alla parte bassa dello schermo, mentre i negativi faranno il contrario.</string>
<string name="use_shader_jit">Shader JIT</string> <string name="use_shader_jit">Shader JIT</string>
<string name="use_disk_shader_cache">Shader Cache su Disco</string> <string name="use_disk_shader_cache">Shader Cache su Disco</string>
<string name="use_disk_shader_cache_description">Riduce lo stuttering salvando e caricando le shader generate sul disco principale. Non può essere usato senza aver prima attivato \"Abilita Shader Hardware\"</string> <string name="use_disk_shader_cache_description">Riduce lo stuttering salvando e caricando le shader generate sul disco principale. Non può essere usato senza aver prima attivato \"Abilita Shader Hardware\"</string>
@ -245,9 +282,9 @@ Divertiti usando l\'emulatore!</string>
<string name="custom_textures">Textures Personalizzate</string> <string name="custom_textures">Textures Personalizzate</string>
<string name="custom_textures_description">Le texture vengono caricate da load/textures/[ID Gioco]/.</string> <string name="custom_textures_description">Le texture vengono caricate da load/textures/[ID Gioco]/.</string>
<string name="preload_textures">Precaricamento delle Textures Personalizzate</string> <string name="preload_textures">Precaricamento delle Textures Personalizzate</string>
<string name="preload_textures_description">Carica tutte le texture personalizzate nella memoria RAM del dispositivo. Potrebbe comportare un uso eccessivamente alto della memoria.</string> <string name="preload_textures_description">Carica tutte le texture personalizzate nella RAM del dispositivo. Questa funzionalità può usare molta memoria.</string>
<string name="async_custom_loading">Caricamento delle Textures Asincrono</string> <string name="async_custom_loading">Caricamento asincrono delle Textures</string>
<string name="async_custom_loading_description">Carica le texture personalizzate in modo asincrono e in background. Riduce lo stutter.</string> <string name="async_custom_loading_description">Carica le texture personalizzate in modo asincrono con i thread in background per ridurre lo stutter del caricamento.</string>
<!-- Audio settings strings --> <!-- Audio settings strings -->
<string name="audio_volume">Volume</string> <string name="audio_volume">Volume</string>
@ -267,13 +304,18 @@ Divertiti usando l\'emulatore!</string>
<string name="vsync">Abilita V-Sync</string> <string name="vsync">Abilita V-Sync</string>
<string name="vsync_description">Sincronizza il frame rate dei giochi con il refresh rate del tuo dispositivo.</string> <string name="vsync_description">Sincronizza il frame rate dei giochi con il refresh rate del tuo dispositivo.</string>
<string name="renderer_debug">Renderer di Debug</string> <string name="renderer_debug">Renderer di Debug</string>
<string name="renderer_debug_description">Logga informazioni di debug riguardante la grafica. Se abilitato, le performance del software emulato diminuiranno drasticamente</string> <string name="renderer_debug_description">Registra ulteriori informazioni di debug relative alla grafica. Quando abilitata, le prestazioni del gioco saranno significativamente ridotte.</string>
<string name="instant_debug_log">Svuota l\'output del log ad ogni messaggio</string> <string name="instant_debug_log">Svuota l\'output del log ad ogni messaggio</string>
<string name="instant_debug_log_description">Invia immediatamente il log di debug al file. Usalo se Azahar si blocca e l\'output del log viene tagliato.</string> <string name="instant_debug_log_description">Invia immediatamente il log di debug al file. Usalo se Azahar si blocca e l\'output del log viene tagliato.</string>
<string name="delay_start_lle_modules">Ritarda l\'avvio con moduli LLE</string> <string name="delay_start_lle_modules">Ritarda l\'avvio con moduli LLE</string>
<string name="delay_start_lle_modules_description">Ritarda l\'avvio dell\'app quando i moduli LLE sono abilitati.</string> <string name="delay_start_lle_modules_description">Ritarda l\'avvio dell\'app quando i moduli LLE sono abilitati.</string>
<string name="deterministic_async_operations">Operazioni Deterministiche desincronizzate</string> <string name="deterministic_async_operations">Operazioni Deterministiche desincronizzate</string>
<string name="deterministic_async_operations_description">Rende le operazioni asincrone deterministiche per il debug. Abilitare questa opzione potrebbe causare blocchi.</string> <string name="deterministic_async_operations_description">Rende le operazioni asincrone deterministiche per il debug. Abilitare questa opzione potrebbe causare blocchi.</string>
<string name="enable_rpc_server">Abilita server RPC</string>
<string name="enable_rpc_server_desc">Abilita il server RPC sulla porta 45987. Questo permette di leggere e scrivere remotamente la memoria guest.</string>
<string name="shader_jit">Abilita shader JIT</string>
<string name="shader_jit_description">Usa il motore JIT invece dell\'interprete per l\'emulazione di shader software.</string>
<!-- Layout settings strings --> <!-- Layout settings strings -->
<string name="layout_screen_orientation">Orientamento schermo</string> <string name="layout_screen_orientation">Orientamento schermo</string>
<string name="layout_screen_orientation_auto_sensor">Automatico</string> <string name="layout_screen_orientation_auto_sensor">Automatico</string>
@ -281,12 +323,20 @@ Divertiti usando l\'emulatore!</string>
<string name="layout_screen_orientation_landscape_reverse">Orizzontale rovesciato</string> <string name="layout_screen_orientation_landscape_reverse">Orizzontale rovesciato</string>
<string name="layout_screen_orientation_portrait">Verticale</string> <string name="layout_screen_orientation_portrait">Verticale</string>
<string name="layout_screen_orientation_portrait_reverse">Verticale rovesciato</string> <string name="layout_screen_orientation_portrait_reverse">Verticale rovesciato</string>
<string name="aspect_ratio_default">Default</string>
<string name="aspect_ratio_16_9">16:9</string>
<string name="aspect_ratio_4_3">4:3</string>
<string name="aspect_ratio_21_9_fullscreen">21:9</string>
<string name="aspect_ratio_16_10_fullscreen_stretched">16:10</string>
<string name="aspect_ratio_stretch">Allunga</string>
<!-- Miscellaneous --> <!-- Miscellaneous -->
<string name="clear">Ripristina</string> <string name="clear">Ripristina</string>
<string name="slider_default">Standard</string> <string name="slider_default">Standard</string>
<string name="ini_saved">Impostazioni salvate</string> <string name="ini_saved">Impostazioni salvate</string>
<string name="gameid_saved">Impostazioni salvate per %1$s</string> <string name="gameid_saved">Impostazioni salvate per %1$s</string>
<string name="error_saving">Errore di salvataggio %1$s.ini: %2$s</string> <string name="error_saving">Errore di salvataggio %1$s.ini: %2$s</string>
<string name="saving">Salvataggio...</string>
<string name="loading">Caricamento...</string> <string name="loading">Caricamento...</string>
<string name="next">Prossimo</string> <string name="next">Prossimo</string>
<string name="back">Indietro</string> <string name="back">Indietro</string>
@ -307,18 +357,23 @@ Divertiti usando l\'emulatore!</string>
<string name="select_rtc_time">Seleziona orario RTC</string> <string name="select_rtc_time">Seleziona orario RTC</string>
<string name="reset_setting_confirmation">Vuoi reimpostare questa impostazione al suo valore standard?</string> <string name="reset_setting_confirmation">Vuoi reimpostare questa impostazione al suo valore standard?</string>
<string name="setting_not_editable">Non puoi modificare questo ora</string> <string name="setting_not_editable">Non puoi modificare questo ora</string>
<string name="setting_disabled">Impostazione disabilitata</string>
<string name="setting_disabled_description">Questa impostazione è attualmente disattivata a causa di un\'altra impostazione che non è il valore appropriato.</string>
<string name="setting_not_editable_description">Questa opzione non può essere modificata mentre un gioco è in esecuzione.</string> <string name="setting_not_editable_description">Questa opzione non può essere modificata mentre un gioco è in esecuzione.</string>
<string name="auto_select">Auto-seleziona.</string> <string name="auto_select">Auto-seleziona.</string>
<string name="start">Avvia</string> <string name="start">Avvia</string>
<string name="cancelling">Cancellazione...</string> <string name="cancelling">Cancellazione...</string>
<string name="important">Importante</string> <string name="important">Importante</string>
<string name="dont_show_again">Non mostrare più</string> <string name="dont_show_again">Non mostrare più</string>
<string name="visibility">Visibilità</string>
<string name="information">Informazione</string>
<!-- Add Directory Screen--> <!-- Add Directory Screen-->
<string name="select_game_folder">Seleziona cartella dei giochi</string> <string name="select_game_folder">Seleziona cartella dei giochi</string>
<!-- Game Properties --> <!-- Game Properties -->
<string name="properties">Propietà</string> <string name="properties">Proprietà</string>
<string name="properties_not_loaded">Impossibile caricare le proprietà di questo gioco.</string> <string name="properties_not_loaded">Impossibile caricare le proprietà del gioco.</string>
<!-- Preferences Screen --> <!-- Preferences Screen -->
<string name="preferences_settings">Impostazioni</string> <string name="preferences_settings">Impostazioni</string>
@ -333,7 +388,7 @@ Divertiti usando l\'emulatore!</string>
<string name="preferences_layout">Layout</string> <string name="preferences_layout">Layout</string>
<!-- ROM loading errors --> <!-- ROM loading errors -->
<string name="loader_error_encrypted">La tua ROM è Criptata!</string> <string name="loader_error_encrypted">La tua ROM è Criptata</string>
<string name="loader_error_invalid_format">Formato ROM non valido</string> <string name="loader_error_invalid_format">Formato ROM non valido</string>
<string name="loader_error_file_not_found">Il file ROM non esiste</string> <string name="loader_error_file_not_found">Il file ROM non esiste</string>
<string name="no_game_present">Nessun gioco avviabile è presente!</string> <string name="no_game_present">Nessun gioco avviabile è presente!</string>
@ -350,6 +405,10 @@ Divertiti usando l\'emulatore!</string>
<string name="emulation_configure_controls">Configura Controlli</string> <string name="emulation_configure_controls">Configura Controlli</string>
<string name="emulation_edit_layout">Modifica Disposizione</string> <string name="emulation_edit_layout">Modifica Disposizione</string>
<string name="emulation_done">Fatto</string> <string name="emulation_done">Fatto</string>
<string name="emulation_button_sliding">Pulsante scorrevole</string>
<string name="emulation_button_sliding_disabled">Tieni premuto il pulsante originariamente premuto</string>
<string name="emulation_button_sliding_enabled">Tieni premuto il pulsante attualmente premuto</string>
<string name="emulation_button_sliding_alternative">Tieni premuto il pulsante originale e quello attualmente premuto</string>
<string name="emulation_toggle_controls">Attiva Controlli</string> <string name="emulation_toggle_controls">Attiva Controlli</string>
<string name="emulation_control_scale">Regola la Dimensione</string> <string name="emulation_control_scale">Regola la Dimensione</string>
<string name="emulation_control_scale_global">Scala Globale</string> <string name="emulation_control_scale_global">Scala Globale</string>
@ -359,8 +418,11 @@ Divertiti usando l\'emulatore!</string>
<string name="emulation_control_dpad_slide_enable">Trascinamento del D-Pad</string> <string name="emulation_control_dpad_slide_enable">Trascinamento del D-Pad</string>
<string name="emulation_open_settings">Apri Impostazioni</string> <string name="emulation_open_settings">Apri Impostazioni</string>
<string name="emulation_open_cheats">Apri Trucchi</string> <string name="emulation_open_cheats">Apri Trucchi</string>
<string name="emulation_aspect_ratio">Proporzione</string>
<string name="emulation_switch_screen_layout">Layout Schermi Orizzontale</string> <string name="emulation_switch_screen_layout">Layout Schermi Orizzontale</string>
<string name="emulation_switch_portrait_layout">Layout Schermi Verticale</string> <string name="emulation_switch_portrait_layout">Layout Schermi Verticale</string>
<string name="emulation_switch_secondary_layout">Layout dello schermo di visualizzazione secondario</string>
<string name="emulation_switch_secondary_layout_description">Il layout utilizzato da uno schermo secondario connesso, cablato o wireless (Chromecast, Miracast)</string>
<string name="emulation_screen_layout_largescreen">Schermo Grande</string> <string name="emulation_screen_layout_largescreen">Schermo Grande</string>
<string name="emulation_screen_layout_portrait">Verticale</string> <string name="emulation_screen_layout_portrait">Verticale</string>
<string name="emulation_screen_layout_single">Schermo singolo</string> <string name="emulation_screen_layout_single">Schermo singolo</string>
@ -368,17 +430,20 @@ Divertiti usando l\'emulatore!</string>
<string name="emulation_screen_layout_hybrid">Schermi Ibridi</string> <string name="emulation_screen_layout_hybrid">Schermi Ibridi</string>
<string name="emulation_screen_layout_original">Originale</string> <string name="emulation_screen_layout_original">Originale</string>
<string name="emulation_portrait_layout_top_full">Standard</string> <string name="emulation_portrait_layout_top_full">Standard</string>
<string name="emulation_secondary_display_default">Predefinito del sistema (specchio)</string>
<string name="emulation_screen_layout_custom">Layout personalizzato</string> <string name="emulation_screen_layout_custom">Layout personalizzato</string>
<string name="emulation_small_screen_position">Posizione schermo piccolo</string> <string name="emulation_small_screen_position">Posizione schermo piccolo</string>
<string name="small_screen_position_description">Dove dovrebbe apparire lo schermo inferiore rispetto a quello superiore nella modalità Schermo Grande?</string> <string name="small_screen_position_description">Dove dovrebbe apparire lo schermo inferiore rispetto a quello superiore nella modalità Schermo Grande?</string>
<string name="small_screen_position_top_right">Alto-Destra</string> <string name="small_screen_position_top_right">In alto a destra</string>
<string name="small_screen_position_middle_right">Centro-Destra</string> <string name="small_screen_position_middle_right">Centro-Destra</string>
<string name="small_screen_position_bottom_right">Basso-Destra (Standard)</string> <string name="small_screen_position_bottom_right">Basso-Destra (Standard)</string>
<string name="small_screen_position_top_left">Alto-Sinistra</string> <string name="small_screen_position_top_left">In alto a sinistra</string>
<string name="small_screen_position_middle_left">Centro-Sinistra</string> <string name="small_screen_position_middle_left">Centro-Sinistra</string>
<string name="small_screen_position_bottom_left">Basso-Sinistra</string> <string name="small_screen_position_bottom_left">Basso-Sinistra</string>
<string name="small_screen_position_above">Sopra</string> <string name="small_screen_position_above">Sopra</string>
<string name="small_screen_position_below">Sotto</string> <string name="small_screen_position_below">Sotto</string>
<string name="screen_gap">Spazio tra gli schermi</string>
<string name="screen_gap_description">Spazio tra gli schermi in tutte le modalità a due schermi. Misurato in px rispetto all\'altezza di 240px dello schermo più grande.</string>
<string name="large_screen_proportion">Proporzioni Schermo Superiore</string> <string name="large_screen_proportion">Proporzioni Schermo Superiore</string>
<string name="large_screen_proportion_description">Quante volte più grande deve essere lo schermo superiore rispetto a quello inferiore nella modalità Schermo Grande?</string> <string name="large_screen_proportion_description">Quante volte più grande deve essere lo schermo superiore rispetto a quello inferiore nella modalità Schermo Grande?</string>
<string name="emulation_adjust_custom_layout">Modifica Layout personalizzato nelle impostazioni</string> <string name="emulation_adjust_custom_layout">Modifica Layout personalizzato nelle impostazioni</string>
@ -392,7 +457,9 @@ Divertiti usando l\'emulatore!</string>
<string name="emulation_custom_layout_height">Altezza</string> <string name="emulation_custom_layout_height">Altezza</string>
<string name="emulation_cycle_landscape_layouts">Rotazione Layout</string> <string name="emulation_cycle_landscape_layouts">Rotazione Layout</string>
<string name="emulation_swap_screens">Inverti Schermi</string> <string name="emulation_swap_screens">Inverti Schermi</string>
<string name="emulation_rotate_upright">Ruota lo schermo in verticale</string>
<string name="emulation_touch_overlay_reset">Ripristina Disposizione</string> <string name="emulation_touch_overlay_reset">Ripristina Disposizione</string>
<string name="emulation_show_controller_overlay">Mostra Overlay Controller</string>
<string name="emulation_close_game">Chiudi il Gioco</string> <string name="emulation_close_game">Chiudi il Gioco</string>
<string name="emulation_toggle_pause">Abilita/disabilita Pausa</string> <string name="emulation_toggle_pause">Abilita/disabilita Pausa</string>
<string name="miscellaneous">Miscellanea</string> <string name="miscellaneous">Miscellanea</string>
@ -404,7 +471,7 @@ Divertiti usando l\'emulatore!</string>
<string name="menu_emulation_amiibo_remove">Rimuovi</string> <string name="menu_emulation_amiibo_remove">Rimuovi</string>
<string name="select_amiibo">Seleziona il file contenente il tuo Amiibo.</string> <string name="select_amiibo">Seleziona il file contenente il tuo Amiibo.</string>
<string name="amiibo_load_error">Impossibile caricare l\'Amiibo</string> <string name="amiibo_load_error">Impossibile caricare l\'Amiibo</string>
<string name="amiibo_load_error_message">Durante il caricamento di un file Amiibo, si è verificato un errore. Controlla che il file sia corretto.</string> <string name="amiibo_load_error_message">Durante il caricamento del file Amiibo specificato, si è verificato un errore. Controlla che il file sia corretto.</string>
<string name="pause_emulation">Metti in pausa emulazione</string> <string name="pause_emulation">Metti in pausa emulazione</string>
<string name="resume_emulation">Riprendi emulazione</string> <string name="resume_emulation">Riprendi emulazione</string>
<string name="lock_drawer">Blocca cassetto</string> <string name="lock_drawer">Blocca cassetto</string>
@ -432,8 +499,8 @@ Divertiti usando l\'emulatore!</string>
<string name="i_forgot">L\'ho Dimenticato</string> <string name="i_forgot">L\'ho Dimenticato</string>
<string name="fixed_length_required">La lunghezza del testo non è corretta (deve essere di %d caratteri)</string> <string name="fixed_length_required">La lunghezza del testo non è corretta (deve essere di %d caratteri)</string>
<string name="max_length_exceeded">Il testo è troppo lungo (non deve essere più lungo di %d caratteri)</string> <string name="max_length_exceeded">Il testo è troppo lungo (non deve essere più lungo di %d caratteri)</string>
<string name="blank_input_not_allowed">Non è consentito lasciarlo vuoto</string> <string name="blank_input_not_allowed">Non è permesso lasciare il campo vuoto</string>
<string name="empty_input_not_allowed">Non è consentito lasciarlo vuoto</string> <string name="empty_input_not_allowed">Non è permesso lasciare il campo vuoto</string>
<string name="invalid_input">Input non valido</string> <string name="invalid_input">Input non valido</string>
<!-- Mii Selector --> <!-- Mii Selector -->
@ -454,12 +521,11 @@ Divertiti usando l\'emulatore!</string>
<string name="continue_button">Continua</string> <string name="continue_button">Continua</string>
<string name="system_archive_not_found">Archivio di Sistema Non Trovato</string> <string name="system_archive_not_found">Archivio di Sistema Non Trovato</string>
<string name="system_archive_not_found_message">%s è mancante. Fai il dump del tuo archivio di sistema.\nProseguire con l\'emulazione potrebbe causare crash e bugs</string> <string name="system_archive_not_found_message">%s è mancante. Fai il dump del tuo archivio di sistema.\nProseguire con l\'emulazione potrebbe causare crash e bugs</string>
<string name="cia_file_not_found">Installazione Fallita. Impossibile trovare il file .CIA specificato.</string> <string name="cia_file_not_found">Installazione Fallita. File CIA non trovato</string>
<string name="system_archive_general">Archivio di Sistema</string> <string name="system_archive_general">Archivio di Sistema</string>
<string name="save_load_error">Errore nel Salvataggio/Caricamento</string> <string name="save_load_error">Errore nel Salvataggio/Caricamento</string>
<string name="fatal_error">Errore Fatale</string> <string name="fatal_error">Errore Fatale</string>
<string name="fatal_error_message">Consulta il log per i dettagli.\nContinuare con l\'emulazione potrebbe causare un crash.</string> <string name="fatal_error_message">Si è verificato un errore fatale. Controllare il log per i dettagli.\nContinuare l\'emulazione può causare crash e bug.</string>
<string name="invalid_region">Regione non valida</string>
<string name="unsupported_encrypted">Applicazione criptata non supportata</string> <string name="unsupported_encrypted">Applicazione criptata non supportata</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -468,7 +534,55 @@ Divertiti usando l\'emulatore!</string>
<!-- About Game Dialog --> <!-- About Game Dialog -->
<string name="play">Riproduci</string> <string name="play">Riproduci</string>
<string name="uninstall_cia">Disinstalla applicazione</string>
<string name="uninstalling">Disinstallazione...</string>
<string name="game_context_open_save_dir">Apri cartella dei salvataggi</string>
<string name="game_context_open_app">Apri cartella applicazione</string>
<string name="game_context_open_mods">Apri cartella delle mod</string>
<string name="game_context_open_textures">Apri cartella delle texture</string>
<string name="game_context_open_dlc">Apri catella DLC</string>
<string name="game_context_open_updates">Apri cartella degli aggiornamenti</string>
<string name="game_context_open_extra">Apri cartella extra</string>
<string name="game_context_uninstall_dlc">Disinstalla DLC</string>
<string name="game_context_uninstall_updates">Disinstalla aggiornamenti</string>
<string name="shortcut">Scorciatoia</string> <string name="shortcut">Scorciatoia</string>
<string name="shortcut_name">Nome della scorciatoia</string>
<string name="edit_icon">Modifica icona</string>
<string name="create_shortcut">Crea scorciatoia</string>
<string name="shortcut_name_empty">Il nome della scorciatoia non può essere vuoto</string>
<string name="shortcut_image_stretch_toggle">Estendi per adattare l\'immagine</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">File:</string>
<string name="game_context_type">Tipo:</string>
<!-- Performance Overlay settings -->
<string name="performance_overlay_show">Mostra overlay prestazioni</string>
<string name="performance_overlay_options">Overlay delle prestazioni</string>
<string name="performance_overlay_enable">Abilita overlay prestazioni</string>
<string name="performance_overlay_options_description">Configura se l\'overlay delle prestazioni viene visualizzato e quali informazioni vengono visualizzate.</string>
<string name="overlay_show_fps">Mostra FPS</string>
<string name="overlay_show_fps_description">Mostra i fotogrammi al secondo attuali.</string>
<string name="overlay_show_frametime">Mostra il frametime</string>
<string name="overlay_show_frametime_description">Mostra il frametime attuale.</string>
<string name="overlay_show_speed">Mostra velocità</string>
<string name="overlay_show_speed_description">Mostra la percentuale di emulazione attuale.</string>
<string name="overlay_show_app_ram_usage">Mostra utilizzo della memoria dell\'app</string>
<string name="overlay_show_app_ram_usage_description">Mostra la quantità di RAM usata dall\'emulatore.</string>
<string name="overlay_show_available_ram">Mostra memoria disponibile</string>
<string name="overlay_show_available_ram_description">Mostra la quantità di RAM disponibile.</string>
<string name="overlay_show_battery_temp">Mostra temperatura batteria</string>
<string name="overlay_show_battery_temp_description">Mostra la temperatura attuale, in Celsius e Fahrenheit, della batteria.</string>
<string name="overlay_position">Posizione overlay</string>
<string name="overlay_position_description">Scegli dove visualizzare l\'overlay delle prestazioni sullo schermo.</string>
<string name="overlay_position_top_left">In alto a sinistra</string>
<string name="overlay_position_top_right">In alto a destra</string>
<string name="overlay_position_bottom_left">In basso a sinistra</string>
<string name="overlay_position_bottom_right">In basso a destra</string>
<string name="overlay_position_center_top">In alto al centro</string>
<string name="overlay_position_center_bottom">In basso al centro</string>
<string name="overlay_background">Sfondo dell\'overlay</string>
<string name="overlay_background_description">Aggiunge uno sfondo dietro all\'overlay per una lettura più facile.</string>
<!-- Cheats --> <!-- Cheats -->
<string name="cheats">Trucchi</string> <string name="cheats">Trucchi</string>
<string name="cheats_add">Aggiungi Trucco</string> <string name="cheats_add">Aggiungi Trucco</string>
@ -486,13 +600,13 @@ Divertiti usando l\'emulatore!</string>
<plurals name="cia_install_toast"> <plurals name="cia_install_toast">
<item quantity="one">Installando %d file. Guarda le notifiche per maggiori dettagli.</item> <item quantity="one">Installando %d file. Guarda le notifiche per maggiori dettagli.</item>
<item quantity="many">Installando %dfiles. Guarda le notifiche per maggiori dettagli.</item> <item quantity="many">Installando %dfiles. Guarda le notifiche per maggiori dettagli.</item>
<item quantity="other">Installando %d files. Guarda le notifiche per maggiori dettagli.</item> <item quantity="other">Installando i file di %d. Guarda le notifiche per maggiori dettagli.</item>
</plurals> </plurals>
<string name="cia_install_notification_channel_description">Notifiche di Azahar durante l\'installazione dei CIA</string> <string name="cia_install_notification_channel_description">Notifiche di Azahar durante l\'installazione dei CIA</string>
<string name="cia_install_notification_title">Installando il CIA</string> <string name="cia_install_notification_title">Installando il CIA</string>
<string name="cia_install_notification_installing">Installazione %1$s (%2$d/%3$d)</string> <string name="cia_install_notification_installing">Installazione %1$s (%2$d/%3$d)</string>
<string name="cia_install_notification_success_title">CIA installato con successo</string> <string name="cia_install_notification_success_title">CIA installato con successo</string>
<string name="cia_install_notification_error_title">Errore nell\'installazione del file CIA.</string> <string name="cia_install_notification_error_title">Errore nell\'installazione del file CIA</string>
<string name="cia_install_success">\"%s\" è stato installato con successo</string> <string name="cia_install_success">\"%s\" è stato installato con successo</string>
<string name="cia_install_error_aborted">L\'installazione di \"%s\" è stata annullata.\n Consulta i log per maggiori dettagli</string> <string name="cia_install_error_aborted">L\'installazione di \"%s\" è stata annullata.\n Consulta i log per maggiori dettagli</string>
<string name="cia_install_error_invalid">\"%s\" non è un CIA valido</string> <string name="cia_install_error_invalid">\"%s\" non è un CIA valido</string>
@ -588,7 +702,11 @@ Divertiti usando l\'emulatore!</string>
<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">Controllata dal gioco</string>
<string name="nearest_neighbor">Nearest Neighbor</string> <string name="nearest_neighbor">Nearest Neighbor</string>
<string name="linear">Lineare</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>
@ -744,7 +862,7 @@ Divertiti usando l\'emulatore!</string>
<string name="december">Dicembre</string> <string name="december">Dicembre</string>
<!-- Artic base --> <!-- Artic base -->
<string name="artic_server_comm_error">Fallimento nella comunicazione con il server Artic Base. L\'emulazione verrà interrotta</string> <string name="artic_server_comm_error">Comunicazione con il server Artic Base fallita. L\'emulazione verrà interrotta</string>
<string name="artic_base">Artic Base</string> <string name="artic_base">Artic Base</string>
<string name="artic_base_connect_description">Connettiti a una console reale che sta eseguendo il server Artic Base</string> <string name="artic_base_connect_description">Connettiti a una console reale che sta eseguendo il server Artic Base</string>
<string name="artic_base_connect">Connetti ad Artic Base</string> <string name="artic_base_connect">Connetti ad Artic Base</string>
@ -755,6 +873,6 @@ Divertiti usando l\'emulatore!</string>
<string name="emulation_quicksave">Salvataggio Rapido</string> <string name="emulation_quicksave">Salvataggio Rapido</string>
<string name="emulation_quickload">Caricamento Rapido</string> <string name="emulation_quickload">Caricamento Rapido</string>
<string name="emulation_occupied_quicksave_slot">Salvataggio Rapido - %1$tF %1$tR</string> <string name="emulation_occupied_quicksave_slot">Salvataggio Rapido - %1$tF %1$tR</string>
<string name="quickload_not_found">Nessun Salvataggio Rapido Disponibile</string> <string name="quickload_not_found">Nessun salvataggio rapido disponibile</string>
</resources> </resources>

View File

@ -35,12 +35,26 @@
<item>@string/emulation_screen_layout_custom</item> <item>@string/emulation_screen_layout_custom</item>
</string-array> </string-array>
<string-array name="secondaryLayouts">
<item>@string/emulation_secondary_display_default</item>
<item>@string/emulation_top_screen</item>
<item>@string/emulation_bottom_screen</item>
<item>@string/emulation_screen_layout_sidebyside</item>
</string-array>
<integer-array name="portraitLayoutValues"> <integer-array name="portraitLayoutValues">
<item>0</item> <item>0</item>
<item>2</item> <item>2</item>
<item>1</item> <item>1</item>
</integer-array> </integer-array>
<integer-array name="secondaryLayoutValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
<string-array name="smallScreenPositions"> <string-array name="smallScreenPositions">
<item>@string/small_screen_position_top_right</item> <item>@string/small_screen_position_top_right</item>
<item>@string/small_screen_position_middle_right</item> <item>@string/small_screen_position_middle_right</item>
@ -134,12 +148,12 @@
</integer-array> </integer-array>
<string-array name="statsPosition"> <string-array name="statsPosition">
<item>@string/overlay_position_top_left</item> <item>@string/performance_overlay_position_top_left</item>
<item>@string/overlay_position_center_top</item> <item>@string/performance_overlay_position_center_top</item>
<item>@string/overlay_position_top_right</item> <item>@string/performance_overlay_position_top_right</item>
<item>@string/overlay_position_bottom_left</item> <item>@string/performance_overlay_position_bottom_left</item>
<item>@string/overlay_position_center_bottom</item> <item>@string/performance_overlay_position_center_bottom</item>
<item>@string/overlay_position_bottom_right</item> <item>@string/performance_overlay_position_bottom_right</item>
</string-array> </string-array>
<integer-array name="statsPositionValues"> <integer-array name="statsPositionValues">
<item>0</item> <item>0</item>

View File

@ -214,6 +214,9 @@
<string name="region_mismatch">Region Mismatch Warning</string> <string name="region_mismatch">Region Mismatch Warning</string>
<string name="region_mismatch_emulated">The country setting is not valid for the selected emulated region.</string> <string name="region_mismatch_emulated">The country setting is not valid for the selected emulated region.</string>
<string name="region_mismatch_console">The country setting is not valid for the current linked console.</string> <string name="region_mismatch_console">The country setting is not valid for the current linked console.</string>
<string name="storage">Storage</string>
<string name="compress_cia_installs">Compress installed CIA content</string>
<string name="compress_cia_installs_description">Compresses the content of CIA files when installed to the emulated SD card. Only affects CIA content which is installed while the setting is enabled.</string>
<!-- Camera settings strings --> <!-- Camera settings strings -->
<string name="inner_camera">Inner Camera</string> <string name="inner_camera">Inner Camera</string>
@ -235,25 +238,27 @@
<string name="spirv_shader_gen_description">Emits the fragment shader used to emulate PICA using SPIR-V instead of GLSL</string> <string name="spirv_shader_gen_description">Emits the fragment shader used to emulate PICA using SPIR-V instead of GLSL</string>
<string name="disable_spirv_optimizer">Disable SPIR-V Optimizer</string> <string name="disable_spirv_optimizer">Disable SPIR-V Optimizer</string>
<string name="disable_spirv_optimizer_description">Disables the SPIR-V optimization pass, reducing stuttering considerably while barely affecting performance.</string> <string name="disable_spirv_optimizer_description">Disables the SPIR-V optimization pass, reducing stuttering considerably while barely affecting performance.</string>
<string name="async_shaders">Enable asynchronous shader compilation</string> <string name="async_shaders">Enable Asynchronous Shader Compilation</string>
<string name="async_shaders_description">Compiles shaders in the background to reduce stuttering during gameplay. When enabled expect temporary graphical glitches</string> <string name="async_shaders_description">Compiles shaders in the background to reduce stuttering during gameplay. When enabled expect temporary graphical glitches</string>
<string name="linear_filtering">Linear Filtering</string> <string name="linear_filtering">Linear Filtering</string>
<string name="linear_filtering_description">Enables linear filtering, which causes game visuals to appear smoother.</string> <string name="linear_filtering_description">Enables linear filtering, which causes game visuals to appear smoother.</string>
<string name="texture_filter_name">Texture Filter</string> <string name="texture_filter_name">Texture Filter</string>
<string name="texture_filter_description">Enhances the visuals of applications by applying a filter to textures. The supported filters are Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale, and MMPX.</string> <string name="texture_filter_description">Enhances the visuals of applications by applying a filter to textures. The supported filters are Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale, and MMPX.</string>
<string name="delay_render_thread">Delay game render thread</string> <string name="delay_render_thread">Delay Game Render Thread</string>
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) applications with dynamic framerates.</string> <string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) applications with dynamic framerates.</string>
<string name="advanced">Advanced</string> <string name="advanced">Advanced</string>
<string name="texture_sampling_name">Texture Sampling</string> <string name="texture_sampling_name">Texture Sampling</string>
<string name="texture_sampling_description">Overrides the sampling filter used by games. This can be useful in certain cases with poorly behaved games when upscaling. If unsure, set this to Game Controlled.</string> <string name="texture_sampling_description">Overrides the sampling filter used by games. This can be useful in certain cases with poorly behaved games when upscaling. If unsure, set this to Game Controlled.</string>
<string name="shaders_accurate_mul">Accurate Multiplication</string> <string name="shaders_accurate_mul">Accurate Multiplication</string>
<string name="shaders_accurate_mul_description">Uses more accurate multiplication in hardware shaders, which may fix some graphical bugs. When enabled, performance will be reduced.</string> <string name="shaders_accurate_mul_description">Uses more accurate multiplication in hardware shaders, which may fix some graphical bugs. When enabled, performance will be reduced.</string>
<string name="asynchronous_gpu">Enable asynchronous GPU emulation</string> <string name="asynchronous_gpu">Enable Asynchronous GPU Emulation</string>
<string name="asynchronous_gpu_description">Uses a separate thread to emulate the GPU asynchronously. When enabled, performance will be improved.</string> <string name="asynchronous_gpu_description">Uses a separate thread to emulate the GPU asynchronously. When enabled, performance will be improved.</string>
<string name="frame_limit_enable">Limit Speed</string> <string name="frame_limit_enable">Limit Speed</string>
<string name="frame_limit_enable_description">When enabled, emulation speed will be limited to a specified percentage of normal speed. If disabled, emulation speed will be uncapped and the turbo speed hotkey will not work.</string> <string name="frame_limit_enable_description">When enabled, emulation speed will be limited to a specified percentage of normal speed. If disabled, emulation speed will be uncapped and the turbo speed hotkey will not work.</string>
<string name="frame_limit_slider">Limit Speed Percent</string> <string name="frame_limit_slider">Limit Speed Percent</string>
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. With the default of 100% emulation will be limited to normal speed. Values higher or lower will increase or decrease the speed limit.</string> <string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. With the default of 100% emulation will be limited to normal speed. Values higher or lower will increase or decrease the speed limit.</string>
<string name="android_hide_images">Hide 3DS Images from Android</string>
<string name="android_hide_images_description">Prevent 3DS camera, screenshot, and custom texture images from being indexed by Android and displayed in the gallery. Your device may need to be rebooted after changing this setting to take effect.</string>
<string name="turbo_limit">Turbo Speed Limit</string> <string name="turbo_limit">Turbo Speed Limit</string>
<string name="turbo_limit_description">Emulation speed limit used while the turbo hotkey is active.</string> <string name="turbo_limit_description">Emulation speed limit used while the turbo hotkey is active.</string>
<string name="expand_to_cutout_area">Expand to Cutout Area</string> <string name="expand_to_cutout_area">Expand to Cutout Area</string>
@ -303,7 +308,7 @@
<string name="audio_volume">Volume</string> <string name="audio_volume">Volume</string>
<string name="audio_stretch">Audio Stretching</string> <string name="audio_stretch">Audio Stretching</string>
<string name="audio_stretch_description">Stretches audio to reduce stuttering. When enabled, increases audio latency and slightly reduces performance.</string> <string name="audio_stretch_description">Stretches audio to reduce stuttering. When enabled, increases audio latency and slightly reduces performance.</string>
<string name="realtime_audio">Enable realtime audio</string> <string name="realtime_audio">Enable Realtime Audio</string>
<string name="realtime_audio_description">Scales audio playback speed to account for drops in emulation framerate. This means that audio will play at full speed even while the game framerate is low. May cause audio desync issues.</string> <string name="realtime_audio_description">Scales audio playback speed to account for drops in emulation framerate. This means that audio will play at full speed even while the game framerate is low. May cause audio desync issues.</string>
<string name="audio_input_type">Audio Input Device</string> <string name="audio_input_type">Audio Input Device</string>
<string name="sound_output_mode">Sound Output Mode</string> <string name="sound_output_mode">Sound Output Mode</string>
@ -318,9 +323,9 @@
<string name="vsync_description">Synchronizes the game frame rate to the refresh rate of your device.</string> <string name="vsync_description">Synchronizes the game frame rate to the refresh rate of your device.</string>
<string name="renderer_debug">Debug Renderer</string> <string name="renderer_debug">Debug Renderer</string>
<string name="renderer_debug_description">Log additional graphics related debug information. When enabled, game performance will be significantly reduced.</string> <string name="renderer_debug_description">Log additional graphics related debug information. When enabled, game performance will be significantly reduced.</string>
<string name="instant_debug_log">Flush log output on every message</string> <string name="instant_debug_log">Flush Log Output on Every Message</string>
<string name="instant_debug_log_description">Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut.</string> <string name="instant_debug_log_description">Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut.</string>
<string name="delay_start_lle_modules">Delay start with LLE modules</string> <string name="delay_start_lle_modules">Delay Start With LLE Modules</string>
<string name="delay_start_lle_modules_description">Delays the start of the app when LLE modules are enabled.</string> <string name="delay_start_lle_modules_description">Delays the start of the app when LLE modules are enabled.</string>
<string name="deterministic_async_operations">Deterministic Async Operations</string> <string name="deterministic_async_operations">Deterministic Async Operations</string>
<string name="deterministic_async_operations_description">Makes async operations deterministic for debugging. Enabling this may cause freezes.</string> <string name="deterministic_async_operations_description">Makes async operations deterministic for debugging. Enabling this may cause freezes.</string>
@ -418,6 +423,10 @@
<string name="emulation_configure_controls">Configure Controls</string> <string name="emulation_configure_controls">Configure Controls</string>
<string name="emulation_edit_layout">Edit Layout</string> <string name="emulation_edit_layout">Edit Layout</string>
<string name="emulation_done">Done</string> <string name="emulation_done">Done</string>
<string name="emulation_button_sliding">Button Sliding</string>
<string name="emulation_button_sliding_disabled">Hold originally pressed button</string>
<string name="emulation_button_sliding_enabled">Hold currently pressed button</string>
<string name="emulation_button_sliding_alternative">Hold original and currently pressed button</string>
<string name="emulation_toggle_controls">Toggle Controls</string> <string name="emulation_toggle_controls">Toggle Controls</string>
<string name="emulation_control_scale">Adjust Scale</string> <string name="emulation_control_scale">Adjust Scale</string>
<string name="emulation_control_scale_global">Global Scale</string> <string name="emulation_control_scale_global">Global Scale</string>
@ -430,6 +439,8 @@
<string name="emulation_aspect_ratio">Aspect Ratio</string> <string name="emulation_aspect_ratio">Aspect Ratio</string>
<string name="emulation_switch_screen_layout">Landscape Screen Layout</string> <string name="emulation_switch_screen_layout">Landscape Screen Layout</string>
<string name="emulation_switch_portrait_layout">Portrait Screen Layout</string> <string name="emulation_switch_portrait_layout">Portrait Screen Layout</string>
<string name="emulation_switch_secondary_layout">Secondary Display Screen Layout</string>
<string name="emulation_switch_secondary_layout_description">The layout used by a connected secondary screen, wired or wireless (Chromecast, Miracast)</string>
<string name="emulation_screen_layout_largescreen">Large Screen</string> <string name="emulation_screen_layout_largescreen">Large Screen</string>
<string name="emulation_screen_layout_portrait">Portrait</string> <string name="emulation_screen_layout_portrait">Portrait</string>
<string name="emulation_screen_layout_single">Single Screen</string> <string name="emulation_screen_layout_single">Single Screen</string>
@ -437,7 +448,15 @@
<string name="emulation_screen_layout_hybrid">Hybrid Screens</string> <string name="emulation_screen_layout_hybrid">Hybrid Screens</string>
<string name="emulation_screen_layout_original">Original</string> <string name="emulation_screen_layout_original">Original</string>
<string name="emulation_portrait_layout_top_full">Default</string> <string name="emulation_portrait_layout_top_full">Default</string>
<string name="emulation_secondary_display_default">System Default (mirror)</string>
<string name="emulation_screen_layout_custom">Custom Layout</string> <string name="emulation_screen_layout_custom">Custom Layout</string>
<string name="bg_color">Background Color</string>
<string name="bg_color_description">The color which appears behind the screens during emulation, represented as an RGB value.</string>
<string name="bg_red">Red</string>
<string name="bg_green">Green</string>
<string name="bg_blue">Blue</string>
<string name="second_screen_opacity">Custom Layout Second Screen Opacity</string>
<string name="second_screen_opacity_description">The opacity of the second 3DS screen when using a custom screen layout. Useful if the second screen is to be positioned on top of the first screen.</string>
<string name="emulation_small_screen_position">Small Screen Position</string> <string name="emulation_small_screen_position">Small Screen Position</string>
<string name="small_screen_position_description">Where should the small screen appear relative to the large one in Large Screen Layout?</string> <string name="small_screen_position_description">Where should the small screen appear relative to the large one in Large Screen Layout?</string>
<string name="small_screen_position_top_right">Top Right</string> <string name="small_screen_position_top_right">Top Right</string>
@ -532,7 +551,6 @@
<string name="save_load_error">Save/Load Error</string> <string name="save_load_error">Save/Load Error</string>
<string name="fatal_error">Fatal Error</string> <string name="fatal_error">Fatal Error</string>
<string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string> <string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string>
<string name="invalid_region">Invalid region</string>
<string name="unsupported_encrypted">Unsupported encrypted application</string> <string name="unsupported_encrypted">Unsupported encrypted application</string>
<!-- Disk Shader Cache --> <!-- Disk Shader Cache -->
@ -558,34 +576,37 @@
<string name="create_shortcut">Create Shortcut</string> <string name="create_shortcut">Create Shortcut</string>
<string name="shortcut_name_empty">Shortcut name cannot be empty</string> <string name="shortcut_name_empty">Shortcut name cannot be empty</string>
<string name="shortcut_image_stretch_toggle">Stretch to fit image</string> <string name="shortcut_image_stretch_toggle">Stretch to fit image</string>
<string name="game_context_id">ID:</string>
<string name="game_context_file">File:</string>
<string name="game_context_type">Type:</string>
<!-- Performance Overlay settings --> <!-- Performance Overlay settings -->
<string name="performance_overlay_show">Show Performance Overlay</string> <string name="performance_overlay_show">Show Performance Overlay</string>
<string name="performance_overlay_options">Performance Overlay</string> <string name="performance_overlay_options">Performance Overlay</string>
<string name="performance_overlay_enable">Enable Performance Overlay</string> <string name="performance_overlay_enable">Enable Performance Overlay</string>
<string name="performance_overlay_options_description">Configure whether the performance overlay is shown and what information is displayed.</string> <string name="performance_overlay_options_description">Configure whether the performance overlay is shown and what information is displayed.</string>
<string name="overlay_show_fps">Show FPS</string> <string name="performance_overlay_show_fps">Show FPS</string>
<string name="overlay_show_fps_description">Display current frames per second.</string> <string name="performance_overlay_show_fps_description">Display current frames per second.</string>
<string name="overlay_show_frametime">Show Frametime</string> <string name="performance_overlay_show_frametime">Show Frametime</string>
<string name="overlay_show_frametime_description">Display current frametime.</string> <string name="performance_overlay_show_frametime_description">Display current frametime.</string>
<string name="overlay_show_speed">Show Speed</string> <string name="performance_overlay_show_speed">Show Speed</string>
<string name="overlay_show_speed_description">Display current emulation speed percentage.</string> <string name="performance_overlay_show_speed_description">Display current emulation speed percentage.</string>
<string name="overlay_show_app_ram_usage">Show App Memory Usage</string> <string name="performance_overlay_show_app_ram_usage">Show App Memory Usage</string>
<string name="overlay_show_app_ram_usage_description">Display the amount of RAM getting used by the emulator.</string> <string name="performance_overlay_show_app_ram_usage_description">Display the amount of RAM getting used by the emulator.</string>
<string name="overlay_show_available_ram">Show Available Memory</string> <string name="performance_overlay_show_available_ram">Show Available Memory</string>
<string name="overlay_show_available_ram_description">Display the amount of RAM which is available.</string> <string name="performance_overlay_show_available_ram_description">Display the amount of RAM which is available.</string>
<string name="overlay_show_battery_temp">Show Battery Temperature</string> <string name="performance_overlay_show_battery_temp">Show Battery Temperature</string>
<string name="overlay_show_battery_temp_description">Display current Battery temperature in Celsius and Fahrenheit.</string> <string name="performance_overlay_show_battery_temp_description">Display current Battery temperature in Celsius and Fahrenheit.</string>
<string name="overlay_position">Overlay Position</string> <string name="performance_overlay_position">Overlay Position</string>
<string name="overlay_position_description">Choose where the performance overlay is displayed on the screen.</string> <string name="performance_overlay_position_description">Choose where the performance overlay is displayed on the screen.</string>
<string name="overlay_position_top_left">Top Left</string> <string name="performance_overlay_position_top_left">Top Left</string>
<string name="overlay_position_top_right">Top Right</string> <string name="performance_overlay_position_top_right">Top Right</string>
<string name="overlay_position_bottom_left">Bottom Left</string> <string name="performance_overlay_position_bottom_left">Bottom Left</string>
<string name="overlay_position_bottom_right">Bottom Right</string> <string name="performance_overlay_position_bottom_right">Bottom Right</string>
<string name="overlay_position_center_top">Center Top</string> <string name="performance_overlay_position_center_top">Center Top</string>
<string name="overlay_position_center_bottom">Center Bottom</string> <string name="performance_overlay_position_center_bottom">Center Bottom</string>
<string name="overlay_background">Overlay Background</string> <string name="performance_overlay_background">Overlay Background</string>
<string name="overlay_background_description">Adds a background behind the overlay for easier reading.</string> <string name="performance_overlay_background_description">Adds a background behind the overlay for easier reading.</string>
<!-- Cheats --> <!-- Cheats -->
<string name="cheats">Cheats</string> <string name="cheats">Cheats</string>

View File

@ -4,14 +4,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id("com.android.application") version "8.8.1" apply false id("com.android.application") version "8.11.1" apply false
id("com.android.library") version "8.8.1" apply false id("com.android.library") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.0.20" apply false id("org.jetbrains.kotlin.android") version "2.0.20" apply false
id("org.jetbrains.kotlin.plugin.serialization") version "2.0.20" id("org.jetbrains.kotlin.plugin.serialization") version "2.0.20"
} }
tasks.register("clean").configure { tasks.register("clean").configure {
delete(rootProject.buildDir) delete(rootProject.layout.buildDirectory)
} }
buildscript { buildscript {

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip

View File

@ -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.
@ -8,31 +8,13 @@
namespace AudioCore::HLE { namespace AudioCore::HLE {
AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) { AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) {
decoder = NeAACDecOpen(); OpenNewDecoder();
if (decoder == nullptr) {
LOG_CRITICAL(Audio_DSP, "Could not open FAAD2 decoder.");
return;
}
auto config = NeAACDecGetCurrentConfiguration(decoder);
config->defObjectType = LC;
config->outputFormat = FAAD_FMT_16BIT;
if (!NeAACDecSetConfiguration(decoder, config)) {
LOG_CRITICAL(Audio_DSP, "Could not configure FAAD2 decoder.");
NeAACDecClose(decoder);
decoder = nullptr;
return;
}
LOG_INFO(Audio_DSP, "Created FAAD2 AAC decoder.");
} }
AACDecoder::~AACDecoder() { AACDecoder::~AACDecoder() {
if (decoder) { if (decoder) {
NeAACDecClose(decoder); NeAACDecClose(decoder);
decoder = nullptr; decoder = nullptr;
LOG_INFO(Audio_DSP, "Destroyed FAAD2 AAC decoder.");
} }
} }
@ -52,6 +34,9 @@ BinaryMessage AACDecoder::ProcessRequest(const BinaryMessage& request) {
case DecoderCommand::Init: { case DecoderCommand::Init: {
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
if (!OpenNewDecoder()) {
response.header.result = ResultStatus::Error;
}
return response; return response;
} }
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
@ -89,6 +74,7 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
response.decode_aac_response.num_samples = 1024; response.decode_aac_response.num_samples = 1024;
if (decoder == nullptr) { if (decoder == nullptr) {
LOG_ERROR(Audio_DSP, "Failed to handle decode request: FAAD2 AAC decoder not open.");
return response; return response;
} }
@ -102,17 +88,22 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
u8* data = memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR); u8* data = memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR);
u32 data_len = request.decode_aac_request.size; u32 data_len = request.decode_aac_request.size;
if (!decoder_initialized) {
unsigned long sample_rate; unsigned long sample_rate;
u8 num_channels; u8 num_channels;
auto init_result = NeAACDecInit(decoder, data, data_len, &sample_rate, &num_channels); auto init_result = NeAACDecInit(decoder, data, data_len, &sample_rate, &num_channels);
if (init_result < 0) { if (init_result < 0) {
LOG_ERROR(Audio_DSP, "Could not initialize FAAD2 AAC decoder for request: {}", init_result); LOG_ERROR(Audio_DSP, "Could not initialize FAAD2 AAC decoder for request: {}",
init_result);
return response; return response;
} }
decoder_initialized = true;
// Advance past the frame header if needed. // Advance past the frame header if needed.
data += init_result; data += init_result;
data_len -= init_result; data_len -= init_result;
}
std::array<std::vector<s16>, 2> out_streams; std::array<std::vector<s16>, 2> out_streams;
@ -125,6 +116,10 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
return response; return response;
} }
// Set the output frame info.
response.decode_aac_response.sample_rate = GetSampleRateEnum(frame_info.samplerate);
response.decode_aac_response.num_channels = frame_info.channels;
// Split the decode result into channels. // Split the decode result into channels.
u32 num_samples = frame_info.samples / frame_info.channels; u32 num_samples = frame_info.samples / frame_info.channels;
for (u32 sample = 0; sample < num_samples; sample++) { for (u32 sample = 0; sample < num_samples; sample++) {
@ -155,11 +150,34 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
} }
// Set the output frame info. // Set the output frame info.
response.decode_aac_response.sample_rate = GetSampleRateEnum(sample_rate);
response.decode_aac_response.num_channels = num_channels;
response.decode_aac_response.num_samples = static_cast<u32_le>(out_streams[0].size()); response.decode_aac_response.num_samples = static_cast<u32_le>(out_streams[0].size());
return response; return response;
} }
bool AACDecoder::OpenNewDecoder() {
if (decoder) {
NeAACDecClose(decoder);
}
decoder_initialized = false;
decoder = NeAACDecOpen();
if (decoder == nullptr) {
LOG_CRITICAL(Audio_DSP, "Could not open FAAD2 decoder.");
return false;
}
auto config = NeAACDecGetCurrentConfiguration(decoder);
config->defObjectType = LC;
config->outputFormat = FAAD_FMT_16BIT;
if (!NeAACDecSetConfiguration(decoder, config)) {
LOG_CRITICAL(Audio_DSP, "Could not configure FAAD2 decoder.");
NeAACDecClose(decoder);
decoder = nullptr;
return false;
}
return true;
}
} // namespace AudioCore::HLE } // namespace AudioCore::HLE

View File

@ -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.
@ -18,9 +18,11 @@ public:
private: private:
BinaryMessage Decode(const BinaryMessage& request); BinaryMessage Decode(const BinaryMessage& request);
bool OpenNewDecoder();
Memory::MemorySystem& memory; Memory::MemorySystem& memory;
NeAACDecHandle decoder = nullptr; NeAACDecHandle decoder = nullptr;
bool decoder_initialized = false;
}; };
} // namespace AudioCore::HLE } // namespace AudioCore::HLE

View File

@ -1,4 +1,4 @@
// Copyright 2016 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,7 +9,7 @@
namespace AudioCore { namespace AudioCore {
constexpr char auto_device_name[] = "auto"; constexpr char auto_device_name[] = "Auto";
/** /**
* This class is an interface for an audio sink. An audio sink accepts samples in stereo signed * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed

View File

@ -60,6 +60,10 @@ if (ENABLE_QT AND UNIX AND NOT APPLE)
target_link_libraries(citra_meta PRIVATE Qt6::DBus gamemode) target_link_libraries(citra_meta PRIVATE Qt6::DBus gamemode)
endif() endif()
if (ENABLE_QT AND APPLE)
target_link_libraries(citra_meta PRIVATE Qt6::GuiPrivate)
endif()
if (ENABLE_QT AND USE_DISCORD_PRESENCE) if (ENABLE_QT AND USE_DISCORD_PRESENCE)
target_link_libraries(citra_meta PRIVATE discord-rpc) target_link_libraries(citra_meta PRIVATE discord-rpc)
endif() endif()

Some files were not shown because too many files have changed in this diff Show More