Compare commits

..

18 commits

Author SHA1 Message Date
e662fe99ac
[gamemode] default disable on msvc, move to UI category
Some checks failed
eden-license / license-header (pull_request) Failing after 16s
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-19 06:55:40 +00:00
217943b1ac
[gamemode] windows fix
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-19 06:55:40 +00:00
336373df41
[gamemode] extra win/lin/macos fixes
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-19 06:55:39 +00:00
47a3308f92
[gamemode] make option available on all nixes
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-19 06:55:39 +00:00
f51e28c00a
[gamemode] Make available on other platforms
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-19 06:55:39 +00:00
cf634d4d6f
[gpu/nvdrv] Rewrite ZBC functions (#2501)
This rewrite attempts to implement a fully correct ZBC (Zero Bandwith Clear) mechanism.
The zbc_mutex attempts to mitigate contention by assuring that only threads which hold the mutex can modify the table.
Notify drivers about the index size, I believe some drivers even need the notification.
Only add new entries if a entry was not previously available.

Reviewed-on: #2501
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: SDK-Chan <sdkchan@eden-emu.dev>
Co-committed-by: SDK-Chan <sdkchan@eden-emu.dev>
2025-09-18 14:46:53 +02:00
b1ce3c8dc1
[docs] CODEOWNERS (#491)
cc: @CamilleLaVey @Lizzie

initial guess for everyone, may need more specificity etc.

Signed-off-by: crueter <crueter@eden-emu.dev>

Reviewed-on: #491
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
2025-09-18 02:38:15 +02:00
e1ffeec212
[docs] refactor: full rewrite, generalization + dedup (#488)
"docs but awesome"

Combines most of the stuff that was repeated thrice over verbatim into a
single common Build Instructions page, with additional caveats marked
elsewhere. Prettifies some stuff too because why not.

cc: @Lizzie @DraVee @MaranBr @SDK-Chan

Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-on: #488
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2025-09-18 02:37:02 +02:00
249e006667
[VMA] Use Host cached and Host coherent for Download operations (#482)
Increase read speeds by using appropriate usage flags

Reviewed-on: #482
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
2025-09-17 21:40:09 +02:00
8ac495acee
[fs] Remove remaining files from NCA bypass and fix some asserts (#2502)
Reviewed-on: #2502
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: MaranBr <maranbr@outlook.com>
Co-committed-by: MaranBr <maranbr@outlook.com>
2025-09-17 17:45:52 +02:00
cda6958111
[host_memory] decrease latency of mapping on linux (#232)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #232
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-09-17 02:31:44 +02:00
dac2efc4c8
[Shader Recompiler] Caching optimization for Texture_Pass (#481)
Add Caching per texture_pass and optimize sorting to single pass.
Use Logical shift instead of arithmetic shift.

Reviewed-on: #481
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
2025-09-17 02:27:03 +02:00
3b3278f44b
[jit, exception] use shared mutex to reduce thread contention of cached code blocks in fastmem trap handler (#320)
ankerl::unordered_dense::map will provide better lookup times, theoretically.
fastmem trap handler usually had mutex contention for non-linkable series of blocks (block linking failures); so just use shared_mutex

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: #320
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-09-16 20:54:00 +02:00
3ca0bde0e9
[core/nvnflinger] Rewrite GetBufferHistory (#528)
This rewrite should improve performance with the buffer history by changing the complexity level to O(1).
Replace std::vector with std::array to ensure that elements are allocated on the stack rather than on the free store.
Avoid expensive resizing at runtime.
Adjust buffer states at the right locations.
Tightly pack the BufferHistoryInfo struct to ensure that it only occupies 28 bytes.

Reviewed-on: #528
Co-authored-by: SDK-Chan <sdkchan@eden-emu.dev>
Co-committed-by: SDK-Chan <sdkchan@eden-emu.dev>
2025-09-16 19:41:52 +02:00
6699361b7e
[cmake] fix freebsd and openbsd, remove CPMUtil Eden copyright (#496)
CPMUtil is technically a completely separate project created and maintained solely by me, so it should actually be copyrighted to me

Reviewed-on: #496
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2025-09-16 18:44:19 +02:00
19036c59b5
[video_core] Simplify DMA options (#525)
This simplifies DMA options in a clearer and more objective way.

Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
Reviewed-on: #525
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: MaranBr <maranbr@outlook.com>
Co-committed-by: MaranBr <maranbr@outlook.com>
2025-09-16 18:42:48 +02:00
80dfc3d76f
[fs] Remove remaining files from NCA bypass (#495)
Fix Android build after PR 94.

Reviewed-on: #495
Co-authored-by: MaranBr <maranbr@outlook.com>
Co-committed-by: MaranBr <maranbr@outlook.com>
2025-09-15 17:47:19 +02:00
f4386423e8
[qt] refactor: qt_common lib (#94)
This is part of a series of PRs made in preparation for the QML rewrite. this PR specifically moves a bunch of utility functions from main.cpp into qt_common, with the biggest benefit being that QML can reuse the exact same code through ctx passthrough.

Also, QtCommon::Frontend is an abstraction layer over several previously Widgets-specific stuff like QMessageBox that gets used everywhere. The idea is that once QML is implemented, these functions can have a Quick version implemented for systems that don't work well with Widgets (sun) or for those on Plasma 6+ (reduces memory usage w/o Widgets linkage) although Quick from C++ is actually anal, but whatever.

Other than that this should also just kinda reduce the size of main.cpp which is a 6000-line behemoth rn, and clangd straight up gives up with it for me (likely caused by the massive amount of headers, which this DOES reduce).

In the future, I probably want to create a common strings lookup table that both Qt and QML can reference--though I'm not sure how much linguist likes that--which should give us a way to keep language consistent (use frozen-map).

TODO: Docs for Qt stuff

Co-authored-by: MaranBr <maranbr@outlook.com>
Reviewed-on: #94
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
2025-09-15 17:21:18 +02:00
153 changed files with 3429 additions and 2688 deletions

View file

@ -5,10 +5,13 @@ HEADER_HASH="$(cat "$PWD/.ci/license/header-hash.txt")"
echo "Getting branch changes"
BRANCH=`git rev-parse --abbrev-ref HEAD`
COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"`
RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}"
FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r`
# BRANCH=`git rev-parse --abbrev-ref HEAD`
# COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"`
# RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}"
# FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r`
BASE=`git merge-base master HEAD`
FILES=`git diff --name-only $BASE`
#FILES=$(git diff --name-only master)

View file

@ -44,6 +44,13 @@ if (PLATFORM_SUN)
endif()
endif()
# Needed for FFmpeg w/ VAAPI and DRM
if (PLATFORM_OPENBSD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/X11R6/include")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/X11R6/include")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/X11R6/lib")
endif()
# Detect current compilation architecture and create standard definitions
# =======================================================================
@ -88,7 +95,7 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
if (MSVC AND ARCHITECTURE_x86)
message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \
This can typically happen if you used the Developer Command Prompt from the start menu;\
This can typically happen if you used the Developer Command Prompt from the start menu; \
instead, run vcvars64.bat directly, located at C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat")
endif()
@ -122,7 +129,7 @@ include(CMakeDependentOption)
include(CTest)
# Disable Warnings as Errors for MSVC
if (CXX_CL)
if (MSVC AND NOT CXX_CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-")
endif()
@ -485,13 +492,32 @@ else()
find_package(Opus 1.3 MODULE REQUIRED)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED MODULE)
find_package(Boost 1.57.0 REQUIRED context system fiber)
find_package(MbedTLS 3)
# wow
if (PLATFORM_LINUX)
find_package(Boost 1.57.0 REQUIRED headers context system fiber)
else()
find_package(Boost 1.57.0 REQUIRED)
endif()
# OpenBSD does not package mbedtls3 (only 2)
if (PLATFORM_OPENBSD)
AddJsonPackage(mbedtls)
else()
find_package(MbedTLS 3 REQUIRED)
endif()
find_package(VulkanUtilityLibraries REQUIRED)
find_package(VulkanHeaders 1.3.274 REQUIRED)
# FreeBSD does not package spirv-headers
if (PLATFORM_FREEBSD)
AddJsonPackage(spirv-headers)
else()
find_package(SPIRV-Headers 1.3.274 REQUIRED)
endif()
find_package(SPIRV-Tools MODULE REQUIRED)
find_package(SPIRV-Headers 1.3.274 REQUIRED)
if (YUZU_TESTS)
find_package(Catch2 3.0.1 REQUIRED)

View file

@ -1,17 +1,6 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 crueter
# SPDX-License-Identifier: GPL-3.0-or-later
# Created-By: crueter
# Docs will come at a later date, mostly this is to just reduce boilerplate
# and some cmake magic to allow for runtime viewing of dependency versions
# Future crueter: Wow this was a lie and a half, at this point I might as well make my own CPN
# haha just kidding... unless?
# TODO(crueter): Remember to get more than 6 hours of sleep whenever making giant cmake changes
if (MSVC OR ANDROID)
set(BUNDLED_DEFAULT ON)
else()
@ -27,6 +16,7 @@ option(CPMUTIL_FORCE_SYSTEM
cmake_minimum_required(VERSION 3.22)
include(CPM)
# cpmfile parsing
set(CPMUTIL_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json")
if (EXISTS ${CPMUTIL_JSON_FILE})
@ -35,12 +25,11 @@ else()
message(WARNING "[CPMUtil] cpmfile ${CPMUTIL_JSON_FILE} does not exist, AddJsonPackage will be a no-op")
endif()
# utility
# Utility stuff
function(cpm_utils_message level name message)
message(${level} "[CPMUtil] ${name}: ${message}")
endfunction()
# utility
function(array_to_list array length out)
math(EXPR range "${length} - 1")
@ -53,7 +42,6 @@ function(array_to_list array length out)
set("${out}" "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# utility
function(get_json_element object out member default)
string(JSON out_type ERROR_VARIABLE err TYPE "${object}" ${member})
@ -73,14 +61,13 @@ function(get_json_element object out member default)
set("${out}" "${outvar}" PARENT_SCOPE)
endfunction()
# Kinda cancerous but whatever
# The preferred usage
function(AddJsonPackage)
set(oneValueArgs
NAME
# these are overrides that can be generated at runtime, so can be defined separately from the json
DOWNLOAD_ONLY
SYSTEM_PACKAGE
BUNDLED_PACKAGE
)
@ -90,6 +77,7 @@ function(AddJsonPackage)
"${ARGN}")
list(LENGTH ARGN argnLength)
# single name argument
if(argnLength EQUAL 1)
set(JSON_NAME "${ARGV0}")
@ -199,7 +187,6 @@ function(AddJsonPackage)
endif()
set(options ${options} ${JSON_OPTIONS})
# end options
# system/bundled
@ -241,7 +228,7 @@ endfunction()
function(AddPackage)
cpm_set_policies()
# TODO(crueter): docs, git clone
# TODO(crueter): git clone?
#[[
URL configurations, descending order of precedence:

View file

@ -57,13 +57,7 @@ If you would like to contribute, we are open to new developers and pull requests
## Building
* **Windows**: [Windows Building Guide](./docs/build/Windows.md)
* **Linux**: [Linux Building Guide](./docs/build/Linux.md)
* **Android**: [Android Building Guide](./docs/build/Android.md)
* **Solaris**: [Solaris Building Guide](./docs/build/Solaris.md)
* **FreeBSD**: [FreeBSD Building Guide](./docs/build/FreeBSD.md)
* **macOS**: [macOS Building Guide](./docs/build/macOS.md)
* **OpenBSD**: [OpenBSD Building Guide](./docs/build/OpenBSD.md)
See the [General Build Guide](docs/Build.md)
## Download

160
docs/Build.md Normal file
View file

@ -0,0 +1,160 @@
# Building Eden
> [!WARNING]
> This guide is intended for developers ONLY. If you are not a developer or packager, you are unlikely to receive support.
This is a full-fledged guide to build Eden on all supported platforms.
## Dependencies
First, you must [install some dependencies](Deps.md).
## Clone
Next, you will want to clone Eden via the terminal:
```sh
git clone https://git.eden-emu.dev/eden-emu/eden.git
cd eden
```
Or use Qt Creator (Create Project -> Import Project -> Git Clone).
## Android
Android has a completely different build process than other platforms. See its [dedicated page](build/Android.md).
## Initial Configuration
If the configure phase fails, see the `Troubleshooting` section below. Usually, as long as you followed the dependencies guide, the defaults *should* successfully configure and build.
### Qt Creator
This is the recommended GUI method for Linux, macOS, and Windows.
<details>
<summary>Click to Open</summary>
> [!WARNING]
> On MSYS2, to use Qt Creator you are recommended to *also* install Qt from the online installer, ensuring to select the "MinGW" version.
Open the CMakeLists.txt file in your cloned directory via File -> Open File or Project (Ctrl+O), if you didn't clone Eden via the project import tool.
Select your desired "kit" (usually, the default is okay). RelWithDebInfo or Release is recommended:
![Qt Creator kits](img/creator-1.png)
Hit "Configure Project", then wait for CMake to finish configuring (may take a while on Windows).
</details>
### Command Line
This is recommended for *BSD, Solaris, Linux, and MSYS2. MSVC is possible, but not recommended.
<details>
<summary>Click to Open</summary>
Note that CMake must be in your PATH, and you must be in the cloned Eden directory. On Windows, you must also set up a Visual C++ development environment. This can be done by running `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat` in the same terminal.
Recommended generators:
- MSYS2: `MSYS Makefiles`
- MSVC: Install **[ninja](https://ninja-build.org/)** and use `Ninja`, OR use `Visual Studio 17 2022`
- macOS: `Ninja` (preferred) or `Xcode`
- Others: `Ninja` (preferred) or `UNIX Makefiles`
BUILD_TYPE should usually be `Release` or `RelWithDebInfo` (debug symbols--compiled executable will be large). If you are using a debugger and annoyed with stuff getting optimized out, try `Debug`.
Also see the [Options](Options.md) page for additional CMake options.
```sh
cmake -S . -B build -G "GENERATOR" -DCMAKE_BUILD_TYPE=<BUILD_TYPE> -DYUZU_TESTS=OFF
```
If you are on Windows and prefer to use Clang:
```sh
cmake -S . -B build -G "GENERATOR" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
```
</details>
### [CLion](https://www.jetbrains.com/clion/)
<details>
<summary>Click to Open</summary>
* Clone the Repository:
<img src="https://user-images.githubusercontent.com/42481638/216899046-0d41d7d6-8e4d-4ed2-9587-b57088af5214.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899061-b2ea274a-e88c-40ae-bf0b-4450b46e9fea.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899076-0e5988c4-d431-4284-a5ff-9ecff973db76.png" width="500">
---
### Building & Setup
* Once Cloned, You will be taken to a prompt like the image below:
<img src="https://user-images.githubusercontent.com/42481638/216899092-3fe4cec6-a540-44e3-9e1e-3de9c2fffc2f.png" width="500">
* Set the settings to the image below:
* Change `Build type: Release`
* Change `Name: Release`
* Change `Toolchain Visual Studio`
* Change `Generator: Let CMake decide`
* Change `Build directory: build`
<img src="https://user-images.githubusercontent.com/42481638/216899164-6cee8482-3d59-428f-b1bc-e6dc793c9b20.png" width="500">
* Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient.
* Once this process has been completed (No loading bar bottom right), you can now build eden
* In the top right, click on the drop-down menu, select all configurations, then select eden
<img src="https://user-images.githubusercontent.com/42481638/216899226-975048e9-bc6d-4ec1-bc2d-bd8a1e15ed04.png" height="500" >
* Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built.
<img src="https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png" width="500">
</details>
## Troubleshooting
If your initial configure failed:
- *Carefully* re-read the [dependencies guide](Deps.md)
- Clear the CPM cache (`.cache/cpm`) and CMake cache (`<build directory>/CMakeCache.txt`)
- Evaluate the error and find any related settings
- See the [CPM docs](CPM.md) to see if you may need to forcefully bundle any packages
Otherwise, feel free to ask for help in Revolt or Discord.
## Caveats
Many platforms have quirks, bugs, and other fun stuff that may cause issues when building OR running. See the [Caveats page](Caveats.md) before continuing.
## Building & Running
### Qt Creator
Simply hit Ctrl+B, or the "hammer" icon in the bottom left. To run, hit the "play" icon, or Ctrl+R.
### Command Line
If you are not on Windows and are using the `UNIX Makefiles` generator, you must also add `-j$(nproc)` to this command.
```
cmake --build build
```
Your compiled executable will be in:
- `build/bin/eden.exe` for Windows,
- `build/bin/eden.app/Contents/MacOS/eden` for macOS,
- and `build/bin/eden` for others.
## Scripts
Some platforms have convenience scripts provided for building.
- **[Linux](scripts/Linux.md)**
- **[Windows](scripts/Windows.md)**
macOS scripts will come soon.

26
docs/CODEOWNERS Normal file
View file

@ -0,0 +1,26 @@
# ui stuff
/src/android @AleksandrPopovich @nyxynx @Producdevity
/src/yuzu @crueter
/src/eden @crueter
/src/frontend_common @crueter
/src/qt_common @crueter
# docs, meta
/docs @Lizzie @crueter
/.ci @crueter
# cmake
*.cmake @crueter
*/CMakeLists.txt @crueter
*.in @crueter
# individual stuff
/src/web_service @AleksandrPopovich
/src/dynarmic @Lizzie
/src/core @Lizzie @Maufeat @PavelBARABANOV @MrPurple666
/src/core/hle @Maufeat @PavelBARABANOV @SDK-Chan
/src/*_room @AleksandrPopovich
/src/video_core @CamilleLaVey @MaranBr @Wildcard @weakboson
# Global owners/triage
* @CamilleLaVey @Maufeat @crueter @MrPurple666 @MaranBr @Lizzie

View file

@ -177,7 +177,7 @@ If `ci` is `true`:
### Examples
In order: OpenSSL CI, Boost (tag + artifact), discord-rpc (sha + options + patches), Opus (options + find_args)
In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discord-rpc (sha + options + patches)
```json
{
@ -245,6 +245,6 @@ include(CPMUtil)
Currently, `cpm-fetch.sh` defines the following directories for cpmfiles (max depth of 2, so subdirs are caught as well):
`externals src/yuzu src/dynarmic .`
`externals src/qt_common src/dynarmic .`
Whenever you add a new cpmfile, update the script accordingly

52
docs/Caveats.md Normal file
View file

@ -0,0 +1,52 @@
# Caveats
## Arch Linux
- httplib AUR package is broken. Set `httplib_FORCE_BUNDLED=ON` if you have it installed.
- Eden is also available as an [AUR package](https://aur.archlinux.org/packages/eden-git). If you are unable to build, either use that or compare your process to the PKGBUILD.
## Gentoo Linux
Do not use the system sirit or xbyak packages.
## macOS
macOS is largely untested. Expect crashes, significant Vulkan issues, and other fun stuff.
## Solaris
Qt Widgets appears to be broken. For now, add `-DENABLE_QT=OFF` to your configure command. In the meantime, a Qt Quick frontend is in the works--check back later!
This is needed for some dependencies that call cc directly (tz):
```sh
echo '#!/bin/sh' >cc
echo 'gcc $@' >>cc
chmod +x cc
export PATH="$PATH:$PWD"
```
Default MESA is a bit outdated, the following environment variables should be set for a smoother experience:
```sh
export MESA_GL_VERSION_OVERRIDE=4.6
export MESA_GLSL_VERSION_OVERRIDE=460
export MESA_EXTENSION_MAX_YEAR=2025
export MESA_DEBUG=1
export MESA_VK_VERSION_OVERRIDE=1.3
# Only if nvidia/intel drm drivers cause crashes, will severely hinder performance
export LIBGL_ALWAYS_SOFTWARE=1
```
- Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`).
- If using OpenIndiana, due to a bug in SDL2's CMake configuration, audio driver defaults to SunOS `<sys/audioio.h>`, which does not exist on OpenIndiana. Using external or bundled SDL2 may solve this.
- System OpenSSL generally does not work. Instead, use `-DYUZU_USE_BUNDLED_OPENSSL=ON` to use a bundled static OpenSSL, or build a system dependency from source.
## OpenBSD
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
## FreeBSD
Eden is not currently available as a port on FreeBSD, though it is in the works. For now, the recommended method of usage is to compile it yourself.
The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_BUNDLED_OPENSSL=ON` to your CMake configure command.

214
docs/Deps.md Normal file
View file

@ -0,0 +1,214 @@
# Dependencies
To build Eden, you MUST have a C++ compiler.
* On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+
- GCC 12 also requires Clang 14+
* On Windows, this is either:
- **[MSVC](https://visualstudio.microsoft.com/downloads/)**,
* *A convenience script to install the **minimal** version (Visual Build Tools) is provided in `.ci/windows/install-msvc.ps1`*
- clang-cl - can be downloaded from the MSVC installer,
- or **[MSYS2](https://www.msys2.org)**
* On macOS, this is Apple Clang
- This can be installed with `xcode-select --install`
The following additional tools are also required:
* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK
* **[Git](https://git-scm.com/)** for version control
- **[Windows installer](https://gitforwindows.org)**
* On Windows, you must install the **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** as well
- *A convenience script to install the latest SDK is provided in `.ci/windows/install-vulkan-sdk.ps1`*
If you are on desktop and plan to use the Qt frontend, you *must* install Qt 6, and optionally Qt Creator (the recommended IDE for building)
* On Linux, *BSD and macOS, this can be done by the package manager
- If you wish to use Qt Creator, append `qtcreator` or `qt-creator` to the commands seen below.
* MSVC/clang-cl users on Windows must install through the [official installer](https://www.qt.io/download-qt-installer-oss)
* Linux and macOS users may choose to use the installer as well.
* MSYS2 can also install Qt 6 via the package manager
If you are on Windows and NOT building with MSYS2, you may go [back home](Build.md) and continue.
## Externals
The following are handled by Eden's externals:
* [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`)
* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL2=ON` OR `-DYUZU_USE_BUNDLED_SDL2=ON` to reduce compile time)
All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only):
* [Boost](https://www.boost.org/users/download/) 1.57.0+
* [Catch2](https://github.com/catchorg/Catch2) 3.0.1 if `YUZU_TESTS` or `DYNARMIC_TESTS` are on
* [fmt](https://fmt.dev/) 8.0.1+
* [lz4](http://www.lz4.org)
* [nlohmann\_json](https://github.com/nlohmann/json) 3.8+
* [OpenSSL](https://www.openssl.org/source/) 1.1.1+
* [ZLIB](https://www.zlib.net/) 1.2+
* [zstd](https://facebook.github.io/zstd/) 1.5+
* [enet](http://enet.bespin.org/) 1.3+
* [Opus](https://opus-codec.org/) 1.3+
* [MbedTLS](https://github.com/Mbed-TLS/mbedtls) 3+
Vulkan 1.3.274+ is also needed:
* [VulkanUtilityLibraries](https://github.com/KhronosGroup/Vulkan-Utility-Libraries)
* [VulkanHeaders](https://github.com/KhronosGroup/Vulkan-Headers)
* [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools)
* [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers)
Certain other dependencies will be fetched by CPM regardless. System packages *can* be used for these libraries, but many are either not packaged by most distributions OR have issues when used by the system:
* [SimpleIni](https://github.com/brofield/simpleini)
* [DiscordRPC](https://github.com/eden-emulator/discord-rpc)
* [cubeb](https://github.com/mozilla/cubeb)
* [libusb](https://github.com/libusb/libusb)
* [VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
* [sirit](https://github.com/eden-emulator/sirit)
* [httplib](https://github.com/yhirose/cpp-httplib) - if `ENABLE_QT_UPDATE_CHECKER` or `ENABLE_WEB_SERVICE` are on
* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on
* [unordered-dense](https://github.com/martinus/unordered_dense)
* [mcl](https://github.com/azahar-emu/mcl) - subject to removal
On amd64:
* [xbyak](https://github.com/herumi/xbyak) - 7.22 or earlier is recommended
* [zycore](https://github.com/zyantific/zycore-c)
* [zydis](https://github.com/zyantific/zydis) 4+
* Note: zydis and zycore-c MUST match. Using one as a system dependency and the other as a bundled dependency WILL break things
On aarch64 OR if `DYNARMIC_TESTS` is on:
* [oaknut](https://github.com/merryhime/oaknut) 2.0.1+
On riscv64:
* [biscuit](https://github.com/lioncash/biscuit) 0.9.1+
## Commands
These are commands to install all necessary dependencies on various Linux and BSD distributions, as well as macOS. Always review what you're running before you hit Enter!
Click on the arrows to expand.
<details>
<summary>Arch Linux</summary>
```sh
sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers
```
* Building with QT Web Engine requires `qt6-webengine` as well.
* Proper Wayland support requires `qt6-wayland`
* GCC 11 or later is required.
</details>
<details>
<summary>Ubuntu, Debian, Mint Linux</summary>
```sh
sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev
```
* Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
* To enable QT Web Engine, add `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake.
</details>
<details>
<summary>Fedora Linux</summary>
```sh
sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel
```
* Force system libraries via CMake arguments:
* SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF`
* FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF`
* [RPM Fusion](https://rpmfusion.org/) is required for `ffmpeg-devel`
* Fedora 32 or later is required.
* Fedora 36+ users with GCC 12 need Clang and should configure CMake with:
</details>
<details>
<summary>macOS</summary>
Install dependencies from **[Homebrew](https://brew.sh/)**
```sh
brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools
```
If you are compiling on Intel Mac, or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` with `/usr/local`.
To run with MoltenVK, install additional dependencies:
```sh
brew install molten-vk vulkan-loader
```
</details>
<details>
<summary>FreeBSD</summary>
```
devel/cmake
devel/sdl20
devel/boost-libs
devel/catch2
devel/libfmt
devel/nlohmann-json
devel/ninja
devel/nasm
devel/autoconf
devel/pkgconf
devel/qt6-base
net/enet
multimedia/ffnvcodec-headers
multimedia/ffmpeg
audio/opus
archivers/liblz4
lang/gcc12
graphics/glslang
graphics/vulkan-utility-libraries
```
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
</details>
<details>
<summary>OpenBSD</summary>
```sh
pkg_add -u
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1.1.0.27
```
</details>
<details>
<summary>Solaris / OpenIndiana</summary>
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
- **gcc**: `sudo pkg install developer/gcc-14`.
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
</details>
<details>
<summary>MSYS2</summary>
* Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`)
* Download and install all dependencies using:
* `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper`
* Add MinGW binaries to the PATH:
* `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc`
* Add VulkanSDK to the PATH:
* `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc`
</details>
## All Done
You may now return to the **[root build guide](Build.md)**.

View file

@ -1,23 +1,3 @@
# Development
* **Windows**: [Windows Building Guide](./build/Windows.md)
* **Linux**: [Linux Building Guide](./build/Linux.md)
* **Android**: [Android Building Guide](./build/Android.md)
* **Solaris**: [Solaris Building Guide](./build/Solaris.md)
* **FreeBSD**: [FreeBSD Building Guide](./build/FreeBSD.md)
* **macOS**: [macOS Building Guide](./build/macOS.md)
* **OpenBSD**: [OpenBSD Building Guide](./build/OpenBSD.md)
# CPM
CPM (CMake Package Manager) is the preferred method of managing dependencies within Eden. Documentation on adding dependencies/using CPMUtil is in the works.
Notes:
- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing
- `CPMUTIL_DEFAULT_SYSTEM` can be set to `OFF` to force the usage of bundled dependencies. This can marginally decrease the final package size.
- When adding new prebuilt dependencies a la OpenSSL, SDL2, or FFmpeg, there *must* be a CMake option made available to forcefully download this bundle. See the OpenSSL implementation in the root CMakeLists for an example.
* This is necessary to allow for creation of fully-qualified source packs that allow for offline builds after download (some package managers and distros enforce this)
# Guidelines
## License Headers
@ -37,6 +17,8 @@ FIX=true .ci/license-header.sh
git commit --amend -a --no-edit
```
If the work is licensed/vendored from other people or projects, you may omit the license headers. Additionally, if you wish to retain authorship over a piece of code, you may attribute it to yourself; however, the code may be changed at any given point and brought under the attribution of Eden.
## Pull Requests
Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed:
```
@ -49,7 +31,7 @@ Pull requests are only to be merged by core developers when properly tested and
- The level of namespacing is generally left to the committer's choice.
- However, we never recommend going more than two levels *except* in `hle`, in which case you may go as many as four levels depending on the specificity of your changes.
- Ocassionally, up to two namespaces may be provided for more clarity.
- Ocassionally, up to two additional namespaces may be provided for more clarity.
* Changes that affect the entire project (sans CMake changes) should be namespaced as `meta`.
- Maintainers are permitted to change namespaces at will.
- Commits within PRs are not required to be namespaced, but it is highly recommended.

69
docs/Options.md Normal file
View file

@ -0,0 +1,69 @@
# CMake Options
To change these options, add `-DOPTION_NAME=NEWVALUE` to the command line.
- On Qt Creator, go to Project -> Current Configuration
Notes:
- Defaults are marked per-platform.
- "Non-UNIX" just means Windows/MSVC and Android (yes, macOS is UNIX
- Android generally doesn't need to change anything; if you do, go to `src/android/app/build.gradle.kts`
- To set a boolean variable to on, use `ON` for the value; to turn it off, use `OFF`
- If a variable is mentioned as being e.g. "ON" for a specific platform(s), that means it is defaulted to OFF on others
- TYPE is always boolean unless otherwise specified
- Format:
* `OPTION_NAME` (TYPE DEFAULT) DESCRIPTION
## Options
- `YUZU_USE_CPM` (ON for non-UNIX) Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched. See the [CPM](CPM.md) and [Deps](Deps.md) docs for more info.
- `ENABLE_WEB_SERVICE` (ON) Enable multiplayer service
- `ENABLE_WIFI_SCAN` (OFF) Enable WiFi scanning (requires iw on Linux) - experimental
- `YUZU_USE_BUNDLED_FFMPEG` (ON for non-UNIX) Download (Windows, Android) or build (UNIX) bundled FFmpeg
- `ENABLE_CUBEB` (ON) Enables the cubeb audio backend
- `YUZU_TESTS` (ON) Compile tests - requires Catch2
- `YUZU_USE_PRECOMPILED_HEADERS` (ON for non-UNIX) Use precompiled headers
- `YUZU_DOWNLOAD_ANDROID_VVL` (ON) Download validation layer binary for Android
- `YUZU_ENABLE_LTO` (OFF) Enable link-time optimization
* Not recommended on Windows
* UNIX may be better off appending `-flto=thin` to compiler args
- `YUZU_DOWNLOAD_TIME_ZONE_DATA` (ON) Always download time zone binaries
* Currently, build fails without this
- `YUZU_USE_FASTER_LD` (ON) Check if a faster linker is available
* Only available on UNIX
- `USE_SYSTEM_MOLTENVK` (OFF, macOS only) Use the system MoltenVK lib (instead of the bundled one)
- `YUZU_TZDB_PATH` (string) Path to a pre-downloaded timezone database (useful for nixOS)
- `ENABLE_OPENSSL` (ON for Linux and *BSD) Enable OpenSSL backend for the ssl service
* Always enabled if the web service is enabled
- `YUZU_USE_BUNDLED_OPENSSL` (ON for MSVC) Download bundled OpenSSL build
* Always on for Android
* Unavailable on OpenBSD
The following options are desktop only:
- `ENABLE_SDL2` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!)
* Unavailable on Android
- `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source
- `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2
* Unavailable on OpenBSD
* Only enabled if YUZU_USE_CPM and ENABLE_SDL2 are both ON
- `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED)
- `ENABLE_OPENGL` (ON) Enable the OpenGL graphics frontend
* Unavailable on Windows/ARM64 and Android
- `ENABLE_QT` (ON) Enable the Qt frontend (recommended)
- `ENABLE_QT_TRANSLATION` (OFF) Enable translations for the Qt frontend
- `ENABLE_QT_UPDATE_CHECKER` (OFF) Enable update checker for the Qt frontend
- `YUZU_USE_BUNDLED_QT` (ON for MSVC) Download bundled Qt binaries
* Note that using **system Qt** requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`, e.g:
* `-DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6`
- `YUZU_QT_MIRROR` (string) What mirror to use for downloading the bundled Qt libraries
- `YUZU_USE_QT_MULTIMEDIA` (OFF) Use QtMultimedia for camera support
- `YUZU_USE_QT_WEB_ENGINE` (OFF) Use QtWebEngine for web applet implementation (requires the huge QtWebEngine dependency; not recommended)
- `USE_DISCORD_PRESENCE` (OFF) Enables Discord Rich Presence (Qt frontend only)
- `YUZU_ROOM` (ON) Enable dedicated room functionality
- `YUZU_ROOM_STANDALONE` (ON) Enable standalone room executable (eden-room)
* Requires `YUZU_ROOM`
- `YUZU_CMD` (ON) Compile the SDL2 frontend (eden-cli) - requires SDL2
- `YUZU_CRASH_DUMPS` Compile crash dump (Minidump) support"
* Currently only available on Windows and Linux
See `src/dynarmic/CMakeLists.txt` for additional options--usually, these don't need changed

10
docs/README.md Normal file
View file

@ -0,0 +1,10 @@
# Eden Build Documentation
This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](CPM.md), and more.
- **[General Build Instructions](Build.md)**
- **[Development Guidelines](Development.md)**
- **[Dependencies](Deps.md)**
- **[CPM - CMake Package Manager](CPM.md)**
- **[Platform-Specific Caveats](Caveats.md)**
- **[User Directory Handling](User.md)**

View file

@ -2,7 +2,7 @@
## Dependencies
* [Android Studio](https://developer.android.com/studio)
* [NDK 25.2.9519653 and CMake 3.22.1](https://developer.android.com/studio/projects/install-ndk#default-version)
* [NDK 27+ and CMake 3.22.1](https://developer.android.com/studio/projects/install-ndk#default-version)
* [Git](https://git-scm.com/download)
### WINDOWS ONLY - Additional Dependencies
@ -16,8 +16,7 @@ git clone --recursive https://git.eden-emu.dev/eden-emu/eden.git
```
Eden by default will be cloned into -
* `C:\Users\<user-name>\eden` on Windows
* `~/eden` on Linux
* And wherever on macOS
* `~/eden` on Linux and macOS
## Building
1. Start Android Studio, on the startup dialog select `Open`.
@ -32,7 +31,7 @@ Eden by default will be cloned into -
`export ANDROID_SDK_ROOT=path/to/sdk`
`export ANDROID_NDK_ROOT=path/to/ndk`.
4. Navigate to `eden/src/android`.
5. Then Build with `./gradlew assemblerelWithDebInfo`.
5. Then Build with `./gradlew assembleRelWithDebInfo`.
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
### Script

81
docs/build/FreeBSD.md vendored
View file

@ -1,81 +0,0 @@
Eden is not currently available as a port on FreeBSD, though it is in the works. For now, the recommended method of usage is to compile it yourself. Check back often, as the build process frequently changes.
## Dependencies.
Eden needs the following dependencies:
```
devel/cmake
devel/sdl20
devel/boost-libs
devel/catch2
devel/libfmt
devel/nlohmann-json
devel/ninja
devel/nasm
devel/autoconf
devel/pkgconf
devel/qt6-base
net/enet
multimedia/ffnvcodec-headers
multimedia/ffmpeg
audio/opus
archivers/liblz4
lang/gcc12
graphics/glslang
graphics/vulkan-utility-libraries
```
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
---
### Build preparations:
Run the following command to clone eden with git:
```sh
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
```
You usually want to add the `--recursive` parameter as it also takes care of the external dependencies for you.
Now change into the eden directory and create a build directory there:
```sh
cd eden
mkdir build
```
Change into that build directory:
```sh
cd build
```
#### 1. Building in Release Mode (usually preferred and the most performant choice):
```sh
cmake .. -GNinja -DYUZU_TESTS=OFF
```
#### 2. Building in Release Mode with debugging symbols (useful if you want to debug errors for a eventual fix):
```sh
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=ON
```
Build the emulator locally:
```sh
ninja
```
Optional: If you wish to install eden globally onto your system issue the following command:
```sh
sudo ninja install
```
OR
```sh
doas -- ninja install
```
## OpenSSL
The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_CPM=ON` to your CMake configure command.

138
docs/build/Linux.md vendored
View file

@ -1,138 +0,0 @@
### Dependencies
You'll need to download and install the following to build Eden:
* [GCC](https://gcc.gnu.org/) v11+ (for C++20 support) & misc
* If GCC 12 is installed, [Clang](https://clang.llvm.org/) v14+ is required for compiling
* [CMake](https://www.cmake.org/) 3.22+
The following are handled by Eden's externals:
* [FFmpeg](https://ffmpeg.org/)
* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+
* [opus](https://opus-codec.org/downloads/) 1.3+
All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available:
* [Boost](https://www.boost.org/users/download/) 1.79.0+
* [Catch2](https://github.com/catchorg/Catch2) 2.13.7 - 2.13.9
* [fmt](https://fmt.dev/) 8.0.1+
* [lz4](http://www.lz4.org) 1.8+
* [nlohmann_json](https://github.com/nlohmann/json) 3.8+
* [OpenSSL](https://www.openssl.org/source/) 1.1.1+
* [ZLIB](https://www.zlib.net/) 1.2+
* [zstd](https://facebook.github.io/zstd/) 1.5+
* [enet](http://enet.bespin.org/) 1.3+
* [cubeb](https://github.com/mozilla/cubeb)
* [SimpleIni](https://github.com/brofield/simpleini)
Certain other dependencies (httplib, jwt, sirit, etc.) will be fetched by CPM regardless. System packages *can* be used for these libraries but this is generally not recommended.
Dependencies are listed here as commands that can be copied/pasted. Of course, they should be inspected before being run.
- Arch / Manjaro:
- `sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip`
- Building with QT Web Engine requires `qt6-webengine` as well.
- Proper wayland support requires `qt6-wayland`
- GCC 11 or later is required.
- Ubuntu / Linux Mint / Debian:
- `sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev`
- Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
- Users need to manually specify building with QT Web Engine enabled. This is done using the parameter `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake.
- Users need to manually disable building SDL2 from externals if they intend to use the version provided by their system by adding the parameters `-DYUZU_USE_EXTERNAL_SDL2=OFF`
```sh
git submodule update --init --recursive
cmake .. -GNinja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
```
- Fedora:
- `sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel`
- Fedora 32 or later is required.
- Due to GCC 12, Fedora 36 or later users need to install `clang`, and configure CMake to use it via `-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang`
- CMake arguments to force system libraries:
- SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF`
- FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF`
- [RPM Fusion](https://rpmfusion.org/) (free) is required to install `ffmpeg-devel`
### Cloning Eden with Git
**Master:**
```bash
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
cd eden
```
The `--recursive` option automatically clones the required Git submodules.
### Building Eden in Release Mode (Optimised)
If you need to run ctests, you can disable `-DYUZU_TESTS=OFF` and install Catch2.
```bash
mkdir build && cd build
cmake .. -GNinja -DYUZU_TESTS=OFF
ninja
sudo ninja install
```
You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..`
`-DYUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS=OFF` might be needed if ninja command failed with `undefined reference to symbol 'spvOptimizerOptionsCreate`, reason currently unknown
Optionally, you can use `cmake-gui ..` to adjust various options (e.g. disable the Qt GUI).
### Building Eden in Debug Mode (Slow)
```bash
mkdir build && cd build
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DYUZU_TESTS=OFF
ninja
```
### Building with debug symbols
```bash
mkdir build && cd build
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU -DYUZU_TESTS=OFF
ninja
```
### Building with Scripts
A convenience script for building is provided in `.ci/linux/build.sh`. You must provide an arch target for optimization, e.g. `.ci/linux/build.sh amd64`. Valid targets:
- `legacy`: x86_64 generic, only needed for CPUs older than 2013 or so
- `amd64`: x86_64-v3, for CPUs newer than 2013 or so
- `steamdeck` / `zen2`: For Steam Deck or Zen >= 2 AMD CPUs (untested on Intel)
- `rog-ally` / `allyx` / `zen4`: For ROG Ally X or Zen >= 4 AMD CPUs (untested on Intel)
- `aarch64`: For armv8-a CPUs, older than mid-2021 or so
- `armv9`: For armv9-a CPUs, newer than mid-2021 or so
- `native`: Optimize to your native host architecture
Extra flags to pass to CMake should be passed after the arch target.
Additional environment variables can be used to control building:
- `NPROC`: Number of threads to use for compilation (defaults to all)
- `TARGET`: Set to `appimage` to disable standalone `eden-cli` and `eden-room` executables
- `BUILD_TYPE`: Sets the build type to use. Defaults to `Release`
The following environment variables are boolean flags. Set to `true` to enable or `false` to disable:
- `DEVEL` (default FALSE): Disable Qt update checker
- `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine
- `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia
After building, an AppImage can be packaged via `.ci/linux/package.sh`. This script takes the same arch targets as the build script. If the build was created in a different directory, you can specify its path relative to the source directory, e.g. `.ci/linux/package.sh amd64 build-appimage`. Additionally, set the `DEVEL` environment variable to `true` to change the app name to `Eden Nightly`.
### Running without installing
After building, the binaries `eden` and `eden-cmd` (depending on your build options) will end up in `build/bin/`.
```bash
# SDL
cd build/bin/
./eden-cmd
# Qt
cd build/bin/
./eden
```

10
docs/build/OpenBSD.md vendored
View file

@ -1,10 +0,0 @@
# Building for OpenBSD
```sh
pkg_add -u
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq
git --recursive https://git.eden-emu.dev/eden-emu/eden
cmake -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DDYNARMIC_USE_PRECOMPILED_HEADERS=OFF -DCMAKE_BUILD_TYPE=Debug -DENABLE_QT=OFF -DENABLE_OPENSSL=OFF -DENABLE_WEB_SERVICE=OFF -B /usr/obj/eden
```
- Modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.

51
docs/build/Solaris.md vendored
View file

@ -1,51 +0,0 @@
# Building for Solaris
## Dependencies.
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
- **gcc**: `sudo pkg install developer/gcc-14`.
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
Then install the libraies: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
### Building
Clone eden with git `git clone --recursive https://git.eden-emu.dev/eden-emu/eden`
```sh
# Needed for some dependencies that call cc directly (tz)
echo '#!/bin/sh' >cc
echo 'gcc $@' >>cc
chmod +x cc
export PATH="$PATH:$PWD"
```
Patch for FFmpeg:
```sh
sed -i 's/ make / gmake /' externals/ffmpeg/CMakeFiles/ffmpeg-build.dir/build.make
```
- **Configure**: `cmake -B build -DYUZU_USE_CPM=ON -DCMAKE_CXX_FLAGS="-I/usr/include/SDL2" -DCMAKE_C_FLAGS="-I/usr/include/SDL2"`.
- **Build**: `cmake --build build`.
- **Installing**: `sudo cmake --install build`.
### Running
Default Mesa is a bit outdated, the following environment variables should be set for a smoother experience:
```sh
export MESA_GL_VERSION_OVERRIDE=4.6
export MESA_GLSL_VERSION_OVERRIDE=460
export MESA_EXTENSION_MAX_YEAR=2025
export MESA_DEBUG=1
export MESA_VK_VERSION_OVERRIDE=1.3
# Only if nvidia/intel drm drivers cause crashes, will severely hinder performance
export LIBGL_ALWAYS_SOFTWARE=1
```
### Notes
- Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`).
- If using OpenIndiana, due to a bug in SDL2 cmake configuration; Audio driver defaults to SunOS `<sys/audioio.h>`, which does not exist on OpenIndiana.
- System OpenSSL generally does not work. Instead, use `-DYUZU_USE_CPM=ON` to use a bundled static OpenSSL, or build a system dependency from source.

259
docs/build/Windows.md vendored
View file

@ -1,259 +0,0 @@
# ⚠️ This guide is for developers ONLY! Support will be provided to developers ONLY.
## 📋 Current building methods:
* [ Minimal Dependencies](#minimal-dependencies)
* [⚡ Method I: MSVC Build for Windows](#method-i-msvc-build-for-windows)
* [🐧 Method II: MinGW-w64 Build with MSYS2](#method-ii-mingw-w64-build-with-msys2)
* [🖥️ Method III: CLion Environment Setup](#method-iii-clion-environment-setup)
* [💻 Building from the command line with MSVC](#building-from-the-command-line-with-msvc)
* [📜 Building with Scripts](#building-with-scripts)
---
## Minimal Dependencies
On Windows, **all** library dependencies are **automatically included** within the `externals` folder.
You still need to install:
* **[CMake](https://cmake.org/download/)** - Used to generate Visual Studio project files.
* **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - Make sure to select **Latest SDK**.
* *A convenience script to install the latest SDK is provided in `.ci/windows/install-vulkan-sdk.ps1`*
* **[Git for Windows](https://gitforwindows.org)** - We recommend installing Git for command line use and version control integration.
<img src="https://i.imgur.com/x0rRs1t.png" width="500">
* *While installing Git Bash, select "Git from the command line and also from 3rd-party software". If missed, manually set `git.exe` path in CMake.*
---
## ⚡ Method I: MSVC Build for Windows
### a. Prerequisites to MSVC Build
* **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - Make sure to **select C++ support** in the installer, or **update to the latest version** if already installed.
* *A convenience script to install the **minimal** version (Visual Build Tools) is provided in `.ci/windows/install-msvc.ps1`*
---
### b. Clone the eden repository with Git
Open Terminal on
```cmd
git clone https://git.eden-emu.dev/eden-emu/eden
cd eden
```
* *By default `eden` downloads to `C:\Users\<user-name>\eden`*
---
### c. Building
* Open the CMake GUI application and point it to the `eden`
<img src="https://i.imgur.com/qOslIWv.png" width="500">
* For the build directory, use a `build/` subdirectory inside the source directory or some other directory of your choice. (Tell CMake to create it.)
* Click the "Configure" button and choose `Visual Studio 17 2022`, with `x64` for the optional platform.
<img src="https://i.imgur.com/DKiREaK.png" width="500">
* *(You may also want to disable `YUZU_TESTS` in this case since Catch2 is not yet supported with this.)*
<img src="https://user-images.githubusercontent.com/22451773/180585999-07316d6e-9751-4d11-b957-1cf57cd7cd58.png" width="500">
* Click "Generate" to create the project files.
<img src="https://i.imgur.com/5LKg92k.png" width="500">
* Open the solution file `yuzu.sln` in Visual Studio 2022, which is located in the build folder.
<img src="https://i.imgur.com/208yMml.png" width="500">
* * Depending on whether you want a graphical user interface or not, select in the Solution Explorer:
* `eden` (GUI)
* `eden-cmd` (command-line only)
* Then **right-click** and choose `Set as StartUp Project`.
<img src="https://i.imgur.com/nPMajnn.png" height="500">
<img src="https://i.imgur.com/BDMLzRZ.png" height="500">
* Select the appropriate build type, `Debug` for debug purposes or `Release` for performance (in case of doubt choose `Release`).
<img src="https://i.imgur.com/qxg4roC.png" width="500">
* **Right-click** the project you want to build and press **Build** in the submenu or press `F5`.
<img src="https://i.imgur.com/CkQgOFW.png" height="500">
---
## 🐧 Method II: MinGW-w64 Build with MSYS2
### a. Prerequisites to MinGW-w64
* **[MSYS2](https://www.msys2.org)** - A versatile and up-to-date development environment for Windows, providing a Unix-like shell, package manager, and toolchain.
---
### b. Install eden dependencies for MinGW-w64
* Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`)
* Download and install all dependencies using:
* `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper`
* Add MinGW binaries to the PATH:
* `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc`
* Add VulkanSDK to the PATH:
* `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc`
---
### c. Clone the eden repository with Git
```cmd
git clone https://git.eden-emu.dev/eden-emu/eden
cd eden
```
---
### d. Building dynamically-linked eden
* This process will generate a *dynamically* linked build
```bash
# Make build dir and enter
mkdir build && cd build
# Generate CMake Makefiles
cmake .. -G "MSYS Makefiles" -DYUZU_TESTS=OFF
# Build
make -j$(nproc)
# Run eden!
./bin/eden.exe
```
* *Warning: This build is not a **static** build meaning that you **need** to include all of the DLLs with the .exe in order to use it or other systems!*
---
### Additional notes
* Eden doesn't require the rather large Qt dependency, but you will lack a GUI frontend
```bash
# ...
# Generate CMake Makefiles (withou QT)
cmake .. -G "MSYS Makefiles" -DYUZU_TESTS=OFF -DENABLE_QT=no
$ ...
```
* Running programs from inside `MSYS2 MinGW x64` shell has a different `%PATH%` than directly from explorer.
* This different `%PATH%` has the locations of the other DLLs required.
<img src="https://user-images.githubusercontent.com/190571/165000848-005e8428-8a82-41b1-bb4d-4ce7797cdac8.png" width="500">
---
## 🖥️ Method III: CLion Environment Setup
### a. Prerequisites to CLion
* [CLion](https://www.jetbrains.com/clion/) - This IDE is not free; for a free alternative, check Method I
---
### b. Cloning eden with CLion
* Clone the Repository:
<img src="https://user-images.githubusercontent.com/42481638/216899046-0d41d7d6-8e4d-4ed2-9587-b57088af5214.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899061-b2ea274a-e88c-40ae-bf0b-4450b46e9fea.png" width="500">
<img src="https://user-images.githubusercontent.com/42481638/216899076-0e5988c4-d431-4284-a5ff-9ecff973db76.png" width="500">
---
### c. Building & Setup
* Once Cloned, You will be taken to a prompt like the image below:
<img src="https://user-images.githubusercontent.com/42481638/216899092-3fe4cec6-a540-44e3-9e1e-3de9c2fffc2f.png" width="500">
* Set the settings to the image below:
* Change `Build type: Release`
* Change `Name: Release`
* Change `Toolchain Visual Studio`
* Change `Generator: Let CMake decide`
* Change `Build directory: build`
<img src="https://user-images.githubusercontent.com/42481638/216899164-6cee8482-3d59-428f-b1bc-e6dc793c9b20.png" width="500">
* Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient.
* Once this process has been completed (No loading bar bottom right), you can now build eden
* In the top right, click on the drop-down menu, select all configurations, then select eden
<img src="https://user-images.githubusercontent.com/42481638/216899226-975048e9-bc6d-4ec1-bc2d-bd8a1e15ed04.png" height="500" >
* Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built.
<img src="https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png" width="500">
---
## 💻 Building from the command line with MSVC
```cmd
# Clone eden and enter
git clone https://git.eden-emu.dev/eden-emu/eden
cd eden
# Make build dir and enter
mkdir build && cd build
# Generate CMake Makefiles
cmake .. -G "Visual Studio 17 2022" -A x64 -DYUZU_TESTS=OFF
# Build
cmake --build . --config Release
```
## 📜 Building with Scripts
* A convenience script for building is provided in `.ci/windows/build.sh`.
* You must run this with Bash, e.g. Git Bash or MinGW TTY.
* To use this script, you must have `windeployqt` installed (usually bundled with Qt) and set the `WINDEPLOYQT` environment variable to its canonical Bash location:
* `WINDEPLOYQT="/c/Qt/6.9.1/msvc2022_64/bin/windeployqt6.exe" .ci/windows/build.sh`.
* You can use `aqtinstall`, more info on <https://github.com/miurahr/aqtinstall> and <https://ddalcino.github.io/aqt-list-server/>
* Extra CMake flags should be placed in the arguments of the script.
#### Additional environment variables can be used to control building:
* `BUILD_TYPE` (default `Release`): Sets the build type to use.
* The following environment variables are boolean flags. Set to `true` to enable or `false` to disable:
* `DEVEL` (default FALSE): Disable Qt update checker
* `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine
* `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia
* `BUNDLE_QT` (default FALSE): Use bundled Qt
* Note that using **system Qt** requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`
* `.ci/windows/build.sh -DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6`
* After building, a zip can be packaged via `.ci/windows/package.sh`. You must have 7-zip installed and in your PATH.
* The resulting zip will be placed into `artifacts` in the source directory.

78
docs/build/macOS.md vendored
View file

@ -1,78 +0,0 @@
Please note this article is intended for development, and Eden on macOS is not currently ready for regular use.
This article was written for developers. Eden support for macOS is not ready for casual use.
## Dependencies
Install dependencies from Homebrew:
```sh
brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools
```
If you are compiling on Intel Mac, or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` with `/usr/local`.
Now, clone the repo:
```sh
git clone --recursive https://git.eden-emu.dev/eden-emu/eden
cd eden
```
## Method I: ninja
---
Build for release
```sh
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
cmake -B build -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON
ninja
```
You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON`
```sh
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
cmake -B build -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
ninja
```
Run the output:
```
bin/eden.app/Contents/MacOS/eden
```
## Method II: Xcode
---
Build for release
```sh
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
# Only if having errors about Xcode 15.0
sudo /usr/bin/xcode-select --switch /Users/admin/Downloads/Xcode.ap
cmake -B build -GXcode -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON
xcodebuild build -project yuzu.xcodeproj -scheme "yuzu" -configuration "RelWithDebInfo"
```
Build with debug symbols:
```sh
export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake"
cmake -B build -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
ninja
```
Run the output:
```
bin/eden.app/Contents/MacOS/eden
```
---
To run with MoltenVK, install additional dependencies:
```sh
brew install molten-vk vulkan-loader
```
Run with Vulkan loader path:
```sh
export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib
bin/eden.app/Contents/MacOS/eden
```

BIN
docs/img/creator-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

31
docs/scripts/Linux.md Normal file
View file

@ -0,0 +1,31 @@
# Linux Build Scripts
* Provided script: `.ci/linux/build.sh`
* Must specify arch target, e.g.: `.ci/linux/build.sh amd64`
* Valid targets:
* `native`: Optimize to your native host architecture
* `legacy`: x86\_64 generic, only needed for CPUs older than 2013 or so
* `amd64`: x86\_64-v3, for CPUs newer than 2013 or so
* `steamdeck` / `zen2`: For Steam Deck or Zen >= 2 AMD CPUs (untested on Intel)
* `rog-ally` / `allyx` / `zen4`: For ROG Ally X or Zen >= 4 AMD CPUs (untested on Intel)
* `aarch64`: For armv8-a CPUs, older than mid-2021 or so
* `armv9`: For armv9-a CPUs, newer than mid-2021 or so
* Extra CMake flags go after the arch target.
### Environment Variables
* `NPROC`: Number of compilation threads (default: all cores)
* `TARGET`: Set `appimage` to disable standalone `eden-cli` and `eden-room`
* `BUILD_TYPE`: Build type (default: `Release`)
Boolean flags (set `true` to enable, `false` to disable):
* `DEVEL` (default `FALSE`): Disable Qt update checker
* `USE_WEBENGINE` (default `FALSE`): Enable Qt WebEngine
* `USE_MULTIMEDIA` (default `FALSE`): Enable Qt Multimedia
* AppImage packaging script: `.ci/linux/package.sh`
* Accepts same arch targets as build script
* Use `DEVEL=true` to rename app to `Eden Nightly`
* This should generally not be used unless in a tailor-made packaging environment (e.g. Actions/CI)

29
docs/scripts/Windows.md Normal file
View file

@ -0,0 +1,29 @@
# Windows Build Scripts
* A convenience script for building is provided in `.ci/windows/build.sh`.
* You must run this with Bash, e.g. Git Bash or the MinGW TTY.
* To use this script, you must have `windeployqt` installed (usually bundled with Qt) and set the `WINDEPLOYQT` environment variable to its canonical Bash location:
* `WINDEPLOYQT="/c/Qt/6.9.1/msvc2022_64/bin/windeployqt6.exe" .ci/windows/build.sh`.
* You can use `aqtinstall`, more info on <https://github.com/miurahr/aqtinstall> and <https://ddalcino.github.io/aqt-list-server/>
* Extra CMake flags should be placed in the arguments of the script.
#### Additional environment variables can be used to control building:
* `BUILD_TYPE` (default `Release`): Sets the build type to use.
* The following environment variables are boolean flags. Set to `true` to enable or `false` to disable:
* `DEVEL` (default FALSE): Disable Qt update checker
* `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine
* `USE_MULTIMEDIA` (default FALSE): Enable Qt Multimedia
* `BUNDLE_QT` (default FALSE): Use bundled Qt
* Note that using **system Qt** requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`
* `.ci/windows/build.sh -DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6`
* After building, a zip can be packaged via `.ci/windows/package.sh`. You must have 7-zip installed and in your PATH.
* The resulting zip will be placed into `artifacts` in the source directory.

View file

@ -1,15 +1,19 @@
# SPDX-FileCopyrightText: 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2020 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
include(CPMUtil)
if (PLATFORM_SUN OR PLATFORM_OPENBSD OR PLATFORM_FREEBSD)
# we love our libraries don't we folks
if (PLATFORM_SUN)
set(libusb_bundled ON)
else()
set(libusb_bundled OFF)
endif()
# TODO(crueter): Fix on *BSD/Solaris
# TODO(crueter): Fix on Solaris
AddJsonPackage(
NAME libusb
BUNDLED_PACKAGE ${libusb_bundled}
@ -19,6 +23,7 @@ if (NOT libusb_ADDED)
return()
endif()
# TODO: *BSD fails to compile--may need different configs/symbols
if (MINGW OR PLATFORM_LINUX OR APPLE)
set(LIBUSB_FOUND ON CACHE BOOL "libusb is present" FORCE)
set(LIBUSB_VERSION "1.0.24" CACHE STRING "libusb version string" FORCE)

View file

@ -234,6 +234,8 @@ if (YUZU_ROOM_STANDALONE)
endif()
if (ENABLE_QT)
add_definitions(-DYUZU_QT_WIDGETS)
add_subdirectory(qt_common)
add_subdirectory(yuzu)
endif()

View file

@ -272,8 +272,6 @@ class GameAdapter(private val activity: AppCompatActivity) :
binding.root.findNavController().navigate(action)
}
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
if (NativeLibrary.gameRequiresFirmware(game.programId) && !NativeLibrary.isFirmwareAvailable()) {
MaterialAlertDialogBuilder(activity)
.setTitle(R.string.loader_requires_firmware)
@ -288,23 +286,6 @@ class GameAdapter(private val activity: AppCompatActivity) :
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} else if (BooleanSetting.DISABLE_NCA_VERIFICATION.getBoolean(false) && !preferences.getBoolean(
Settings.PREF_HIDE_NCA_POPUP, false)) {
MaterialAlertDialogBuilder(activity)
.setTitle(R.string.nca_verification_disabled)
.setMessage(activity.getString(R.string.nca_verification_disabled_description))
.setPositiveButton(android.R.string.ok) { _, _ ->
launch()
}
.setNeutralButton(R.string.dont_show_again) { _, _ ->
preferences.edit {
putBoolean(Settings.PREF_HIDE_NCA_POPUP, true)
}
launch()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} else {
launch()
}

View file

@ -35,7 +35,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_SAMPLE_SHADING("sample_shading"),
PICTURE_IN_PICTURE("picture_in_picture"),
USE_CUSTOM_RTC("custom_rtc_enabled"),
DISABLE_NCA_VERIFICATION("disable_nca_verification"),
BLACK_BACKGROUNDS("black_backgrounds"),
JOYSTICK_REL_CENTER("joystick_rel_center"),
DPAD_SLIDE("dpad_slide"),

View file

@ -37,7 +37,6 @@ object Settings {
const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning"
const val PREF_SHOULD_SHOW_EDENS_VEIL_DIALOG = "ShouldShowEdensVeilDialog"
const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
const val PREF_HIDE_NCA_POPUP = "HideNCAVerificationPopup"
const val SECTION_STATS_OVERLAY = "Stats Overlay"
// Deprecated input overlay preference keys

View file

@ -297,13 +297,6 @@ abstract class SettingsItem(
descriptionId = R.string.use_custom_rtc_description
)
)
put(
SwitchSetting(
BooleanSetting.DISABLE_NCA_VERIFICATION,
titleId = R.string.disable_nca_verification,
descriptionId = R.string.disable_nca_verification_description
)
)
put(
StringInputSetting(
StringSetting.WEB_TOKEN,

View file

@ -210,7 +210,6 @@ class SettingsFragmentPresenter(
add(IntSetting.LANGUAGE_INDEX.key)
add(BooleanSetting.USE_CUSTOM_RTC.key)
add(LongSetting.CUSTOM_RTC.key)
add(BooleanSetting.DISABLE_NCA_VERIFICATION.key)
add(HeaderSetting(R.string.network))
add(StringSetting.WEB_TOKEN.key)

View file

@ -119,8 +119,8 @@
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقت أثناء تحديثات الذاكرة، مما يقلل استخدام المعالج ويحسن أدائه. قد يسبب هذا أعطالاً أو تعطلًا في بعض الألعاب.</string>
<string name="cpuopt_unsafe_host_mmu">تمكين محاكاة MMU المضيف</string>
<string name="cpuopt_unsafe_host_mmu_description">يعمل هذا التحسين على تسريع وصول الذاكرة بواسطة البرنامج الضيف. يؤدي تمكينه إلى إجراء عمليات قراءة/كتابة ذاكرة الضيف مباشرة في الذاكرة والاستفادة من MMU المضيف. يؤدي تعطيل هذا إلى إجبار جميع عمليات الوصول إلى الذاكرة على استخدام محاكاة MMU البرمجية.</string>
<string name="dma_accuracy">مستوى DMA</string>
<string name="dma_accuracy_description">يتحكم في دقة تحديد مستوى DMA. الدقة الأعلى يمكنها إصلاح بعض المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اتركه على الوضع الافتراضي.</string>
<string name="dma_accuracy">دقة DMA</string>
<string name="dma_accuracy_description">يتحكم في دقة تحديد DMA. يمكن أن تصلح الدقة الآمنة المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اترك هذا على الوضع الافتراضي.</string>
<!-- Memory Layouts -->
<string name="memory_4gb">4 جيجابايت (موصى به)</string>
@ -498,8 +498,6 @@
<string name="use_custom_rtc">ساعة مخصصة في الوقت الحقيقي</string>
<string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة في الوقت الفعلي منفصلة عن وقت النظام الحالي لديك</string>
<string name="set_custom_rtc">تعيين ساعة مخصصة في الوقت الحقيقي</string>
<string name="disable_nca_verification">تعطيل التحقق من NCA</string>
<string name="disable_nca_verification_description">يعطل التحقق من سلامة أرشيفات محتوى NCA. قد يحسن هذا من سرعة التحميل لكنه يخاطر بتلف البيانات أو تمرير ملفات غير صالحة دون اكتشاف. ضروري لجعل الألعاب والتحديثات التي تتطلب نظامًا أساسيًا 20+ تعمل.</string>
<!-- Network settings strings -->
<string name="generate">توليد</string>
@ -794,9 +792,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">افتراضي</string>
<string name="dma_accuracy_normal">عادي</string>
<string name="dma_accuracy_high">عالي</string>
<string name="dma_accuracy_extreme">مفرط</string>
<string name="dma_accuracy_unsafe">غير آمن (سريع)</string>
<string name="dma_accuracy_safe">آمن (مستقر)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">هەندێک لە بازنەکردنەکانی هەڵگر لە کاتی نوێکردنەوەی بیرگە دەنێرێت، کەمکردنەوەی بەکارهێنانی CPU و باشترکردنی کارایی. لەوانەیە لە هەندێک یاری کێشە درووست بکات.</string>
<string name="cpuopt_unsafe_host_mmu">چالاککردنی میمیکردنی MMU میواندە</string>
<string name="cpuopt_unsafe_host_mmu_description">ئەم باشکردنە خێرایی دەستکەوتنی بیرگە لەلایەن پرۆگرامی میوانەکە زیاد دەکات. چالاککردنی وای لێدەکات کە خوێندنەوە/نووسینەکانی بیرگەی میوانەکە ڕاستەوخۆ لە بیرگە ئەنجام بدرێت و میمیکردنی MMU میواندە بەکاربهێنێت. ناچالاککردنی ئەمە هەموو دەستکەوتنەکانی بیرگە ڕەت دەکاتەوە لە بەکارهێنانی میمیکردنی MMU نەرمەکاڵا.</string>
<string name="dma_accuracy">ئاستی DMA</string>
<string name="dma_accuracy_description">کۆنتڕۆڵی وردی ڕێکخستنی DMA دەکات. وردی زیاتر دەتوانێ هەندێک کێشە لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، بە ڕێکخستنی بنەڕەتی بێڵە.</string>
<string name="dma_accuracy">وردیی DMA</string>
<string name="dma_accuracy_description">کۆنتڕۆڵی وردیی وردیی DMA دەکات. وردییی پارێزراو دەتوانێت کێشەکان لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، ئەمە بە سەر ڕەھەوادا بهێڵە.</string>
<string name="memory_4gb">4GB (پێشنیارکراو)</string>
<string name="memory_6gb">6GB (نائاسایش)</string>
@ -482,8 +482,6 @@
<string name="use_custom_rtc">RTCی تایبەتمەند</string>
<string name="use_custom_rtc_description">ڕێگەت پێدەدات کاتژمێرێکی کاتی ڕاستەقینەی تایبەتمەند دابنێیت کە جیاوازە لە کاتی ئێستای سیستەمەکەت.</string>
<string name="set_custom_rtc">دانانی RTCی تایبەتمەند</string>
<string name="disable_nca_verification">ناچالاککردنی پشکنینی NCA</string>
<string name="disable_nca_verification_description">پشکنینی پێکهاتەی ئارشیڤەکانی ناوەڕۆکی NCA ناچالاک دەکات. ئەمە لەوانەیە خێرایی بارکردن به‌ره‌وپێش ببات، بەڵام مەترسی لەناوچوونی داتا یان ئەوەی فایلە نادروستەکان بەبێ ئەوەی دۆزرایەوە تێپەڕبن زیاتر دەکات. بۆ ئەوەی یاری و نوێکردنەوەکان کار بکەن کە پێویستی بە فریموێری 20+ هەیە زۆر پێویستە.</string>
<!-- Network settings strings -->
<string name="generate">بەرهەم هێنان</string>
@ -763,9 +761,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">بنەڕەتی</string>
<string name="dma_accuracy_normal">ئاسایی</string>
<string name="dma_accuracy_high">بەرز</string>
<string name="dma_accuracy_extreme">زۆر بەرز</string>
<string name="dma_accuracy_unsafe">نەپارێزراو (خێرا)</string>
<string name="dma_accuracy_safe">پارێزراو (جێگیر)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -127,8 +127,8 @@
<string name="skip_cpu_inner_invalidation_description">Přeskočí některé invalidace mezipaměti na straně CPU během aktualizací paměti, čímž sníží zatížení CPU a zlepší jeho výkon. Může způsobit chyby nebo pády v některých hrách.</string>
<string name="cpuopt_unsafe_host_mmu">Povolit emulaci hostitelské MMU</string>
<string name="cpuopt_unsafe_host_mmu_description">Tato optimalizace zrychluje přístup do paměti hostovaného programu. Její povolení způsobí, že čtení a zápisy do paměti hosta se provádějí přímo v paměti a využívají hostitelskou MMU. Zakázání této funkce vynutí použití softwarové emulace MMU pro všechny přístupy do paměti.</string>
<string name="dma_accuracy">Úroveň DMA</string>
<string name="dma_accuracy_description">Ovládá přesnost DMA. Vyšší přesnost může opravit problémy v některých hrách, ale může také ovlivnit výkon. Pokud si nejste jisti, ponechejte výchozí nastavení.</string>
<string name="dma_accuracy">Přesnost DMA</string>
<string name="dma_accuracy_description">Ovládá přesnost DMA. Bezpečná přesnost může opravit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, ponechte to na výchozím nastavení.</string>
<string name="memory_4gb">4GB (Doporučeno)</string>
<string name="memory_6gb">6GB (Nebezpečné)</string>
@ -458,8 +458,6 @@
<string name="use_custom_rtc">Vlastní RTC</string>
<string name="use_custom_rtc_description">Vlastní nastavení času</string>
<string name="set_custom_rtc">Nastavit vlastní RTC</string>
<string name="disable_nca_verification">Zakázat ověřování NCA</string>
<string name="disable_nca_verification_description">Zakáže ověřování integrity archivů obsahu NCA. To může zlepšit rychlost načítání, ale hrozí poškození dat nebo neodhalení neplatných souborů. Je nutné, aby fungovaly hry a aktualizace vyžadující firmware 20+.</string>
<!-- Network settings strings -->
<string name="generate">Generovat</string>
@ -737,9 +735,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Výchozí</string>
<string name="dma_accuracy_normal">Normální</string>
<string name="dma_accuracy_high">Vysoká</string>
<string name="dma_accuracy_extreme">Extrémní</string>
<string name="dma_accuracy_unsafe">Nebezpečné (rychlé)</string>
<string name="dma_accuracy_safe">Bezpečné (stabilní)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen.</string>
<string name="cpuopt_unsafe_host_mmu">Host-MMU-Emulation aktivieren</string>
<string name="cpuopt_unsafe_host_mmu_description">Diese Optimierung beschleunigt Speicherzugriffe durch das Gastprogramm. Wenn aktiviert, erfolgen Speicherlese- und -schreibvorgänge des Gastes direkt im Speicher und nutzen die MMU des Hosts. Das Deaktivieren erzwingt die Verwendung der Software-MMU-Emulation für alle Speicherzugriffe.</string>
<string name="dma_accuracy">DMA-Level</string>
<string name="dma_accuracy_description">Steuert die DMA-Präzisionsgenauigkeit. Eine höhere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel auf „Standard“ belassen.</string>
<string name="dma_accuracy">DMA-Genauigkeit</string>
<string name="dma_accuracy_description">Steuert die DMA-Präzisionsgenauigkeit. Sichere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel lassen Sie dies auf Standard stehen.</string>
<string name="memory_4gb">4 GB (Empfohlen)</string>
<string name="memory_6gb">6 GB (Unsicher)</string>
@ -486,8 +486,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="select_rtc_date">RTC-Datum auswählen</string>
<string name="select_rtc_time">RTC-Zeit auswählen</string>
<string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string>
<string name="disable_nca_verification">NCA-Verifizierung deaktivieren</string>
<string name="disable_nca_verification_description">Deaktiviert die Integritätsprüfung von NCA-Inhaltsarchiven. Dies kann die Ladegeschwindigkeit verbessern, riskiert jedoch Datenbeschädigung oder dass ungültige Dateien unentdeckt bleiben. Ist notwendig, um Spiele und Updates, die Firmware 20+ benötigen, zum Laufen zu bringen.</string>
<!-- Network settings strings -->
<string name="generate">Generieren</string>
@ -829,9 +827,8 @@ Wirklich fortfahren?</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Standard</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Hoch</string>
<string name="dma_accuracy_extreme">Extrem</string>
<string name="dma_accuracy_unsafe">Unsicher (schnell)</string>
<string name="dma_accuracy_safe">Sicher (stabil)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché durante actualizaciones de memoria, reduciendo el uso de CPU y mejorando su rendimiento. Puede causar fallos en algunos juegos.</string>
<string name="cpuopt_unsafe_host_mmu">Habilitar emulación de MMU del host</string>
<string name="cpuopt_unsafe_host_mmu_description">Esta optimización acelera los accesos a la memoria por parte del programa invitado. Al habilitarla, las lecturas/escrituras de memoria del invitado se realizan directamente en la memoria y utilizan la MMU del host. Deshabilitar esto obliga a que todos los accesos a la memoria utilicen la emulación de MMU por software.</string>
<string name="dma_accuracy">Nivel de DMA</string>
<string name="dma_accuracy_description">Controla la precisión del DMA. Una mayor precisión puede solucionar problemas en algunos juegos, pero también puede afectar el rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado.</string>
<string name="dma_accuracy">Precisión de DMA</string>
<string name="dma_accuracy_description">Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado.</string>
<string name="memory_4gb">4GB (Recomendado)</string>
<string name="memory_6gb">6GB (Inseguro)</string>
@ -506,8 +506,6 @@
<string name="use_custom_rtc">RTC personalizado</string>
<string name="use_custom_rtc_description">Te permite tener un reloj personalizado en tiempo real diferente del tiempo del propio sistema.</string>
<string name="set_custom_rtc">Configurar RTC personalizado</string>
<string name="disable_nca_verification">Desactivar verificación NCA</string>
<string name="disable_nca_verification_description">Desactiva la verificación de integridad de los archivos de contenido NCA. Esto puede mejorar la velocidad de carga, pero arriesga corrupción de datos o que archivos inválidos pasen desapercibidos. Es necesario para que funcionen juegos y actualizaciones que requieren firmware 20+.</string>
<!-- Network settings strings -->
<string name="generate">Generar</string>
@ -872,9 +870,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Predeterminado</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Alto</string>
<string name="dma_accuracy_extreme">Extremo</string>
<string name="dma_accuracy_unsafe">Inseguro (rápido)</string>
<string name="dma_accuracy_safe">Seguro (estable)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">بعضی ابطال‌های حافظه نهان در هنگام به‌روزرسانی‌های حافظه را رد می‌کند، استفاده از CPU را کاهش داده و عملکرد آن را بهبود می‌بخشد. ممکن است در برخی بازی‌ها باعث مشکلات یا خرابی شود.</string>
<string name="cpuopt_unsafe_host_mmu">فعال‌سازی شبیه‌سازی MMU میزبان</string>
<string name="cpuopt_unsafe_host_mmu_description">این بهینه‌سازی دسترسی‌های حافظه توسط برنامه میهمان را تسریع می‌کند. فعال‌سازی آن باعث می‌شود خواندن/نوشتن حافظه میهمان مستقیماً در حافظه انجام شود و از MMU میزبان استفاده کند. غیرفعال کردن این قابلیت، همه دسترسی‌های حافظه را مجبور به استفاده از شبیه‌سازی نرم‌افزاری MMU می‌کند.</string>
<string name="dma_accuracy">سطح DMA</string>
<string name="dma_accuracy_description">دقت صحت DMA را کنترل می کند. دقت بالاتر می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز می تواند بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، آن را روی پیش فرض بگذارید.</string>
<string name="dma_accuracy">دقت DMA</string>
<string name="dma_accuracy_description">دقت صحت DMA را کنترل می کند. دقت ایمن می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز ممکن است بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، این گزینه را روی پیش فرض بگذارید.</string>
<string name="memory_4gb">4 گیگابایت (توصیه شده)</string>
<string name="memory_6gb">6 گیگابایت (ناامن)</string>
@ -504,8 +504,6 @@
<string name="use_custom_rtc">زمان سفارشی</string>
<string name="use_custom_rtc_description">به شما امکان می‌دهد یک ساعت سفارشی جدا از زمان فعلی سیستم خود تنظیم کنید.</string>
<string name="set_custom_rtc">تنظیم زمان سفارشی</string>
<string name="disable_nca_verification">غیرفعال کردن تأیید اعتبار NCA</string>
<string name="disable_nca_verification_description">بررسی صحت آرشیوهای محتوای NCA را غیرفعال می‌کند. این ممکن است سرعت بارگذاری را بهبود بخشد اما خطر خرابی داده یا تشخیص داده نشدن فایل‌های نامعتبر را به همراه دارد. برای کار کردن بازی‌ها و به‌روزرسانی‌هایی که به فرمور ۲۰+ نیاز دارند، ضروری است.</string>
<!-- Network settings strings -->
<string name="generate">تولید</string>
@ -871,9 +869,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">پیش فرض</string>
<string name="dma_accuracy_normal">معمولی</string>
<string name="dma_accuracy_high">بالا</string>
<string name="dma_accuracy_extreme">فوق العاده</string>
<string name="dma_accuracy_unsafe">ناایمن (سریع)</string>
<string name="dma_accuracy_safe">ایمن (پایدار)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Ignore certaines invalidations de cache côté CPU lors des mises à jour mémoire, réduisant l\'utilisation du CPU et améliorant ses performances. Peut causer des bugs ou plantages sur certains jeux.</string>
<string name="cpuopt_unsafe_host_mmu">Activer l\'émulation de la MMU hôte</string>
<string name="cpuopt_unsafe_host_mmu_description">Cette optimisation accélère les accès mémoire par le programme invité. L\'activer entraîne que les lectures/écritures mémoire de l\'invité sont effectuées directement en mémoire et utilisent la MMU de l\'hôte. Désactiver cela force tous les accès mémoire à utiliser l\'émulation logicielle de la MMU.</string>
<string name="dma_accuracy">Niveau DMA</string>
<string name="dma_accuracy_description">Contrôle la précision du DMA. Une précision plus élevée peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez-la sur Défaut.</string>
<string name="dma_accuracy">Précision DMA</string>
<string name="dma_accuracy_description">Contrôle la précision du DMA. Une précision sûre peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez ce paramètre sur Par défaut.</string>
<string name="memory_4gb">4 Go (Recommandé)</string>
<string name="memory_6gb">6 Go (Dangereux)</string>
@ -506,8 +506,6 @@
<string name="use_custom_rtc">RTC personnalisé</string>
<string name="use_custom_rtc_description">Vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string>
<string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string>
<string name="disable_nca_verification">Désactiver la vérification NCA</string>
<string name="disable_nca_verification_description">Désactive la vérification d\'intégrité des archives de contenu NCA. Cela peut améliorer la vitesse de chargement mais risque une corruption des données ou que des fichiers invalides ne soient pas détectés. Est nécessaire pour faire fonctionner les jeux et mises à jour nécessitant un firmware 20+.</string>
<!-- Network settings strings -->
<string name="generate">Générer</string>
@ -920,9 +918,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Défaut</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Élevé</string>
<string name="dma_accuracy_extreme">Extrême</string>
<string name="dma_accuracy_unsafe">Dangereux (rapide)</string>
<string name="dma_accuracy_safe">Sûr (stable)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -129,8 +129,8 @@
<string name="skip_cpu_inner_invalidation_description">מדלג על איפוסי מטמון מסוימים במהלך עדכוני זיכרון, מפחית שימוש במעבד ומשפר ביצועים. עלול לגרום לתקלות או קריסות בחלק מהמשחקים.</string>
<string name="cpuopt_unsafe_host_mmu">הפעל אמולציית MMU מארח</string>
<string name="cpuopt_unsafe_host_mmu_description">אופטימיזציה זו מאיצה את גישת הזיכרון על ידי התוכנית האורחת. הפעלתה גורמת לכך שפעולות קריאה/כתיבה לזיכרון האורח מתבצעות ישירות לזיכרון ומשתמשות ב-MMU של המארח. השבתת זאת מאלצת את כל גישות הזיכרון להשתמש באמולציית MMU תוכנתית.</string>
<string name="dma_accuracy">רמת DMA</string>
<string name="dma_accuracy_description">שולטת בדיוק הדיוק של DMA. דיוק גבוה יותר יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר ברירת מחדל.</string>
<string name="dma_accuracy">דיוק DMA</string>
<string name="dma_accuracy_description">שולט בדיוק הדיוק של DMA. דיוק בטוח יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר זאת על ברירת מחדל.</string>
<string name="memory_4gb">4GB (מומלץ)</string>
<string name="memory_6gb">6GB (לא בטוח)</string>
@ -505,8 +505,6 @@
<string name="use_custom_rtc">RTC מותאם אישית</string>
<string name="use_custom_rtc_description">מאפשר לך לקבוע שעון זמן אמת נפרד משעון המערכת שלך.</string>
<string name="set_custom_rtc">קבע RTC מותאם אישית</string>
<string name="disable_nca_verification">השבת אימות NCA</string>
<string name="disable_nca_verification_description">משבית את אימות השלמות של ארכיוני התוכן של NCA. זה עשוי לשפר את מהירות הטעינה אך מסתכן בשחיקת נתונים או שמא קבצים לא חוקיים יעברו ללא זיהוי. זה הכרחי כדי לגרום למשחקים ועדכונים הדורשים firmware 20+ לעבוד.</string>
<!-- Network settings strings -->
<string name="generate">יצירה</string>
@ -802,9 +800,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">ברירת מחדל</string>
<string name="dma_accuracy_normal">רגיל</string>
<string name="dma_accuracy_high">גבוה</string>
<string name="dma_accuracy_extreme">קיצוני</string>
<string name="dma_accuracy_unsafe">לא בטוח (מהיר)</string>
<string name="dma_accuracy_safe">בטוח (יציב)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Kihagy néhány CPU-oldali gyorsítótár-érvénytelenítést memóriafrissítések közben, csökkentve a CPU használatát és javítva a teljesítményt. Néhány játékban hibákat vagy összeomlást okozhat.</string>
<string name="cpuopt_unsafe_host_mmu">Gazda MMU emuláció engedélyezése</string>
<string name="cpuopt_unsafe_host_mmu_description">Ez az optimalizáció gyorsítja a vendégprogram memória-hozzáférését. Engedélyezése esetén a vendég memóriaolvasási/írási műveletei közvetlenül a memóriában történnek, és kihasználják a gazda MMU-ját. Letiltás esetén minden memória-hozzáférés a szoftveres MMU emulációt használja.</string>
<string name="dma_accuracy">DMA szint</string>
<string name="dma_accuracy_description">Szabályozza a DMA pontosságát. A magasabb pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításnál.</string>
<string name="dma_accuracy">DMA pontosság</string>
<string name="dma_accuracy_description">Szabályozza a DMA pontosságát. A biztonságos pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításon.</string>
<string name="memory_4gb">4GB (Ajánlott)</string>
<string name="memory_6gb">6GB (Nem biztonságos)</string>
@ -501,8 +501,6 @@
<string name="use_custom_rtc">Egyéni RTC</string>
<string name="use_custom_rtc_description">Megadhatsz egy valós idejű órát, amely eltér a rendszer által használt órától.</string>
<string name="set_custom_rtc">Egyéni RTC beállítása</string>
<string name="disable_nca_verification">NCA ellenőrzés letiltása</string>
<string name="disable_nca_verification_description">Letiltja az NCA tartalomarchívumok integritás-ellenőrzését. Ez javíthatja a betöltési sebességet, de az adatsérülés vagy az érvénytelen fájlok észrevétlen maradásának kockázatával jár. Elengedhetetlen a 20+ firmware-et igénylő játékok és frissítések működtetéséhez.</string>
<!-- Network settings strings -->
<string name="generate">Generálás</string>
@ -909,9 +907,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Alapértelmezett</string>
<string name="dma_accuracy_normal">Normál</string>
<string name="dma_accuracy_high">Magas</string>
<string name="dma_accuracy_extreme">Extrém</string>
<string name="dma_accuracy_unsafe">Nem biztonságos (gyors)</string>
<string name="dma_accuracy_safe">Biztonságos (stabil)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Melewati beberapa pembatalan cache sisi CPU selama pembaruan memori, mengurangi penggunaan CPU dan meningkatkan kinerjanya. Mungkin menyebabkan gangguan atau crash pada beberapa game.</string>
<string name="cpuopt_unsafe_host_mmu">Aktifkan Emulasi MMU Host</string>
<string name="cpuopt_unsafe_host_mmu_description">Optimasi ini mempercepat akses memori oleh program tamu. Mengaktifkannya menyebabkan pembacaan/penulisan memori tamu dilakukan langsung ke memori dan memanfaatkan MMU Host. Menonaktifkan ini memaksa semua akses memori menggunakan Emulasi MMU Perangkat Lunak.</string>
<string name="dma_accuracy">Level DMA</string>
<string name="dma_accuracy_description">Mengontrol akurasi presisi DMA. Presisi yang lebih tinggi dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi performa dalam beberapa kasus. Jika tidak yakin, biarkan di Bawaan.</string>
<string name="dma_accuracy">Akurasi DMA</string>
<string name="dma_accuracy_description">Mengontrol keakuratan presisi DMA. Presisi aman dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi kinerja dalam beberapa kasus. Jika tidak yakin, biarkan ini pada Bawaan.</string>
<string name="memory_4gb">4GB (Direkomendasikan)</string>
<string name="memory_6gb">6GB (Tidak Aman)</string>
@ -502,8 +502,6 @@
<string name="use_custom_rtc">RTC Kustom</string>
<string name="use_custom_rtc_description">Memungkinkan Anda untuk mengatur jam waktu nyata kustom yang terpisah dari waktu sistem saat ini Anda.</string>
<string name="set_custom_rtc">Setel RTC Kustom</string>
<string name="disable_nca_verification">Nonaktifkan Verifikasi NCA</string>
<string name="disable_nca_verification_description">Menonaktifkan verifikasi integritas arsip konten NCA. Ini dapat meningkatkan kecepatan pemuatan tetapi berisiko kerusakan data atau file yang tidak valid tidak terdeteksi. Diperlukan untuk membuat game dan pembaruan yang membutuhkan firmware 20+ bekerja.</string>
<!-- Network settings strings -->
<string name="generate">Hasilkan</string>
@ -864,9 +862,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Bawaan</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Tinggi</string>
<string name="dma_accuracy_extreme">Ekstrem</string>
<string name="dma_accuracy_unsafe">Tidak Aman (cepat)</string>
<string name="dma_accuracy_safe">Aman (stabil)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Salta alcuni invalidamenti della cache lato CPU durante gli aggiornamenti di memoria, riducendo l\'uso della CPU e migliorandone le prestazioni. Potrebbe causare glitch o crash in alcuni giochi.</string>
<string name="cpuopt_unsafe_host_mmu">Abilita emulazione MMU host</string>
<string name="cpuopt_unsafe_host_mmu_description">Questa ottimizzazione accelera gli accessi alla memoria da parte del programma guest. Abilitandola, le letture/scritture della memoria guest vengono eseguite direttamente in memoria e sfruttano la MMU host. Disabilitandola, tutti gli accessi alla memoria sono costretti a utilizzare l\'emulazione software della MMU.</string>
<string name="dma_accuracy">Livello DMA</string>
<string name="dma_accuracy_description">Controlla la precisione del DMA. Una precisione più alta può risolvere problemi in alcuni giochi, ma in alcuni casi può influire sulle prestazioni. Se non sei sicuro, lascia su Predefinito.</string>
<string name="dma_accuracy">Precisione DMA</string>
<string name="dma_accuracy_description">Controlla la precisione del DMA. La precisione sicura può risolvere problemi in alcuni giochi, ma in alcuni casi può anche influire sulle prestazioni. In caso di dubbi, lascia questo su Predefinito.</string>
<string name="memory_4gb">4GB (Consigliato)</string>
<string name="memory_6gb">6GB (Non sicuro)</string>
@ -505,8 +505,6 @@
<string name="use_custom_rtc">RTC Personalizzato</string>
<string name="use_custom_rtc_description">Ti permette di impostare un orologio in tempo reale personalizzato, completamente separato da quello di sistema.</string>
<string name="set_custom_rtc">Imposta un orologio in tempo reale personalizzato</string>
<string name="disable_nca_verification">Disabilita verifica NCA</string>
<string name="disable_nca_verification_description">Disabilita la verifica dell\'integrità degli archivi di contenuto NCA. Può migliorare la velocità di caricamento ma rischia il danneggiamento dei dati o che file non validi passino inosservati. Necessario per far funzionare giochi e aggiornamenti che richiedono il firmware 20+.</string>
<!-- Network settings strings -->
<string name="generate">Genera</string>
@ -833,9 +831,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Predefinito</string>
<string name="dma_accuracy_normal">Normale</string>
<string name="dma_accuracy_high">Alto</string>
<string name="dma_accuracy_extreme">Estremo</string>
<string name="dma_accuracy_unsafe">Non sicuro (veloce)</string>
<string name="dma_accuracy_safe">Sicuro (stabile)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">メモリ更新時のCPU側キャッシュ無効化をスキップし、CPU使用率を減らして性能を向上させます。一部のゲームで不具合やクラッシュが発生する可能性があります。</string>
<string name="cpuopt_unsafe_host_mmu">ホストMMUエミュレーションを有効化</string>
<string name="cpuopt_unsafe_host_mmu_description">この最適化により、ゲストプログラムによるメモリアクセスが高速化されます。有効にすると、ゲストのメモリ読み書きが直接メモリ内で実行され、ホストのMMUを利用します。無効にすると、すべてのメモリアクセスでソフトウェアMMUエミュレーションが使用されます。</string>
<string name="dma_accuracy">DMAレベル</string>
<string name="dma_accuracy_description">DMAの精度を制御します。精度を高くすると一部のゲームの問題が修正される場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、デフォルトのままにしてください。</string>
<string name="dma_accuracy">DMA精度</string>
<string name="dma_accuracy_description">DMAの精度を制御します。安全な精度は一部のゲームの問題を修正できる場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、これをデフォルトのままにしてください。</string>
<string name="memory_4gb">4GB (推奨)</string>
<string name="memory_6gb">6GB (安全でない)</string>
@ -491,8 +491,6 @@
<string name="use_custom_rtc">カスタム RTC</string>
<string name="use_custom_rtc_description">現在のシステム時間とは別に、任意のリアルタイムクロックを設定できます。</string>
<string name="set_custom_rtc">カスタムRTCを設定</string>
<string name="disable_nca_verification">NCA検証を無効化</string>
<string name="disable_nca_verification_description">NCAコンテンツアーカイブの整合性検証を無効にします。読み込み速度が向上する可能性がありますが、データ破損や不正なファイルが検出されないリスクがあります。ファームウェア20以上が必要なゲームや更新を動作させるために必要です。</string>
<!-- Network settings strings -->
<string name="generate">生成</string>
@ -792,9 +790,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">デフォルト</string>
<string name="dma_accuracy_normal">標準</string>
<string name="dma_accuracy_high"></string>
<string name="dma_accuracy_extreme">最高</string>
<string name="dma_accuracy_unsafe">安全でない(高速)</string>
<string name="dma_accuracy_safe">安全(安定)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">메모리 업데이트 시 일부 CPU 측 캐시 무효화를 건너뛰어 CPU 사용량을 줄이고 성능을 향상시킵니다. 일부 게임에서 오류 또는 충돌을 일으킬 수 있습니다.</string>
<string name="cpuopt_unsafe_host_mmu">호스트 MMU 에뮬레이션 사용</string>
<string name="cpuopt_unsafe_host_mmu_description">이 최적화는 게스트 프로그램의 메모리 접근 속도를 높입니다. 활성화하면 게스트의 메모리 읽기/쓰기가 메모리에서 직접 수행되고 호스트의 MMU를 활용합니다. 비활성화하면 모든 메모리 접근에 소프트웨어 MMU 에뮬레이션을 사용하게 됩니다.</string>
<string name="dma_accuracy">DMA 수준</string>
<string name="dma_accuracy_description">DMA 정밀도를 제어합니다. 높은 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않다면 기본값으로 두세요.</string>
<string name="dma_accuracy">DMA 정확도</string>
<string name="dma_accuracy_description">DMA 정밀도 정확도를 제어합니다. 안전한 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않은 경우 기본값으로 두십시오.</string>
<string name="memory_4gb">4GB (권장)</string>
<string name="memory_6gb">6GB (안전하지 않음)</string>
@ -501,8 +501,6 @@
<string name="use_custom_rtc">사용자 지정 RTC</string>
<string name="use_custom_rtc_description">현재 시스템 시간과 별도로 사용자 지정 RTC를 설정할 수 있습니다.</string>
<string name="set_custom_rtc">사용자 지정 RTC 설정</string>
<string name="disable_nca_verification">NCA 검증 비활성화</string>
<string name="disable_nca_verification_description">NCA 콘텐츠 아카이브의 무결성 검증을 비활성화합니다. 로딩 속도를 향상시킬 수 있지만 데이터 손상이나 유효하지 않은 파일이 미검증될 위험이 있습니다. 펌웨어 20+가 필요한 게임 및 업데이트를 실행하려면 필요합니다.</string>
<!-- Network settings strings -->
<string name="generate">생성</string>
@ -863,9 +861,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">기본값</string>
<string name="dma_accuracy_normal">보통</string>
<string name="dma_accuracy_high">높음</string>
<string name="dma_accuracy_extreme">극단적</string>
<string name="dma_accuracy_unsafe">안전하지 않음(빠름)</string>
<string name="dma_accuracy_safe">안전함(안정적)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Hopper over enkelte CPU-side cache-invalideringer under minneoppdateringer, reduserer CPU-bruk og forbedrer ytelsen. Kan forårsake feil eller krasj i noen spill.</string>
<string name="cpuopt_unsafe_host_mmu">Aktiver verts-MMU-emulering</string>
<string name="cpuopt_unsafe_host_mmu_description">Denne optimaliseringen fremskynder minnetilgang av gjesteprogrammet. Hvis aktivert, utføres gjestens minnelesing/skriving direkte i minnet og bruker vertens MMU. Deaktivering tvinger alle minnetilganger til å bruke programvarebasert MMU-emulering.</string>
<string name="dma_accuracy">DMA-nivå</string>
<string name="dma_accuracy_description">Styrer DMA-presisjonsnøyaktigheten. Høyere presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la den stå på Standard.</string>
<string name="dma_accuracy">DMA-nøyaktighet</string>
<string name="dma_accuracy_description">Kontrollerer DMA-presisjonsnøyaktigheten. Sikker presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la dette stå på Standard.</string>
<string name="memory_4gb">4GB (Anbefalt)</string>
<string name="memory_6gb">6GB (Usikkert)</string>
@ -482,8 +482,6 @@
<string name="use_custom_rtc">Tilpasset Sannhetstidsklokke</string>
<string name="use_custom_rtc_description">Gjør det mulig å stille inn en egendefinert sanntidsklokke separat fra den gjeldende systemtiden.</string>
<string name="set_custom_rtc">Angi tilpasset RTC</string>
<string name="disable_nca_verification">Deaktiver NCA-verifisering</string>
<string name="disable_nca_verification_description">Deaktiverer integritetsverifisering av NCA-innholdsarkiv. Dette kan forbedre lastehastigheten, men medfører risiko for datakorrupsjon eller at ugyldige filer ikke oppdages. Er nødvendig for å få spill og oppdateringer som trenger firmware 20+ til å fungere.</string>
<!-- Network settings strings -->
<string name="generate">Generer</string>
@ -773,9 +771,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Standard</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Høy</string>
<string name="dma_accuracy_extreme">Ekstrem</string>
<string name="dma_accuracy_unsafe">Usikker (rask)</string>
<string name="dma_accuracy_safe">Sikker (stabil)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Pomija niektóre unieważnienia pamięci podręcznej po stronie CPU podczas aktualizacji pamięci, zmniejszając użycie CPU i poprawiając jego wydajność. Może powodować błędy lub awarie w niektórych grach.</string>
<string name="cpuopt_unsafe_host_mmu">Włącz emulację MMU hosta</string>
<string name="cpuopt_unsafe_host_mmu_description">Ta optymalizacja przyspiesza dostęp do pamięci przez program gościa. Włączenie powoduje, że odczyty/zapisy pamięci gościa są wykonywane bezpośrednio w pamięci i wykorzystują MMU hosta. Wyłączenie wymusza użycie programowej emulacji MMU dla wszystkich dostępów do pamięci.</string>
<string name="dma_accuracy">Poziom DMA</string>
<string name="dma_accuracy_description">Kontroluje dokładność precyzji DMA. Wyższy poziom może naprawić problemy w niektórych grach, ale może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość «Domyślny».</string>
<string name="dma_accuracy">Dokładność DMA</string>
<string name="dma_accuracy_description">Kontroluje dokładność precyzji DMA. Bezpieczna precyzja może naprawić problemy w niektórych grach, ale w niektórych przypadkach może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość Domyślną.</string>
<string name="memory_4gb">4GB (Zalecane)</string>
<string name="memory_6gb">6GB (Niebezpieczne)</string>
@ -482,8 +482,6 @@
<string name="use_custom_rtc">Niestandardowy RTC</string>
<string name="use_custom_rtc_description">Ta opcja pozwala na wybranie własnych ustawień czasu używanych w czasie emulacji, innych niż czas systemu Android.</string>
<string name="set_custom_rtc">Ustaw niestandardowy czas RTC</string>
<string name="disable_nca_verification">Wyłącz weryfikację NCA</string>
<string name="disable_nca_verification_description">Wyłącza weryfikację integralności archiwów zawartości NCA. Może to poprawić szybkość ładowania, ale niesie ryzyko uszkodzenia danych lub niezauważenia nieprawidłowych plików. Konieczne, aby działały gry i aktualizacje wymagające firmware\'u 20+.</string>
<!-- Network settings strings -->
<string name="generate">Generuj</string>
@ -770,9 +768,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">預設</string>
<string name="dma_accuracy_normal">普通</string>
<string name="dma_accuracy_high"></string>
<string name="dma_accuracy_extreme">極高</string>
<string name="dma_accuracy_unsafe">Niezabezpieczone (szybkie)</string>
<string name="dma_accuracy_safe">Bezpieczne (stabilne)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo o uso da CPU e melhorando seu desempenho. Pode causar falhas ou travamentos em alguns jogos.</string>
<string name="cpuopt_unsafe_host_mmu">Ativar Emulação de MMU do Host</string>
<string name="cpuopt_unsafe_host_mmu_description">Esta otimização acelera os acessos à memória pelo programa convidado. Ativar isso faz com que as leituras/gravações de memória do convidado sejam feitas diretamente na memória e utilizem a MMU do Host. Desativar isso força todos os acessos à memória a usarem a Emulação de MMU por Software.</string>
<string name="dma_accuracy">Nível DMA</string>
<string name="dma_accuracy_description">Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode impactar o desempenho em alguns casos. Se não tiver certeza, deixe em Padrão.</string>
<string name="dma_accuracy">Precisão de DMA</string>
<string name="dma_accuracy_description">Controla a precisão do DMA. A precisão segura pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho em alguns casos. Se não tiver certeza, deixe isso como Padrão.</string>
<string name="memory_4gb">4GB (Recomendado)</string>
<string name="memory_6gb">6GB (Inseguro)</string>
@ -506,8 +506,6 @@
<string name="use_custom_rtc">Data e hora personalizadas</string>
<string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
<string name="set_custom_rtc">Definir um relógio em tempo real personalizado</string>
<string name="disable_nca_verification">Desativar verificação NCA</string>
<string name="disable_nca_verification_description">Desativa a verificação de integridade de arquivos de conteúdo NCA. Pode melhorar a velocidade de carregamento, mas arrisica corromper dados ou que arquivos inválidos passem despercebidos. É necessário para fazer jogos e atualizações que exigem firmware 20+ funcionarem.</string>
<!-- Network settings strings -->
<string name="generate">Gerar</string>
@ -921,9 +919,8 @@ uma tentativa de mapeamento automático</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Padrão</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Alto</string>
<string name="dma_accuracy_extreme">Extremo</string>
<string name="dma_accuracy_unsafe">Inseguro (rápido)</string>
<string name="dma_accuracy_safe">Seguro (estável)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo a utilização da CPU e melhorando o desempenho. Pode causar falhas ou crashes em alguns jogos.</string>
<string name="cpuopt_unsafe_host_mmu">Ativar Emulação de MMU do Anfitrião</string>
<string name="cpuopt_unsafe_host_mmu_description">Esta otimização acelera os acessos à memória pelo programa convidado. Ativar faz com que as leituras/escritas de memória do convidado sejam efetuadas diretamente na memória e utilizem a MMU do Anfitrião. Desativar força todos os acessos à memória a usar a Emulação de MMU por Software.</string>
<string name="dma_accuracy">Nível DMA</string>
<string name="dma_accuracy_description">Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe em Predefinido.</string>
<string name="dma_accuracy">Precisão da DMA</string>
<string name="dma_accuracy_description">Controla a precisão da DMA. A precisão segura pode resolver problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe esta opção em Predefinido.</string>
<string name="memory_4gb">4GB (Recomendado)</string>
<string name="memory_6gb">6GB (Inseguro)</string>
@ -506,8 +506,6 @@
<string name="use_custom_rtc">RTC personalizado</string>
<string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
<string name="set_custom_rtc">Defina um relógio em tempo real personalizado</string>
<string name="disable_nca_verification">Desativar verificação NCA</string>
<string name="disable_nca_verification_description">Desativa a verificação de integridade dos arquivos de conteúdo NCA. Pode melhorar a velocidade de carregamento, mas arrisca a corrupção de dados ou que ficheiros inválidos passem despercebidos. É necessário para que jogos e atualizações que necessitam de firmware 20+ funcionem.</string>
<!-- Network settings strings -->
<string name="generate">Gerar</string>
@ -921,9 +919,8 @@ uma tentativa de mapeamento automático</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Predefinido</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">Alto</string>
<string name="dma_accuracy_extreme">Extremo</string>
<string name="dma_accuracy_unsafe">Inseguro (rápido)</string>
<string name="dma_accuracy_safe">Seguro (estável)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
<string name="cpuopt_unsafe_host_mmu">Включить эмуляцию MMU хоста</string>
<string name="cpuopt_unsafe_host_mmu_description">Эта оптимизация ускоряет доступ к памяти гостевой программой. При включении операции чтения/записи памяти гостя выполняются напрямую в памяти с использованием MMU хоста. Отключение заставляет все обращения к памяти использовать программную эмуляцию MMU.</string>
<string name="dma_accuracy">Уровень DMA</string>
<string name="dma_accuracy_description">Управляет точностью DMA. Более высокий уровень может исправить проблемы в некоторых играх, но также может повлиять на производительность. Если не уверены, оставьте значение «По умолчанию».</string>
<string name="dma_accuracy">Точность DMA</string>
<string name="dma_accuracy_description">Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию.</string>
<string name="memory_4gb">4 ГБ (Рекомендуется)</string>
<string name="memory_6gb">6 ГБ (Небезопасно)</string>
@ -508,8 +508,6 @@
<string name="use_custom_rtc">Пользовательский RTC</string>
<string name="use_custom_rtc_description">Позволяет установить пользовательские часы реального времени отдельно от текущего системного времени.</string>
<string name="set_custom_rtc">Установить пользовательский RTC</string>
<string name="disable_nca_verification">Отключить проверку NCA</string>
<string name="disable_nca_verification_description">Отключает проверку целостности архивов содержимого NCA. Может улучшить скорость загрузки, но есть риск повреждения данных или того, что недействительные файлы останутся незамеченными. Необходимо для работы игр и обновлений, требующих прошивку 20+.</string>
<!-- Network settings strings -->
<string name="generate">Создать</string>
@ -922,9 +920,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">По умолчанию</string>
<string name="dma_accuracy_normal">Нормальный</string>
<string name="dma_accuracy_high">Высокий</string>
<string name="dma_accuracy_extreme">Экстремальный</string>
<string name="dma_accuracy_unsafe">Небезопасно (быстро)</string>
<string name="dma_accuracy_safe">Безопасно (стабильно)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>
@ -958,7 +955,7 @@
<!-- Screen Layouts -->
<string name="screen_layout_auto">Авто</string>
<string name="screen_layout_sensor_landscape">Альбомная (сенсор)</string>
<string name="screen_layout_landscape">Пейзаж</string>
<string name="screen_layout_landscape">Альбомная</string>
<string name="screen_layout_reverse_landscape">Обратная альбомная</string>
<string name="screen_layout_sensor_portrait">Портретная (сенсор)</string>
<string name="screen_layout_portrait">Портрет</string>

View file

@ -121,8 +121,8 @@
<string name="skip_cpu_inner_invalidation_description">Preskače određena poništavanja keša na strani CPU-a tokom ažuriranja memorije, smanjujući opterećenje procesora i poboljšavajući performanse. Može izazvati greške u nekim igrama.</string>
<string name="cpuopt_unsafe_host_mmu">Омогући емулацију MMU домаћина</string>
<string name="cpuopt_unsafe_host_mmu_description">Ова оптимизација убрзава приступ меморији од стране гостујућег програма. Укључивање изазива да се читања/уписа меморије госта обављају директно у меморији и користе MMU домаћина. Искључивање присиљава све приступе меморији да користе софтверску емулацију MMU.</string>
<string name="dma_accuracy">DMA ниво</string>
<string name="dma_accuracy_description">Контролише тачност DMA прецизности. Виши ниво може да поправи проблеме у неким играма, али може и да утиче на перформансе. Ако нисте сигурни, оставите на «Подразумевано».</string>
<string name="dma_accuracy">DMA тачност</string>
<string name="dma_accuracy_description">Управља прецизношћу DMA-а. Сигурна прецизност може да исправи проблеме у неким играма, али у неким случајевима може да утиче и на перформансе. Ако нисте сигурни, оставите ово на Подразумевано.</string>
<!-- Shader Backend -->
<string name="shader_backend">Схадер Бацкенд</string>
@ -457,8 +457,6 @@
<string name="use_custom_rtc">Цустом РТЦ</string>
<string name="use_custom_rtc_description">Омогућава вам да поставите прилагођени сат у реалном времену одвојено од тренутног времена система.</string>
<string name="set_custom_rtc">Подесите прилагођени РТЦ</string>
<string name="disable_nca_verification">Искључи верификацију НЦА</string>
<string name="disable_nca_verification_description">Искључује верификацију интегритета НЦА архива садржаја. Ово може побољшати брзину учитавања, али ризикује оштећење података или да неважећи фајлови прођу незапажено. Неопходно је да би игре и ажурирања која захтевају firmware 20+ радили.</string>
<!-- Network settings strings -->
<string name="generate">Генериши</string>
@ -917,9 +915,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Подразумевано</string>
<string name="dma_accuracy_normal">Нормално</string>
<string name="dma_accuracy_high">Високо</string>
<string name="dma_accuracy_extreme">Екстремно</string>
<string name="dma_accuracy_unsafe">Небезбедно (брзо)</string>
<string name="dma_accuracy_safe">Безбедно (стабилно)</string>
<!-- ASTC Decoding Method -->
<string name="accelerate_astc">АСТЦ метода декодирања</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
<string name="cpuopt_unsafe_host_mmu">Увімкнути емуляцію MMU хоста</string>
<string name="cpuopt_unsafe_host_mmu_description">Ця оптимізація пришвидшує доступ до пам\'яті гостьовою програмою. Увімкнення призводить до того, що читання/запис пам\'яті гостя виконуються безпосередньо в пам\'яті та використовують MMU хоста. Вимкнення змушує всі звернення до пам\'яті використовувати програмну емуляцію MMU.</string>
<string name="dma_accuracy">Рівень DMA</string>
<string name="dma_accuracy_description">Керує точністю DMA. Вищий рівень може виправити проблеми в деяких іграх, але також може вплинути на продуктивність. Якщо не впевнені, залиште значення «Типово».</string>
<string name="dma_accuracy">Точність DMA</string>
<string name="dma_accuracy_description">Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням.</string>
<string name="memory_4gb">4 ГБ (Рекомендовано)</string>
<string name="memory_6gb">6 ГБ (Небезпечно)</string>
@ -495,8 +495,6 @@
<string name="use_custom_rtc">Свій RTC</string>
<string name="use_custom_rtc_description">Дозволяє встановити власний час (Real-time clock, або RTC), відмінний від системного.</string>
<string name="set_custom_rtc">Встановити RTC</string>
<string name="disable_nca_verification">Вимкнути перевірку NCA</string>
<string name="disable_nca_verification_description">Вимкає перевірку цілісності архівів вмісту NCA. Може покращити швидкість завантаження, але ризикує пошкодженням даних або тим, що недійсні файли залишаться непоміченими. Необхідно для роботи ігор та оновлень, які вимагають прошивки 20+.</string>
<!-- Network settings strings -->
<string name="generate">Створити</string>
@ -811,9 +809,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Типово</string>
<string name="dma_accuracy_normal">Нормальний</string>
<string name="dma_accuracy_high">Високий</string>
<string name="dma_accuracy_extreme">Екстремальний</string>
<string name="dma_accuracy_unsafe">Небезпечно (швидко)</string>
<string name="dma_accuracy_safe">Безпечно (стабільно)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -128,8 +128,8 @@
<string name="skip_cpu_inner_invalidation_description">Bỏ qua một số lần vô hiệu hóa bộ nhớ đệm phía CPU trong khi cập nhật bộ nhớ, giảm mức sử dụng CPU và cải thiện hiệu suất. Có thể gây ra lỗi hoặc treo máy trong một số trò chơi.</string>
<string name="cpuopt_unsafe_host_mmu">Bật giả lập MMU Máy chủ</string>
<string name="cpuopt_unsafe_host_mmu_description">Tối ưu hóa này tăng tốc độ truy cập bộ nhớ của chương trình khách. Bật nó lên khiến các thao tác đọc/ghi bộ nhớ khách được thực hiện trực tiếp vào bộ nhớ và sử dụng MMU của Máy chủ. Tắt tính năng này buộc tất cả quyền truy cập bộ nhớ phải sử dụng Giả lập MMU Phần mềm.</string>
<string name="dma_accuracy">Cấp độ DMA</string>
<string name="dma_accuracy_description">Điều khiển độ chính xác của DMA. Độ chính xác cao hơn có thể sửa lỗi trong một số trò chơi, nhưng cũng có thể ảnh hưởng đến hiệu suất trong một số trường hợp. Nếu không chắc chắn, hãy để ở Mặc định.</string>
<string name="dma_accuracy">Độ chính xác DMA</string>
<string name="dma_accuracy_description">Điều khiển độ chính xác của DMA. Độ chính xác an toàn có thể khắc phục sự cố trong một số trò chơi, nhưng trong một số trường hợp cũng có thể ảnh hưởng đến hiệu suất. Nếu không chắc chắn, hãy để giá trị này ở Mặc định.</string>
<string name="memory_4gb">4GB (Được đề xuất)</string>
<string name="memory_6gb">6GB (Không an toàn)</string>
@ -482,8 +482,6 @@
<string name="use_custom_rtc">RTC tuỳ chỉnh</string>
<string name="use_custom_rtc_description">Cho phép bạn thiết lập một đồng hồ thời gian thực tùy chỉnh riêng biệt so với thời gian hệ thống hiện tại.</string>
<string name="set_custom_rtc">Thiết lập RTC tùy chỉnh</string>
<string name="disable_nca_verification">Tắt xác minh NCA</string>
<string name="disable_nca_verification_description">Tắt xác minh tính toàn vẹn của kho lưu trữ nội dung NCA. Có thể cải thiện tốc độ tải nhưng có nguy cơ hỏng dữ liệu hoặc các tệp không hợp lệ không bị phát hiện. Cần thiết để các trò chơi và bản cập nhật yêu cầu firmware 20+ hoạt động.</string>
<!-- Network settings strings -->
<string name="generate">Tạo</string>
@ -776,9 +774,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Mặc định</string>
<string name="dma_accuracy_normal">Bình thường</string>
<string name="dma_accuracy_high">Cao</string>
<string name="dma_accuracy_extreme">Cực cao</string>
<string name="dma_accuracy_unsafe">Không an toàn (nhanh)</string>
<string name="dma_accuracy_safe">An toàn (ổn định)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -127,8 +127,8 @@
<string name="skip_cpu_inner_invalidation_description">在内存更新期间跳过某些CPU端缓存无效化减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。</string>
<string name="cpuopt_unsafe_host_mmu">启用主机 MMU 模拟</string>
<string name="cpuopt_unsafe_host_mmu_description">此优化可加速来宾程序的内存访问。启用后,来宾内存读取/写入将直接在内存中执行并利用主机的 MMU。禁用此功能将强制所有内存访问使用软件 MMU 模拟。</string>
<string name="dma_accuracy">DMA 级别</string>
<string name="dma_accuracy_description">控制 DMA 精度。更高的精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。</string>
<string name="dma_accuracy">DMA 精度</string>
<string name="dma_accuracy_description">控制 DMA 精度。安全精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。</string>
<string name="memory_4gb">4GB (推荐)</string>
<string name="memory_6gb">6GB (不安全)</string>
@ -500,8 +500,6 @@
<string name="use_custom_rtc">自定义系统时间</string>
<string name="use_custom_rtc_description">此选项允许您设置与目前系统时间相独立的自定义系统时钟。</string>
<string name="set_custom_rtc">设置自定义系统时间</string>
<string name="disable_nca_verification">禁用NCA验证</string>
<string name="disable_nca_verification_description">禁用NCA内容存档的完整性验证。可能会提高加载速度但存在数据损坏或无效文件未被检测到的风险。对于需要固件20+的游戏和更新是必需的。</string>
<!-- Network settings strings -->
<string name="generate">生成</string>
@ -914,9 +912,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">默认</string>
<string name="dma_accuracy_normal">普通</string>
<string name="dma_accuracy_high"></string>
<string name="dma_accuracy_extreme">极高</string>
<string name="dma_accuracy_unsafe">不安全(快速)</string>
<string name="dma_accuracy_safe">安全(稳定)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -120,8 +120,8 @@
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些CPU端快取無效化減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或崩潰。</string>
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
<string name="dma_accuracy">DMA 級別</string>
<string name="dma_accuracy_description">控制 DMA 精確度。更高的精確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。</string>
<string name="dma_accuracy">DMA 精度</string>
<string name="dma_accuracy_description">控制 DMA 精度。安全精度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。</string>
<!-- Memory Layouts -->
<string name="memory_4gb">4GB (推薦)</string>
@ -505,8 +505,6 @@
<string name="use_custom_rtc">自訂 RTC</string>
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂即時時鐘。</string>
<string name="set_custom_rtc">設定自訂 RTC</string>
<string name="disable_nca_verification">停用NCA驗證</string>
<string name="disable_nca_verification_description">停用NCA內容存檔的完整性驗證。可能會提高載入速度但存在資料損毀或無效檔案未被偵測到的風險。對於需要韌體20+的遊戲和更新是必需的。</string>
<!-- Network settings strings -->
<string name="generate">生成</string>
@ -919,9 +917,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">預設</string>
<string name="dma_accuracy_normal">普通</string>
<string name="dma_accuracy_high"></string>
<string name="dma_accuracy_extreme">極高</string>
<string name="dma_accuracy_unsafe">不安全(快速)</string>
<string name="dma_accuracy_safe">安全(穩定)</string>
<!-- Resolutions -->
<string name="resolution_quarter">0.25X (180p/270p)</string>

View file

@ -454,15 +454,13 @@
<string-array name="dmaAccuracyNames">
<item>@string/dma_accuracy_default</item>
<item>@string/dma_accuracy_normal</item>
<item>@string/dma_accuracy_high</item>
<item>@string/dma_accuracy_extreme</item>
<item>@string/dma_accuracy_unsafe</item>
<item>@string/dma_accuracy_safe</item>
</string-array>
<integer-array name="dmaAccuracyValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
<string-array name="appletEntries">

View file

@ -115,8 +115,8 @@
<string name="fast_cpu_time_description">Use Boost (1700MHz) to run at the Switch\'s highest native clock, or Fast (2000MHz) to run at 2x clock.</string>
<string name="memory_layout">Memory Layout</string>
<string name="memory_layout_description">(EXPERIMENTAL) Change the emulated memory layout. This setting will not increase performance, but may help with games utilizing high resolutions via mods. Do not use on phones with 8GB of RAM or less. Only works on the Dynarmic (JIT) backend.</string>
<string name="dma_accuracy">DMA Level</string>
<string name="dma_accuracy_description">Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave it at Default.</string>
<string name="dma_accuracy">DMA Accuracy</string>
<string name="dma_accuracy_description">Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave this on Default.</string>
<!-- Shader Backend -->
<string name="shader_backend">Shader Backend</string>
@ -475,8 +475,6 @@
<string name="use_custom_rtc">Custom RTC</string>
<string name="use_custom_rtc_description">Allows you to set a custom real-time clock separate from your current system time.</string>
<string name="set_custom_rtc">Set custom RTC</string>
<string name="disable_nca_verification">Disable NCA Verification</string>
<string name="disable_nca_verification_description">Disables integrity verification of NCA content archives. This may improve loading speed but risks data corruption or invalid files going undetected. Some games that require firmware versions 20+ may need this as well.</string>
<string name="generate">Generate</string>
@ -785,9 +783,6 @@
<string name="loader_requires_firmware">Game Requires Firmware</string>
<string name="loader_requires_firmware_description"><![CDATA[The game you are trying to launch requires firmware to boot or to get past the opening menu. Please <a href="https://yuzu-mirror.github.io/help/quickstart"> dump and install firmware</a>, or press "OK" to launch anyways.]]></string>
<string name="nca_verification_disabled">NCA Verification Disabled</string>
<string name="nca_verification_disabled_description">This is required to run new games and updates, but may cause instability or crashes if NCA files are corrupt, modified, or tampered with. If unsure, re-enable verification in Advanced Settings -> System, and use firmware versions of 19.0.1 or below.</string>
<!-- Intent Launch strings -->
<string name="searching_for_game">Searching for game...</string>
<string name="game_not_found_for_title_id">Game not found for Title ID: %1$s</string>
@ -945,9 +940,8 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Default</string>
<string name="dma_accuracy_normal">Normal</string>
<string name="dma_accuracy_high">High</string>
<string name="dma_accuracy_extreme">Extreme</string>
<string name="dma_accuracy_unsafe">Unsafe (fast)</string>
<string name="dma_accuracy_safe">Safe (stable)</string>
<!-- ASTC Decoding Method -->
<string name="accelerate_astc">ASTC Decoding Method</string>

View file

@ -598,12 +598,17 @@ public:
bool ClearBackingRegion(size_t physical_offset, size_t length) {
#ifdef __linux__
// Set MADV_REMOVE on backing map to destroy it instantly.
// This also deletes the area from the backing file.
int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
return true;
// Only incur syscall cost IF memset would be slower (theshold = 16MiB)
// TODO(lizzie): Smarter way to dynamically get this threshold (broadwell != raptor lake) for example
if (length >= 2097152UL * 8) {
// Set MADV_REMOVE on backing map to destroy it instantly.
// This also deletes the area from the backing file.
int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
return true;
} else {
return false;
}
#else
return false;
#endif

View file

@ -154,11 +154,19 @@ bool IsGPULevelHigh() {
values.current_gpu_accuracy == GpuAccuracy::High;
}
bool IsDMALevelDefault() {
return values.dma_accuracy.GetValue() == DmaAccuracy::Default;
}
bool IsDMALevelSafe() {
return values.dma_accuracy.GetValue() == DmaAccuracy::Safe;
}
bool IsFastmemEnabled() {
if (values.cpu_debug_mode) {
return static_cast<bool>(values.cpuopt_fastmem);
}
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) {
if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe) {
return static_cast<bool>(values.cpuopt_unsafe_host_mmu);
}
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)

View file

@ -443,7 +443,7 @@ struct Values {
SwitchableSetting<DmaAccuracy, true> dma_accuracy{linkage,
DmaAccuracy::Default,
DmaAccuracy::Default,
DmaAccuracy::Extreme,
DmaAccuracy::Safe,
"dma_accuracy",
Category::RendererAdvanced,
Specialization::Default,
@ -626,10 +626,6 @@ struct Values {
true, true, &rng_seed_enabled};
Setting<std::string> device_name{
linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true};
SwitchableSetting<bool> disable_nca_verification{linkage, true, "disable_nca_verification",
Category::System, Specialization::Default};
Setting<bool> hide_nca_verification_popup{
linkage, false, "hide_nca_verification_popup", Category::System, Specialization::Default};
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
@ -793,6 +789,9 @@ void UpdateGPUAccuracy();
bool IsGPULevelExtreme();
bool IsGPULevelHigh();
bool IsDMALevelDefault();
bool IsDMALevelSafe();
bool IsFastmemEnabled();
void SetNceEnabled(bool is_64bit);
bool IsNceEnabled();

View file

@ -136,7 +136,7 @@ ENUM(ShaderBackend, Glsl, Glasm, SpirV);
ENUM(GpuAccuracy, Normal, High, Extreme);
ENUM(DmaAccuracy, Default, Normal, High, Extreme);
ENUM(DmaAccuracy, Default, Unsafe, Safe);
ENUM(CpuBackend, Dynarmic, Nce);

View file

@ -107,7 +107,6 @@ add_library(core STATIC
file_sys/fssystem/fssystem_nca_header.cpp
file_sys/fssystem/fssystem_nca_header.h
file_sys/fssystem/fssystem_nca_reader.cpp
file_sys/fssystem/fssystem_passthrough_storage.h
file_sys/fssystem/fssystem_pooled_buffer.cpp
file_sys/fssystem/fssystem_pooled_buffer.h
file_sys/fssystem/fssystem_sparse_storage.cpp

View file

@ -305,7 +305,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
}
// Paranoid mode for debugging optimizations
// Paranoia mode for debugging optimizations
if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) {
config.unsafe_optimizations = false;
config.optimizations = Dynarmic::no_optimizations;

View file

@ -4,7 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
@ -238,9 +237,7 @@ void BucketTree::Initialize(size_t node_size, s64 end_offset) {
ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
ASSERT(Common::IsPowerOfTwo(node_size));
if (!Settings::values.disable_nca_verification.GetValue()) {
ASSERT(end_offset > 0);
}
ASSERT(end_offset > 0);
ASSERT(!this->IsInitialized());
m_node_size = node_size;

View file

@ -1,10 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
@ -14,7 +13,6 @@
#include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h"
#include "core/file_sys/fssystem/fssystem_indirect_storage.h"
#include "core/file_sys/fssystem/fssystem_integrity_romfs_storage.h"
#include "core/file_sys/fssystem/fssystem_passthrough_storage.h"
#include "core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h"
#include "core/file_sys/fssystem/fssystem_nca_file_system_driver.h"
#include "core/file_sys/fssystem/fssystem_sparse_storage.h"
@ -1296,91 +1294,65 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl(
ASSERT(base_storage != nullptr);
ASSERT(layer_info_offset >= 0);
if (!Settings::values.disable_nca_verification.GetValue()) {
// Define storage types.
using VerificationStorage = HierarchicalIntegrityVerificationStorage;
using StorageInfo = VerificationStorage::HierarchicalStorageInformation;
// Define storage types.
using VerificationStorage = HierarchicalIntegrityVerificationStorage;
using StorageInfo = VerificationStorage::HierarchicalStorageInformation;
// Validate the meta info.
HierarchicalIntegrityVerificationInformation level_hash_info;
std::memcpy(std::addressof(level_hash_info), std::addressof(meta_info.level_hash_info),
sizeof(level_hash_info));
// Validate the meta info.
HierarchicalIntegrityVerificationInformation level_hash_info;
std::memcpy(std::addressof(level_hash_info),
std::addressof(meta_info.level_hash_info),
sizeof(level_hash_info));
R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(level_hash_info.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(level_hash_info.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
// Get the base storage size.
s64 base_storage_size = base_storage->GetSize();
// Get the base storage size.
s64 base_storage_size = base_storage->GetSize();
// Create storage info.
StorageInfo storage_info;
for (s32 i = 0; i < static_cast<s32>(level_hash_info.max_layers - 2); ++i) {
const auto& layer_info = level_hash_info.info[i];
R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
storage_info[i + 1] = std::make_shared<OffsetVfsFile>(
base_storage, layer_info.size, layer_info_offset + layer_info.offset);
}
// Set the last layer info.
const auto& layer_info = level_hash_info.info[level_hash_info.max_layers - 2];
const s64 last_layer_info_offset = layer_info_offset > 0 ? 0LL : layer_info.offset.Get();
R_UNLESS(last_layer_info_offset + layer_info.size <= base_storage_size,
// Create storage info.
StorageInfo storage_info;
for (s32 i = 0; i < static_cast<s32>(level_hash_info.max_layers - 2); ++i) {
const auto& layer_info = level_hash_info.info[i];
R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
storage_info[level_hash_info.max_layers - 1] = std::make_shared<OffsetVfsFile>(
std::move(base_storage), layer_info.size, last_layer_info_offset);
// Make the integrity romfs storage.
auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();
R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
// Initialize the integrity storage.
R_TRY(integrity_storage->Initialize(level_hash_info, meta_info.master_hash, storage_info,
max_data_cache_entries, max_hash_cache_entries,
buffer_level));
// Set the output.
*out = std::move(integrity_storage);
R_SUCCEED();
} else {
// Read IVFC layout
HierarchicalIntegrityVerificationInformation lhi{};
std::memcpy(std::addressof(lhi), std::addressof(meta_info.level_hash_info), sizeof(lhi));
R_UNLESS(IntegrityMinLayerCount <= lhi.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(lhi.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
const auto& data_li = lhi.info[lhi.max_layers - 2];
const s64 base_size = base_storage->GetSize();
// Compute the data layer window
const s64 data_off = (layer_info_offset > 0) ? 0LL : data_li.offset.Get();
R_UNLESS(data_off + data_li.size <= base_size, ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(data_off + data_li.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
// TODO: Passthrough (temporary compatibility: integrity disabled)
auto data_view = std::make_shared<OffsetVfsFile>(base_storage, data_li.size, data_off);
R_UNLESS(data_view != nullptr, ResultAllocationMemoryFailedAllocateShared);
auto passthrough = std::make_shared<PassthroughStorage>(std::move(data_view));
R_UNLESS(passthrough != nullptr, ResultAllocationMemoryFailedAllocateShared);
*out = std::move(passthrough);
R_SUCCEED();
storage_info[i + 1] = std::make_shared<OffsetVfsFile>(base_storage,
layer_info.size,
layer_info_offset + layer_info.offset);
}
// Set the last layer info.
const auto& layer_info = level_hash_info.info[level_hash_info.max_layers - 2];
const s64 last_layer_info_offset = layer_info_offset > 0 ? 0LL : layer_info.offset.Get();
R_UNLESS(last_layer_info_offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
storage_info[level_hash_info.max_layers - 1]
= std::make_shared<OffsetVfsFile>(std::move(base_storage),
layer_info.size,
last_layer_info_offset);
// Make the integrity romfs storage.
auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();
R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
// Initialize the integrity storage.
R_TRY(integrity_storage->Initialize(level_hash_info,
meta_info.master_hash,
storage_info,
max_data_cache_entries,
max_hash_cache_entries,
buffer_level));
// Set the output.
*out = std::move(integrity_storage);
R_SUCCEED();
}
Result NcaFileSystemDriver::CreateRegionSwitchStorage(VirtualFile* out,

View file

@ -13,13 +13,11 @@ u8 NcaHeader::GetProperKeyGeneration() const {
}
bool NcaPatchInfo::HasIndirectTable() const {
static constexpr unsigned char BKTR[4] = {'B', 'K', 'T', 'R'};
return std::memcmp(indirect_header.data(), BKTR, sizeof(BKTR)) == 0;
return this->indirect_size != 0;
}
bool NcaPatchInfo::HasAesCtrExTable() const {
static constexpr unsigned char BKTR[4] = {'B', 'K', 'T', 'R'};
return std::memcmp(aes_ctr_ex_header.data(), BKTR, sizeof(BKTR)) == 0;
return this->aes_ctr_ex_size != 0;
}
} // namespace FileSys

View file

@ -1,32 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {
//TODO: No integrity verification.
class PassthroughStorage final : public IReadOnlyStorage {
YUZU_NON_COPYABLE(PassthroughStorage);
YUZU_NON_MOVEABLE(PassthroughStorage);
public:
explicit PassthroughStorage(VirtualFile base) : base_(std::move(base)) {}
~PassthroughStorage() override = default;
size_t Read(u8* buffer, size_t size, size_t offset) const override {
if (!base_ || size == 0)
return 0;
return base_->Read(buffer, size, offset);
}
size_t GetSize() const override {
return base_ ? base_->GetSize() : 0;
}
private:
VirtualFile base_{};
};
} // namespace FileSys

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -126,6 +129,10 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
std::string out = GetSaveDataSpaceIdPath(space);
LOG_INFO(Common_Filesystem, "Save ID: {:016X}", save_id);
LOG_INFO(Common_Filesystem, "User ID[1]: {:016X}", user_id[1]);
LOG_INFO(Common_Filesystem, "User ID[0]: {:016X}", user_id[0]);
switch (type) {
case SaveDataType::System:
return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]);

View file

@ -256,61 +256,103 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) {
}
NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
LOG_DEBUG(Service_NVDRV, "called");
ZbcEntry entry = {};
std::memset(&entry, 0, sizeof(entry));
// TODO(ogniK): What does this even actually do?
// TODO(myself): This thing I guess
if (params.type == 1) {
for (auto i = 0; i < 4; ++i) {
entry.color_ds[i] = params.color_ds[i];
entry.color_l2[i] = params.color_l2[i];
}
ASSERT(this->max_color_entries < 16);
this->color_entries[this->max_color_entries] = entry;
++this->max_color_entries;
} else if (params.type == 2) {
entry.depth = params.depth;
ASSERT(this->max_depth_entries < 16);
this->depth_entries[this->max_depth_entries] = entry;
++this->max_depth_entries;
if (params.type > supported_types) {
LOG_ERROR(Service_NVDRV, "ZBCSetTable: invalid type {:#X}", params.type);
return NvResult::BadParameter;
}
std::scoped_lock lk(zbc_mutex);
switch (static_cast<ZBCTypes>(params.type)) {
case ZBCTypes::color: {
ZbcColorEntry color_entry{};
std::copy_n(std::begin(params.color_ds), color_entry.color_ds.size(), color_entry.color_ds.begin());
std::copy_n(std::begin(params.color_l2), color_entry.color_l2.size(), color_entry.color_l2.begin());
color_entry.format = params.format;
color_entry.ref_cnt = 1u;
auto color_it = std::ranges::find_if(zbc_colors,
[&](const ZbcColorEntry& color_in_question) {
return color_entry.format == color_in_question.format &&
color_entry.color_ds == color_in_question.color_ds &&
color_entry.color_l2 == color_in_question.color_l2;
});
if (color_it != zbc_colors.end()) {
++color_it->ref_cnt;
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused color entry fmt={:#X}, ref_cnt={:#X}",
params.format, color_it->ref_cnt);
} else {
zbc_colors.push_back(color_entry);
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added color entry fmt={:#X}, index={:#X}",
params.format, zbc_colors.size() - 1);
}
break;
}
case ZBCTypes::depth: {
ZbcDepthEntry depth_entry{params.depth, params.format, 1u};
auto depth_it = std::ranges::find_if(zbc_depths,
[&](const ZbcDepthEntry& depth_entry_in_question) {
return depth_entry.format == depth_entry_in_question.format &&
depth_entry.depth == depth_entry_in_question.depth;
});
if (depth_it != zbc_depths.end()) {
++depth_it->ref_cnt;
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused depth entry fmt={:#X}, ref_cnt={:#X}",
depth_entry.format, depth_it->ref_cnt);
} else {
zbc_depths.push_back(depth_entry);
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added depth entry fmt={:#X}, index={:#X}",
depth_entry.format, zbc_depths.size() - 1);
}
}
}
return NvResult::Success;
}
NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
LOG_DEBUG(Service_NVDRV, "called");
struct ZbcQueryParams {
u32_le color_ds[4];
u32_le color_l2[4];
u32_le depth;
u32_le ref_cnt;
u32_le format;
u32_le type;
u32_le index_size;
} entry = {};
std::memset(&entry, 0, sizeof(entry));
auto const index = params.index_size;
if (params.type == 0) { //no
entry.index_size = 15;
} else if (params.type == 1) { //color
ASSERT(index < 16);
for (auto i = 0; i < 4; ++i) {
params.color_ds[i] = this->color_entries[index].color_ds[i];
params.color_l2[i] = this->color_entries[index].color_l2[i];
}
// TODO: Only if no error thrown (otherwise dont modify)
params.format = this->color_entries[index].format;
//params.ref_cnt = this->color_entries[index].ref_cnt;
} else if (params.type == 2) { //depth
ASSERT(index < 16);
params.depth = this->depth_entries[index].depth;
// TODO: Only if no error thrown (otherwise dont modify)
params.format = this->depth_entries[index].format;
//params.ref_cnt = this->depth_entries[index].ref_cnt;
} else {
UNREACHABLE();
if (params.type > supported_types) {
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid type {:#X}", params.type);
return NvResult::BadParameter;
}
std::scoped_lock lk(zbc_mutex);
switch (static_cast<ZBCTypes>(params.type)) {
case ZBCTypes::color: {
if (params.index_size >= zbc_colors.size()) {
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid color index {:#X}", params.index_size);
return NvResult::BadParameter;
}
const auto& colors = zbc_colors[params.index_size];
std::copy_n(colors.color_ds.begin(), colors.color_ds.size(), std::begin(params.color_ds));
std::copy_n(colors.color_l2.begin(), colors.color_l2.size(), std::begin(params.color_l2));
params.depth = 0;
params.ref_cnt = colors.ref_cnt;
params.format = colors.format;
params.index_size = static_cast<u32>(zbc_colors.size());
break;
}
case ZBCTypes::depth: {
if (params.index_size >= zbc_depths.size()) {
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid depth index {:#X}", params.index_size);
return NvResult::BadParameter;
}
const auto& depth_entry = zbc_depths[params.index_size];
std::fill(std::begin(params.color_ds), std::end(params.color_ds), 0);
std::fill(std::begin(params.color_l2), std::end(params.color_l2), 0);
params.depth = depth_entry.depth;
params.ref_cnt = depth_entry.ref_cnt;
params.format = depth_entry.format;
params.index_size = static_cast<u32>(zbc_depths.size());
}
}
return NvResult::Success;
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -34,6 +37,11 @@ public:
Kernel::KEvent* QueryEvent(u32 event_id) override;
private:
enum class ZBCTypes {
color = 1,
depth = 2,
};
struct IoctlGpuCharacteristics {
u32_le arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
u32_le impl; // 0xB (NVGPU_GPU_IMPL_GM20B)
@ -139,6 +147,21 @@ private:
};
static_assert(sizeof(IoctlZbcQueryTable) == 52, "IoctlZbcQueryTable is incorrect size");
struct ZbcColorEntry {
std::array<u32, 4> color_ds{};
std::array<u32, 4> color_l2{};
u32 format{};
u32 ref_cnt{};
};
static_assert(sizeof(ZbcColorEntry) == 40, "ZbcColorEntry is incorrect size");
struct ZbcDepthEntry {
u32 depth{};
u32 format{};
u32 ref_cnt{};
};
static_assert(sizeof(ZbcDepthEntry) == 12, "ZbcDepthEntry is incorrect size");
struct IoctlFlushL2 {
u32_le flush; // l2_flush | l2_invalidate << 1 | fb_flush << 2
u32_le reserved;
@ -182,17 +205,11 @@ private:
Kernel::KEvent* error_notifier_event;
Kernel::KEvent* unknown_event;
struct ZbcEntry {
u32_le color_ds[4];
u32_le color_l2[4];
u32_le depth;
u32_le type;
u32_le format;
};
std::array<ZbcEntry, 16> color_entries;
std::array<ZbcEntry, 16> depth_entries;
u8 max_color_entries;
u8 max_depth_entries;
// ZBC Tables
std::mutex zbc_mutex{};
std::vector<ZbcColorEntry> zbc_colors{};
std::vector<ZbcDepthEntry> zbc_depths{};
const u32 supported_types = 2u;
};
} // namespace Service::Nvidia::Devices

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -97,18 +100,18 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
slots[slot].needs_cleanup_on_release = false;
slots[slot].buffer_state = BufferState::Acquired;
// Mark tracked buffer history records as acquired
for (auto& buffer_history_record : core->buffer_history) {
if (buffer_history_record.frame_number == core->frame_counter) {
buffer_history_record.state = BufferState::Acquired;
break;
}
}
// TODO: for now, avoid resetting the fence, so that when we next return this
// slot to the producer, it will wait for the fence to pass. We should fix this
// by properly waiting for the fence in the BufferItemConsumer.
// slots[slot].fence = Fence::NoFence();
const auto target_frame_number = slots[slot].frame_number;
for (size_t i = 0; i < core->history.size(); i++) {
if (core->history[i].frame_number == target_frame_number) {
core->history[i].state = BufferState::Acquired;
break;
}
}
}
// If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -10,12 +13,19 @@
namespace Service::android {
BufferQueueCore::BufferQueueCore() {
history.resize(8);
};
BufferQueueCore::BufferQueueCore() = default;
BufferQueueCore::~BufferQueueCore() = default;
void BufferQueueCore::PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state) {
buffer_history_pos = (buffer_history_pos + 1) % BUFFER_HISTORY_SIZE;
buffer_history[buffer_history_pos] = BufferHistoryInfo{
.frame_number = frame_number,
.queue_time = queue_time,
.presentation_time = presentation_time,
.state = state,
};
}
void BufferQueueCore::SignalDequeueCondition() {
dequeue_possible.store(true);
dequeue_condition.notify_all();
@ -47,7 +57,7 @@ s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const {
s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const {
const auto min_buffer_count = GetMinMaxBufferCountLocked(async);
auto max_buffer_count = (std::max)(default_max_buffer_count, min_buffer_count);
auto max_buffer_count = std::max(default_max_buffer_count, min_buffer_count);
if (override_max_buffer_count != 0) {
ASSERT(override_max_buffer_count >= min_buffer_count);

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -15,6 +18,7 @@
#include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/buffer_slot.h"
#include "core/hle/service/nvnflinger/pixel_format.h"
#include "core/hle/service/nvnflinger/status.h"
#include "core/hle/service/nvnflinger/window.h"
@ -23,22 +27,19 @@ namespace Service::android {
#ifdef _MSC_VER
#pragma pack(push, 1)
struct BufferHistoryInfo {
#elif defined(__GNUC__) || defined(__clang__)
struct __attribute__((packed)) BufferHistoryInfo {
#endif
struct BufferInfo {
u64 frame_number;
s64 queue_time;
s64 presentation_time{};
BufferState state{BufferState::Free};
}
#if defined(__GNUC__) || defined(__clang__)
__attribute__((packed))
#endif
;
s64 presentation_time;
BufferState state;
};
#ifdef _MSC_VER
#pragma pack(pop)
#endif
static_assert(sizeof(BufferInfo) == 0x1C,
"BufferInfo is an invalid size");
static_assert(sizeof(BufferHistoryInfo) == 0x1C, "BufferHistoryInfo must be 28 bytes");
class IConsumerListener;
class IProducerListener;
@ -49,10 +50,13 @@ class BufferQueueCore final {
public:
static constexpr s32 INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT;
static constexpr u32 BUFFER_HISTORY_SIZE = 8;
BufferQueueCore();
~BufferQueueCore();
void PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state);
private:
void SignalDequeueCondition();
bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
@ -88,11 +92,11 @@ private:
const s32 max_acquired_buffer_count{}; // This is always zero on HOS
bool buffer_has_been_queued{};
u64 frame_counter{};
std::array<BufferHistoryInfo, BUFFER_HISTORY_SIZE> buffer_history{};
u32 buffer_history_pos{BUFFER_HISTORY_SIZE-1};
u32 transform_hint{};
bool is_allocating{};
mutable std::condition_variable_any is_allocating_condition;
std::vector<BufferInfo> history{8};
};
} // namespace Service::android

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -530,11 +533,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
item.is_droppable = core->dequeue_buffer_cannot_block || async;
item.swap_interval = swap_interval;
position = (position + 1) % 8;
core->history[position] = {.frame_number = core->frame_counter,
.queue_time = slots[slot].queue_time,
.state = BufferState::Queued};
sticky_transform = sticky_transform_;
if (core->queue.empty()) {
@ -551,6 +549,15 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
// mark it as freed
if (core->StillTracking(*front)) {
slots[front->slot].buffer_state = BufferState::Free;
// Mark tracked buffer history records as free
for (auto& buffer_history_record : core->buffer_history) {
if (buffer_history_record.frame_number == front->frame_number) {
buffer_history_record.state = BufferState::Free;
break;
}
}
// Reset the frame number of the freed buffer so that it is the first in line to
// be dequeued again
slots[front->slot].frame_number = 0;
@ -564,6 +571,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
}
}
core->PushHistory(core->frame_counter, slots[slot].queue_time, slots[slot].presentation_time, BufferState::Queued);
core->buffer_has_been_queued = true;
core->SignalDequeueCondition();
output->Inflate(core->default_width, core->default_height, core->transform_hint,
@ -938,33 +946,46 @@ void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
break;
}
case TransactionId::GetBufferHistory: {
LOG_WARNING(Service_Nvnflinger, "called, transaction=GetBufferHistory");
LOG_DEBUG(Service_Nvnflinger, "called, transaction=GetBufferHistory");
std::scoped_lock lock{core->mutex};
auto buffer_history_count = (std::min)(parcel_in.Read<s32>(), (s32)core->history.size());
if (buffer_history_count <= 0) {
const s32 request = parcel_in.Read<s32>();
if (request <= 0) {
parcel_out.Write(Status::BadValue);
parcel_out.Write<s32>(0);
status = Status::None;
break;
}
auto info = new BufferInfo[buffer_history_count];
auto pos = position;
for (int i = 0; i < buffer_history_count; i++) {
info[i] = core->history[(pos - i) % core->history.size()];
LOG_WARNING(Service_Nvnflinger, "frame_number={}, state={}",
core->history[(pos - i) % core->history.size()].frame_number,
(u32)core->history[(pos - i) % core->history.size()].state);
pos--;
constexpr u32 history_max = BufferQueueCore::BUFFER_HISTORY_SIZE;
std::array<BufferHistoryInfo, history_max> buffer_history_snapshot{};
s32 valid_index{};
{
std::scoped_lock lk(core->mutex);
const u32 current_history_pos = core->buffer_history_pos;
u32 index_reversed{};
for (u32 i = 0; i < history_max; ++i) {
// Wrap values backwards e.g. 7, 6, 5, etc. in the range of 0-7
index_reversed = (current_history_pos + history_max - i) % history_max;
const auto& current_history_buffer = core->buffer_history[index_reversed];
// Here we use the frame number as a terminator.
// Because a buffer without frame_number is not considered complete
if (current_history_buffer.frame_number == 0) {
break;
}
buffer_history_snapshot[valid_index] = current_history_buffer;
++valid_index;
}
}
const s32 limit = std::min(request, valid_index);
parcel_out.Write(Status::NoError);
parcel_out.Write(buffer_history_count);
parcel_out.WriteFlattenedObject<BufferInfo>(info);
status = Status::None;
parcel_out.Write<s32>(limit);
for (s32 i = 0; i < limit; ++i) {
parcel_out.Write(buffer_history_snapshot[i]);
}
break;
}
default:
@ -972,9 +993,7 @@ void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
break;
}
if (status != Status::None) {
parcel_out.Write(status);
}
parcel_out.Write(status);
const auto serialized = parcel_out.Serialize();
std::memcpy(parcel_reply.data(), serialized.data(),

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -15,7 +18,7 @@ namespace Service::android {
class GraphicBuffer;
enum class BufferState : s32 {
enum class BufferState : u32 {
Free = 0,
Dequeued = 1,
Queued = 2,

View file

@ -6,8 +6,13 @@
* SPDX-License-Identifier: 0BSD
*/
#include "dynarmic/backend/exception_handler.h"
#include <cstring>
#include <functional>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <optional>
#include <sys/mman.h>
#ifdef __APPLE__
# include <signal.h>
# include <sys/ucontext.h>
@ -21,17 +26,10 @@
# endif
#endif
#include <cstring>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <vector>
#include <ankerl/unordered_dense.h>
#include "dynarmic/common/assert.h"
#include <mcl/bit_cast.hpp>
#include "dynarmic/backend/exception_handler.h"
#include "dynarmic/common/common_types.h"
#if defined(MCL_ARCHITECTURE_X86_64)
# include "dynarmic/backend/x64/block_of_code.h"
#elif defined(MCL_ARCHITECTURE_ARM64)
@ -43,42 +41,80 @@
#else
# error "Invalid architecture"
#endif
#include <mcl/bit_cast.hpp>
namespace Dynarmic::Backend {
namespace {
struct CodeBlockInfo {
u64 code_begin, code_end;
u64 size;
std::function<FakeCall(u64)> cb;
};
class SigHandler {
public:
SigHandler();
~SigHandler();
void AddCodeBlock(CodeBlockInfo info);
void RemoveCodeBlock(u64 host_pc);
bool SupportsFastmem() const { return supports_fast_mem; }
private:
auto FindCodeBlockInfo(u64 host_pc) {
return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](const auto& x) { return x.code_begin <= host_pc && x.code_end > host_pc; });
auto FindCodeBlockInfo(u64 offset) noexcept {
return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](auto const& e) {
return e.first <= offset && e.first + e.second.size > offset;
});
}
static void SigAction(int sig, siginfo_t* info, void* raw_context);
bool supports_fast_mem = true;
void* signal_stack_memory = nullptr;
std::vector<CodeBlockInfo> code_block_infos;
std::mutex code_block_infos_mutex;
ankerl::unordered_dense::map<u64, CodeBlockInfo> code_block_infos;
std::shared_mutex code_block_infos_mutex;
struct sigaction old_sa_segv;
struct sigaction old_sa_bus;
std::size_t signal_stack_size;
public:
SigHandler() noexcept {
signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
static void SigAction(int sig, siginfo_t* info, void* raw_context);
stack_t signal_stack{};
signal_stack.ss_sp = signal_stack_memory;
signal_stack.ss_size = signal_stack_size;
signal_stack.ss_flags = 0;
if (sigaltstack(&signal_stack, nullptr) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n");
supports_fast_mem = false;
return;
}
struct sigaction sa{};
sa.sa_handler = nullptr;
sa.sa_sigaction = &SigHandler::SigAction;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n");
supports_fast_mem = false;
return;
}
#ifdef __APPLE__
if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n");
supports_fast_mem = false;
return;
}
#endif
}
~SigHandler() noexcept {
munmap(signal_stack_memory, signal_stack_size);
}
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {
std::unique_lock guard(code_block_infos_mutex);
code_block_infos.insert_or_assign(offset, cbi);
}
void RemoveCodeBlock(u64 offset) noexcept {
std::unique_lock guard(code_block_infos_mutex);
code_block_infos.erase(offset);
}
bool SupportsFastmem() const noexcept { return supports_fast_mem; }
};
std::mutex handler_lock;
@ -91,64 +127,8 @@ void RegisterHandler() {
}
}
SigHandler::SigHandler() {
const size_t signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
signal_stack_memory = std::malloc(signal_stack_size);
stack_t signal_stack;
signal_stack.ss_sp = signal_stack_memory;
signal_stack.ss_size = signal_stack_size;
signal_stack.ss_flags = 0;
if (sigaltstack(&signal_stack, nullptr) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n");
supports_fast_mem = false;
return;
}
struct sigaction sa;
sa.sa_handler = nullptr;
sa.sa_sigaction = &SigHandler::SigAction;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n");
supports_fast_mem = false;
return;
}
#ifdef __APPLE__
if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) {
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n");
supports_fast_mem = false;
return;
}
#endif
}
SigHandler::~SigHandler() {
std::free(signal_stack_memory);
}
void SigHandler::AddCodeBlock(CodeBlockInfo cbi) {
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
if (auto iter = FindCodeBlockInfo(cbi.code_begin); iter != code_block_infos.end()) {
code_block_infos.erase(iter);
}
code_block_infos.push_back(cbi);
}
void SigHandler::RemoveCodeBlock(u64 host_pc) {
std::lock_guard<std::mutex> guard(code_block_infos_mutex);
const auto iter = FindCodeBlockInfo(host_pc);
if (iter == code_block_infos.end()) {
return;
}
code_block_infos.erase(iter);
}
void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
ASSERT(sig == SIGSEGV || sig == SIGBUS);
DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS);
#ifndef MCL_ARCHITECTURE_RISCV
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(raw_context);
#ifndef __OpenBSD__
@ -157,7 +137,6 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
#endif
#if defined(MCL_ARCHITECTURE_X86_64)
# if defined(__APPLE__)
# define CTX_RIP (mctx->__ss.__rip)
# define CTX_RSP (mctx->__ss.__rsp)
@ -179,26 +158,18 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
# else
# error "Unknown platform"
# endif
{
std::lock_guard<std::mutex> guard(sig_handler->code_block_infos_mutex);
const auto iter = sig_handler->FindCodeBlockInfo(CTX_RIP);
if (iter != sig_handler->code_block_infos.end()) {
FakeCall fc = iter->cb(CTX_RIP);
std::shared_lock guard(sig_handler->code_block_infos_mutex);
if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_RIP); iter != sig_handler->code_block_infos.end()) {
FakeCall fc = iter->second.cb(CTX_RIP);
CTX_RSP -= sizeof(u64);
*mcl::bit_cast<u64*>(CTX_RSP) = fc.ret_rip;
CTX_RIP = fc.call_rip;
return;
}
}
fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP);
#elif defined(MCL_ARCHITECTURE_ARM64)
# if defined(__APPLE__)
# define CTX_PC (mctx->__ss.__pc)
# define CTX_SP (mctx->__ss.__sp)
@ -240,30 +211,19 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
# else
# error "Unknown platform"
# endif
{
std::lock_guard<std::mutex> guard(sig_handler->code_block_infos_mutex);
const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC);
if (iter != sig_handler->code_block_infos.end()) {
FakeCall fc = iter->cb(CTX_PC);
std::shared_lock guard(sig_handler->code_block_infos_mutex);
if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) {
FakeCall fc = iter->second.cb(CTX_PC);
CTX_PC = fc.call_pc;
return;
}
}
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
#elif defined(MCL_ARCHITECTURE_RISCV)
ASSERT_FALSE("Unimplemented");
#else
# error "Invalid architecture"
#endif
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus;
@ -284,26 +244,26 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
} // anonymous namespace
struct ExceptionHandler::Impl final {
Impl(u64 code_begin_, u64 code_end_)
: code_begin(code_begin_)
, code_end(code_end_) {
Impl(u64 offset_, u64 size_)
: offset(offset_)
, size(size_) {
RegisterHandler();
}
void SetCallback(std::function<FakeCall(u64)> cb) {
CodeBlockInfo cbi;
cbi.code_begin = code_begin;
cbi.code_end = code_end;
cbi.cb = cb;
sig_handler->AddCodeBlock(cbi);
sig_handler->AddCodeBlock(offset, CodeBlockInfo{
.size = size,
.cb = cb
});
}
~Impl() {
sig_handler->RemoveCodeBlock(code_begin);
sig_handler->RemoveCodeBlock(offset);
}
private:
u64 code_begin, code_end;
u64 offset;
u64 size;
};
ExceptionHandler::ExceptionHandler() = default;
@ -311,28 +271,22 @@ ExceptionHandler::~ExceptionHandler() = default;
#if defined(MCL_ARCHITECTURE_X86_64)
void ExceptionHandler::Register(X64::BlockOfCode& code) {
const u64 code_begin = mcl::bit_cast<u64>(code.getCode());
const u64 code_end = code_begin + code.GetTotalCodeSize();
impl = std::make_unique<Impl>(code_begin, code_end);
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(code.getCode()), code.GetTotalCodeSize());
}
#elif defined(MCL_ARCHITECTURE_ARM64)
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
const u64 code_end = code_begin + size;
impl = std::make_unique<Impl>(code_begin, code_end);
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(mem.ptr()), size);
}
#elif defined(MCL_ARCHITECTURE_RISCV)
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr<u64>());
const u64 code_end = code_begin + size;
impl = std::make_unique<Impl>(code_begin, code_end);
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(mem.ptr<u64>()), size);
}
#else
# error "Invalid architecture"
#endif
bool ExceptionHandler::SupportsFastmem() const noexcept {
return static_cast<bool>(impl) && sig_handler->SupportsFastmem();
return bool(impl) && sig_handler->SupportsFastmem();
}
void ExceptionHandler::SetFastmemCallback(std::function<FakeCall(u64)> cb) {

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(Qt6 REQUIRED COMPONENTS Core)
find_package(Qt6 REQUIRED COMPONENTS Core)
add_library(qt_common STATIC
qt_common.h
qt_common.cpp
uisettings.cpp
uisettings.h
qt_config.cpp
qt_config.h
shared_translation.cpp
shared_translation.h
qt_path_util.h qt_path_util.cpp
qt_game_util.h qt_game_util.cpp
qt_frontend_util.h qt_frontend_util.cpp
qt_meta.h qt_meta.cpp
qt_content_util.h qt_content_util.cpp
qt_rom_util.h qt_rom_util.cpp
qt_applet_util.h qt_applet_util.cpp
qt_progress_dialog.h qt_progress_dialog.cpp
)
create_target_directory_groups(qt_common)
# TODO(crueter)
if (ENABLE_QT)
target_link_libraries(qt_common PRIVATE Qt6::Widgets)
endif()
add_subdirectory(externals)
target_link_libraries(qt_common PRIVATE core Qt6::Core SimpleIni::SimpleIni QuaZip::QuaZip frozen::frozen)
target_link_libraries(qt_common PRIVATE Qt6::Core)
if (NOT WIN32)
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
endif()

View file

@ -14,3 +14,7 @@ set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
# QuaZip
AddJsonPackage(quazip)
# frozen
# TODO(crueter): Qt String Lookup
AddJsonPackage(frozen)

View file

@ -8,5 +8,12 @@
"options": [
"QUAZIP_INSTALL OFF"
]
},
"frozen": {
"package": "frozen",
"repo": "serge-sans-paille/frozen",
"sha": "61dce5ae18",
"hash": "1ae3d073e659c1f24b2cdd76379c90d6af9e06bc707d285a4fafce05f7a4c9e592ff208c94a9ae0f0d07620b3c6cec191f126b03d70ad4dfa496a86ed5658a6d",
"bundled": true
}
}

View file

@ -0,0 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_applet_util.h"

View file

@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_APPLET_UTIL_H
#define QT_APPLET_UTIL_H
// TODO
namespace QtCommon::Applets {
}
#endif // QT_APPLET_UTIL_H

View file

@ -1,12 +1,19 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_common.h"
#include "common/fs/fs.h"
#include <QGuiApplication>
#include <QStringLiteral>
#include <QWindow>
#include "common/logging/log.h"
#include "core/frontend/emu_window.h"
#include "yuzu/qt_common.h"
#include <QFile>
#include <QMessageBox>
#include <JlCompress.h>
#if !defined(WIN32) && !defined(__APPLE__)
#include <qpa/qplatformnativeinterface.h>
@ -15,7 +22,19 @@
#endif
namespace QtCommon {
Core::Frontend::WindowSystemType GetWindowSystemType() {
#ifdef YUZU_QT_WIDGETS
QWidget* rootObject = nullptr;
#else
QObject* rootObject = nullptr;
#endif
std::unique_ptr<Core::System> system = nullptr;
std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr;
std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr;
Core::Frontend::WindowSystemType GetWindowSystemType()
{
// Determine WSI type based on Qt platform.
QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("windows"))
@ -35,7 +54,8 @@ Core::Frontend::WindowSystemType GetWindowSystemType() {
return Core::Frontend::WindowSystemType::Windows;
} // namespace Core::Frontend::WindowSystemType
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) {
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
{
Core::Frontend::EmuWindow::WindowSystemInfo wsi;
wsi.type = GetWindowSystemType();
@ -43,8 +63,8 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
// Our Win32 Qt external doesn't have the private API.
wsi.render_surface = reinterpret_cast<void*>(window->winId());
#elif defined(__APPLE__)
wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)(
reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
wsi.render_surface = reinterpret_cast<void* (*) (id, SEL)>(
objc_msgSend)(reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
#else
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
wsi.display_connection = pni->nativeResourceForWindow("display", window);
@ -57,4 +77,46 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
return wsi;
}
const QString tr(const char* str)
{
return QGuiApplication::tr(str);
}
const QString tr(const std::string& str)
{
return QGuiApplication::tr(str.c_str());
}
#ifdef YUZU_QT_WIDGETS
void Init(QWidget* root)
#else
void Init(QObject* root)
#endif
{
system = std::make_unique<Core::System>();
rootObject = root;
vfs = std::make_unique<FileSys::RealVfsFilesystem>();
provider = std::make_unique<FileSys::ManualContentProvider>();
}
std::filesystem::path GetEdenCommand() {
std::filesystem::path command;
QString appimage = QString::fromLocal8Bit(getenv("APPIMAGE"));
if (!appimage.isEmpty()) {
command = std::filesystem::path{appimage.toStdString()};
} else {
const QStringList args = QGuiApplication::arguments();
command = args[0].toStdString();
}
// If relative path, make it an absolute path
if (command.c_str()[0] == '.') {
command = Common::FS::GetCurrentDir() / command;
}
return command;
}
} // namespace QtCommon

44
src/qt_common/qt_common.h Normal file
View file

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_COMMON_H
#define QT_COMMON_H
#include <QWindow>
#include "core/core.h"
#include "core/file_sys/registered_cache.h"
#include <core/frontend/emu_window.h>
#include <memory>
#include <core/file_sys/vfs/vfs_real.h>
namespace QtCommon {
#ifdef YUZU_QT_WIDGETS
extern QWidget *rootObject;
#else
extern QObject *rootObject;
#endif
extern std::unique_ptr<Core::System> system;
extern std::shared_ptr<FileSys::RealVfsFilesystem> vfs;
extern std::unique_ptr<FileSys::ManualContentProvider> provider;
typedef std::function<bool(std::size_t, std::size_t)> QtProgressCallback;
Core::Frontend::WindowSystemType GetWindowSystemType();
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow *window);
#ifdef YUZU_QT_WIDGETS
void Init(QWidget *root);
#else
void Init(QObject *root);
#endif
const QString tr(const char *str);
const QString tr(const std::string &str);
std::filesystem::path GetEdenCommand();
} // namespace QtCommon
#endif

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

View file

@ -0,0 +1,313 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_content_util.h"
#include "common/fs/fs.h"
#include "frontend_common/content_manager.h"
#include "frontend_common/firmware_manager.h"
#include "qt_common/qt_common.h"
#include "qt_common/qt_progress_dialog.h"
#include "qt_frontend_util.h"
#include <JlCompress.h>
namespace QtCommon::Content {
bool CheckGameFirmware(u64 program_id, QObject* parent)
{
if (FirmwareManager::GameRequiresFirmware(program_id)
&& !FirmwareManager::CheckFirmwarePresence(*system)) {
auto result = QtCommon::Frontend::ShowMessage(
QMessageBox::Warning,
"Game Requires Firmware",
"The game you are trying to launch requires firmware to boot or to get past the "
"opening menu. Please <a href='https://yuzu-mirror.github.io/help/quickstart'>"
"dump and install firmware</a>, or press \"OK\" to launch anyways.",
QMessageBox::Ok | QMessageBox::Cancel,
parent);
return result == QMessageBox::Ok;
}
return true;
}
void InstallFirmware(const QString& location, bool recursive)
{
QtCommon::Frontend::QtProgressDialog progress(tr("Installing Firmware..."),
tr("Cancel"),
0,
100,
rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
progress.show();
// Declare progress callback.
auto callback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
};
static constexpr const char* failedTitle = "Firmware Install Failed";
static constexpr const char* successTitle = "Firmware Install Succeeded";
QMessageBox::Icon icon;
FirmwareInstallResult result;
const auto ShowMessage = [&]() {
QtCommon::Frontend::ShowMessage(icon,
failedTitle,
GetFirmwareInstallResultString(result));
};
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
// Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in
// there.)
std::filesystem::path firmware_source_path = location.toStdString();
if (!Common::FS::IsDir(firmware_source_path)) {
return;
}
std::vector<std::filesystem::path> out;
const Common::FS::DirEntryCallable dir_callback =
[&out](const std::filesystem::directory_entry& entry) {
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
out.emplace_back(entry.path());
}
return true;
};
callback(100, 10);
if (recursive) {
Common::FS::IterateDirEntriesRecursively(firmware_source_path,
dir_callback,
Common::FS::DirEntryFilter::File);
} else {
Common::FS::IterateDirEntries(firmware_source_path,
dir_callback,
Common::FS::DirEntryFilter::File);
}
if (out.size() <= 0) {
result = FirmwareInstallResult::NoNCAs;
icon = QMessageBox::Warning;
ShowMessage();
return;
}
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
if (sysnand_content_vdir->IsWritable()
&& !sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
result = FirmwareInstallResult::FailedDelete;
icon = QMessageBox::Critical;
ShowMessage();
return;
}
LOG_INFO(Frontend,
"Cleaned nand/system/Content/registered folder in preparation for new firmware.");
callback(100, 20);
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
bool success = true;
int i = 0;
for (const auto& firmware_src_path : out) {
i++;
auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(),
FileSys::OpenMode::Read);
auto firmware_dst_vfile = firmware_vdir
->CreateFileRelative(firmware_src_path.filename().string());
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
LOG_ERROR(Frontend,
"Failed to copy firmware file {} to {} in registered folder!",
firmware_src_path.generic_string(),
firmware_src_path.filename().string());
success = false;
}
if (callback(100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) {
result = FirmwareInstallResult::FailedCorrupted;
icon = QMessageBox::Warning;
ShowMessage();
return;
}
}
if (!success) {
result = FirmwareInstallResult::FailedCopy;
icon = QMessageBox::Critical;
ShowMessage();
return;
}
// Re-scan VFS for the newly placed firmware files.
system->GetFileSystemController().CreateFactories(*vfs);
auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) {
progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size));
return progress.wasCanceled();
};
auto results = ContentManager::VerifyInstalledContents(*QtCommon::system,
*QtCommon::provider,
VerifyFirmwareCallback,
true);
if (results.size() > 0) {
const auto failed_names = QString::fromStdString(
fmt::format("{}", fmt::join(results, "\n")));
progress.close();
QtCommon::Frontend::Critical(tr("Firmware integrity verification failed!"),
tr("Verification failed for the following files:\n\n%1")
.arg(failed_names));
return;
}
progress.close();
const auto pair = FirmwareManager::GetFirmwareVersion(*system);
const auto firmware_data = pair.first;
const std::string display_version(firmware_data.display_version.data());
result = FirmwareInstallResult::Success;
QtCommon::Frontend::Information(rootObject,
tr(successTitle),
tr(GetFirmwareInstallResultString(result))
.arg(QString::fromStdString(display_version)));
}
QString UnzipFirmwareToTmp(const QString& location)
{
namespace fs = std::filesystem;
fs::path tmp{fs::temp_directory_path()};
if (!fs::create_directories(tmp / "eden" / "firmware")) {
return "";
}
tmp /= "eden";
tmp /= "firmware";
QString qCacheDir = QString::fromStdString(tmp.string());
QFile zip(location);
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
if (result.isEmpty()) {
return "";
}
return qCacheDir;
}
// Content //
void VerifyGameContents(const std::string& game_path)
{
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."),
tr("Cancel"),
0,
100,
rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
const auto callback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
};
const auto result = ContentManager::VerifyGameContents(*system, game_path, callback);
switch (result) {
case ContentManager::GameVerificationResult::Success:
QtCommon::Frontend::Information(rootObject,
tr("Integrity verification succeeded!"),
tr("The operation completed successfully."));
break;
case ContentManager::GameVerificationResult::Failed:
QtCommon::Frontend::Critical(rootObject,
tr("Integrity verification failed!"),
tr("File contents may be corrupt or missing."));
break;
case ContentManager::GameVerificationResult::NotImplemented:
QtCommon::Frontend::Warning(
rootObject,
tr("Integrity verification couldn't be performed"),
tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. "
"File contents could not be checked for validity."));
}
}
void InstallKeys()
{
const QString key_source_location
= QtCommon::Frontend::GetOpenFileName(tr("Select Dumped Keys Location"),
{},
QStringLiteral("Decryption Keys (*.keys)"),
{},
QtCommon::Frontend::Option::ReadOnly);
if (key_source_location.isEmpty()) {
return;
}
FirmwareManager::KeyInstallResult result = FirmwareManager::InstallKeys(key_source_location
.toStdString(),
"keys");
system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
switch (result) {
case FirmwareManager::KeyInstallResult::Success:
QtCommon::Frontend::Information(tr("Decryption Keys install succeeded"),
tr("Decryption Keys were successfully installed"));
break;
default:
QtCommon::Frontend::Critical(tr("Decryption Keys install failed"),
tr(FirmwareManager::GetKeyInstallResultString(result)));
break;
}
}
void VerifyInstalledContents() {
// Initialize a progress dialog.
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, QtCommon::rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
// Declare progress callback.
auto QtProgressCallback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
};
const std::vector<std::string> result =
ContentManager::VerifyInstalledContents(*QtCommon::system, *QtCommon::provider, QtProgressCallback);
progress.close();
if (result.empty()) {
QtCommon::Frontend::Information(tr("Integrity verification succeeded!"),
tr("The operation completed successfully."));
} else {
const auto failed_names =
QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
QtCommon::Frontend::Critical(
tr("Integrity verification failed!"),
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
}
}
} // namespace QtCommon::Content

View file

@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_CONTENT_UTIL_H
#define QT_CONTENT_UTIL_H
#include <QObject>
#include "common/common_types.h"
namespace QtCommon::Content {
//
bool CheckGameFirmware(u64 program_id, QObject *parent);
static constexpr std::array<const char *, 6> FIRMWARE_RESULTS
= {"Successfully installed firmware version %1",
"",
"Unable to locate potential firmware NCA files",
"Failed to delete one or more firmware files.",
"One or more firmware files failed to copy into NAND.",
"Firmware installation cancelled, firmware may be in a bad state or corrupted."
"Restart Eden or re-install firmware."};
enum class FirmwareInstallResult {
Success,
NoOp,
NoNCAs,
FailedDelete,
FailedCopy,
FailedCorrupted,
};
inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result)
{
return FIRMWARE_RESULTS.at(static_cast<std::size_t>(result));
}
void InstallFirmware(const QString &location, bool recursive);
QString UnzipFirmwareToTmp(const QString &location);
// Keys //
void InstallKeys();
// Content //
void VerifyGameContents(const std::string &game_path);
void VerifyInstalledContents();
}
#endif // QT_CONTENT_UTIL_H

View file

@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_frontend_util.h"
#include "qt_common/qt_common.h"
#ifdef YUZU_QT_WIDGETS
#include <QFileDialog>
#endif
namespace QtCommon::Frontend {
StandardButton ShowMessage(
Icon icon, const QString &title, const QString &text, StandardButtons buttons, QObject *parent)
{
#ifdef YUZU_QT_WIDGETS
QMessageBox *box = new QMessageBox(icon, title, text, buttons, (QWidget *) parent);
return static_cast<QMessageBox::StandardButton>(box->exec());
#endif
// TODO(crueter): If Qt Widgets is disabled...
// need a way to reference icon/buttons too
}
const QString GetOpenFileName(const QString &title,
const QString &dir,
const QString &filter,
QString *selectedFilter,
Options options)
{
#ifdef YUZU_QT_WIDGETS
return QFileDialog::getOpenFileName((QWidget *) rootObject, title, dir, filter, selectedFilter, options);
#endif
}
} // namespace QtCommon::Frontend

View file

@ -0,0 +1,148 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_FRONTEND_UTIL_H
#define QT_FRONTEND_UTIL_H
#include <QGuiApplication>
#include "qt_common/qt_common.h"
#ifdef YUZU_QT_WIDGETS
#include <QFileDialog>
#include <QWidget>
#include <QMessageBox>
#endif
/**
* manages common functionality e.g. message boxes and such for Qt/QML
*/
namespace QtCommon::Frontend {
Q_NAMESPACE
#ifdef YUZU_QT_WIDGETS
using Options = QFileDialog::Options;
using Option = QFileDialog::Option;
using StandardButton = QMessageBox::StandardButton;
using StandardButtons = QMessageBox::StandardButtons;
using Icon = QMessageBox::Icon;
#else
enum Option {
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseNativeDialog = 0x00000008,
ReadOnly = 0x00000010,
HideNameFilterDetails = 0x00000020,
DontUseCustomDirectoryIcons = 0x00000040
};
Q_ENUM_NS(Option)
Q_DECLARE_FLAGS(Options, Option)
Q_FLAG_NS(Options)
enum StandardButton {
// keep this in sync with QDialogButtonBox::StandardButton and QPlatformDialogHelper::StandardButton
NoButton = 0x00000000,
Ok = 0x00000400,
Save = 0x00000800,
SaveAll = 0x00001000,
Open = 0x00002000,
Yes = 0x00004000,
YesToAll = 0x00008000,
No = 0x00010000,
NoToAll = 0x00020000,
Abort = 0x00040000,
Retry = 0x00080000,
Ignore = 0x00100000,
Close = 0x00200000,
Cancel = 0x00400000,
Discard = 0x00800000,
Help = 0x01000000,
Apply = 0x02000000,
Reset = 0x04000000,
RestoreDefaults = 0x08000000,
FirstButton = Ok, // internal
LastButton = RestoreDefaults, // internal
YesAll = YesToAll, // obsolete
NoAll = NoToAll, // obsolete
Default = 0x00000100, // obsolete
Escape = 0x00000200, // obsolete
FlagMask = 0x00000300, // obsolete
ButtonMask = ~FlagMask // obsolete
};
Q_ENUM_NS(StandardButton)
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
typedef StandardButton Button;
#endif
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
Q_FLAG_NS(StandardButtons)
enum Icon {
// keep this in sync with QMessageDialogOptions::StandardIcon
NoIcon = 0,
Information = 1,
Warning = 2,
Critical = 3,
Question = 4
};
Q_ENUM_NS(Icon)
#endif
// TODO(crueter) widgets-less impl, choices et al.
StandardButton ShowMessage(Icon icon,
const QString &title,
const QString &text,
StandardButtons buttons = StandardButton::NoButton,
QObject *parent = nullptr);
#define UTIL_OVERRIDES(level) \
inline StandardButton level(QObject *parent, \
const QString &title, \
const QString &text, \
StandardButtons buttons = StandardButton::Ok) \
{ \
return ShowMessage(Icon::level, title, text, buttons, parent); \
} \
inline StandardButton level(QObject *parent, \
const char *title, \
const char *text, \
StandardButtons buttons \
= StandardButton::Ok) \
{ \
return ShowMessage(Icon::level, tr(title), tr(text), buttons, parent); \
} \
inline StandardButton level(const char *title, \
const char *text, \
StandardButtons buttons \
= StandardButton::Ok) \
{ \
return ShowMessage(Icon::level, tr(title), tr(text), buttons, rootObject); \
} \
inline StandardButton level(const QString title, \
const QString &text, \
StandardButtons buttons \
= StandardButton::Ok) \
{ \
return ShowMessage(Icon::level, title, text, buttons, rootObject); \
}
UTIL_OVERRIDES(Information)
UTIL_OVERRIDES(Warning)
UTIL_OVERRIDES(Critical)
UTIL_OVERRIDES(Question)
const QString GetOpenFileName(const QString &title,
const QString &dir,
const QString &filter,
QString *selectedFilter = nullptr,
Options options = Options());
} // namespace QtCommon::Frontend
#endif // QT_FRONTEND_UTIL_H

View file

@ -0,0 +1,577 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_game_util.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/service/am/am_types.h"
#include "frontend_common/content_manager.h"
#include "qt_common.h"
#include "qt_common/uisettings.h"
#include "qt_frontend_util.h"
#include "yuzu/util/util.h"
#include <QDesktopServices>
#include <QStandardPaths>
#include <QUrl>
#ifdef _WIN32
#include "common/scope_exit.h"
#include "common/string_util.h"
#include <shlobj.h>
#include <windows.h>
#else
#include "fmt/ostream.h"
#include <fstream>
#endif
namespace QtCommon::Game {
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
const std::string& comment,
const std::filesystem::path& icon_path,
const std::filesystem::path& command,
const std::string& arguments,
const std::string& categories,
const std::string& keywords,
const std::string& name)
try {
#ifdef _WIN32 // Windows
HRESULT hr = CoInitialize(nullptr);
if (FAILED(hr)) {
LOG_ERROR(Frontend, "CoInitialize failed");
return false;
}
SCOPE_EXIT
{
CoUninitialize();
};
IShellLinkW* ps1 = nullptr;
IPersistFile* persist_file = nullptr;
SCOPE_EXIT
{
if (persist_file != nullptr) {
persist_file->Release();
}
if (ps1 != nullptr) {
ps1->Release();
}
};
HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IShellLinkW,
reinterpret_cast<void**>(&ps1));
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
return false;
}
hres = ps1->SetPath(command.c_str());
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to set path");
return false;
}
if (!arguments.empty()) {
hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data());
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to set arguments");
return false;
}
}
if (!comment.empty()) {
hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data());
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to set description");
return false;
}
}
if (std::filesystem::is_regular_file(icon_path)) {
hres = ps1->SetIconLocation(icon_path.c_str(), 0);
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to set icon location");
return false;
}
}
hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&persist_file));
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to get IPersistFile interface");
return false;
}
hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE);
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to save shortcut");
return false;
}
return true;
#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Any desktop NIX
std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop");
std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
if (!shortcut_stream.is_open()) {
LOG_ERROR(Frontend, "Failed to create shortcut");
return false;
}
// TODO: Migrate fmt::print to std::print in futures STD C++ 23.
fmt::print(shortcut_stream, "[Desktop Entry]\n");
fmt::print(shortcut_stream, "Type=Application\n");
fmt::print(shortcut_stream, "Version=1.0\n");
fmt::print(shortcut_stream, "Name={}\n", name);
if (!comment.empty()) {
fmt::print(shortcut_stream, "Comment={}\n", comment);
}
if (std::filesystem::is_regular_file(icon_path)) {
fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
}
fmt::print(shortcut_stream, "TryExec={}\n", command.string());
fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments);
if (!categories.empty()) {
fmt::print(shortcut_stream, "Categories={}\n", categories);
}
if (!keywords.empty()) {
fmt::print(shortcut_stream, "Keywords={}\n", keywords);
}
return true;
#else // Unsupported platform
return false;
#endif
} catch (const std::exception& e) {
LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
return false;
}
bool MakeShortcutIcoPath(const u64 program_id,
const std::string_view game_file_name,
std::filesystem::path& out_icon_path)
{
// Get path to Yuzu icons directory & icon extension
std::string ico_extension = "png";
#if defined(_WIN32)
out_icon_path = Common::FS::GetEdenPath(Common::FS::EdenPath::IconsDir);
ico_extension = "ico";
#elif defined(__linux__) || defined(__FreeBSD__)
out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
#endif
// Create icons directory if it doesn't exist
if (!Common::FS::CreateDirs(out_icon_path)) {
out_icon_path.clear();
return false;
}
// Create icon file path
out_icon_path /= (program_id == 0 ? fmt::format("eden-{}.{}", game_file_name, ico_extension)
: fmt::format("eden-{:016X}.{}", program_id, ico_extension));
return true;
}
void OpenEdenFolder(const Common::FS::EdenPath& path)
{
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(Common::FS::GetEdenPathString(path))));
}
void OpenRootDataFolder()
{
OpenEdenFolder(Common::FS::EdenPath::EdenDir);
}
void OpenNANDFolder()
{
OpenEdenFolder(Common::FS::EdenPath::NANDDir);
}
void OpenSDMCFolder()
{
OpenEdenFolder(Common::FS::EdenPath::SDMCDir);
}
void OpenModFolder()
{
OpenEdenFolder(Common::FS::EdenPath::LoadDir);
}
void OpenLogFolder()
{
OpenEdenFolder(Common::FS::EdenPath::LogDir);
}
static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type)
{
switch (type) {
case QtCommon::Game::InstalledEntryType::Game:
return tr("Error Removing Contents");
case QtCommon::Game::InstalledEntryType::Update:
return tr("Error Removing Update");
case QtCommon::Game::InstalledEntryType::AddOnContent:
return tr("Error Removing DLC");
default:
return QStringLiteral("Error Removing <Invalid Type>");
}
}
// Game Content //
void RemoveBaseContent(u64 program_id, InstalledEntryType type)
{
const auto res = ContentManager::RemoveBaseContent(system->GetFileSystemController(),
program_id);
if (res) {
QtCommon::Frontend::Information(rootObject,
"Successfully Removed",
"Successfully removed the installed base game.");
} else {
QtCommon::Frontend::Warning(
rootObject,
GetGameListErrorRemoving(type),
tr("The base game is not installed in the NAND and cannot be removed."));
}
}
void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
{
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
if (res) {
QtCommon::Frontend::Information(rootObject,
"Successfully Removed",
"Successfully removed the installed update.");
} else {
QtCommon::Frontend::Warning(rootObject,
GetGameListErrorRemoving(type),
tr("There is no update installed for this title."));
}
}
void RemoveAddOnContent(u64 program_id, InstalledEntryType type)
{
const size_t count = ContentManager::RemoveAllDLC(*system, program_id);
if (count == 0) {
QtCommon::Frontend::Warning(rootObject,
GetGameListErrorRemoving(type),
tr("There are no DLCs installed for this title."));
return;
}
QtCommon::Frontend::Information(rootObject,
tr("Successfully Removed"),
tr("Successfully removed %1 installed DLC.").arg(count));
}
// Global Content //
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target)
{
const auto target_file_name = [target] {
switch (target) {
case GameListRemoveTarget::GlShaderCache:
return "opengl.bin";
case GameListRemoveTarget::VkShaderCache:
return "vulkan.bin";
default:
return "";
}
}();
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
const auto target_file = shader_cache_folder_path / target_file_name;
if (!Common::FS::Exists(target_file)) {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Transferable Shader Cache"),
tr("A shader cache for this title does not exist."));
return;
}
if (Common::FS::RemoveFile(target_file)) {
QtCommon::Frontend::Information(rootObject,
tr("Successfully Removed"),
tr("Successfully removed the transferable shader cache."));
} else {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Transferable Shader Cache"),
tr("Failed to remove the transferable shader cache."));
}
}
void RemoveVulkanDriverPipelineCache(u64 program_id)
{
static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
const auto target_file = shader_cache_folder_path / target_file_name;
if (!Common::FS::Exists(target_file)) {
return;
}
if (!Common::FS::RemoveFile(target_file)) {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Vulkan Driver Pipeline Cache"),
tr("Failed to remove the driver pipeline cache."));
}
}
void RemoveAllTransferableShaderCaches(u64 program_id)
{
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
if (!Common::FS::Exists(program_shader_cache_dir)) {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Transferable Shader Caches"),
tr("A shader cache for this title does not exist."));
return;
}
if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) {
QtCommon::Frontend::Information(rootObject,
tr("Successfully Removed"),
tr("Successfully removed the transferable shader caches."));
} else {
QtCommon::Frontend::Warning(
rootObject,
tr("Error Removing Transferable Shader Caches"),
tr("Failed to remove the transferable shader cache directory."));
}
}
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path)
{
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
const auto config_file_name = program_id == 0
? Common::FS::PathToUTF8String(file_path.filename())
.append(".ini")
: fmt::format("{:016X}.ini", program_id);
const auto custom_config_file_path = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir)
/ "custom" / config_file_name;
if (!Common::FS::Exists(custom_config_file_path)) {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Custom Configuration"),
tr("A custom configuration for this title does not exist."));
return;
}
if (Common::FS::RemoveFile(custom_config_file_path)) {
QtCommon::Frontend::Information(rootObject,
tr("Successfully Removed"),
tr("Successfully removed the custom game configuration."));
} else {
QtCommon::Frontend::Warning(rootObject,
tr("Error Removing Custom Configuration"),
tr("Failed to remove the custom game configuration."));
}
}
void RemoveCacheStorage(u64 program_id)
{
const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
auto vfs_nand_dir = vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir),
FileSys::OpenMode::Read);
const auto cache_storage_path
= FileSys::SaveDataFactory::GetFullPath({},
vfs_nand_dir,
FileSys::SaveDataSpaceId::User,
FileSys::SaveDataType::Cache,
0 /* program_id */,
{},
0);
const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path);
// Not an error if it wasn't cleared.
Common::FS::RemoveDirRecursively(path);
}
// Metadata //
void ResetMetadata()
{
const QString title = tr("Reset Metadata Cache");
if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir)
/ "game_list/")) {
QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty."));
} else if (Common::FS::RemoveDirRecursively(
Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) {
QtCommon::Frontend::Information(rootObject,
title,
tr("The operation completed successfully."));
UISettings::values.is_game_list_reload_pending.exchange(true);
} else {
QtCommon::Frontend::Warning(
rootObject,
title,
tr("The metadata cache couldn't be deleted. It might be in use or non-existent."));
}
}
// Uhhh //
// Messages in pre-defined message boxes for less code spaghetti
inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QString& game_title)
{
int result = 0;
QMessageBox::StandardButtons buttons;
switch (imsg) {
case ShortcutMessages::Fullscreen:
buttons = QMessageBox::Yes | QMessageBox::No;
result
= QtCommon::Frontend::Information(tr("Create Shortcut"),
tr("Do you want to launch the game in fullscreen?"),
buttons);
return result == QMessageBox::Yes;
case ShortcutMessages::Success:
QtCommon::Frontend::Information(tr("Shortcut Created"),
tr("Successfully created a shortcut to %1").arg(game_title));
return false;
case ShortcutMessages::Volatile:
buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
result = QtCommon::Frontend::Warning(
tr("Shortcut may be Volatile!"),
tr("This will create a shortcut to the current AppImage. This may "
"not work well if you update. Continue?"),
buttons);
return result == QMessageBox::Ok;
default:
buttons = QMessageBox::Ok;
QtCommon::Frontend::Critical(tr("Failed to Create Shortcut"),
tr("Failed to create a shortcut to %1").arg(game_title),
buttons);
return false;
}
}
void CreateShortcut(const std::string& game_path,
const u64 program_id,
const std::string& game_title_,
const ShortcutTarget &target,
std::string arguments_,
const bool needs_title)
{
// Get path to Eden executable
std::filesystem::path command = GetEdenCommand();
// Shortcut path
std::filesystem::path shortcut_path = GetShortcutPath(target);
if (!std::filesystem::exists(shortcut_path)) {
CreateShortcutMessagesGUI(ShortcutMessages::Failed,
QString::fromStdString(shortcut_path.generic_string()));
LOG_ERROR(Frontend, "Invalid shortcut target {}", shortcut_path.generic_string());
return;
}
const FileSys::PatchManager pm{program_id, QtCommon::system->GetFileSystemController(),
QtCommon::system->GetContentProvider()};
const auto control = pm.GetControlMetadata();
const auto loader =
Loader::GetLoader(*QtCommon::system, QtCommon::vfs->OpenFile(game_path, FileSys::OpenMode::Read));
std::string game_title{game_title_};
// Delete illegal characters from title
if (needs_title) {
game_title = fmt::format("{:016X}", program_id);
if (control.first != nullptr) {
game_title = control.first->GetApplicationName();
} else {
loader->ReadTitle(game_title);
}
}
const std::string illegal_chars = "<>:\"/\\|?*.";
for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) {
if (illegal_chars.find(*it) != std::string::npos) {
game_title.erase(it.base() - 1);
}
}
const QString qgame_title = QString::fromStdString(game_title);
// Get icon from game file
std::vector<u8> icon_image_file{};
if (control.second != nullptr) {
icon_image_file = control.second->ReadAllBytes();
} else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
}
QImage icon_data =
QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
std::filesystem::path out_icon_path;
if (QtCommon::Game::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
if (!SaveIconToFile(out_icon_path, icon_data)) {
LOG_ERROR(Frontend, "Could not write icon to file");
}
} else {
QtCommon::Frontend::Critical(
tr("Create Icon"),
tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
.arg(QString::fromStdString(out_icon_path.string())));
}
#if defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__)
// Special case for AppImages
// Warn once if we are making a shortcut to a volatile AppImage
if (command.string().ends_with(".AppImage") && !UISettings::values.shortcut_already_warned) {
if (!CreateShortcutMessagesGUI(ShortcutMessages::Volatile, qgame_title)) {
return;
}
UISettings::values.shortcut_already_warned = true;
}
#endif
// Create shortcut
std::string arguments{arguments_};
if (CreateShortcutMessagesGUI(ShortcutMessages::Fullscreen, qgame_title)) {
arguments = "-f " + arguments;
}
const std::string comment = fmt::format("Start {:s} with the Eden Emulator", game_title);
const std::string categories = "Game;Emulator;Qt;";
const std::string keywords = "Switch;Nintendo;";
if (QtCommon::Game::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
arguments, categories, keywords, game_title)) {
CreateShortcutMessagesGUI(ShortcutMessages::Success,
qgame_title);
return;
}
CreateShortcutMessagesGUI(ShortcutMessages::Failed,
qgame_title);
}
constexpr std::string GetShortcutPath(ShortcutTarget target) {
{
std::string shortcut_path{};
if (target == ShortcutTarget::Desktop) {
shortcut_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)
.toStdString();
} else if (target == ShortcutTarget::Applications) {
shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)
.toStdString();
}
return shortcut_path;
}
}
void CreateHomeMenuShortcut(ShortcutTarget target) {
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QtCommon::Frontend::Warning(tr("No firmware available"),
tr("Please install firmware to use the home menu."));
return;
}
auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
if (!qlaunch_nca) {
QtCommon::Frontend::Warning(tr("Home Menu Applet"),
tr("Home Menu is not available. Please reinstall firmware."));
return;
}
auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
const auto game_path = qlaunch_applet_nca->GetFullPath();
// TODO(crueter): Make this use the Eden icon
CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false);
}
} // namespace QtCommon::Game

View file

@ -0,0 +1,85 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_GAME_UTIL_H
#define QT_GAME_UTIL_H
#include <QObject>
#include <QStandardPaths>
#include "common/fs/path_util.h"
namespace QtCommon::Game {
enum class InstalledEntryType {
Game,
Update,
AddOnContent,
};
enum class GameListRemoveTarget {
GlShaderCache,
VkShaderCache,
AllShaderCache,
CustomConfiguration,
CacheStorage,
};
enum class ShortcutTarget {
Desktop,
Applications,
};
enum class ShortcutMessages{
Fullscreen = 0,
Success = 1,
Volatile = 2,
Failed = 3
};
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
const std::string& comment,
const std::filesystem::path& icon_path,
const std::filesystem::path& command,
const std::string& arguments,
const std::string& categories,
const std::string& keywords,
const std::string& name);
bool MakeShortcutIcoPath(const u64 program_id,
const std::string_view game_file_name,
std::filesystem::path& out_icon_path);
void OpenEdenFolder(const Common::FS::EdenPath &path);
void OpenRootDataFolder();
void OpenNANDFolder();
void OpenSDMCFolder();
void OpenModFolder();
void OpenLogFolder();
void RemoveBaseContent(u64 program_id, InstalledEntryType type);
void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
void RemoveVulkanDriverPipelineCache(u64 program_id);
void RemoveAllTransferableShaderCaches(u64 program_id);
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
void RemoveCacheStorage(u64 program_id);
// Metadata //
void ResetMetadata();
// Shortcuts //
void CreateShortcut(const std::string& game_path,
const u64 program_id,
const std::string& game_title_,
const ShortcutTarget& target,
std::string arguments_,
const bool needs_title);
constexpr std::string GetShortcutPath(ShortcutTarget target);
void CreateHomeMenuShortcut(ShortcutTarget target);
}
#endif // QT_GAME_UTIL_H

75
src/qt_common/qt_meta.cpp Normal file
View file

@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_meta.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/frontend/applets/cabinet.h"
#include "core/frontend/applets/controller.h"
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/hle/service/am/frontend/applet_web_browser_types.h"
namespace QtCommon::Meta {
void RegisterMetaTypes()
{
// Register integral and floating point types
qRegisterMetaType<u8>("u8");
qRegisterMetaType<u16>("u16");
qRegisterMetaType<u32>("u32");
qRegisterMetaType<u64>("u64");
qRegisterMetaType<u128>("u128");
qRegisterMetaType<s8>("s8");
qRegisterMetaType<s16>("s16");
qRegisterMetaType<s32>("s32");
qRegisterMetaType<s64>("s64");
qRegisterMetaType<f32>("f32");
qRegisterMetaType<f64>("f64");
// Register string types
qRegisterMetaType<std::string>("std::string");
qRegisterMetaType<std::wstring>("std::wstring");
qRegisterMetaType<std::u8string>("std::u8string");
qRegisterMetaType<std::u16string>("std::u16string");
qRegisterMetaType<std::u32string>("std::u32string");
qRegisterMetaType<std::string_view>("std::string_view");
qRegisterMetaType<std::wstring_view>("std::wstring_view");
qRegisterMetaType<std::u8string_view>("std::u8string_view");
qRegisterMetaType<std::u16string_view>("std::u16string_view");
qRegisterMetaType<std::u32string_view>("std::u32string_view");
// Register applet types
// Cabinet Applet
qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>(
"std::shared_ptr<Service::NFC::NfcDevice>");
// Controller Applet
qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
// Profile Select Applet
qRegisterMetaType<Core::Frontend::ProfileSelectParameters>(
"Core::Frontend::ProfileSelectParameters");
// Software Keyboard Applet
qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
"Core::Frontend::KeyboardInitializeParameters");
qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
"Core::Frontend::InlineAppearParameters");
qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
qRegisterMetaType<Service::AM::Frontend::SwkbdResult>("Service::AM::Frontend::SwkbdResult");
qRegisterMetaType<Service::AM::Frontend::SwkbdTextCheckResult>(
"Service::AM::Frontend::SwkbdTextCheckResult");
qRegisterMetaType<Service::AM::Frontend::SwkbdReplyType>(
"Service::AM::Frontend::SwkbdReplyType");
// Web Browser Applet
qRegisterMetaType<Service::AM::Frontend::WebExitReason>("Service::AM::Frontend::WebExitReason");
// Register loader types
qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus");
}
}

15
src/qt_common/qt_meta.h Normal file
View file

@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_META_H
#define QT_META_H
#include <QObject>
namespace QtCommon::Meta {
//
void RegisterMetaTypes();
}
#endif // QT_META_H

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_path_util.h"
#include <QDesktopServices>
#include <QString>
#include <QUrl>
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "qt_common/qt_frontend_util.h"
#include <fmt/format.h>
namespace QtCommon::Path {
bool OpenShaderCache(u64 program_id, QObject *parent)
{
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)};
if (!Common::FS::CreateDirs(shader_cache_folder_path)) {
QtCommon::Frontend::ShowMessage(QMessageBox::Warning, "Error Opening Shader Cache", "Failed to create or open shader cache for this title, ensure your app data directory has write permissions.", QMessageBox::Ok, parent);
}
const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)};
const auto qt_shader_cache_path = QString::fromStdString(shader_path_string);
return QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
}
}

View file

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_PATH_UTIL_H
#define QT_PATH_UTIL_H
#include "common/common_types.h"
#include <QObject>
namespace QtCommon::Path { bool OpenShaderCache(u64 program_id, QObject *parent); }
#endif // QT_PATH_UTIL_H

View file

@ -0,0 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_progress_dialog.h"

View file

@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_PROGRESS_DIALOG_H
#define QT_PROGRESS_DIALOG_H
#include <QWindow>
#ifdef YUZU_QT_WIDGETS
#include <QProgressDialog>
#endif
namespace QtCommon::Frontend {
#ifdef YUZU_QT_WIDGETS
using QtProgressDialog = QProgressDialog;
// TODO(crueter): QML impl
#else
class QtProgressDialog
{
public:
QtProgressDialog(const QString &labelText,
const QString &cancelButtonText,
int minimum,
int maximum,
QObject *parent = nullptr,
Qt::WindowFlags f = Qt::WindowFlags());
bool wasCanceled() const;
void setWindowModality(Qt::WindowModality modality);
void setMinimumDuration(int durationMs);
void setAutoClose(bool autoClose);
void setAutoReset(bool autoReset);
public slots:
void setLabelText(QString &text);
void setRange(int min, int max);
void setValue(int progress);
bool close();
void show();
};
#endif // YUZU_QT_WIDGETS
}
#endif // QT_PROGRESS_DIALOG_H

View file

@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_rom_util.h"
#include <QCoreApplication>
namespace QtCommon::ROM {
bool RomFSRawCopy(size_t total_size,
size_t& read_size,
QtProgressCallback callback,
const FileSys::VirtualDir& src,
const FileSys::VirtualDir& dest,
bool full)
{
// TODO(crueter)
// if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
// return false;
// if (dialog.wasCanceled())
// return false;
// std::vector<u8> buffer(CopyBufferSize);
// auto last_timestamp = std::chrono::steady_clock::now();
// const auto QtRawCopy = [&](const FileSys::VirtualFile& src_file,
// const FileSys::VirtualFile& dest_file) {
// if (src_file == nullptr || dest_file == nullptr) {
// return false;
// }
// if (!dest_file->Resize(src_file->GetSize())) {
// return false;
// }
// for (std::size_t i = 0; i < src_file->GetSize(); i += buffer.size()) {
// if (dialog.wasCanceled()) {
// dest_file->Resize(0);
// return false;
// }
// using namespace std::literals::chrono_literals;
// const auto new_timestamp = std::chrono::steady_clock::now();
// if ((new_timestamp - last_timestamp) > 33ms) {
// last_timestamp = new_timestamp;
// dialog.setValue(
// static_cast<int>(std::min(read_size, total_size) * 100 / total_size));
// QCoreApplication::processEvents();
// }
// const auto read = src_file->Read(buffer.data(), buffer.size(), i);
// dest_file->Write(buffer.data(), read, i);
// read_size += read;
// }
// return true;
// };
// if (full) {
// for (const auto& file : src->GetFiles()) {
// const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName());
// if (!QtRawCopy(file, out))
// return false;
// }
// }
// for (const auto& dir : src->GetSubdirectories()) {
// const auto out = dest->CreateSubdirectory(dir->GetName());
// if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full))
// return false;
// }
// return true;
return true;
}
}

View file

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_ROM_UTIL_H
#define QT_ROM_UTIL_H
#include "qt_common/qt_common.h"
#include <cstddef>
namespace QtCommon::ROM {
bool RomFSRawCopy(size_t total_size,
size_t& read_size,
QtProgressCallback callback,
const FileSys::VirtualDir& src,
const FileSys::VirtualDir& dest,
bool full);
}
#endif // QT_ROM_UTIL_H

View file

@ -7,23 +7,21 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "yuzu/configuration/shared_translation.h"
#include "shared_translation.h"
#include <QCoreApplication>
#include <QWidget>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "common/settings_setting.h"
#include "common/time_zone.h"
#include "yuzu/uisettings.h"
#include "qt_common/uisettings.h"
#include <map>
#include <memory>
#include <tuple>
#include <utility>
namespace ConfigurationShared {
std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
{
std::unique_ptr<TranslationMap> translations = std::make_unique<TranslationMap>();
const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); };
@ -290,16 +288,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
"and safe to set at 16x on most GPUs."));
INSERT(Settings,
gpu_accuracy,
tr("GPU Level:"),
tr("GPU Accuracy:"),
tr("Controls the GPU emulation accuracy.\nMost games render fine with Normal, but High is still "
"required for some.\nParticles tend to only render correctly with High "
"accuracy.\nExtreme should only be used for debugging.\nThis option can "
"be changed while playing.\nSome games may require booting on high to render "
"properly."));
"accuracy.\nExtreme should only be used as a last resort."));
INSERT(Settings,
dma_accuracy,
tr("DMA Level:"),
tr("Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases.\nIf unsure, leave it at Default."));
tr("DMA Accuracy:"),
tr("Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases.\nIf unsure, leave this on Default."));
INSERT(Settings,
use_asynchronous_shaders,
tr("Use asynchronous shader building (Hack)"),
@ -409,12 +405,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
"their resolution, details and supported controllers and depending on this setting.\n"
"Setting to Handheld can help improve performance for low end systems."));
INSERT(Settings, current_user, QString(), QString());
INSERT(Settings, disable_nca_verification, tr("Disable NCA Verification"),
tr("Disables integrity verification of NCA content archives."
"\nThis may improve loading speed but risks data corruption or invalid files going "
"undetected.\n"
"Is necessary to make games and updates work that needs firmware 20+."));
INSERT(Settings, hide_nca_verification_popup, QString(), QString());
// Controls
@ -476,7 +466,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
return translations;
}
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent)
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
{
std::unique_ptr<ComboboxTranslationMap> translations = std::make_unique<ComboboxTranslationMap>();
const auto& tr = [&](const char* text, const char* context = "") {
@ -540,9 +530,8 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent)
translations->insert({Settings::EnumMetadata<Settings::DmaAccuracy>::Index(),
{
PAIR(DmaAccuracy, Default, tr("Default")),
PAIR(DmaAccuracy, Normal, tr("Normal")),
PAIR(DmaAccuracy, High, tr("High")),
PAIR(DmaAccuracy, Extreme, tr("Extreme")),
PAIR(DmaAccuracy, Unsafe, tr("Unsafe (fast)")),
PAIR(DmaAccuracy, Safe, tr("Safe (stable)")),
}});
translations->insert(
{Settings::EnumMetadata<Settings::CpuAccuracy>::Index(),
@ -653,58 +642,58 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent)
translations->insert(
{Settings::EnumMetadata<Settings::TimeZone>::Index(),
{
{static_cast<u32>(Settings::TimeZone::Auto),
tr("Auto (%1)", "Auto select time zone")
.arg(QString::fromStdString(
Settings::GetTimeZoneString(Settings::TimeZone::Auto)))},
{static_cast<u32>(Settings::TimeZone::Default),
tr("Default (%1)", "Default time zone")
.arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))},
PAIR(TimeZone, Cet, tr("CET")),
PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")),
PAIR(TimeZone, Cuba, tr("Cuba")),
PAIR(TimeZone, Eet, tr("EET")),
PAIR(TimeZone, Egypt, tr("Egypt")),
PAIR(TimeZone, Eire, tr("Eire")),
PAIR(TimeZone, Est, tr("EST")),
PAIR(TimeZone, Est5Edt, tr("EST5EDT")),
PAIR(TimeZone, Gb, tr("GB")),
PAIR(TimeZone, GbEire, tr("GB-Eire")),
PAIR(TimeZone, Gmt, tr("GMT")),
PAIR(TimeZone, GmtPlusZero, tr("GMT+0")),
PAIR(TimeZone, GmtMinusZero, tr("GMT-0")),
PAIR(TimeZone, GmtZero, tr("GMT0")),
PAIR(TimeZone, Greenwich, tr("Greenwich")),
PAIR(TimeZone, Hongkong, tr("Hongkong")),
PAIR(TimeZone, Hst, tr("HST")),
PAIR(TimeZone, Iceland, tr("Iceland")),
PAIR(TimeZone, Iran, tr("Iran")),
PAIR(TimeZone, Israel, tr("Israel")),
PAIR(TimeZone, Jamaica, tr("Jamaica")),
PAIR(TimeZone, Japan, tr("Japan")),
PAIR(TimeZone, Kwajalein, tr("Kwajalein")),
PAIR(TimeZone, Libya, tr("Libya")),
PAIR(TimeZone, Met, tr("MET")),
PAIR(TimeZone, Mst, tr("MST")),
PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")),
PAIR(TimeZone, Navajo, tr("Navajo")),
PAIR(TimeZone, Nz, tr("NZ")),
PAIR(TimeZone, NzChat, tr("NZ-CHAT")),
PAIR(TimeZone, Poland, tr("Poland")),
PAIR(TimeZone, Portugal, tr("Portugal")),
PAIR(TimeZone, Prc, tr("PRC")),
PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")),
PAIR(TimeZone, Roc, tr("ROC")),
PAIR(TimeZone, Rok, tr("ROK")),
PAIR(TimeZone, Singapore, tr("Singapore")),
PAIR(TimeZone, Turkey, tr("Turkey")),
PAIR(TimeZone, Uct, tr("UCT")),
PAIR(TimeZone, Universal, tr("Universal")),
PAIR(TimeZone, Utc, tr("UTC")),
PAIR(TimeZone, WSu, tr("W-SU")),
PAIR(TimeZone, Wet, tr("WET")),
PAIR(TimeZone, Zulu, tr("Zulu")),
}});
{static_cast<u32>(Settings::TimeZone::Auto),
tr("Auto (%1)", "Auto select time zone")
.arg(QString::fromStdString(
Settings::GetTimeZoneString(Settings::TimeZone::Auto)))},
{static_cast<u32>(Settings::TimeZone::Default),
tr("Default (%1)", "Default time zone")
.arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))},
PAIR(TimeZone, Cet, tr("CET")),
PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")),
PAIR(TimeZone, Cuba, tr("Cuba")),
PAIR(TimeZone, Eet, tr("EET")),
PAIR(TimeZone, Egypt, tr("Egypt")),
PAIR(TimeZone, Eire, tr("Eire")),
PAIR(TimeZone, Est, tr("EST")),
PAIR(TimeZone, Est5Edt, tr("EST5EDT")),
PAIR(TimeZone, Gb, tr("GB")),
PAIR(TimeZone, GbEire, tr("GB-Eire")),
PAIR(TimeZone, Gmt, tr("GMT")),
PAIR(TimeZone, GmtPlusZero, tr("GMT+0")),
PAIR(TimeZone, GmtMinusZero, tr("GMT-0")),
PAIR(TimeZone, GmtZero, tr("GMT0")),
PAIR(TimeZone, Greenwich, tr("Greenwich")),
PAIR(TimeZone, Hongkong, tr("Hongkong")),
PAIR(TimeZone, Hst, tr("HST")),
PAIR(TimeZone, Iceland, tr("Iceland")),
PAIR(TimeZone, Iran, tr("Iran")),
PAIR(TimeZone, Israel, tr("Israel")),
PAIR(TimeZone, Jamaica, tr("Jamaica")),
PAIR(TimeZone, Japan, tr("Japan")),
PAIR(TimeZone, Kwajalein, tr("Kwajalein")),
PAIR(TimeZone, Libya, tr("Libya")),
PAIR(TimeZone, Met, tr("MET")),
PAIR(TimeZone, Mst, tr("MST")),
PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")),
PAIR(TimeZone, Navajo, tr("Navajo")),
PAIR(TimeZone, Nz, tr("NZ")),
PAIR(TimeZone, NzChat, tr("NZ-CHAT")),
PAIR(TimeZone, Poland, tr("Poland")),
PAIR(TimeZone, Portugal, tr("Portugal")),
PAIR(TimeZone, Prc, tr("PRC")),
PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")),
PAIR(TimeZone, Roc, tr("ROC")),
PAIR(TimeZone, Rok, tr("ROK")),
PAIR(TimeZone, Singapore, tr("Singapore")),
PAIR(TimeZone, Turkey, tr("Turkey")),
PAIR(TimeZone, Uct, tr("UCT")),
PAIR(TimeZone, Universal, tr("Universal")),
PAIR(TimeZone, Utc, tr("UTC")),
PAIR(TimeZone, WSu, tr("W-SU")),
PAIR(TimeZone, Wet, tr("WET")),
PAIR(TimeZone, Zulu, tr("Zulu")),
}});
translations->insert({Settings::EnumMetadata<Settings::AudioMode>::Index(),
{
PAIR(AudioMode, Mono, tr("Mono")),

View file

@ -11,23 +11,20 @@
#include <map>
#include <memory>
#include <typeindex>
#include <utility>
#include <vector>
#include <QString>
#include "common/common_types.h"
#include "common/settings.h"
class QWidget;
#include "common/settings_enums.h"
namespace ConfigurationShared {
using TranslationMap = std::map<u32, std::pair<QString, QString>>;
using ComboboxTranslations = std::vector<std::pair<u32, QString>>;
using ComboboxTranslationMap = std::map<u32, ComboboxTranslations>;
std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent);
std::unique_ptr<TranslationMap> InitializeTranslations(QObject *parent);
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent);
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent);
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map = {
{Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))},

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