Compare commits

..

1 Commits

Author SHA1 Message Date
Eden CI 8feb7d9c65 [dist, android] Update translations from Transifex
Signed-off-by: Eden CI <ci@eden-emu.dev>
2026-06-27 10:01:56 -04:00
493 changed files with 29070 additions and 26241 deletions
-5
View File
@@ -1,5 +0,0 @@
- [ ] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [ ] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [ ] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
@@ -0,0 +1,20 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 16c6092..9e75548 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,14 @@ project(adrenotools LANGUAGES CXX C)
set(GEN_INSTALL_TARGET OFF CACHE BOOL "")
-add_subdirectory(lib/linkernsbypass)
+include(CPM)
+set(CPM_USE_LOCAL_PACKAGES OFF)
+
+CPMAddPackage(
+ NAME linkernsbypass
+ URL "https://github.com/bylaws/liblinkernsbypass/archive/aa3975893d.zip"
+ URL_HASH SHA512=43d3d146facb7ec99d066a9b8990369ab7b9eec0d5f9a67131b0a0744fde0af27d884ca1f2a272cd113718a23356530ed97703c8c0659c4c25948d50c106119e
+)
set(LIB_SOURCES src/bcenabler.cpp
src/driver.cpp
@@ -1,26 +0,0 @@
From 52bbc5af6523daa22ad62fe4b84bc8d623d11a53 Mon Sep 17 00:00:00 2001
From: crueter <crueter@eden-emu.dev>
Date: Fri, 26 Jun 2026 01:09:40 -0400
Subject: [PATCH] use cpmfile def for linkernsbypass
---
CMakeLists.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 16c6092..85b242c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,8 @@ project(adrenotools LANGUAGES CXX C)
set(GEN_INSTALL_TARGET OFF CACHE BOOL "")
-add_subdirectory(lib/linkernsbypass)
+include(CPMUtil)
+AddJsonPackage(linkernsbypass)
set(LIB_SOURCES src/bcenabler.cpp
src/driver.cpp
--
2.54.0
+5
View File
@@ -112,6 +112,11 @@ Files: src/yuzu/*.ui
Copyright: 2018-2022 yuzu Emulator Project
License: GPL-2.0-or-later
Files: src/yuzu/compatdb.ui
src/yuzu/main.ui
Copyright: 2014-2017 Citra Emulator Project
License: GPL-2.0-or-later
Files: src/yuzu/loading_screen.ui
Copyright: 2019 James Rowe <jroweboy@gmail.com>
License: GPL-2.0-or-later
-1
View File
@@ -1 +0,0 @@
AI and LLM use is *strictly* prohibited within our codebase and surrounding community, including issues and comments. This includes using AI or LLMs to write docs/commit messages, debug issues, brainstorm ideas, research concepts, or search the codebase.
-1
View File
@@ -1 +0,0 @@
AI and LLM use is *strictly* prohibited within our codebase and surrounding community, including issues and comments. This includes using AI or LLMs to write docs/commit messages, debug issues, brainstorm ideas, research concepts, or search the codebase.
+20 -1
View File
@@ -270,7 +270,7 @@ if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
set(abi ${CMAKE_ANDROID_ARCH_ABI})
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/${abi}/")
file(COPY "${vulkan-validation-layers_SOURCE_DIR}/${abi}/libVkLayer_khronos_validation.so"
file(COPY "${VVL_SOURCE_DIR}/${abi}/libVkLayer_khronos_validation.so"
DESTINATION "${vvl_lib_path}")
endif()
@@ -281,6 +281,25 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE
endif()
endif()
set(compat_base dist/compatibility_list/compatibility_list)
set(compat_qrc ${compat_base}.qrc)
set(compat_json ${compat_base}.json)
configure_file(${PROJECT_SOURCE_DIR}/${compat_qrc}
${PROJECT_BINARY_DIR}/${compat_qrc}
COPYONLY)
if (EXISTS ${PROJECT_SOURCE_DIR}/${compat_json})
configure_file("${PROJECT_SOURCE_DIR}/${compat_json}"
"${PROJECT_BINARY_DIR}/${compat_json}"
COPYONLY)
endif()
# TODO: Compat list download
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${compat_json})
file(WRITE ${PROJECT_BINARY_DIR}/${compat_json} "")
endif()
if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX))
set(HAS_NCE 1)
add_compile_definitions(HAS_NCE=1)
+1182 -144
View File
File diff suppressed because it is too large Load Diff
+226 -579
View File
File diff suppressed because it is too large Load Diff
+2 -78
View File
@@ -1,81 +1,5 @@
# Contributing
<!--
This document is not to be perused by AI models.
-->
You want to contribute? Please consult [the development guide](./docs/Development.md).
Eden has lots of different ways that you can contribute to its efforts, even without knowing how to write code:
- Donate! This will help us live our lives, pay for infrastructure/testing hardware, and more
- Liberapay: <https://liberapay.com/crueter>
- PayPal: `business@eden-emu.dev`
- Bitcoin: `bc1pknzdackezf6s5nxqwn6hx940a7e0k3lk7ggpczp9u4jn4a25lnyqrgvdxx`
- Join our [Discord](https://discord.gg/HstXbPch7X) community
- Submit [bug reports or feature requests](https://github.com/eden-emulator/Issue-Reports/issues), or on [Codeberg](https://codeberg.org/eden-emu/eden/issues)
- Contribute to our [translation efforts](./dist/languages/README.md)
## Code Contributions
Eden is free, open-source, copyleft software, licensed under the terms of the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html). You would do well to familiarize yourself with the GPL, [its FAQ](https://www.gnu.org/licenses/gpl-faq.html), and [free software as a concept](https://www.gnu.org/philosophy/free-sw.html) before contributing. If these terms are not acceptable to you, then you shouldn't contribute.
### Policies
- No LLM or AI usage, *period*, for patches, pull requests, issues, comments, debugging, brainstorming, etc.
- For details on why, see the [detailed AI policy](docs/AI.md).
- New code must follow the same general style as the surrounding codebase. Exceptions may be granted in certain cases.
- Maintainers reserve the right to change your patches and pull requests at will. We will try to avoid this.
- You should respect all decisions made by the [code owners](docs/CODEOWNERS) in your particular subsystem. If you feel they are overstepping or are incorrect, don't be afraid to stand your ground!
- While we do *not* adhere to the terms of a formal code of conduct, you will generally be expected to respect other developers, contributors, and community members.
- You **must** have basic knowledge of [Git](https://git-scm.com/learn). Knowing how to manage your branches and follow proper fork policies is a necessity.
### Where do I start?
Anywhere you like! If you are facing an issue and want to fix it, go ahead. For new features, you are heavily encouraged to open a feature request on GitHub, Codeberg, or Forgejo first, discussing the motivations, potential implementation, and user flow of your desired feature. Our UI/UX designers will work with you to refine your feature before you actually choose to implement it.
You may also search for open issues on [GitHub](https://github.com/eden-emulator/Issue-Reports/issues), [Codeberg](https://codeberg.org/eden-emu/eden/issues), or [Forgejo](https://git.eden-emu.dev/eden-emu/eden/issues). For larger features/refactors, you should first express your interest in the issue to ensure another developer isn't already working on it.
### Great! Can I contribute already?
There are five primary ways to contribute.
- Submit pull requests directly to our source tree
- You must first request an account on our Forgejo. See [Signup](#how-do-i-sign-up)
- Submit pull requests to our [GitHub mirror](https://github.com/eden-emulator/Issue-Reports)
- Note that this is subject to being removed by DMCA, so don't rely on this.
- Submit pull requests to our [Codeberg mirror](https://codeberg.org/eden-emu/eden)
- Codeberg is not subject to draconian DMCA laws, but they have been hostile to emulators such as Torzu in the past. Thus, you shouldn't rely on this either.
- Submit patches to [`patch@eden-emu.dev`](mailto:patch@eden-emu.dev)
- These **must** be in `git format-patch` format. You should familiarize yourself with the [art of patching](https://www.gitkraken.com/learn/git/git-patch) beforehand.
- Alongside the contents of your email, please attach the patch/diff file itself for easy access and use.
- Email our developers at [`developers@eden-emu.dev`](mailto:developers@eden-emu.dev) with any of your relevant findings or code changes.
To test your changes, ensure to read the [build documentation](./docs/Build.md) for your specific platform(s) to ensure everything compiles and works properly. You should also make sure that your branch is up-to-date with the upstream `master` branch before opening a pull request.
### How do I sign up?
<details>
<summary>To sign up and begin contributing... (click to open)</summary>
Email [crueter@crueter.xyz](mailto:crueter@crueter.xyz) with the following format:
```txt
Subject: [Eden Git] Registration Request
Username: <Your Desired Username>
Email: <Your Desired Email>
I wish to sign up because... <your reason here>
```
Received mail that does not follow this format will be ignored.
Once your request is processed, you will receive a confirmation email with your temporary password and some information on Git access and policies. If you do not receive a response within 48 hours, feel free to send another email.
> [!WARNING]
> Some email providers may place the response email in your spam/junk folder; notable offenders include Gmail and Outlook. *Always* ensure to check your Spam or Junk folder.
</details>
## Non-code Contributions
Alongside the other contribution methods listed up top, you can also choose to contribute through documentation, organization, or community guides. These can be done either through the code contribution methods described above, or created externally and shared via our Discord community.
If you have an external tool/page that you believe would be handy to integrate/link into Eden, please additionally email our developers at [`developers@eden-emu.dev`](mailto:developers@eden-emu.dev). **Do not submit vibe-coded or AI generated tools or applications**.
Don't forget to [get a git account](./docs/SIGNUP.md) - not a requirement per se but it's highly recommended.
+23 -3
View File
@@ -50,9 +50,16 @@ Check out our [website](https://eden-emu.dev) for the latest news on exciting fe
[![Packaging status](https://repology.org/badge/vertical-allrepos/eden-emulator.svg)](https://repology.org/project/eden-emulator/versions)
## Contribute
## Development
To contribute to Eden; be it financially, code, bug reports, or otherwise, see our [Contributing guidelines](./CONTRIBUTING.md).
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Stoat](https://stt.gg/qKgFEAbH).
You can also follow us on [X (Twitter)](https://nitter.poast.org/edenemuofficial) for updates and announcements.
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Stoat to learn more about the current state of the emulator.
See the [sign-up instructions](docs/SIGNUP.md) for information on registration.
Alternatively, if you wish to add translations, go to the [Eden project on Transifex](https://app.transifex.com/edenemu/eden-emulator) and review [the translations README](./dist/languages).
## Documentation
@@ -66,10 +73,23 @@ For information on provided development tooling, see the [Tools directory](./too
## Download
You can download the latest releases from [our release page](https://git.eden-emu.dev/eden-emu/eden/releases).
You can download the latest releases from [here](https://git.eden-emu.dev/eden-emu/eden/releases).
Save us some bandwidth! We have [mirrors available](./docs/user/ThirdParty.md#mirrors) as well.
## Support
If you enjoy the project and would like to support us financially, please check out our developers' [donation pages](https://eden-emu.dev/donations)!
Any donations received will go towards things such as:
* Switch consoles to explore and reverse-engineer the hardware
* Switch games for testing, reverse-engineering, and implementing new features
* Web hosting and infrastructure setup
* Additional hardware (e.g. GPUs as needed to improve rendering support, other peripherals to add support for, etc.)
* CI Infrastructure
If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/HstXbPch7X) and talk to Camille or any of our other developers.
## License
Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file.
+79 -45
View File
@@ -3,10 +3,11 @@
"hash": "1229f345b014f7ca544dedb4edb3311e41ba736f9aa9a67f88b5f26f3c983288c6bb6cdedcfb0b8a02c63088a37e6a0d7ba97d9c2a4d721b213916327cffe28a",
"min_version": "0.9.1",
"repo": "lioncash/biscuit",
"version": "v0.19.0"
"tag": "v%VERSION%",
"version": "0.19.0"
},
"boost": {
"artifact": "%VERSION%-cmake.tar.xz",
"artifact": "%TAG%-cmake.tar.xz",
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
"hash": "6ae6e94664fe7f2fb01976b59b276ac5df8085c7503fa829d810fbfe495960cfec44fa2c36e2cb23480bc19c956ed199d4952b02639a00a6c07625d4e7130c2d",
"min_version": "1.57",
@@ -15,13 +16,15 @@
"0001-clang-cl.patch"
],
"repo": "boostorg/boost",
"version": "boost-1.90.0"
"tag": "boost-%VERSION%",
"version": "1.90.0"
},
"boost_headers": {
"bundled": true,
"hash": "4ef845775e2277a8104ded6ddf749aa262ce52cf8438042869a048f9a0156dd772fbbcfa74efa1378fecef339b7286f6fe4b4feb5c45d49966b35d08e3e83507",
"repo": "boostorg/headers",
"version": "boost-1.90.0"
"tag": "boost-%VERSION%",
"version": "1.90.0"
},
"catch2": {
"hash": "7eea385d79d88a5690cde131fe7ccda97d5c54ea09d6f515000d7bf07c828809d61c1ac99912c1ee507cf933f61c1c47ecdcc45df7850ffa82714034b0fccf35",
@@ -31,7 +34,8 @@
"0001-solaris-isnan-fix.patch"
],
"repo": "catchorg/Catch2",
"version": "v3.13.0"
"tag": "v%VERSION%",
"version": "3.13.0"
},
"cpp-jwt": {
"find_args": "CONFIG",
@@ -44,7 +48,8 @@
"0001-fix-missing-decl.patch"
],
"repo": "arun11299/cpp-jwt",
"version": "7f24eb4c32"
"sha": "7f24eb4c32",
"version": "1.5.1"
},
"cubeb": {
"find_args": "CONFIG",
@@ -56,26 +61,31 @@
"BUNDLE_SPEEX ON"
],
"repo": "mozilla/cubeb",
"version": "fa02160712"
"sha": "fa02160712",
"version": "0.0.0"
},
"discord-rpc": {
"find_args": "MODULE",
"hash": "8213c43dcb0f7d479f5861091d111ed12fbdec1e62e6d729d65a4bc181d82f48a35d5fd3cd5c291f2393ac7c9681eabc6b76609755f55376284c8a8d67e148f3",
"package": "DiscordRPC",
"repo": "eden-emulator/discord-rpc",
"version": "0d8b2d6a37"
"sha": "0d8b2d6a37",
"version": "3.4.1"
},
"enet": {
"find_args": "MODULE",
"hash": "a0d2fa8c957704dd49e00a726284ac5ca034b50b00d2b20a94fa1bbfbb80841467834bfdc84aa0ed0d6aab894608fd6c86c3b94eee46343f0e6d9c22e391dbf9",
"min_version": "1.3",
"repo": "lsalzman/enet",
"version": "v1.3.18"
"tag": "v%VERSION%",
"version": "1.3.18"
},
"ffmpeg": {
"bundled": true,
"hash": "ed177621176b3961bdcaa339187d3a7688c1c8b060b79c4bb0257cbc67ad7021ae5d5adca5303b45625abbbe3d9aafdd87ce777b8690ac295290d744c875489a",
"repo": "FFmpeg/FFmpeg",
"version": "c7b5f1537d"
"sha": "c7b5f1537d",
"version": "8.0.1"
},
"ffmpeg-ci": {
"ci": true,
@@ -89,20 +99,23 @@
"hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2",
"min_version": "8",
"repo": "fmtlib/fmt",
"tag": "%VERSION%",
"version": "12.1.0"
},
"frozen": {
"hash": "b8dfe741c82bc178dfc9749d4ab5a130cee718d9ee7b71d9b547cf5f7f23027ed0152ad250012a8546399fcc1e12187efc68d89d6731256c4d2df7d04eef8d5c",
"package": "frozen",
"repo": "serge-sans-paille/frozen",
"version": "61dce5ae18"
"sha": "61dce5ae18",
"version": "1.2.0"
},
"gamemode": {
"find_args": "MODULE",
"hash": "e87ec14ed3e826d578ebf095c41580069dda603792ba91efa84f45f4571a28f4d91889675055fd6f042d7dc25b0b9443daf70963ae463e38b11bcba95f4c65a9",
"min_version": "1.7",
"repo": "FeralInteractive/gamemode",
"version": "ce6fe122f3"
"sha": "ce6fe122f3",
"version": "1.8.2"
},
"httplib": {
"find_args": "MODULE GLOBAL",
@@ -115,20 +128,23 @@
"0001-mingw.patch"
],
"repo": "yhirose/cpp-httplib",
"version": "v0.46.0"
"tag": "v%VERSION%",
"version": "0.46.0"
},
"lagoon": {
"hash": "b9380f99c6effaeccc6d8f81d4942e852c11ad28613df637e155451556ae5826f93765bee57a5c87a9740d2bd1db463ad0f55a947772fe9d57eeabae3efa373e",
"repo": "loongson-community/lagoon",
"tag": "%VERSION%",
"version": "1.0.0"
},
"libadrenotools": {
"hash": "f6526620cb752876edc5ed4c0925d57b873a8218ee09ad10859ee476e9333259784f61c1dcc55a2bcba597352d18aff22cd2e4c1925ec2ae94074e09d7da2265",
"patches": [
"0001-use-cpmfile-def-for-linkernsbypass.patch"
"0001-linkerns-cpm.patch"
],
"repo": "eden-emulator/libadrenotools",
"version": "8ba23b42d7"
"sha": "8ba23b42d7",
"version": "1.0.0"
},
"libusb": {
"find_args": "MODULE",
@@ -137,52 +153,53 @@
"0001-netbsd-gettime.patch"
],
"repo": "libusb/libusb",
"version": "v1.0.29"
},
"linkernsbypass": {
"bundled": "true",
"hash": "bbe3f1f08e2bc7172b36e8f052912cc374289fc9a8e5a39ae7547a0c232de8f57ba24883451896b7a9a5d1be0e4de5c5b0f70c2022eda18d7d5a754847521800",
"repo": "bylaws/liblinkernsbypass",
"version": "aa3975893d"
"tag": "v%VERSION%",
"version": "1.0.29"
},
"llvm-mingw": {
"artifact": "clang-rt-builtins.tar.zst",
"git_host": "git.eden-emu.dev",
"hash": "d902392caf94e84f223766e2cc51ca5fab6cae36ab8dc6ef9ef6a683ab1c483bfcfe291ef0bd38ab16a4ecc4078344fa8af72da2f225ab4c378dee23f6186181",
"repo": "eden-emu/llvm-mingw",
"tag": "%VERSION%",
"version": "20250828"
},
"lz4": {
"hash": "35c21a5d9cfb5bbf314a5321d02b36819491d2ee3cf8007030ca09d13ca4dae672247b7aeab553e973093604fc48221cb03dc92197c6efe8fc3746891363fdab",
"name": "lz4",
"repo": "lz4/lz4",
"sha": "ebb370ca83",
"source_subdir": "build/cmake",
"version": "ebb370ca83"
"version": "1.10.0"
},
"moltenvk": {
"artifact": "MoltenVK-macOS.tar",
"bundled": true,
"hash": "5695b36ca5775819a71791557fcb40a4a5ee4495be6b8442e0b666d0c436bec02aae68cc6210183f7a5c986bdbec0e117aecfad5396e496e9c2fd5c89133a347",
"repo": "V380-Ori/Ryujinx.MoltenVK",
"version": "v1.4.1-ryujinx"
"tag": "v%VERSION%-ryujinx",
"version": "1.4.1"
},
"nlohmann": {
"hash": "6cc1e86261f8fac21cc17a33da3b6b3c3cd5c116755651642af3c9e99bb3538fd42c1bd50397a77c8fb6821bc62d90e6b91bcdde77a78f58f2416c62fc53b97d",
"min_version": "3.8",
"package": "nlohmann_json",
"repo": "nlohmann/json",
"version": "v3.12.0"
"tag": "v%VERSION%",
"version": "3.12.0"
},
"oaknut": {
"hash": "9697e80a7d5d9bcb3ce51051a9a24962fb90ca79d215f1f03ae6b58da8ba13a63b5dda1b4dde3d26ac6445029696b8ef2883f4e5a777b342bba01283ed293856",
"min_version": "2.0.1",
"repo": "eden-emulator/oaknut",
"version": "v2.0.3"
"tag": "v%VERSION%",
"version": "2.0.3"
},
"oboe": {
"bundled": true,
"hash": "ce4011afe7345370d4ead3b891cd69a5ef224b129535783586c0ca75051d303ed446e6c7f10bde8da31fff58d6e307f1732a3ffd03b249f9ef1fd48fd4132715",
"repo": "google/oboe",
"tag": "%VERSION%",
"version": "1.10.0"
},
"openssl": {
@@ -193,7 +210,8 @@
"0001-add-bundled-cert.patch"
],
"repo": "openssl/openssl",
"version": "openssl-3.6.2"
"tag": "openssl-%VERSION%",
"version": "3.6.2"
},
"openssl-ci": {
"ci": true,
@@ -216,6 +234,7 @@
"0004-use-shell-wrapper.patch"
],
"repo": "jimmy-park/openssl-cmake",
"tag": "%VERSION%",
"version": "3.6.2"
},
"opus": {
@@ -231,7 +250,8 @@
"0002-no-install.patch"
],
"repo": "xiph/opus",
"version": "a3f0ec02b3"
"sha": "a3f0ec02b3",
"version": "1.5.2"
},
"quazip": {
"hash": "609c240c7f029ac26a37d8fbab51bc16284e05e128b78b9b9c0e95d083538c36047a67d682759ac990e4adb0eeb90f04f1ea7fe2253bbda7e7e3bcce32e53dd8",
@@ -244,14 +264,16 @@
],
"package": "QuaZip-Qt6",
"repo": "stachenov/quazip",
"version": "2e95c9001b"
"sha": "2e95c9001b",
"version": "1.5"
},
"sdl3": {
"hash": "df5a323af7ac366661a3c0e887969c72584d232f3cc211419d59b0487b620b6b2859d4549c9e8df002ee489290062e466fcfddf7edc0872a37b1f2845e81c0f3",
"min_version": "3.2.10",
"package": "SDL3",
"repo": "libsdl-org/SDL",
"version": "release-3.4.8"
"tag": "release-%VERSION%",
"version": "3.4.8"
},
"sdl3-ci": {
"ci": true,
@@ -266,16 +288,19 @@
"hash": "b937c18a7b6277d77ca7ebfb216af4984810f77af4c32d101b7685369a4bd5eb61406223f82698e167e6311a728d07415ab59639fdf19eff71ad6dc2abfda989",
"package": "SimpleIni",
"repo": "brofield/simpleini",
"version": "v4.25"
"tag": "v%VERSION%",
"version": "4.25"
},
"sirit": {
"artifact": "sirit-source-%VERSION%.tar.zst",
"find_args": "CONFIG",
"hash": "b7cd6885acae3fc8698288d19febba0dd45e4a02a2b6563d2eb995a988d0847046e8d16a5dea7e0bf832b4321bcec134cdbafc553f6ede039e4cf34525c5dce5",
"options": [
"SIRIT_USE_SYSTEM_SPIRV_HEADERS ON"
],
"repo": "eden-emulator/sirit",
"version": "v1.0.5"
"tag": "v%VERSION%",
"version": "1.0.5",
"hash": "10b3ff60bdcad428bb4f54360ff749212333a1d24c0b3ed99e466b1bfcf99d2db6cf596c0f965854a2095dfef9b7ce4e045edb070fa9f76eb3b295ab03a4a293"
},
"sirit-ci": {
"ci": true,
@@ -285,13 +310,13 @@
"version": "1.0.5"
},
"spirv-headers": {
"hash": "d624371dd455c66a300344c89812598ffe11b5eedba555779f789e85c29dc67317741858c60e0744a1e6755cc0d2759b8659f0674f4cc31479c4cb6fc25ed23b",
"hash": "cae8cd179c9013068876908fecc1d158168310ad6ac250398a41f0f5206ceff6469e2aaeab9c820bce9d1b08950c725c89c46e94b89a692be9805432cf749396",
"options": [
"SPIRV_WERROR OFF"
],
"package": "SPIRV-Headers",
"repo": "KhronosGroup/SPIRV-Headers",
"version": "vulkan-sdk-1.4.341.0"
"sha": "04f10f650d"
},
"tzdb": {
"artifact": "%VERSION%.tar.gz",
@@ -299,6 +324,7 @@
"hash": "cce65a12bf90f4ead43b24a0b95dfad77ac3d9bfbaaf66c55e6701346e7a1e44ca5d2f23f47ee35ee02271eb1082bf1762af207aad9fb236f1c8476812d008ed",
"package": "nx_tzdb",
"repo": "eden-emu/tzdb_to_nx",
"tag": "%VERSION%",
"version": "230326"
},
"unordered-dense": {
@@ -310,40 +336,46 @@
"0001-avoid-memset-when-clearing-an-empty-table.patch"
],
"repo": "martinus/unordered_dense",
"version": "7b55cab841"
"sha": "7b55cab841",
"version": "4.8.1"
},
"vulkan-headers": {
"hash": "d2846ea228415772645eea4b52a9efd33e6a563043dd3de059e798be6391a8f0ca089f455ae420ff22574939ed0f48ed7c6ff3d5a9987d5231dbf3b3f89b484b",
"min_version": "1.4.317",
"package": "VulkanHeaders",
"repo": "KhronosGroup/Vulkan-Headers",
"version": "v1.4.345"
"tag": "v%VERSION%",
"version": "1.4.345"
},
"vulkan-memory-allocator": {
"find_args": "CONFIG",
"hash": "deb5902ef8db0e329fbd5f3f4385eb0e26bdd9f14f3a2334823fb3fe18f36bc5d235d620d6e5f6fe3551ec3ea7038638899db8778c09f6d5c278f5ff95c3344b",
"package": "VulkanMemoryAllocator",
"repo": "GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator",
"version": "v3.3.0"
"tag": "v%VERSION%",
"version": "3.3.0"
},
"vulkan-utility-libraries": {
"hash": "114f6b237a6dcba923ccc576befb5dea3f1c9b3a30de7dc741f234a831d1c2d52d8a224afb37dd57dffca67ac0df461eaaab6a5ab5e503b393f91c166680c3e1",
"package": "VulkanUtilityLibraries",
"repo": "KhronosGroup/Vulkan-Utility-Libraries",
"version": "v1.4.345"
"tag": "v%VERSION%",
"version": "1.4.345"
},
"vulkan-validation-layers": {
"artifact": "android-binaries-%NUMERIC_VERSION%.zip",
"artifact": "android-binaries-%VERSION%.zip",
"hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753",
"numeric_version": "1.4.341.0",
"package": "VVL",
"repo": "KhronosGroup/Vulkan-ValidationLayers",
"version": "vulkan-sdk-%NUMERIC_VERSION%"
"tag": "vulkan-sdk-%VERSION%",
"version": "1.4.341.0"
},
"xbyak": {
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a",
"package": "xbyak",
"repo": "herumi/xbyak",
"version": "v7.35.2"
"tag": "v%VERSION%",
"version": "7.35.2"
},
"zlib": {
"hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4",
@@ -354,7 +386,8 @@
],
"package": "ZLIB",
"repo": "madler/zlib",
"version": "v1.3.2"
"tag": "v%VERSION%",
"version": "1.3.2"
},
"zstd": {
"find_args": "MODULE",
@@ -364,7 +397,8 @@
"ZSTD_BUILD_SHARED OFF"
],
"repo": "facebook/zstd",
"sha": "b8d6101fba",
"source_subdir": "build/cmake",
"version": "b8d6101fba"
"version": "1.5.7"
}
}
+354
View File
@@ -0,0 +1,354 @@
[
{
"compatibility": 0,
"directory": "the-legend-of-zelda-breath-of-the-wild",
"releases": [
{"id": "01007EF00011E000"}
],
"title": "The Legend of Zelda: Breath of the Wild"
},
{
"compatibility": 1,
"directory": "super-mario-odyssey",
"releases": [
{"id": "0100000000010000"}
],
"title": "Super Mario Odyssey"
},
{
"compatibility": 0,
"directory": "animal-crossing-new-horizons",
"releases": [
{"id": "01006F8002326000"}
],
"title": "Animal Crossing: New Horizons"
},
{
"compatibility": 1,
"directory": "pokemon-legends-z-a",
"releases": [
{"id": "0100F43008C44000"}
],
"title": "Pokémon Legends: Z-A"
},
{
"compatibility": 1,
"directory": "the-legend-of-zelda-tears-of-the-kingdom",
"releases": [
{"id": "0100F2C0115B6000"}
],
"title": "The Legend of Zelda: Tears of the Kingdom"
},
{
"compatibility": 0,
"directory": "super-mario-galaxy",
"releases": [
{"id": "010099C022B96000"}
],
"title": "Super Mario Galaxy"
},
{
"compatibility": 3,
"directory": "star-wars-republic-commando",
"releases": [
{"id": "0100FA10115F8000"}
],
"title": "Star Wars: Republic Commando"
},
{
"compatibility": 0,
"directory": "doki-doki-literature-club-plus",
"releases": [
{"id": "010086901543E000"}
],
"title": "Doki Doki Literature Club Plus"
},
{
"compatibility": 1,
"directory": "pokemon-scarlet",
"releases": [
{"id": "0100A3D008C5C000"}
],
"title": "Pokémon Scarlet"
},
{
"compatibility": 1,
"directory": "pokemon-violet",
"releases": [
{"id": "01008F6008C5E000"}
],
"title": "Pokémon Violet"
},
{
"compatibility": 2,
"directory": "pokemon-legends-arceus",
"releases": [
{"id": "01001E300D162000"}
],
"title": "Pokémon Legends: Arceus"
},
{
"compatibility": 0,
"directory": "splatoon-2",
"releases": [
{"id": "01003BC0000A0000"}
],
"title": "Splatoon 2"
},
{
"compatibility": 1,
"directory": "super-smash-bros-ultimate",
"releases": [
{"id": "01006A800016E000"}
],
"title": "Super Smash Bros. Ultimate"
},
{
"compatibility": 0,
"directory": "mario-kart-8-deluxe",
"releases": [
{"id": "0100152000022000"}
],
"title": "Mario Kart 8 Deluxe"
},
{
"compatibility": 0,
"directory": "splatoon-3",
"releases": [
{"id": "0100C2500FC20000"}
],
"title": "Splatoon 3"
},
{
"compatibility": 0,
"directory": "new-super-mario-bros-u-deluxe",
"releases": [
{"id": "0100EA80032EA000"}
],
"title": "New Super Mario Bros. U Deluxe"
},
{
"compatibility": 0,
"directory": "hyrule-warriors-age-of-calamity",
"releases": [
{"id": "01002B00111A2000"}
],
"title": "Hyrule Warriors: Age of Calamity"
},
{
"compatibility": 2,
"directory": "luigis-mansion-3",
"releases": [
{"id": "0100DCA0064A6000"}
],
"title": "Luigi's Mansion 3"
},
{
"compatibility": 2,
"directory": "pokemon-brilliant-diamond",
"releases": [
{"id": "0100000011D90000"}
],
"title": "Pokémon Brilliant Diamond"
},
{
"compatibility": 2,
"directory": "pokemon-shining-pearl",
"releases": [
{"id": "010018E011D92000"}
],
"title": "Pokémon Shining Pearl"
},
{
"compatibility": 1,
"directory": "super-mario-3d-world-bowsers-fury",
"releases": [
{"id": "010028600EBDA000"}
],
"title": "Super Mario 3D World + Bowser's Fury"
},
{
"compatibility": 0,
"directory": "the-legend-of-zelda-links-awakening",
"releases": [
{"id": "01006BB00C6F0000"}
],
"title": "The Legend of Zelda: Link's Awakening"
},
{
"compatibility": 1,
"directory": "fire-emblem-three-houses",
"releases": [
{"id": "010055D009F78000"}
],
"title": "Fire Emblem: Three Houses"
},
{
"compatibility": 2,
"directory": "metroid-dread",
"releases": [
{"id": "010093801237C000"}
],
"title": "Metroid Dread"
},
{
"compatibility": 0,
"directory": "paper-mario-the-origami-king",
"releases": [
{"id": "0100A3900C3E2000"}
],
"title": "Paper Mario: The Origami King"
},
{
"compatibility": 1,
"directory": "xenoblade-chronicles-definitive-edition",
"releases": [
{"id": "0100FF500E34A000"}
],
"title": "Xenoblade Chronicles: Definitive Edition"
},
{
"compatibility": 2,
"directory": "xenoblade-chronicles-3",
"releases": [
{"id": "010074F013262000"}
],
"title": "Xenoblade Chronicles 3"
},
{
"compatibility": 1,
"directory": "pikmin-3-deluxe",
"releases": [
{"id": "0100F8600D4B0000"}
],
"title": "Pikmin 3 Deluxe"
},
{
"compatibility": 0,
"directory": "donkey-kong-country-tropical-freeze",
"releases": [
{"id": "0100C1F0054B6000"}
],
"title": "Donkey Kong Country: Tropical Freeze"
},
{
"compatibility": 1,
"directory": "kirby-and-the-forgotten-land",
"releases": [
{"id": "01004D300C5AE000"}
],
"title": "Kirby and the Forgotten Land"
},
{
"compatibility": 2,
"directory": "mario-party-superstars",
"releases": [
{"id": "01006B400D8B2000"}
],
"title": "Mario Party Superstars"
},
{
"compatibility": 0,
"directory": "clubhouse-games-51-worldwide-classics",
"releases": [
{"id": "0100F8600D4B0000"}
],
"title": "Clubhouse Games: 51 Worldwide Classics"
},
{
"compatibility": 1,
"directory": "ring-fit-adventure",
"releases": [
{"id": "01006B300BAF8000"}
],
"title": "Ring Fit Adventure"
},
{
"compatibility": 2,
"directory": "arms",
"releases": [
{"id": "01009B500007C000"}
],
"title": "ARMS"
},
{
"compatibility": 0,
"directory": "super-mario-maker-2",
"releases": [
{"id": "01009B90006DC000"}
],
"title": "Super Mario Maker 2"
},
{
"compatibility": 0,
"directory": "pokemon-lets-go-pikachu",
"releases": [
{"id": "010003F003A34000"}
],
"title": "Pokémon: Let's Go, Pikachu!"
},
{
"compatibility": 1,
"directory": "pokemon-lets-go-eevee",
"releases": [
{"id": "0100187003A36000"}
],
"title": "Pokémon: Let's Go, Eevee!"
},
{
"compatibility": 2,
"directory": "pokemon-sword",
"releases": [
{"id": "0100ABF008968000"}
],
"title": "Pokémon Sword"
},
{
"compatibility": 2,
"directory": "pokemon-shield",
"releases": [
{"id": "01008DB008C2C000"}
],
"title": "Pokémon Shield"
},
{
"compatibility": 1,
"directory": "new-pokemon-snap",
"releases": [
{"id": "0100F4300C182000"}
],
"title": "New Pokémon Snap"
},
{
"compatibility": 0,
"directory": "mario-golf-super-rush",
"releases": [
{"id": "0100C9C00E25C000"}
],
"title": "Mario Golf: Super Rush"
},
{
"compatibility": 1,
"directory": "mario-tennis-aces",
"releases": [
{"id": "0100BDE00862A000"}
],
"title": "Mario Tennis Aces"
},
{
"compatibility": 2,
"directory": "wario-ware-get-it-together",
"releases": [
{"id": "0100563010F22000"}
],
"title": "WarioWare: Get It Together!"
},
{
"compatibility": 0,
"directory": "big-brain-academy-brain-vs-brain",
"releases": [
{"id": "0100190010F24000"}
],
"title": "Big Brain Academy: Brain vs. Brain"
}
]
+5
View File
@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="compatibility_list">
<file>compatibility_list.json</file>
</qresource>
</RCC>
+14
View File
@@ -0,0 +1,14 @@
[main]
host = https://www.transifex.com
[o:yuzu-emulator:p:yuzu:r:emulator]
file_filter = <lang>.ts
source_file = en.ts
source_lang = en
type = QT
[o:yuzu-emulator:p:yuzu:r:yuzu-android]
file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml
source_file = ../../src/android/app/src/main/res/values/strings.xml
type = ANDROID
lang_map = ja_JP:ja, ko_KR:ko, pt_BR:pt-rBR, pt_PT:pt-rPT, ru_RU:ru, vi_VN:vi, zh_CN:zh-rCN, zh_TW:zh-rTW
+1 -5
View File
@@ -1,11 +1,7 @@
# Translating
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with the [Eden project on transifex](https://app.transifex.com/edenemu/eden-emulator), so you can update the translation by executing `tx pull -t -a` in the root of this repository. If you want to contribute to the translation, please go the transifex link and submit your translation there.
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with the [Eden project on transifex](https://app.transifex.com/edenemu/eden-emulator), so you can update the translation by executing `tx pull -t -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically. Do not directly open PRs on github to modify the translation.
When creating/improving translations, please keep in mind:
- You are responsible for providing accurate translations that do NOT contain illicit content or messages,
- Many of our developers do not speak the languages you may be translating, so will only be able to help with confusions about the source language,
- And bad-faith translations or attempts to insert illicit content may result in an immediate removal of access.
New language requests will not be honored for the time being.
+765 -613
View File
File diff suppressed because it is too large Load Diff
+768 -611
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+761 -604
View File
File diff suppressed because it is too large Load Diff
+768 -610
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+769 -611
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+746 -589
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+744 -587
View File
File diff suppressed because it is too large Load Diff
+749 -590
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+853 -703
View File
File diff suppressed because it is too large Load Diff
+754 -597
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+749 -590
View File
File diff suppressed because it is too large Load Diff
+750 -590
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+750 -590
View File
File diff suppressed because it is too large Load Diff
+749 -590
View File
File diff suppressed because it is too large Load Diff
+747 -590
View File
File diff suppressed because it is too large Load Diff
+748 -590
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+768 -610
View File
File diff suppressed because it is too large Load Diff
+753 -596
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
# ui stuff
/src/android @AleksandrPopovich @Producdevity
/src/android @AleksandrPopovich @kleidis @Producdevity
/src/yuzu @crueter
/src/eden @crueter
/src/frontend_common @crueter
+51 -103
View File
@@ -8,7 +8,6 @@ CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful u
- [Common Properties](#common-properties)
- [Standard Packages](#standard-packages)
- [Versioning](#versioning)
- [Artifact Naming Errata](#artifact-naming-errata)
- [Patches](#patches)
- [Pre-built CI Packages](#pre-built-ci-packages)
- [Usage](#usage)
@@ -23,18 +22,12 @@ CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful u
- [Addendum: Module Path Packages](#addendum-module-path-packages)
- [Example: OpenSSL](#example-openssl)
- [Addendum: Adding Qt](#addendum-adding-qt)
- [Addendum: Package-Specific Overrides](#addendum-package-specific-overrides)
- [Addendum: Supply-Chain Security](#addendum-supply-chain-security)
- [Checksumming](#checksumming)
- [Caching](#caching)
- [Immutable Commit Hashes](#immutable-commit-hashes)
## Global Options
- `CPMUTIL_FORCE_SYSTEM` (default `OFF`): Require all CPM dependencies to use system packages.
- You may optionally override this for each package: [Package-Specific Overrides](#addendum-package-specific-overrides)
- `CPMUTIL_FORCE_SYSTEM` (default `OFF`): Require all CPM dependencies to use system packages. NOT RECOMMENDED!
- You may optionally override this (section)
- `CPMUTIL_FORCE_BUNDLED` (default `ON` on MSVC and Android, `OFF` elsewhere): Require all CPM dependencies to use bundled packages.
- You may optionally override this for each package: [Package-Specific Overrides](#addendum-package-specific-overrides)
- `CPMUTIL_PATCH_DIR` (default `${PROJECT_SOURCE_DIR}/.patch`): Path to patches used in packages. Stored as `<PATCH DIR>/json-package-name/0001-patch-name.patch`, etc.
- `CPM_SOURCE_CACHE` (default `${PROJECT_SOURCE_DIR}/.cache/cpm`): Where downloaded dependencies get stored.
@@ -57,25 +50,23 @@ And may optionally define other properties like:
For instance:
```json
{
"fmt": {
"repo": "fmtlib/fmt",
"version": "12.1.0",
"hash": "f0da8...23f2",
"min_version": "8",
"options": [
"FMT_TEST ON"
],
"patches": [
"0001-disable-reference-copy.patch"
]
}
"fmt": {
"repo": "fmtlib/fmt",
"tag": "12.1.0",
"hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2",
"min_version": "8",
"options": [
"FMT_TEST ON"
],
"patches": [
"0001-disable-reference-copy.patch"
]
}
```
Calling `AddJsonPackage(fmt)`:
- Searches for a system package named `fmt` of version 8 or higher (`find_package(fmt 8)`)
- Searches for a system package named `fmt` of version 8 or higher
- If found, uses the system package and caches it for future use
- If not found:
- Downloads fmt 12.1.0 from the GitHub Archive into `.cache/cpm/fmt/12.1.0`
@@ -94,82 +85,63 @@ These JSON properties are used by standard and CI packages alike.
- `package`: The package name used by `find_package` to check for the existence of a system package.
- If unset, defaults to the JSON key
- `repo`: The Git repository the package is stored in, if applicable.
- `version`: The version of the package. This is required.
- Generally, this should be a 10-wide Git commit hash or Git tag.
- Tags must be fully qualified and include prefixes and suffixes, e.g. `boost-1.88.0`
- `version`: The version of the package to download. This is required.
- `min_version`: The minimum required version of the package, if a system package is desired.
- `git_host`: The Git host the package is stored in, if applicable. Defaults to `github.com`.
## Standard Packages
Normal packages, like the prior `fmt` example, *must* also define:
- `hash`: The SHA512 hash of the downloaded artifact. CPMUtil generally computes this for you--if not, use `tools/cpmutil.sh package hash <JSON key>`
- `min_version`: The minimum required version of the package, if a system package is desired.
And may optionally define:
- `url`: Download from a raw URL.
- `artifact`: A GitHub/Forgejo/Gitea release artifact. Requires `repo` to be set and valid.
- `numeric_version`: Replaces `%NUMERIC_VERSION%` in artifact and version definitions; see [Artifact Naming Errata](#artifact-naming-errata).
See [Versioning](#versioning) for version/artifact information.
- `hash`: The SHA512 hash of the downloaded artifact. CPMUtil generally computes this for you.
- A valid version/URL identifier:
- `url`: Download from a raw URL.
- `sha`: A short or fully-qualified Git commit sha. CPMUtil recommends using 10-character wide shas.
- `tag`: A Git tag. See [Versioning](#versioning) for its relation to `version`.
- `artifact`: A GitHub/Forgejo/Gitea release artifact (requires `tag`). See [Versioning](#versioning) for its relation to `tag` and `version`.
The following are optional to define:
- `source_subdir`: A subdirectory containing the `CMakeLists.txt` to configure a project. Useful for projects like `zstd`.
- `bundled`: Force the usage of a bundled package. Useful for packages where the system package is broken or nonexistent; e.g. external fragment shaders or data archives.
- Note that this will conflict with `CPMUTIL_FORCE_SYSTEM`; for this reason, when using non-library archives, it may be best to allow the user to download and extract the archive manually and specify a local directory to it.
- `bundled`: Force the usage of a bundled package. Useful for packages where the system package is broken or nonexistent; e.g. including external fragment shaders.
- `find_args`: Additional arguments passed to `find_package`, e.g. `MODULE`
- `patches`: Array of in-tree patches to apply to the downloaded source code. See [#Patches](TODO).
- `options`: Array of CMake options to apply before configuring the package, e.g. `"FMT_TEST ON"`.
### Versioning
When fetching from a Git repository, there are generally three methods of versioning:
When using tags or artifacts, it may be cumbersome to repeat the version multiple times; especially if it's constantly changing. For this purpose, `tag` and `artifact` both support basic version text replacement.
- Commit hashes
- Git tags
- Release artifacts
`tag` can use `%VERSION%` to have its version replaced with the `version` defined for the package, e.g. for OpenSSL; when downloading, `tag` will evaluate to `openssl-3.6.2`:
When `repo` is set, `version` field can be set to any commitish value, including commit hashes or Git tags. In the case of artifacts, `version` must be a Git tag, and `artifact` must be set to a release artifact attached to that tag. Many repositories intentionally version the filenames of their release artifacts; for this purpose, CPMUtil allows you to implant the version number into the artifact name. To do so, add `%VERSION%` to the artifact name; CPMUtil will then automatically replace `%VERSION%` with the `version` field. This means that when changing versions, you only need to update the version, not the artifact!
```json
"openssl": {
"repo": "openssl/openssl",
"version": "3.6.2",
"tag": "openssl-%VERSION%"
}
```
Take Boost as an example. The artifact for Boost 1.90.0 is `boost-1.90.0-cmake.tar.xz`, and the tag is `boost-1.90.0`. Thus, we can set the artifact to `%VERSION%-cmake.tar.xz`:
`artifact` also supports `%VERSION%` replacement, and can also use `%TAG%` to be replaced by the computed tag. Take this Boost definition:
```json
"boost": {
"repo": "boostorg/boost",
"version": "boost-1.90.0",
"artifact": "%VERSION%-cmake.tar.xz"
"tag": "boost-%VERSION%",
"version": "1.90.0"
}
```
The artifact will then evaluate as `boost-1.90.0-cmake.tar.xz`.
Boost's artifact for this version is stored in `boost-1.90.0-cmake.tar.xz`. Notice that the computed tag,`boost-1.90.0`, is in the name of the artifact! Thus, `artifact` can be either:
### Artifact Naming Errata
- `boost-%VERSION%-cmake.tar.xz`
- Or, even simpler: `%TAG%-cmake.tar.xz`
While `%VERSION%` replacement is generally good enough for well-packaged projects, occasionally there may be some problematic packages. Take, for instance, Vulkan Validation Layers:
- Tag (`version`): `vulkan-sdk-1.4.341.0`
- Artifact: `android-binaries-1.4.341.0.zip`
Attempting to add version replacement to the artifact definition **would not work here!** In this case, you must utilize the `numeric_version` field described earlier; we would set `numeric_version` to `1.4.341.0` and add `%NUMERIC_VERSION%` replacements into our artifact and version fields:
```json
"vulkan-validation-layers": {
"artifact": "android-binaries-%NUMERIC_VERSION%.zip",
"repo": "KhronosGroup/Vulkan-ValidationLayers",
"version": "vulkan-sdk-%NUMERIC_VERSION%",
"numeric_version": "1.4.341.0"
},
```
`artifact` will thus evaluate to `android-binaries-1.4.341.0.zip`, and `version` to `vulkan-sdk-1.4.341.0`. CPMUtil's auto-updater will also account for this and only update `numeric_version`!
Future updates need only change the `version` identifier, and the artifact and tag will automatically be updated!
### Patches
CPMUtil is able to apply in-place source tree patches to downloaded packages. These are defined in JSON as an array of names, preferably using `git-format-patch`'s scheme of `<4 digit number>-patch-name.patch`.
They are stored in `<CPMUTIL_PATCH_DIR>/<json-key>` (remember that `CPMUTIL_PATCH_DIR` defaults to `$ROOT/.patch`); e.g. `boost` patches would be in `.patch/boost`. Let's say we've made three patches and want to add them; in the Boost JSON definition, we would add:
CPMUtil is able to apply in-place source tree patches to downloaded packages. These are defined in JSON as an array of names, preferably using `git-format-patch`'s scheme of `<4 digit number>-patch-name.patch`. These are stored in `<CPMUTIL_PATCH_DIR>/<json-key>` (remember that `CPMUTIL_PATCH_DIR` defaults to `$ROOT/.patch`); e.g. `boost` patches would be in `.patch/boost`. Let's say we've made three patches and want to add them; in the Boost JSON definition, we would add:
```json
"patches": [
@@ -179,7 +151,7 @@ They are stored in `<CPMUTIL_PATCH_DIR>/<json-key>` (remember that `CPMUTIL_PATC
]
```
Then, when Boost is downloaded, it will apply these patches to the source tree in the order they are defined (compound/dependent patches are okay!). Note that when you add, remove, or modify patches, CPMUtil will invalidate your downloaded cache and re-fetch the source.
Then, when Boost is downloaded, it will apply these patches in order to the source tree.
To learn how to make patches, see [Addendum: Making Patches](#addendum-making-patches).
@@ -227,9 +199,12 @@ If you're only concerned with basic usage, you can stop reading. For more advanc
CPMUtil stores downloaded packages within `.cache/cpm` by default (see `CPM_SOURCE_CACHE`). Subdirectories stored within are lowercase representations of the `find_package` name for the package; for instance, a `vulkan-headers` definition with `package: "VulkanHeaders"` would be stored in `.cache/cpm/vulkanheaders`.
Within these subdirectories, additional directories are created for each individual version, corresponding directly to their `version` field. CI packages use `<platform>-<architecture>-<version>` unconditionally.
Within these subdirectories, additional directories are created for each individual version:
To see the cache directory for a given package, use `tools/cpmutil.sh package dir <JSON key>`.
- A four-character shorthand of `sha`, if defined
- If `sha` is not defined, the fully qualified `version` is used
CI packages use `<platform>-<architecture>-<version>` unconditionally.
## Addendum: Making Patches
@@ -267,7 +242,7 @@ If you are packaging a project that uses CPMUtil, read this!
For sandboxed environments (e.g. Gentoo, nixOS) you must install all dependencies to the system beforehand and set `-DCPMUTIL_FORCE_SYSTEM=ON`. If a dependency is missing, get creating!
Alternatively, if CPMUtil pulls in a package that has no suitable way to install or use a system version, download it separately and pass `-D<PackageName>_CUSTOM_DIR=/path/to/downloaded/dir`.
Alternatively, if CPMUtil pulls in a package that has no suitable way to install or use a system version, download it separately and pass `-DPackageName_DIR=/path/to/downloaded/dir` (e.g. shaders)
### Unsandboxed
@@ -288,12 +263,14 @@ Using the prior Vulkan example:
"repo": "KhronosGroup/Vulkan-Headers",
"package": "VulkanHeaders",
"min_version": "1.4.317",
"version": "v1.4.342"
"version": "1.4.342",
"tag": "v%VERSION%"
},
"vulkan-utility-libraries": {
"repo": "KhronosGroup/Vulkan-Utility-Libraries",
"package": "VulkanUtilityLibraries",
"version": "v1.4.342"
"version": "1.4.342",
"tag": "v%VERSION%"
}
```
@@ -341,32 +318,3 @@ AddQt(QDash-CI/Qt 6.11.1)
```
Then, call `find_package(Qt6 ...)` and it will pull Qt from your downloaded source.
## Addendum: Package-Specific Overrides
There are three variables that CPMUtil defines for each package; these can be overriden by the user or in your CMake. `package` refers either to the `package` value in the JSON, or the package's JSON key if unset (see `package` in [Common Properties](#common-properties)):
- `<package>_FORCE_BUNDLED`: Forcefully bundle the package. This has the same effect as `CPMUTIL_FORCE_BUNDLED`, but only for this package.
- `<package>_FORCE_BUNDLED`: Forcefully use the system package, failing if it can't be found. This has the same effect as `SYSTEM`, but only for this package.
- `<package>_CUSTOM_DIR`: Path to an extracted copy of the package. CPMUtil will not attempt to download the package and will instead use the custom directory.
- For an example, see [CPMUtil's test case](https://git.crueter.xyz/CMake/CPMUtil/src/branch/master/tests/dir/CMakeLists.txt)
Additionally, in CMake, you can add `FORCE_BUNDLED_PACKAGE ON` to your `AddJsonPackage` command--note that you will have to use the `NAME <key>` syntax as described in [Module Path Packages](#addendum-module-path-packages). This will overrule *all* other overrides, including `CPMUTIL_FORCE_SYSTEM` and `<package>_FORCE_SYSTEM`--use with caution!
## Addendum: Supply-Chain Security
Many package managers suffer from the issue of supply chain security, specifically in regards to silent overwrites of existing packages or archives, e.g. tag sliding and artifact overwriting. CPMUtil has three methods to protect against this.
### Checksumming
CPMUtil *requires* SHA512 checksums for standard packages, and soon will for CI packages as well. If an attacker or compromised account slides a tag, overwrites a release artifact, or otherwise attempts to compromise anything that CPMUtil may fetch, **CPMUtil will not allow the download to continue!** This means that consumers of your build system can **only** download an artifact if the contents of the artifact are *exactly* indentical to what it was when it was configured--any changes at all will be rejected by CPMUtil.
### Caching
CPMUtil uses a mutable cache system, stored by default in `.cache/cpm`. Dependencies are downloaded and extracted here, and can be reused infinitely. This means that, for instance, if a package is compromised but you already have a cached local copy, you won't have to worry at all!
### Immutable Commit Hashes
CPMUtil is capable of using immutable Git commit hashes for its artifacts. These are (barring SHA1 collisions) completely immune to supply chain attacks--that is, unless the entire root server gets compromised to serve infected artifacts/source code; at which point there are much larger issues to worry about. This means that once you set a package to use a Git commit hash for its version, **it will stay the same forever**. This is useful if you want to ensure that consumers are never faced with download failures stemming from hash mismatches in case of compromised artifacts.
Do note, however, that this will render the package incompatible with CPMUtil's built-in auto-updater, so you will have to manually update the package.
+5 -4
View File
@@ -20,17 +20,18 @@ This contains documentation created by developers. This contains build instructi
- **[Driver Bugs](./DriverBugs.md)**
- **[Building Older Commits](./build/OlderCommits.md)**
- Subsystems:
- **[Dynarmic](./dynarmic/README.md)**
- **[HOS Kernel](./HosKernel.md)**
- **[Settings](./Settings.md)**
- **[Dynarmic](./dynarmic/README.md)**
- **[HOS Kernel](./HosKernel.md)**
- **[Settings](./Settings.md)**
## Policies
Policies and information on development.
- **[AI and LLM Usage](./policies/AI.md)**
- **[Release Policy](./policies/Release.md)**
- **[Coding guidelines](./policies/Coding.md)**
- **[Contributing](../CONTRIBUTING.md)**
- **[Coding Style guidelines](./policies/CodingStyle.md)**
## Externals
+76
View File
@@ -0,0 +1,76 @@
# Signup
To prevent spam and reduce bandwidth usage, registration is closed, and will likely remain this way.
## Valid Reasons
First of all, you MUST have a valid reason to sign up for our Git. Valid reasons include (but are not limited to):
- I want to add feature XYZ...
- I want to improve the macOS version...
- I want to improve the Vulkan backend...
- I want to fix bug XYZ...
- I have experience in XYZ...
- I can provide insight on XYZ...
## Invalid Reasons
The following are not valid reasons to sign up:
- I want to contribute to Eden.
* Be at least somewhat specific! We always welcome contributors and developers, but generic "I want to contribute" messages don't give us enough information.
- I want to support Eden.
* If you wish to support us through development, be more specific; otherwise, to support us, check out our [donations page](https://eden-emu.dev/donations).
- I want to report issues.
* Most of our issue tracking is handled on [GitHub](https://github.com/eden-emulator/Issue-Reports) for the time being. This is subject to change.
- I want to play/use Eden.
* To download and use Eden, see our [Releases page](https://github.com/eden-emulator/Releases/releases)!
- I want to see the source code.
* To see Eden's source code, go [here](https://git.eden-emu.dev/eden-emu/eden).
## Other Information
Requests that appear suspicious, automated, OR blank will generally be automatically filtered. In cases of suspicion, or any of the invalid reasons listed above, you may receive an email back asking for clarification.
You MUST use the following format:
```
Subject: [Eden Git] Registration Request
Username: <Your Desired Username>
Email: <Your Desired Email>
I wish to sign up because... <your reason here>
```
Email notifications are disabled for the time being, so you don't have to use a real email. If you wish to remain anonymous, either send a separate email asking for access to a shared anonymous account, *or* create a fake username and email. Do note that the email you sign up with is used to accredit commits on the web UI, and *must* match your configured GPG key.
## Patches
In general, PRs are the preferred method of tracking patches, as they allow us to go through our standard triage, CI, and testing process without having to deal with the minutiae of incremental patches. However, we also understand that many people prefer to use raw patches, and that's totally okay! While we currently don't have a mailing list, we do accept email patches. To do so:
1. Make your changes on a clean copy of the master branch
2. Commit your changes with a descriptive, well-formed message (see the [commit message docs](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/Development.md#pull-requests)), and a proper description thoroughly explaining your changes.
* Note that we don't need to know all the individual details about your code. A description explaining the motivation and general implementation of your changes is enough, alongside caveats and any potential blockers.
3. Format your patch with `git format-patch -1 HEAD`.
4. Email us with the subject `[Eden] [PATCH] <brief patch description...>`, with a brief description of your patch, and the previously-formatted patch file as an attachment.
* If you don't include the first two bracketed parts, your email may be lost!
The following emails are currently set up to receive and process patches:
- [eden@eden-emu.dev](mailto:eden@eden-emu.dev]
- [crueter@eden-emu.dev](mailto:eden@eden-emu.dev)
## Instructions
If you have read everything above and affirm that you will not abuse your access, click the summary below to get the email to send your request to.
<details>
<summary>I affirm that I have read ALL of the information above, and will not abuse my access to Eden, nor will I send unnecessary spam to the following email.</summary>
Email [crueter@crueter.xyz](mailto:crueter@crueter.xyz) with the format above.
Once your request is processed, you should receive a confirmation email from crueter with your password alongside a link to a repository containing instructions on SSH, etc. Note that you are required to change your password. If your request is rejected, you will receive a notice as such, asking for clarification if needed. If you do not receive a response in 48 hours, you may send another email.
> [!WARNING]
> Some email providers may place the response email in your spam/junk folder; notable offenders include Gmail and Outlook. *Always* ensure to check your Spam/Junk folder, until Google/Microsoft finally end their vendetta against the great evil of my `.xyz` domain.
</details>
+36 -40
View File
@@ -1,65 +1,59 @@
# AI Policy
AI and LLM use is *strictly* prohibited within our codebase and surrounding community, including issues and comments. This includes using AI or LLMs to write docs/commit messages, debug issues, brainstorm ideas, research concepts, or search the codebase.
Use at your peril.
- [AI Policy](#ai-policy)
- [Low-quality code](#low-quality-code)
- [Licensing concerns](#licensing-concerns)
- [Vibe-coding](#vibe-coding)
- [Commit messages](#commit-messages)
- [Miscellaneous concerns](#miscellaneous-concerns)
- [Unacceptable Use Examples](#unacceptable-use-examples)
- [Addendum: Commit Messages](#addendum-commit-messages)
AI is a *tool*, not a replacement or catch-all solution. It is generally okay at a few *very specific* use cases:
## Low-quality code
- Automation of tedious changes where you have already made the pattern clear and done the necessary groundwork.
- Conversion of code from one paradigm to another.
AI is notorious for producing low-quality code; be it:
For everything else, AI is subpar at best, and actively harmful at worst. In general, you are **heavily** encouraged to not use AI at all.
- nonfunctional,
- verbose/inefficient,
- breaking other parts of the codebase,
- or writing/architecting in a completely different style
## Why?
All code, AI or not, is held under a **strict standard of excellence**. AI/LLM-generated code will fail this test 10 times out of 10.
AI is notorious for hallucinating facts out of thin air and sometimes outright lying to users. Additionally, code written by LLMs is often needlessly verbose and horrifically inefficient (not to mention the rather ridiculous level of over-commenting). The end result is often one of three things:
## Licensing concerns
- Completely nonfunctional code
- Code that works, but is extraordinarily verbose or not nearly as efficient as it can be
- Code that works well and is written well, but solves a different problem than was intended, or solves the same problem but in a completely incorrect way that will break other things horribly.
This is an area of ongoing litigation, and as such is still very iffy. For the time being, know that allowing AI to ingest the codebase may end up with its copyleft code regurgitated into incompatibly-licensed proprietary or permissive software. For you, this means to **not** feed code into LLMs.
Human-written code will, without exception, always be of infinitely higher quality when properly researched and implemented by someone familiar with *both* the surrounding code and the programming language in use. LLMs may produce a "good enough" result, but this result is often subpar.
AI models may have also ingested AGPLv3 code, which is license-incompatible with our codebase.
**All code is held under a STRICT STANDARD OF EXCELLENCE**. AI code is no different, and since it often produces subpar or outright terrible code, it will often fail to meet this excellence standard.
## Vibe-coding
On a lesser-known note, LLM outputs often contain unicode symbols such as emojis or the arrow symbol. Please don't put Unicode symbols in your code. It messes with many an IDE, and the three people viewing your code on Lynx will be very unhappy.
Just don't. If you're not going to put the effort in to understand every line of code you wrote, neither will we, and your patch or pull request will be ignored.
**Learn to code**. It's worth it, we promise!
## Commit messages
## Acceptable Use
AI-generated commit messages are absolutely terrible, and your pull request or patch will immediately be rejected if you choose to do this. They are, quite simply, actively detrimental to our understanding of your changes, and if you're not willing to summarize the intent behind your changes, then we're not going to bother reading the code you wrote.
As stated previously, AI is good in a few *very specific* cases. In these cases, it's usually fine to use AI, as long as you **explicitly provide notice that it was used**.
Write concise, simple, and descriptive commit messages that actually convey the proper intent behind what your change is trying to do.
- Anything directly outside of the realm of the code written in your PR or patch is none of our business.
- This primarily covers research.
- However, we *still* strongly discourage this for the reasons mentioned above.
- Assistance with cleanups, and minor nitpicks/optimizations.
- This is still discouraged, but it's okay to occasionally use LLMs to catch any minor mistakes you made in your code.
- Debugging
- In general, LLMs are not good at debugging, but if you solve a bug you're facing with help from an AI, and said fix **works properly**, then that's fine.
See the [Addendum](#addendum-commit-messages) for an instance of how bad AI models are at commit messages.
## Unacceptable Use
## Miscellaneous concerns
- While many environmental concerns about AI are typically blown out of proportion, it *is* a legitimate issue, and should be taken into account.
- Many people have significant concerns over the ethics of AI usage due to inhumane and predatory behavior by large AI companies, particularly Anthropic and OpenAI. This can technically be avoided through the usage of local LLMs.
- LLMs have a tendency to add unicode characters (such as the arrow → and the em-dash — symbols) to their output, which can make viewing code or documents harder on command-line editors and viewers.
- Dedicated coding models--namely Claude--also like to add a lot of comments to overexplain every individual line of code it produces. This actually makes it *harder* to understand the code!
## Unacceptable Use Examples
Here are a few examples of unacceptable use:
Well, everything else. But here are a few examples:
- Commit messages
- LLMs are absolutely horrible at this. They are needlessly verbose, almost never catch the actual intent of the commit, and will almost always hallucinate false information about said changes.
- See the addendum for an example
- Solving problems
- Slapping a few files and a "please fix bug XYZ" into an LLM is a recipe for disaster that will pretty much never work.
- Fully AI-generated code, aka "vibecoding"
- Fully AI-generated code
- This shouldn't need explaining. Do not do this under any circumstance, especially if you don't actually understand what's going on.
- Writing code based on pseudo-instructions
- If you don't know how to write code, don't. If you've figured out the root cause (preferably without feeding random files into an LLM) and actively know what's going on, provide information to other developers or friends of yours who have knowledge of the language and/or the codebase.
## Addendum: Commit Messages
The patchset for pull request [#3422](https://git.eden-emu.dev/eden-emu/eden/pulls/3422) was fed into several LLMs to generate a commit message. One LLM produced the following:
The patchset for pull request [#3422](https://git.eden-emu.dev/eden-emu/eden/pulls/3422) was fed into several LLMs to generate a commit message. All of them sucked, and not a single one caught on to what the commit actually did. For example:
```txt
profile_manager: Refactor user deletion to use index instead of UUID
@@ -93,10 +87,10 @@ This is:
- Needlessly verbose (nobody cares about most of these details)
- Doesn't address the actual purpose of the PR (fixing a double-deletion bug in the profile manager)
- Has unicode arrows (this is bad for command-line editors)
- Uses corporate and word-salad language
- Has unicode arrows
- Uses overly corporate and, well, robotic language
Another (code-oriented) LLM output the following:
As another example:
```txt
profile(manager/ui): switch to index-based deletion and unify removal logic
@@ -114,3 +108,5 @@ This consolidates profile removal behavior, fixes potential race conditions in t
This has all of the same problems as the other one. Needlessly verbose, doesn't address *what* it actually fixes ("consolidates profile removal behavior"... okay, why? What does it fix?), etc. It even has the bonus of totally hallucinating the addition of a method!
On a more "philosophical" note, LLMs tend to be geared towards *corporate language*, as that's what they're trained on. This is why AI-generated commit messages feel like "word salad", and typically pad out the commit message to make it *look* like a lot of things were changed (trust me, it's like that in the corporate world). They typically also drift towards unneeded buzzwords and useless implementation details.
**Don't use AI for commit messages**.
+28 -29
View File
@@ -2,41 +2,44 @@
These are **not** stylistic guidelines, they're, for the most part, suggestions on how to architecture new systems or improve upon the existing codebase.
## Foreword
# Foreword
Keep your code simple, efficient, and readable.
Don't try to micro-optimize out of the get go, while yes, most of the code is pretty, subpar, most of these are aftertoughts and details that can be glossed over **generally**.
## C++ guidelines
Architectural issues are more important, for example an API returning a `std::string` is not as efficient as one that operates on `std::string_view` directly (cost of constructing an `std::string` w/o small-string optimization and all of that).
Regardless of the details, try to keep things simple. As a general rule of thumb.
# C++ guidelines
Everyone has their own way of viewing good/bad C++ practices, my general outline:
- At your disposal you may use `boost::container::static_vector<>` (beware it has a ctor/initialization cost which goes up the more elements you add).
- Or you may use `boost::container::small_vector<>` (which has an initialization cost as well, and will use extra book-keeping for heap, try to keep a balance).
- Or you may use `boost::container::small_vector<>` (which has an initialization cost as well, and will use extra book-keeping for heap, try to keep a balance).
- Don't use `[[likely]]` or `[[unlikely]]`; PGO builds exist for that.
- Don't use inline assembly to try to outsmart the compiler unless you're 100% sure the assembly you're writing is actually good.
- And if so, try to restructure your C++ code so the compiler vectorizes it/makes it better
- Or if that fails, use intrinsics instead of raw `asm volatile`.
- And if so, try to restructure your C++ code so the compiler vectorizes it/makes it better, right?
- Or if that fails, use intrinsics instead of raw `asm volatile`.
- Use `std::optional<>` instead of `std::unique_ptr<>` if possible.
- `std::unique_ptr<>` carries indirection cost due to it being memory allocated on the heap.
- It isn't often that objects that contain `std::unique_ptr<>`, are allocated on the heap themselves, allocating even more things on the heap seems redundant.
- `std::unique_ptr<>` carries indirection cost due to it being memory allocated on the heap.
- It isn't often that objects that contain `std::unique_ptr<>`, are allocated on the heap themselves, allocating even more things on the heap seems redundant.
- Avoid `std::recursive_mutex` at all costs.
- It's basically implemented as a linked list most of the time and has HEAVY performance penalties.
- It's basically implemented as a linked list most of the time and has HEAVY performance penalties.
- Exploit the fact `std::atomic<uint32_t>/std::atomic<int32_t>` is basically free on most arches that matter.
- In x86_64, an atomic `uint32_t` is basically `mov [m32], r32`, which is essentially free/cheap.
- In x86_64, an atomic `uint32_t` is basically `mov [m32], r32`, which is essentially free/cheap.
- Avoid template parameters unless you really need them.
- For small inlineable functions this is fine, for more complex ones, please consider the generated assembly.
- For small inlineable functions this is fine, for more complex ones, please consider the generated assembly.
- Dont make your own memcpy/memset/strcpy/strncpy/etc.
- Seriously DON'T DO THIS. You will NOT beat the compiler.
- Nor 30 years of writing optimized `mem*`.
- If your code is slow, don't blame `mem*`, blame your code.
- Seriously DON'T DO THIS. You will NOT beat the compiler.
- Nor 30 years of writing optimized `mem*`.
- If your code is slow, don't blame `mem*`, blame your code.
- Try to avoid using `virtual` since vtable indirection has a cost
- Avoid `dynamic_cast` and `typeid` at all costs.
- The reason is because the project has `-fno-rtti` disabled by default, due to the costs of dynamic polymorphism.
- The reason is because the project has `-fno-rtti` disabled by default, due to the costs of dynamic polymorphism.
- Always copy-on-value for objects with `sizeof(void *) >= sizeof(T) * 2`, i.e objects sized as 2 pointers or less, for bigger objects you can use ref/pointer as usual.
- Try using move semantics instead of references, whenever possible.
- Remember function parameters are extremelly cheap as fuck, don't be afraid to place upto 8 parameters on a given function.
- Don't save a reference in structures of a parent object, i.e:
```c++
struct Child {
Parent& parent;
@@ -45,9 +48,7 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
}
};
```
- Instead you can do the following:
- Instead you can do the following:
```c++
struct Child {
void Mehod(Parent& parent) {
@@ -55,17 +56,15 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
}
};
```
- This reduces the amount of pointers you have lying around, and also works better because of the aforementioned cheapness of parameter functions.
- This reduces the amount of pointers you have lying around, and also works better because of the aforementioned cheapness of parameter functions.
# Engineering guidelines
## Engineering guidelines
Coding isn't also writing stuff but architecturing stuff, consider the following:
Programming, alongside the physical act of writing code, also consists of architecting the code you write into a coherent, maintainable system.
- Try to reduce your usage of dependencies
- Dependencies that are legitimately useful to have are few and far between.
- At the same time, NIHing your own implementations of widely adopted algorithms or standards can be quite subpar.
- For dependencies that are very large but contain something you need, consider cherry-picking the individual files it needs (or writing a smaller version of it)
- Try to reduce dependency on... dependencies
- While some dependencies are useful `boost::container` and `fmt` to name a few, remember each dependency added incurs a cost.
- It may also be subpar with a hand rolled implementation, biggest exemplar of this is `spirv-tools` providing subpar SPIRV optimizations in comparison to the in-house optimizer.
- Try to rely less on indirection for architecturing systems
- If the underlying HLE kernel emulation requires it, try making a solution that keeps things local
- For example, there isn't a need for file descriptors to each be a pointer, when they could be a fixed table size with elements that may be emplaced at will.
- If the underlying HLE kernel emulation requires it, try making a solution that keeps things local
- For example, there isn't a need for file descriptors to each be a pointer, when they could be a fixed table size with elements that may be emplaced at will.
+126
View File
@@ -0,0 +1,126 @@
# Coding Style guidelines
These are mostly "suggestions", if you feel like your code is readable, comprehensible to others; and most importantly doesn't result in unreadable spaghetti you're fine to go.
But for new developers you may find that following these guidelines will make everything x10 easier.
## Naming conventions
Simply put, types/classes are named as `PascalCase`, same for methods and functions like `AddElement`. Variables are named `like_this_snake_case` and constants are `IN_SCREAMING_CASE`.
Except for Qt MOC where `functionName` is preferred.
Template typenames prefer short names like `T`, `I`, `U`, if a longer name is required either `Iterator` or `perform_action` are fine as well. Do not use names like `SS` as systems like solaris define it for registers, in general do not use any of the following for short names:
- `SS`, `DS`, `GS`, `FS`: Segment registers, defined by Solaris `<ucontext.h>`
- `EAX`, `EBX`, `ECX`, `EDX`, `ESI`, `EDI`, `ESP`, `EBP`, `EIP`: Registers, defined by Solaris.
- `X`: Defined by some utility headers, avoid.
- `_`: Defined by gettext, avoid.
- `N`, `M`, `S`: Preferably don't use this for types, use it for numeric constants.
- `TR`: Used by some weird `<ucontext.h>` whom define the Task Register as a logical register to provide to the user... (Need to remember which OS in specific).
Macros must always be in `SCREAMING_CASE`. Do not use short letter macros as systems like Solaris will conflict with them; a good rule of thumb is >5 characters per macro - i.e `THIS_MACRO_IS_GOOD`, `AND_ALSO_THIS_ONE`.
Try not using hungarian notation, if you're able.
## Formatting
Formatting is extremelly lax, the general rule of thumb is: Don't add new lines just to increase line count. The less lines we have to look at, the better. This means also packing densely your code while not making it a clusterfuck. Strike a balance of "this is a short and comprehensible piece of code" and "my eyes are actually happy to see this!". Don't just drop the entire thing in a single line and call it "dense code", that's just spaghetti posing as code. In general, be mindful of what other devs need to look at.
Do not put if/while/etc braces after lines:
```c++
// no dont do this
// this is more lines of code for no good reason (why braces need their separate lines?)
// and those take space in someone's screen, cumulatively
if (thing)
{ //<--
some(); // ...
} //<-- 2 lines of code for basically "opening" and "closing" an statment
// do this
if (thing) { //<-- [...] and with your brain you can deduce it's this piece of code
// that's being closed
some(); // ...
} //<-- only one line, and it's clearer since you know its closing something [...]
// or this, albeit the extra line isn't needed (at your discretion of course)
if (thing)
some(); // ...
// this is also ok, keeps things in one line and makes it extremely clear
if (thing) some();
// NOT ok, don't be "clever" and use the comma operator to stash a bunch of statments
// in a single line, doing this will definitely ruin someone's day - just do the thing below
// vvv
if (thing) some(), thing(), a2(a1(), y1(), j1()), do_complex_shit(wa(), wo(), ploo());
// ... and in general don't use the comma operator for "multiple statments", EXCEPT if you think
// that it makes the code more readable (the situation may be rare however)
// Wow so much clearer! Now I can actually see what each statment is meant to do!
if (thing) {
some();
thing();
a2(a1(), y1(), j1());
do_complex_shit(wa(), wo(), ploo());
}
```
Brace rules are lax, if you can get the point across, do it:
```c++
// this is fine
do {
if (thing) {
return 0;
}
} while (other);
// this is also ok --- albeit a bit more dense
do if (thing) return 0; while (other);
// ok as well
do {
if (thing) return 0;
} while (other);
```
There is no 80-column limit but preferably be mindful of other developer's readability (like don't just put everything onto one line).
```c++
// someone is going to be mad due to this
SDL_AudioSpec obtained;
device_name.empty() ? device = SDL_OpenAudioDevice(nullptr, capture, &spec, &obtained, false) : device = SDL_OpenAudioDevice(device_name.c_str(), capture, &spec, &obtained, false);
// maybe consider this
SDL_AudioSpec obtained;
if (device_name.empty()) {
device = SDL_OpenAudioDevice(nullptr, capture, &spec, &obtained, false);
} else {
device = SDL_OpenAudioDevice(device_name.c_str(), capture, &spec, &obtained, false);
}
// or this is fine as well
SDL_AudioSpec obtained;
device = SDL_OpenAudioDevice(device_name.empty() ? nullptr : device_name.c_str(), capture, &spec, &obtained, false);
```
A note about operators: Use them sparingly, yes, the language is lax on them, but some usages can be... tripping to say the least.
```c++
a, b, c; //<-- NOT OK multiple statments with comma operator is definitely a recipe for disaster
return c ? a : b; //<-- OK ternaries at end of return statments are clear and fine
return a, b; //<-- NOT OK return will take value of `b` but also evaluate `a`, just use a separate statment
void f(int a[]) //<-- OK? if you intend to use the pointer as an array, otherwise just mark it as *
```
And about templates, use them sparingly, don't just do meta-templating for the sake of it, do it when you actually need it. This isn't a competition to see who can make the most complicated and robust meta-templating system. Just use what works, and preferably stick to the standard libary instead of reinventing the wheel. Additionally:
```c++
// NOT OK This will create (T * N * C * P) versions of the same function. DO. NOT. DO. THIS.
template<typename T, size_t N, size_t C, size_t P> inline void what() const noexcept;
// OK use parameters like a normal person, don't be afraid to use them :)
template<typename T> inline void what(size_t n, size_t c, size_t p) const noexcept;
```
+10
View File
@@ -0,0 +1,10 @@
# Release Policy
Release when lots of new changes and fixes. Hotfix if more bugs. Release candidate if lot of things to test. Simple as.
## Checklist
- [ ] Update Transifex
- [ ] Test for regressions and bugs
- [ ] Write a changelog
- [ ] Ensure all platforms work
+1 -1
View File
@@ -14,7 +14,7 @@ Use this guide whenever you want to modify the Date or Time that Eden reports to
## Steps
1. Navigate to *Emulation > Configure*.
1. Navigate to *Emulation Configure*.
2. Click on the **System** item on the left-hand side navigation, then check the *Custom RTC Date* box.
3. The Date/Time option now becomes editable. Set it to the value you want and hit **OK**.
4. GREAT SCOTT! We have time traveled! You can of course go forward or backward in time (as long as it is not before the year 1970) and your game should update accordingly (e.g. certain *Super Mario Odyssey* moons that take time for flowers to grow will now be fully grown.).
-3
View File
@@ -27,6 +27,3 @@ There are two main applications, an SDL-based app (`eden-cli`) and a Qt based ap
- `--user/-u`: Specify the user index.
- `--version/-v`: Display version and quit.
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only).
- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings.
- `--filter/-x`: Sets the debug log filter irrespective of settings.
- `--singlecore/-s`: Forces single-core regardless of settings.
+1 -1
View File
@@ -30,7 +30,7 @@ Use this guide for when you want to configure specific controller settings to be
#### Steps
1. Launch Eden and wait for it to load.
2. Navigate to *Emulation > Configure...*
2. Navigate to *Emulation > Configure*
3. Select **Controls** from the left-hand menu and configure your controller for the way you want it to be in game.
4. Select **New** and enter a name for the profile in the box that appears. Press **OK** to save the profile settings.
5. Select **OK** to close the settings menu.
+7 -7
View File
@@ -16,14 +16,14 @@ Use this guide when you want to use the Steam Deck's native gyro functionality f
### Steps
1. Go into Steam Deck's Desktop Mode, and use the shortcut to launch EmuDeck.
2. Install [SteamDeckGyroDSU](https://github.com/kmicki/SteamDeckGyroDSU/releases) by going to *3rd Party Tools > Gyroscope* and clicking **Install.**
2. Install [SteamDeckGyroDSU](https://github.com/kmicki/SteamDeckGyroDSU/releases) by going to *3rd Party Tools > Gyroscope* and clicking **Install.**
a. Alternatively you can install [SteamDeckGyroDSU](https://github.com/kmicki/SteamDeckGyroDSU/releases) manually following the GitHub page instructions.
3. Upon completion of the installation. You will need to reboot your Steam Deck. Do so before continuing on.
4. Go back into the Steam Deck Desktop Mode and open the Dolphin File Explorer.
5. Navigate to the following directory to see you controller configuration: `/home/deck/.config/Eden`
6. *Right-Click* the **qt-config.ini** file and open it with ***Kate***
7. Look for the following line: `player_0_motionleft=[empty]`.
8. Change the line to now say: `player_0_motionleft="motion:0,pad:0,port:26760,guid:0000000000000000000000007f000001,engine:cemuhookudp"`
5. Navigate to the following directory to see you controller configuration: `/home/deck/.config/Eden`
6. *Right-Click* the **qt-config.ini** file and open it with ***Kate***
7. Look for the following line: `player_0_motionleft=[empty]`.
8. Change the line to now say: `player_0_motionleft="motion:0,pad:0,port:26760,guid:0000000000000000000000007f000001,engine:cemuhookudp"`
9. Save the file and open Eden.
10. Launch a compatible title, like *The Legend of Zelda: Breath of the Wild*.
11. Test the gyro capabilities, for the above mentioned title, it is accessed by holding down the **R Trigger** and moving the Steam Deck around.
10. Launch a compatible title, like *The Legend of Zelda: Breath of the Wild*.
11. Test the gyro capabilities, for the above mentioned title, it is accessed by holding down the **R Trigger** and moving the Steam Deck around.
+1 -1
View File
@@ -4,7 +4,7 @@ Use this guide when you want to install Updates or DLC for your games in Eden.
<aside>
***NOTE***: This applies to separate Update/DLC files, not "merged" NSP/XCI's which include the base game and Updates/DLC applied on top of them in a single file. These files work in Eden, but would not require the following steps.
***NOTE***: This applies to separate Update/DLC files, not merged NSP/XCIs which include the base game and Updates/DLC applied on top of them in a single file. These files work in Eden, but would not require the following steps.
</aside>
+9 -9
View File
@@ -10,7 +10,7 @@ This FAQ will serve as a general quick question and answer simple questions.
No - The only emulator that has this kind of functionality is *Ryujinx* and it's forks. This solution requires loading a custom module on a modded switch console to work.
### Can I Play Online Games?
No - This would require hijacking requests to Nintendo's official servers to a custom server infrastructure built to emulate that functionality. This is how services like [*Pretendo*](https://pretendo.network/) operate. As such, you would not be able to play "Online", you can however play multiplayer games.
No - This would require hijacking requests to Nintendo's official servers to a custom server infrastructure built to emulate that functionality. This is how services like [*Pretendo*](https://pretendo.network/) operate. As such, you would not be able to play Online, you can however play multiplayer games.
### What's the Difference Between Online and Multiplayer?
I have chosen the wording carefully here for a reason.
@@ -21,7 +21,7 @@ I have chosen the wording carefully here for a reason.
The rule of thumb here is simple: If a game supports the ability to communicate without a server (Local Wireless, LAN, etc.) you will be able to play with other users. If it requires a server to function - it will not. You will need to look up if your title support Local Wireless/LAN play as an option.
### How Does Multiplayer Work on Eden Exactly?
Eden's multiplayer works by emulating the Switch's local wireless (LDN) system, then tunneling that traffic over the internet through "rooms" that act like lobbies. Each player runs their own instance of the emulator, and as long as everyone joins the same room and the game supports local wireless multiplayer, the emulated consoles see each other as if they were on the same local network. This design avoids typical one-save netplay issues because every user keeps an independent save and console state while only the in-game wireless packets are forwarded through the room server. In practice, you pick or host a room, configure your network interface/port forwarding if needed, then launch any LDN-capable game; from the game's perspective it is just doing standard local wireless, while the emulator handles discovery and communication over the internet or LAN.
Eden's multiplayer works by emulating the Switch's local wireless (LDN) system, then tunneling that traffic over the internet through rooms that act like lobbies. Each player runs their own instance of the emulator, and as long as everyone joins the same room and the game supports local wireless multiplayer, the emulated consoles see each other as if they were on the same local network. This design avoids typical one-save netplay issues because every user keeps an independent save and console state while only the in-game wireless packets are forwarded through the room server. In practice, you pick or host a room, configure your network interface/port forwarding if needed, then launch any LDN-capable game; from the game's perspective it is just doing standard local wireless, while the emulator handles discovery and communication over the internet or LAN.
### What Do I Need to Do?
That depends entirely on what your goal is and your level of technical ability, you have a 2 options on how to proceed.
@@ -71,7 +71,7 @@ There are 2 primary methods that you can use to connect to an existing room, dep
</aside>
## Joining a Public Lobby
1. Open Eden and navigate to *Multiplayer > Browse Public Game Lobby*.
1. Open Eden and navigate to *Multiplayer Browse Public Game Lobby*.
2. The **Public Room Browser** will now open and display a list of publicly accessible rooms. Find one you want to connect to and double click it.
<aside>
@@ -84,7 +84,7 @@ There are 2 primary methods that you can use to connect to an existing room, dep
### Direct Connecting to a Room
If the hoster has not made the lobby public, or you don't want to find it in the public game browser - use this option to connect.
1. Open Eden and navigate to *Multiplayer > Direct Connect*.
1. Open Eden and navigate to *Multiplayer Direct Connect*.
2. Enter the *Server Address, Port*, *Nickname* (what your user will be called in the room), and a *Password* (if the hoster set one, otherwise leave it blank) and hit **Connect.**
3. You will now see a window showing everyone on the lobby, or an error message.
@@ -101,7 +101,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
- Ability to allow programs through the firewall on your device.
### Steps
1. Open Eden and navigate to *Emulation > Multiplayer > Create Room.*
1. Open Eden and navigate to *Emulation Multiplayer Create Room.*
2. Fill out the following information in the popup dialog box.
@@ -144,7 +144,7 @@ Quite often the person with whom you want to play is located off of your interna
Port forwarding is a networking technique that directs incoming traffic arriving at a specific port on a router or firewall to a designated device and port inside a private local network. When an external client contacts the public IP address of the router on that port, the router rewrites the packet's destination information (IP address and sometimes port number) and forwards it to the internal host that is listening on the corresponding service. This allows services such as web servers, game servers, or remote desktop sessions hosted behind NAT (Network Address Translation) to be reachable from the wider Internet despite the devices themselves having non-routable private addresses.
The process works by creating a static mapping-often called a "port-forward rule"-in the router's configuration. The rule specifies three pieces of data: the external (public) port, the internal (private) IP address of the target machine, and the internal port on which that machine expects the traffic. When a packet arrives, the router checks its NAT table, matches the external port to a rule, and then translates the packet's destination to the internal address before sending it onward. Responses from the internal host are similarly rewritten so they appear to come from the router's public IP, completing the bidirectional communication loop. This mechanism enables seamless access to services inside a protected LAN without exposing the entire network.
The process works by creating a static mappingoften called a port-forward rule”—in the router's configuration. The rule specifies three pieces of data: the external (public) port, the internal (private) IP address of the target machine, and the internal port on which that machine expects the traffic. When a packet arrives, the router checks its NAT table, matches the external port to a rule, and then translates the packet's destination to the internal address before sending it onward. Responses from the internal host are similarly rewritten so they appear to come from the router's public IP, completing the bidirectional communication loop. This mechanism enables seamless access to services inside a protected LAN without exposing the entire network.
For our purposes we would pick the port we want to expose (*e.g. 24872*) and we would access our router's configuration and create a port-forward rule to send the traffic from an external connection to your local machine over our specified port (*24872)*. The exact way to do so, varies greatly by router manufacturer - and sometimes require contacting your ISP to do so depending on your agreement. You can look up your router on [*portforward.com*](https://portforward.com/router.htm) which may have instructions on how to do so for your specific equipment. If it is not there, you will have to use Google/ChatGPT to determine the steps for your equipment.
@@ -160,7 +160,7 @@ Remember you can't have one port open for multiple devices at the same time - yo
</aside>
Using a Tunnelling service may be the solution to avoid port forward, but also avoid worrying about your users setup. A tunnelling service works by having a lightweight client run on the machine that hosts the game server. That client immediately opens an **outbound** encrypted connection (typically over TLS/QUIC) to a relay node operated by the tunnel provider's cloud infrastructure. Because outbound traffic is almost always allowed through NAT routers and ISP firewalls, the tunnel can be established even when the host sits behind carrier-grade NAT or a strict firewall. The tunnel provider then assigns a public address (e.g., `mygame.playit.gg:12345`). When a remote player connects to that address, the traffic reaches the the tunnel provider relay, which forwards it through the already-established tunnel back to the client on the private network, and finally onto the local game server's port. In effect, the server appears to the Internet as if it were listening on the public address, while the host never needs to configure port-forwarding rules or expose its own IP directly.
Using a Tunnelling service may be the solution to avoid port forward, but also avoid worrying about your users setup. A tunnelling service works by having a lightweight client run on the machine that hosts the game server. That client immediately opens an **outbound** encrypted connection (typically over TLS/QUIC) to a relay node operated by the tunnel provider's cloud infrastructure. Because outbound traffic is almost always allowed through NAT routers and ISP firewalls, the tunnel can be established even when the host sits behind carrier-grade NAT or a strict firewall. The tunnel provider then assigns a public address (e.g.,`mygame.playit.gg:12345`). When a remote player connects to that address, the traffic reaches the the tunnel provider relay, which forwards it through the already-established tunnel back to the client on the private network, and finally onto the local game server's port. In effect, the server appears to the Internet as if it were listening on the public address, while the host never needs to configure port-forwarding rules or expose its own IP directly.
For our purposes we would spawn the listener for the port that way chose when hosting our room. The user would connect to our assigned public address/port combination, and it would be routed to our machine. The tunnel must remain active for as long as you want the connection to remain open. Closing the terminal will kill the tunnel and disconnect the users.
@@ -204,7 +204,7 @@ Use this guide when you need to determine the connection information for the Pub
### Method 1: Grabbing the Address from the Log File
1. Open Eden and Connect to the room you want to identify.
1. See the *Joining a Multiplayer Room* section for instructions on how to do so if you need them.
2. Go to *File > Open Eden Folder*, then open the **config** folder.
2. Go to *File Open Eden Folder*, then open the **config** folder.
3. Open the the **qt-config.ini** file in a text editor.
4. Search for the following keys:
1. `Multiplayer\ip=`
@@ -286,7 +286,7 @@ This guide will assume you are the one hosting the game and go over things *Pars
2. If you are joining a game, you will have to send a connection request the host will have to accept.
3. Verify that the remote player can see the screen and that there is no issues with the connection.
4. Launch Eden.
5. Navigate to *Emulation > Configure*.
5. Navigate to *Emulation Configure*.
6. Select the **Controls** tab.
7. Set up your controller, if necessary.
8. Select the **Player 2** tab and select the **Connect Controller** checkbox. This enables inputs from another device to be seen as a second controller.
+5 -5
View File
@@ -33,12 +33,12 @@ Use this guide to get starting using the Eden emulator.
<aside>
***INFO***: You may get a "*Windows protected your PC"* SmartScreen message that appears. This is just Windows Defender saying it did not recognize the application and did not run it - Eden is completely safe. Click **More info** and then **Run anyway** to dismiss this message.
***INFO***: You may get a *Windows protected your PC* SmartScreen message that appears. This is just Windows Defender saying it did not recognize the application and did not run it - Eden is completely safe. Click **More info** and then **Run anyway** to dismiss this message.
</aside>
4. Eden will now launch and notify you about missing Decryption keys. Close the dialog box by hitting **OK**.
5. Navigate to **Tools > Install Decryption Keys**, navigate to the folder containing your key files and select the file, you should only be able to select one.
6. Navigate to **Tools > Install Firmware**, *Select **From Folder*** or ***From ZIP*** - depending on how your firmware is stored, navigate to where it is stored and select it.
5. Navigate to **Tools Install Decryption Keys**, navigate to the folder containing your key files and select the file, you should only be able to select one.
6. Navigate to **Tools Install Firmware**, *Select **From Folder*** or ***From ZIP*** - depending on how your firmware is stored, navigate to where it is stored and select it.
7. Double-Click the main window to add the folder containing your games.
8. Go to *Emulation > Configure > Input* and set up your controller of choice. Click **OK** to close the dialog window.
9. Double-Click a game to run it.
@@ -72,8 +72,8 @@ Use this guide to get starting using the Eden emulator.
4. If you have had a different Switch emulator installed, it will detect and ask if you want to import those settings. Make your selection to close the screen.
5. Eden will now launch and notify you about missing Encryption keys. Close the dialog box by hitting **OK**.
6. Navigate to **Tools > Install Decryption Keys**, navigate to the folder containing your ***prod.keys*** file and select the file and hit **Open**.
7. Navigate to **Tools > Install Firmware >** *Select **From Folder*** or ***From ZIP*** - depending on how your firmware is stored, navigate to where it is stored and select it.
6. Navigate to **Tools Install Decryption Keys**, navigate to the folder containing your ***prod.keys*** file and select the file and hit **Open**.
7. Navigate to **Tools Install Firmware ** *Select **From Folder*** or ***From ZIP*** - depending on how your firmware is stored, navigate to where it is stored and select it.
8. Double-Click the main window to add the folder containing your games.
9. Go to *Emulation > Configure > Input* and set up your controller. Click **OK** to close the dialog window.
10. Double-Click a game to run it.
+1 -1
View File
@@ -22,7 +22,7 @@ Use this guide when you need to allow Eden to run on a Mac system, but are being
### Why am I Seeing This?
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isn't on the list of trusted ones, it will stop the program from executing and display the message above.
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isnt on the list of trusted ones, it will stop the program from executing and display the message above.
---
+9 -9
View File
@@ -20,7 +20,7 @@ Use this when you want to import the Eden AppImage into your Steam Library along
#### Initial Setup
1. Press the **STEAM** button and then go to *Power > Switch to Desktop* to enter the Desktop mode.
1. Press the **STEAM** button and then go to *Power Switch to Desktop* to enter the Desktop mode.
2. Install ***Steam ROM Manager*** (if needed), there are 2 ways you can accomplish this, either manually or through [*EmuDeck*](https://www.emudeck.com/#downloads).
@@ -53,8 +53,8 @@ Use this when you want to import the Eden AppImage into your Steam Library along
EmuDeck will automatically create an *Emulators - Emulators* parser for ***Steam ROM Manager*** that uses shell scripts to launch them. We will follow this convention.
1. In the file explorer go to your **EmuDeck installation folder > tools > launchers**
2. Right-Click some empty space and hit **Create New > Text File,** call this new file ***eden.sh*** instead of ***Text File.txt***
1. In the file explorer go to your **EmuDeck installation folder tools launchers**
2. Right-Click some empty space and hit **Create New Text File,** call this new file ***eden.sh*** instead of ***Text File.txt***
3. Right-Click the ***eden.sh*** file you created and hit ***Open with Kate***.
4. Paste the following code into the contents of the file, save and close the file.
@@ -103,7 +103,7 @@ We will need to create a new parser for the Emulators. Unlike with the EmuDeck
<aside>
***TIP***: You may need to go to **Settings > Theme** and set it to *Classic* to view this option.
***TIP***: You may need to go to **Settings Theme** and set it to *Classic* to view this option.
</aside>
@@ -119,7 +119,7 @@ We will need to create a new parser for the Emulators. Unlike with the EmuDeck
2. Parser Specific Configuration
1. **Search Glob**: *${title}@(.AppImage|.APPIMAGE|.appimage)*
3. Executable Configuration
1. **Executable Modifier**: *"${exePath}"*
1. **Executable Modifier**: *"${exePath}*
4. Title Modification Configuration
1. **Title Modifier**: *${fuzzyTitle}*
@@ -181,7 +181,7 @@ Use this when you want to import your games inside Eden into Steam to launch wit
### Steps
1. Press the **STEAM** button and then go to *Power > Switch to Desktop* to enter the Desktop mode.
1. Press the **STEAM** button and then go to *Power Switch to Desktop* to enter the Desktop mode.
1. Install ***Steam ROM Manager***, there are 2 ways you can accomplish this, either manually or through [*EmuDeck*](https://www.emudeck.com/#downloads).
@@ -215,7 +215,7 @@ Use this when you want to import your games inside Eden into Steam to launch wit
<aside>
***TIP***: Your layout may look different depending on how you installed *Steam ROM Manager*. You may need to go to **Settings > Theme** and change it to *Classic* to follow along.
***TIP***: Your layout may look different depending on how you installed *Steam ROM Manager*. You may need to go to **Settings Theme** and change it to *Classic* to follow along.
</aside>
@@ -229,13 +229,13 @@ Use this when you want to import your games inside Eden into Steam to launch wit
2. Change the **Parser title** from *Nintendo Switch - Yuzu* to *Nintendo Switch - Eden.*
3. Hit the **Browse** option under the *ROMs directory* section. Select the directory containing your Switch ROMs.
4. Under *Steam collections*, you can add a Steam category name. This just organizes the games under a common category in your Steam Library, this is optional but recommended.
5. Scroll down slightly to the **Executable Configuration > Executable**, select **Browse** and select the Eden AppImage.
5. Scroll down slightly to the **Executable Configuration Executable**, select **Browse** and select the Eden AppImage.
6. Leave everything else the same and hit **Save** to save the parser.
---
4. Click the Eden parser to view the options on the right, select **Test** at the bottom of the screen to ensure that *Steam ROM Manager* detects your games correctly.
1. *Steam ROM Manager* will start to scan the specified ROMs directory and match them to games. Look over the results to ensure they are accurate. If you do not see any entries - check your parsers ROMs directory field.
1. When you are happy with the results, click the **Add Games** > **Parse** to start the actual Parsing.
1. When you are happy with the results, click the **Add Games** **Parse** to start the actual Parsing.
1. The program will now identify the games and pull artwork from [*SteamGridDB*](https://www.steamgriddb.com/).
2. Review the game matches and ensure everything is there.
+10 -10
View File
@@ -30,15 +30,15 @@ Use this guide for when you want to configure automated backup/syncing of your E
## Overview
Rather than giving a breakdown of all the platforms and configurations, those will be in the platform's specific guides - this will serve as a general overview of Syncthing.
Rather than giving a breakdown of all the platforms and configurations, those will be in the platforms specific guides - this will serve as a general overview of Syncthing.
### What is Syncthing Anyway?
Syncthing is a continuous file synchronization program (in the layman's - make sure 2 or more systems with the same files are always up to date). This is perfect for game saves where we would want to play on 1 device, save our game, and then continue playing it on another device. This technology is what Epic/Steam/etc. use to allow you to do this on games run through their respective services. Syncthing is an open source implementation of this technology that you control, rather than relying on a 3rd party. This has a few key benefits, most notably - better security, privacy, and speed (when on your LAN).
Syncthing is a continuous file synchronization program (in the laymans - make sure 2 or more systems with the same files are always up to date). This is perfect for game saves where we would want to play on 1 device, save our game, and then continue playing it on another device. This technology is what Epic/Steam/etc. use to allow you to do this on games run through their respective services. Syncthing is an open source implementation of this technology that you control, rather than relying on a 3rd party. This has a few key benefits, most notably - better security, privacy, and speed (when on your LAN).
### What are some common issues?
Syncthing is fairly robust and doesn't have many issues luckily, but there are some things you should watch out for (almost all of them a user issue).
Syncthing is fairly robust and doesnt have many issues luckily, but there are some things you should watch out for (almost all of them a user issue).
- Sync conflicts
- If for whatever reason you update the same file on 2 different machines, the system does not know which updated file is considered the one to sync across. This results in a ***sync conflict*** where it may not sync the files as you would expect. Worst case scenario, this can result in your save progress being lost if you are not careful. When one of these occurs, it will create a copy of the file and store it with a specific name, like this example, *Paper Mario.sync-conflict-20251102-072925-TZBBN6S.srm.* To resolve this, you must remove the other files and remove the *.sync-conflict-<TIMESTAMP>-<Syncthing Device ID>* from the file name of the file you want to keep.
@@ -86,7 +86,7 @@ Use this when you want to set this machine as the initial source of truth (push
1. Right-Click the *Syncthing* Tray icon in your taskbar and select **Open Syncthing.**
2. You will now have a browser window open up to a web GUI to configure *Syncthing*. You will get a pop up about allowing anonymous usage and setting a password, make your selections to close them.
3. We'll start by adding the folder with our save files that we want to sync by Pressing **+ Add Folder**.
3. Well start by adding the folder with our save files that we want to sync by Pressing **+ Add Folder**.
4. A pop-up window will appear, fill in the Folder label field with whatever you want to call it, like Switch Saves.
5. Enter the Full folder path to where your save files are stored on this machine.
@@ -105,7 +105,7 @@ Use this when you want to set this machine as the initial source of truth (push
Use this when you want to set this machine up as a child (pull files from the other devices). Afterwards they will all be equal partners, not a parent/child relationship, this just helps with initial setup.
1. Install Syncthing Tray on the client device following the section above. Copy the child's ID and store it so it is accessible to the Parent.
1. Install Syncthing Tray on the client device following the section above. Copy the childs ID and store it so it is accessible to the Parent.
2. ***ON THE PARENT***: Right-Click the *Syncthing* Tray icon in your taskbar and select **Open Syncthing** if it is not open already**.**
3. You will now have a browser window open up to a web GUI to configure *Syncthing*. You will get a pop up about allowing anonymous usage and setting a password, make your selections to close them.
4. Navigate down to **+ Add Remote Device**, we are going to add our Child device, so I hope you have its ID handy. If not, go back and get it.
@@ -126,7 +126,7 @@ Use this when you want to set this machine up as a child (pull files from the ot
</aside>
13. *Syncthing* will now pull all the files from the Parent and store them in your local save directory. At this point the files are in sync and alterations to one will affect the other and both can be considered "*Parents*" for other devices you want to add. Repeat these steps for as many devices you want.
13. *Syncthing* will now pull all the files from the Parent and store them in your local save directory. At this point the files are in sync and alterations to one will affect the other and both can be considered *Parents* for other devices you want to add. Repeat these steps for as many devices you want.
## Linux
@@ -166,9 +166,9 @@ Use this when you want to set this machine up as a child (pull files from the ot
Use this when you want to set this machine as the initial source of truth (push files out to all the other devices). Afterwards they will all be equal partners, not a parent/child relationship, this just helps with initial setup.
1. Right-Click the *Syncthing* Tray icon in your taskbar and select **Open Syncthing.**
1. If you don't have a taskbar in your distro, you can also reach it directly by opening a web browser to: *http://127.0.0.1:8384/.*
1. If you dont have a taskbar in your distro, you can also reach it directly by opening a web browser to: *http://127.0.0.1:8384/.*
2. You will now have a browser window open up to a web GUI to configure *Syncthing*. You will get a pop up about allowing anonymous usage and setting a password, make your selections to close them.
3. We'll start by adding the folder with our save files that we want to sync by Pressing **+ Add Folder**.
3. Well start by adding the folder with our save files that we want to sync by Pressing **+ Add Folder**.
4. A pop-up window will appear, fill in the Folder label field with whatever you want to call it, like Switch Saves.
5. Enter the Full folder path to where your save files are stored on this machine.
@@ -187,7 +187,7 @@ Use this when you want to set this machine as the initial source of truth (push
Use this when you want to set this machine up as a child (pull files from the other devices). Afterwards they will all be equal partners, not a parent/child relationship, this just helps with initial setup.
1. Install Syncthing Tray on the client device following the section above. Copy the child's ID and store it so it is accessible to the Parent.
1. Install Syncthing Tray on the client device following the section above. Copy the childs ID and store it so it is accessible to the Parent.
2. ***ON THE PARENT***: Right-Click the *Syncthing* Tray icon in your taskbar and select **Open Syncthing** if it is not open already**.**
3. You will now have a browser window open up to a web GUI to configure *Syncthing*. You will get a pop up about allowing anonymous usage and setting a password, make your selections to close them.
4. Navigate down to **+ Add Remote Device**, we are going to add our Child device, so I hope you have its ID handy. If not, go back and get it.
@@ -208,4 +208,4 @@ Use this when you want to set this machine up as a child (pull files from the ot
</aside>
13. *Syncthing* will now pull all the files from the Parent and store them in your local save directory. At this point the files are in sync and alterations to one will affect the other and both can be considered "*Parents*" for other devices you want to add. Repeat these steps for as many devices you want.
13. *Syncthing* will now pull all the files from the Parent and store them in your local save directory. At this point the files are in sync and alterations to one will affect the other and both can be considered *Parents* for other devices you want to add. Repeat these steps for as many devices you want.
+8 -8
View File
@@ -9,12 +9,12 @@ While most of the links mentioned in this guide are relatively "safe"; we urge u
## Mirrors
The main origin repository is always at <https://git.eden-emu.dev/eden-emu/eden>.
The main origin repository is always at https://git.eden-emu.dev/eden-emu/eden.
- <https://github.com/eden-emulator/mirror>
- <https://git.crueter.xyz/mirror/eden>
- <https://codeberg.org/eden-emu/eden>
- <https://collective.taymaerz.de/eden/eden>
- https://github.com/eden-emulator/mirror
- https://git.crueter.xyz/mirror/eden
- https://codeberg.org/eden-emu/eden
- https://collective.taymaerz.de/eden/eden
Other mirrors obviously exist on the internet, but we can't guarantee their reliability and/or availability.
@@ -24,7 +24,7 @@ If you're someone wanting to make a mirror, simply setup forgejo and automatical
Very nice handy app, here's a quick rundown how to configure:
1. Copy the URL: <https://git.eden-emu.dev/eden-emu/eden/> (or one of your favourite mirrors)
1. Copy the URL: https://git.eden-emu.dev/eden-emu/eden/ (or one of your favourite mirrors)
2. Open Obtainium and tap `Add App`.
3. Paste the URL into the `App Source URL` field.
4. Override Source: Look for the `Override Source` dropdown menu and select `Forgejo (Codeberg)`.
@@ -36,7 +36,7 @@ Note: Even though the site isn't Codeberg, it uses the same Forgejo/Gitea backen
### Method 1
1. Download the ZIP from [GitHub](https://github.com/GlazedBelmont/es-de-android-custom-systems)
1. Download ZIP from [here](https://github.com/GlazedBelmont/es-de-android-custom-systems)
2. Unzip the file and extract `es_systems.xml` and `es_find_rules.xml` to `\Odin2\Internal shared storage\ES-DE\custom_systems`.
3. Press `Start -> Other Settings -> Alternative Emulators` and set it to Eden (Standalone).
@@ -61,7 +61,7 @@ Note: Even though the site isn't Codeberg, it uses the same Forgejo/Gitea backen
</emulator>
```
1. Add this line of text to your `es_systems.xml` underneath where the rest of your switch system entries are:
3. Add this line of text to your `es_systems.xml` underneath where the rest of your switch system entries are:
```xml
<command label="Eden (Standalone)">%EMULATOR_EDEN% %ACTION%=android.nfc.action.TECH_DISCOVERED %DATA%=%ROMPROVIDER%</command>
+1 -1
View File
@@ -68,7 +68,7 @@ Faulting package-relative application ID:
2. Confirm there are no logs created in the log directory.
1. See the [How to Access Logs](./HowToAccessLogs.md) page for the log location if you need it.
2. If there are any entries in here since you tried step 1, this is likely not your issue.
3. Navigate to your *Windows Event Viewer* (Start Menu > **eventvwr.msc)**.
3. Navigate to your *Windows Event Viewer* (Start Menu **eventvwr.msc)**.
4. Expand **Windows Logs** and select **Application.**
5. Look for an entry with the Level of Error, and look for a message similar to the following
+3 -3
View File
@@ -30,14 +30,14 @@ TBD
</aside>
1. Navigate to the Amiibo section of the game. The method for initiating the scanning varies from game to game, for *Captain Toad's Treasure Tracker*, you need to go to the press the **+** button when on the level select. You will need to look up how to do so with your specific game.
1. Navigate to the Amiibo section of the game. The method for initiating the scanning varies from game to game, for *Captain Toads Treasure Tracker*, you need to go to the press the **+** button when on the level select. You will need to look up how to do so with your specific game.
2. Upon activating the Amiibo scan functionality, you should get a Scan page. Eden is now looking for an Amiibo file to be loaded, which emulates scanning an Amiibo on actual hardware.
3. Navigate to **File > Load/Remove Amiibo...**, or press the hotkey to do the same (**F2** on keyboard by default).
3. Navigate to **File > Load/Remove Amiibo**, or press the hotkey to do the same (**F2** on keyboard by default).
4. In the file explorer that opens, navigate to the amiibo file you want to use.
<aside>
***NOTE***: It seems the scanning functionality is spotty and will sometimes throw a "*The current game is not looking for amiibos*" message, even though it is. Usually you just need to try loading it again or restarting the scanning from the game. In some situations it was only resolved by restarting the game.
***NOTE***: It seems the scanning functionality is spotty and will sometimes throw a "*The current game is not looking for amiibos* message, even though it is. Usually you just need to try loading it again or restarting the scanning from the game. In some situations it was only resolved by restarting the game.
</aside>
+10 -10
View File
@@ -58,24 +58,24 @@ Community Member [Ninjistix](https://github.com/Ninjistix) created a utility (Wi
```
[Super Mario Bros. Wonder - Various] <- Optional
[# 1. Always Star Power]
[ 1. Always Star Power]
040E0000 00880580 52800035
[# 2. Star Power + Bubble Mode (Invincible)]
[ 2. Star Power + Bubble Mode (Invincible)]
040E0000 00880580 52800075
[# 3. Can Fast Travel to Any Course and World]
[ 3. Can Fast Travel to Any Course and World]
040E0000 00935E10 52800036
040E0000 0048A528 52800028
040E0000 005D9F58 52800028
[# 4. Got All Top of Flag Poles]
[ 4. Got All Top of Flag Poles]
040E0000 0048A818 52800028
```
### Step 3: Enabling/Disabling Cheats
Cheats are enabled by default, but can be disabled so they don't affect gameplay fairly easily using the game properties.
Cheats are enabled by default, but can be disabled so they dont affect gameplay fairly easily using the game properties.
1. Open Eden and press and hold the game you want to apply the cheat to.
2. Scroll down on the properties until you see **Add-ons**, select this option.
@@ -130,24 +130,24 @@ Community Member [Ninjistix](https://github.com/Ninjistix) created a utility (Wi
```
[Super Mario Bros. Wonder - Various] <- Optional
[# 1. Always Star Power]
[ 1. Always Star Power]
040E0000 00880580 52800035
[# 2. Star Power + Bubble Mode (Invincible)]
[ 2. Star Power + Bubble Mode (Invincible)]
040E0000 00880580 52800075
[# 3. Can Fast Travel to Any Course and World]
[ 3. Can Fast Travel to Any Course and World]
040E0000 00935E10 52800036
040E0000 0048A528 52800028
040E0000 005D9F58 52800028
[# 4. Got All Top of Flag Poles]
[ 4. Got All Top of Flag Poles]
040E0000 0048A818 52800028
```
### Step 3: Enabling/Disabling Cheats
Cheats are enabled by default, but can be disabled so they don't affect gameplay fairly easily using the game properties.
Cheats are enabled by default, but can be disabled so they dont affect gameplay fairly easily using the game properties.
1. *Right-Click* the game and select *Configure Game*.
2. In the **Add-Ons** section, locate the cheat you wish to enable.
-5
View File
@@ -59,11 +59,6 @@ endif()
if (PLATFORM_PS4 OR PLATFORM_MANAGARM)
# Doesn't support VA-API, don't go thru the embarrassment of trying to enable it
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
elseif (ANDROID)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-mediacodec
--enable-jni
)
elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING AND NOT ANDROID)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
@@ -16,6 +16,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
ANTIFLICKER("antiflicker"),
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
EMULATE_BGR565("emulate_bgr565"),
RESCALE_HACK("rescale_hack"),
@@ -27,7 +27,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
RENDERER_DYNA_STATE("dyna_state"),
DMA_ACCURACY("dma_accuracy"),
GPU_FENCE_BEHAVIOR("gpu_fence_behavior"),
FRAME_PACING_MODE("frame_pacing_mode"),
AUDIO_OUTPUT_ENGINE("output_engine"),
MAX_ANISOTROPY("max_anisotropy"),
@@ -669,15 +669,6 @@ abstract class SettingsItem(
valuesId = R.array.dmaAccuracyValues
)
)
put(
SingleChoiceSetting(
IntSetting.GPU_FENCE_BEHAVIOR,
titleId = R.string.gpu_fence_behavior,
descriptionId = R.string.gpu_fence_behavior_description,
choicesId = R.array.gpuFenceBehaviorNames,
valuesId = R.array.gpuFenceBehaviorValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
@@ -766,6 +757,13 @@ abstract class SettingsItem(
descriptionId = R.string.skip_cpu_inner_invalidation_description
)
)
put(
SwitchSetting(
BooleanSetting.ANTIFLICKER,
titleId = R.string.antiflicker,
descriptionId = R.string.antiflicker_description
)
)
put(
SwitchSetting(
BooleanSetting.FIX_BLOOM_EFFECTS,
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
@@ -169,7 +169,7 @@ class InputDialogFragment : DialogFragment() {
NativeInput.onGamePadButtonEvent(
controllerData.getGUID(),
controllerData.getPort(),
InputHandler.getButtonIdFromEvent(event),
event.keyCode,
action
)
onInputReceived(event.device)
@@ -283,7 +283,6 @@ class SettingsFragmentPresenter(
add(IntSetting.RENDERER_ACCURACY.key)
add(IntSetting.DMA_ACCURACY.key)
add(IntSetting.GPU_FENCE_BEHAVIOR.key)
add(IntSetting.MAX_ANISOTROPY.key)
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
@@ -299,6 +298,7 @@ class SettingsFragmentPresenter(
add(IntSetting.FAST_GPU_TIME.key)
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
add(BooleanSetting.ANTIFLICKER.key)
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
add(BooleanSetting.EMULATE_BGR565.key)
add(BooleanSetting.RESCALE_HACK.key)
@@ -49,12 +49,6 @@ object InputHandler {
MotionEvent.AXIS_RTRIGGER
)
// Currently, Android doesn't support Joy-Con D-pad buttons. We fall back to the scan code
private const val LINUX_BUTTON_DPAD_UP = 0x220
private const val LINUX_BUTTON_DPAD_DOWN = 0x221
private const val LINUX_BUTTON_DPAD_LEFT = 0x222
private const val LINUX_BUTTON_DPAD_RIGHT = 0x223
fun isPhysicalGameController(device: InputDevice?): Boolean {
device ?: return false
@@ -93,25 +87,12 @@ object InputHandler {
NativeInput.onGamePadButtonEvent(
controllerData.getGUID(),
controllerData.getPort(),
getButtonIdFromEvent(event),
event.keyCode,
action
)
return true
}
fun getButtonIdFromEvent(event: KeyEvent): Int {
if (event.keyCode == 0) {
return when (event.scanCode) {
LINUX_BUTTON_DPAD_UP -> KeyEvent.KEYCODE_DPAD_UP
LINUX_BUTTON_DPAD_DOWN -> KeyEvent.KEYCODE_DPAD_DOWN
LINUX_BUTTON_DPAD_LEFT -> KeyEvent.KEYCODE_DPAD_LEFT
LINUX_BUTTON_DPAD_RIGHT -> KeyEvent.KEYCODE_DPAD_RIGHT
else -> return 0
}
}
return event.keyCode
}
fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
val controllerData =
androidControllers[event.device.controllerNumber] ?: return false
+1 -1
View File
@@ -27,7 +27,7 @@ if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools)
endif()
target_link_libraries(yuzu-android PRIVATE ${FFmpeg_LIBRARIES} OpenSSL::SSL cpp-jwt::cpp-jwt)
target_link_libraries(yuzu-android PRIVATE OpenSSL::SSL cpp-jwt::cpp-jwt)
if (ENABLE_UPDATE_CHECKER)
target_compile_definitions(yuzu-android PUBLIC ENABLE_UPDATE_CHECKER)
endif()
+97 -61
View File
@@ -20,96 +20,132 @@ struct RomMetadata {
std::vector<u8> icon;
bool isHomebrew;
};
static ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
static RomMetadata CacheRomMetadata(const std::string& path) {
auto& instance = EmulationSession::GetInstance();
const auto file = Core::GetGameFileFromPath(instance.System().GetFilesystem(), path);
if (auto loader = Loader::GetLoader(instance.System(), file, 0, 0); loader) {
RomMetadata entry;
loader->ReadTitle(entry.title);
loader->ReadProgramId(entry.programId);
loader->ReadIcon(entry.icon);
ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
const FileSys::PatchManager pm{
entry.programId,
instance.System().GetFileSystemController(),
instance.System().GetContentProvider()
};
const auto control = pm.GetControlMetadata();
RomMetadata CacheRomMetadata(const std::string& path) {
const auto file =
Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path);
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
if (control.first != nullptr) {
entry.developer = control.first->GetDeveloperName();
entry.version = control.first->GetVersionString();
RomMetadata entry;
loader->ReadTitle(entry.title);
loader->ReadProgramId(entry.programId);
loader->ReadIcon(entry.icon);
const FileSys::PatchManager pm{
entry.programId, EmulationSession::GetInstance().System().GetFileSystemController(),
EmulationSession::GetInstance().System().GetContentProvider()};
const auto control = pm.GetControlMetadata();
if (control.first != nullptr) {
entry.developer = control.first->GetDeveloperName();
entry.version = control.first->GetVersionString();
} else {
FileSys::NACP nacp;
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
entry.developer = nacp.GetDeveloperName();
} else {
FileSys::NACP nacp{};
entry.developer = loader->ReadControlData(nacp) == Loader::ResultStatus::Success
? nacp.GetDeveloperName()
: "";
entry.version = "1.0.0";
entry.developer = "";
}
if (loader->GetFileType() == Loader::FileType::NRO) {
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
entry.isHomebrew = loader_nro->IsHomebrew();
} else {
entry.isHomebrew = false;
}
m_rom_metadata_cache[path] = entry;
return entry;
entry.version = "1.0.0";
}
return {};
if (loader->GetFileType() == Loader::FileType::NRO) {
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
entry.isHomebrew = loader_nro->IsHomebrew();
} else {
entry.isHomebrew = false;
}
m_rom_metadata_cache[path] = entry;
return entry;
}
static RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
if (reload)
RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
if (reload) {
return CacheRomMetadata(path);
if (auto it = m_rom_metadata_cache.find(path); it != m_rom_metadata_cache.end())
return it->second;
}
if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) {
return search->second;
}
return CacheRomMetadata(path);
}
extern "C" {
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, jstring jpath) {
if (auto const file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read); file) {
if (auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file); loader) {
auto const file_type = loader->GetFileType();
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error)
return false;
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) && !Loader::IsBootableGameContainer(file, file_type))
return false;
u64 program_id = 0;
return loader->ReadProgramId(program_id) == Loader::ResultStatus::Success;
}
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj,
jstring jpath) {
const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read);
if (!file) {
return false;
}
return false;
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file);
if (!loader) {
return false;
}
const auto file_type = loader->GetFileType();
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
return false;
}
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) &&
!Loader::IsBootableGameContainer(file, file_type)) {
return false;
}
u64 program_id = 0;
Loader::ResultStatus res = loader->ReadProgramId(program_id);
if (res != Loader::ResultStatus::Success) {
return false;
}
return true;
}
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj, jstring jpath) {
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj,
jstring jpath) {
return Common::Android::ToJString(
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
}
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj, jstring jpath) {
return Common::Android::ToJString(env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj,
jstring jpath) {
return Common::Android::ToJString(
env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
}
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj, jstring jpath) {
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj,
jstring jpath) {
return Common::Android::ToJString(
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
}
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj, jstring jpath, jboolean jreload) {
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj,
jstring jpath, jboolean jreload) {
return Common::Android::ToJString(
env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
}
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj, jstring jpath) {
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj,
jstring jpath) {
auto icon_data = GetRomMetadata(Common::Android::GetJString(env, jpath)).icon;
jbyteArray icon = env->NewByteArray(jsize(icon_data.size()));
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon), reinterpret_cast<jbyte*>(icon_data.data()));
jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size()));
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon),
reinterpret_cast<jbyte*>(icon_data.data()));
return icon;
}
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj, jstring jpath) {
return jboolean(GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj,
jstring jpath) {
return static_cast<jboolean>(
GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
}
void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) {
+2 -11
View File
@@ -36,13 +36,10 @@
#include <frontend_common/content_manager.h>
#include <jni.h>
extern "C" {
#include <libavcodec/jni.h>
}
#include "common/android/multiplayer/multiplayer.h"
#include "common/android/android_common.h"
#include "common/android/id_cache.h"
#include "common/detached_tasks.h"
#include "common/dynamic_library.h"
#include "common/fs/path_util.h"
#include "common/logging.h"
@@ -355,6 +352,7 @@ void EmulationSession::ShutdownEmulation() {
if (m_load_result == Core::SystemResultStatus::Success) {
m_system.DetachDebugger();
m_system.ShutdownMainProcess();
m_detached_tasks.WaitForAllTasks();
m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
m_window.reset();
OnEmulationStopped(Core::SystemResultStatus::Success);
@@ -682,13 +680,6 @@ const char* fallback_cpu_detection() {
} // namespace
extern "C" {
jint InitFFmpegOnLoad(JavaVM* vm) {
av_jni_set_java_vm(vm, nullptr);
return 0;
}
}
extern "C" {
void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance,
+2
View File
@@ -6,6 +6,7 @@
#include <android/native_window_jni.h>
#include "common/android/applets/software_keyboard.h"
#include "common/detached_tasks.h"
#include "core/core.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/acc/profile_manager.h"
@@ -74,6 +75,7 @@ private:
// Core emulation
Core::System m_system;
InputCommon::InputSubsystem m_input_subsystem;
Common::DetachedTasks m_detached_tasks;
Core::PerfStatsResults m_perf_stats{};
int m_shaders_building{0};
std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
@@ -473,11 +473,9 @@
<string name="advanced">متقدم</string>
<string name="renderer_accuracy">وضع وحدة معالجة الرسومات</string>
<string name="renderer_accuracy_description">يتحكم هذا الخيار في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع الوضع السريع، لكن الوضع الدقيق لا يزال ضروريًا لبعضها. تميل الجسيمات إلى الظهور بشكل صحيح فقط مع الوضع الدقيق.</string>
<string name="renderer_accuracy_description">يتحكم في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع وضعي سريع أو متوازن، لكن الوضع الدقيق لا يزال مطلوبًا لبعض الألعاب. تميل الجسيمات إلى العرض بشكل صحيح فقط عند استخدام الوضع الدقيق.</string>
<string name="dma_accuracy">دقة DMA</string>
<string name="dma_accuracy_description">يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي.</string>
<string name="gpu_fence_behavior">سلوك حاجز وحدة معالجة الرسومات</string>
<string name="gpu_fence_behavior_description">يتحكم في سلوك تزامن حاجز وحدة معالجة الرسوميات. الخيار الفوري هو الأسرع، لكنه قد يسبب بعض المشاكل. الخيار المتوازن يقدم توافقًا أفضل وقد يصلح مشاكل في بعض الألعاب. الخيار الدقيق يحسن التوافق أكثر لكنه قد يقلل الأداء قليلاً. الخيار الصارم هو الأبطأ، لكنه قد يصلح المشاكل التي تتطلب تزامنًا أكثر صرامة. الإعداد الافتراضي يتبع إعداد دقة وحدة معالجة الرسوميات.</string>
<string name="anisotropic_filtering">تصفية متباينة الخواص</string>
<string name="anisotropic_filtering_description">يحسن جودة الأنسجة عند عرضها بزوايا مائلة</string>
<string name="vram_usage_mode">وضع استخدام ذاكرة VRAM</string>
@@ -508,6 +506,8 @@
<string name="fast_gpu_time_description">يُجبر هذا الخيار معظم الألعاب على العمل بأعلى دقة عرض أصلية. استخدم 256 للحصول على أقصى أداء و512 للحصول على أعلى جودة رسومات.</string>
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
<string name="antiflicker">مضاد الوميض</string>
<string name="antiflicker_description">يُجبر هذا الوضع وظائف وحدة معالجة الرسومات على الانتظار حتى يتم إرسال العمل إليها. استخدمه مع وضع وحدة معالجة الرسومات السريع لتجنب الوميض مع تأثير أقل على الأداء.</string>
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string>
<string name="emulate_bgr565">محاكاة BGR565</string>
@@ -573,12 +573,6 @@
<string name="gpu_log_level_description">مستوى التفاصيل لسجلات وحدة معالجة الرسومات (كلما زاد المستوى، زادت التفاصيل وزادت التكاليف الإضافية)</string>
<string name="gpu_log_vulkan_calls">تسجيل استدعاءات واجهة برمجة تطبيقات Vulkan</string>
<string name="gpu_log_vulkan_calls_description">تتبع جميع استدعاءات واجهة برمجة تطبيقات Vulkan في المخزن المؤقت الحلقي</string>
<string name="gpu_log_shader_dumps">تفريغ مظللات SPIR-V</string>
<string name="gpu_log_shader_dumps_description">احفظ ملفات SPIR-V الثنائية المُعاد تجميعها (.spv) في مجلد التفريغ. افحصها باستخدام spirv-dis/spirv-cross/spirv-val.</string>
<string name="dump_guest_shaders">تظليلات ضيف التفريغ (ماكسويل)</string>
<string name="dump_guest_shaders_description">احفظ ملفات بايت كود برنامج التظليل الضيف الخاص بـ «ماكسويل» (*.ash) في مجلد «dump». افحصها باستخدام nvdisasm.</string>
<string name="dump_macros">تفريغ ماكرو ماكسويل</string>
<string name="dump_macros_description">احفظ ملفات برامج ماكرو ماكسويل (*.macro) في مجلد «dump». افحصها باستخدام برنامج «envydis».</string>
<string name="gpu_log_memory_tracking">تتبع ذاكرة وحدة معالجة الرسومات</string>
<string name="gpu_log_memory_tracking_description">مراقبة تخصيصات ذاكرة وحدة معالجة الرسومات وإلغاء تخصيصها</string>
<string name="gpu_log_driver_debug">معلومات تصحيح أخطاء برنامج التشغيل</string>
@@ -998,6 +992,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">سريع</string>
<string name="renderer_accuracy_medium">متوازن</string>
<string name="renderer_accuracy_high">دقيق</string>
<!-- DMA Accuracy -->
@@ -1005,13 +1000,6 @@
<string name="dma_accuracy_unsafe">غير آمن</string>
<string name="dma_accuracy_safe">آمن</string>
<!-- GPU Fence Behavior -->
<string name="gpu_fence_behavior_default">افتراضي</string>
<string name="gpu_fence_behavior_immediate">فوري</string>
<string name="gpu_fence_behavior_balanced">متوازن</string>
<string name="gpu_fence_behavior_accurate">دقيق</string>
<string name="gpu_fence_behavior_strict">صارم</string>
<string name="vram_usage_conservative">محافظ</string>
<string name="vram_usage_aggressive">عدواني</string>
@@ -445,6 +445,7 @@
<string name="advanced">Pokročilé</string>
<string name="renderer_accuracy">Režim GPU</string>
<string name="renderer_accuracy_description">Určuje režim emulovaného GPU. Většina her běží bez problémů v rychlém, nebo vyváženém režimu, ale některé stále vyžadují přesný režim. Částicové efekty se většinou zobrazují korektně pouze v přesném režimu. </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 vyřešit 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, použijte výchozí nastavení.</string>
<string name="anisotropic_filtering">Anizotropní filtrování</string>
@@ -706,6 +707,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Rychlý</string>
<string name="renderer_accuracy_medium">Vyvážený</string>
<string name="renderer_accuracy_high">Přesný</string>
<!-- DMA Accuracy -->
@@ -457,6 +457,7 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="advanced">Erweitert</string>
<string name="renderer_accuracy">GPU-Modus</string>
<string name="renderer_accuracy_description">Steuert den GPU-Emulationsmodus. Die meisten Spiele werden im Modus \"Fast\" oder \"Balanced\" gut gerendert, für einige ist jedoch weiterhin der Modus \"Accurate\" erforderlich. Partikel werden in der Regel nur im Modus \"Accurate\" korrekt gerendert.</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="anisotropic_filtering">Anisotrope Filterung</string>
@@ -926,6 +927,7 @@ Wirklich fortfahren?</string>
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Schnell</string>
<string name="renderer_accuracy_medium">Ausgeglichen</string>
<string name="renderer_accuracy_high">Genau</string>
<!-- DMA Accuracy -->
@@ -467,9 +467,9 @@
<string name="advanced">Avanzado</string>
<string name="renderer_accuracy">Modo de la GPU</string>
<string name="renderer_accuracy_description">Controla el modo de la emulación de la GPU. La mayoría de los juegos se renderizan correctamente en los modos Rápido o Equilibrado, pero algunos requieren Preciso. Las partículas tienden a renderizarse correctamente solo con el modo Preciso.</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="gpu_fence_behavior">Comportamiento de vallado de la GPU</string>
<string name="anisotropic_filtering">Filtrado anisotrópico</string>
<string name="anisotropic_filtering_description">Mejora la calidad de las texturas al ser observadas desde ángulos oblicuos</string>
<string name="vram_usage_mode">Modo de uso de VRAM</string>
@@ -500,6 +500,8 @@
<string name="fast_gpu_time_description">Fuerza a la mayoría de los juegos a ejecutarse a su resolución nativa más alta. Usa 256 para un máximo rendimiento y 512 para una fidelidad gráfica óptima.</string>
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
<string name="antiflicker">Antiparpadeo</string>
<string name="antiflicker_description">Fuerza a las funciones de devolución de llamada de la GPU a esperar a que se envíen las tareas a la GPU.\nÚsalo con el modo de GPU rápida para evitar el parpadeo con un menor impacto en el rendimiento.</string>
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
<string name="emulate_bgr565">Emular BGR565</string>
@@ -565,12 +567,6 @@
<string name="gpu_log_level_description">Nivel de detalle de los registros de la GPU (más alto = más detalles, más sobrecarga)</string>
<string name="gpu_log_vulkan_calls">Registros de llamadas del API de Vulkan</string>
<string name="gpu_log_vulkan_calls_description">Rastrear todas las llamadas del API de Vulkan en el búfer circular</string>
<string name="gpu_log_shader_dumps">Volcar sombreadores SPIR-V</string>
<string name="gpu_log_shader_dumps_description">Guardar binarios recompilados SPIR-V (.spv) a la carpeta de volcado. Inspeccionar con spirv-dis/spirv-cross/spirv-val.</string>
<string name="dump_guest_shaders">Volcar sombreadores huesped (Maxwell)</string>
<string name="dump_guest_shaders_description">Guardar archivos bytecode del sombreador huesped Maxwell (*.ash) a la carpeta de volcado. Inspeccionar con nvdisasm.</string>
<string name="dump_macros">Volcar macros Maxwell</string>
<string name="dump_macros_description">Guardar archivos de programa macro Maxwell (*.macro) a la carpeta de volcado. Inspeccionar con envydis.</string>
<string name="gpu_log_memory_tracking">Rastrear memoria de la GPU</string>
<string name="gpu_log_memory_tracking_description">Monitorizar las asignaciones y desasignaciones de memoria de la GPU</string>
<string name="gpu_log_driver_debug">Información de depuración del controlador</string>
@@ -990,6 +986,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Rápido</string>
<string name="renderer_accuracy_medium">Equilibrado</string>
<string name="renderer_accuracy_high">Preciso</string>
<!-- DMA Accuracy -->
@@ -997,13 +994,6 @@
<string name="dma_accuracy_unsafe">Inseguro</string>
<string name="dma_accuracy_safe">Seguro</string>
<!-- GPU Fence Behavior -->
<string name="gpu_fence_behavior_default">Predeterminado</string>
<string name="gpu_fence_behavior_immediate">Inmediato</string>
<string name="gpu_fence_behavior_balanced">Equilibrado</string>
<string name="gpu_fence_behavior_accurate">Preciso</string>
<string name="gpu_fence_behavior_strict">Estricto</string>
<string name="vram_usage_conservative">Conservador</string>
<string name="vram_usage_aggressive">Agresivo</string>
@@ -939,6 +939,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Rapide</string>
<string name="renderer_accuracy_medium">Moyen</string>
<string name="renderer_accuracy_high">Précis</string>
<!-- DMA Accuracy -->
@@ -445,6 +445,7 @@
<string name="advanced">Zaawansowane</string>
<string name="renderer_accuracy">Tryb GPU</string>
<string name="renderer_accuracy_description">Steruje trybem emulacji GPU. Większość gier renderuje się poprawnie w trybach Szybki lub Zrównoważony, ale dla niektórych nadal wymagany jest tryb Dokładny. Efekty cząsteczkowe zwykle renderują się poprawnie tylko w trybie Dokładnym.</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="anisotropic_filtering">Filtrowanie anizotropowe</string>
@@ -892,6 +893,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Szybkie</string>
<string name="renderer_accuracy_medium">Zrównoważony</string>
<string name="renderer_accuracy_high">Dokładny</string>
<!-- DMA Accuracy -->
@@ -840,6 +840,7 @@
<string name="renderer_none">Nenhum</string>
<string name="renderer_accuracy_medium">Média</string>
<string name="renderer_accuracy_high">Alta</string>
<!-- DMA Accuracy -->
@@ -424,9 +424,6 @@
<string name="cpu_accuracy">Точность ЦП</string>
<string name="value_with_units">%1$s%2$s</string>
<string name="program_args">Аргументы Homebrew</string>
<string name="program_args_description">Аргументы командной строки, переданные Homebrew при запуске (например, -noglsl)</string>
<!-- System settings strings -->
<string name="device_name">Название устройства</string>
<string name="use_docked_mode">Режим док-станции</string>
@@ -469,11 +466,9 @@
<string name="advanced">Расширенные</string>
<string name="renderer_accuracy">Режим ГПУ</string>
<string name="renderer_accuracy_description">Управляет режимом эмуляции ГПУ. Большинство игр нормально отображаются в режиме Быстрый, но для некоторых требуется режим Точный. Частицы обычно корректно отображаются только в режиме Точный.</string>
<string name="renderer_accuracy_description">Управляет режимом эмуляции графического процессора. Большинство игр нормально отображаются в режимах «Быстрый» или «Сбалансированный», но для некоторых требуется режим «Точный». Частицы обычно корректно отображаются только в режиме «Точный».</string>
<string name="dma_accuracy">Точность DMA</string>
<string name="dma_accuracy_description">Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию.</string>
<string name="gpu_fence_behavior">Поведение барьеров ГПУ</string>
<string name="gpu_fence_behavior_description">Управляет поведением синхронизации через барьеры ГПУ. Мгновенный — самый быстрый вариант, но может вызывать некоторые проблемы. Сбалансированный обеспечивает лучшую совместимость и может исправлять проблемы в некоторых играх. Точный ещё больше повышает совместимость ценой некоторого снижения производительности. Строгий — самый медленный вариант, но может исправлять проблемы, требующие более строгой синхронизации. По умолчанию соответствует настройке точности ГПУ.</string>
<string name="anisotropic_filtering">Анизотропная фильтрация</string>
<string name="anisotropic_filtering_description">Улучшает качество текстур под углом</string>
<string name="vram_usage_mode">Режим VRAM</string>
@@ -495,8 +490,6 @@
<string name="renderer_reactive_flushing_description">Повышение точности рендеринга в некоторых играх за счет снижения производительности.</string>
<string name="enable_buffer_history">Включить историю буфера</string>
<string name="enable_buffer_history_description">Позволяет обращаться к предыдущим состояниям буфера. Эта опция может повысить качество рендеринга и стабильность производительности в некоторых играх.</string>
<string name="enable_gpu_buffer_readback">Включить обратное чтение буфера ГПУ</string>
<string name="enable_gpu_buffer_readback_description">Сохраняет измененные ГПУ данные буфера путем чтения их обратно перед выгрузками. Некоторые игры требуют этого, чтобы рендерить определенные эффекты правильно. Может вызывать проблемы если оборудование не может обработать дополнительную рабочую нагрузку.</string>
<string name="use_optimized_vertex_buffers">Оптимизированные вершинные буферы</string>
<string name="use_optimized_vertex_buffers_description">Включает оптимизированную привязку вершинного буфера для повышения производительности. Требует Mesa Turnip 26.0+ / QCOM. Приводит к вылету на старых версиях драйверов Turnip (25.3 и ниже).</string>
@@ -506,6 +499,8 @@
<string name="fast_gpu_time_description">Принудительно запускает большинство игр в их максимальном нативном разрешении. Используйте значение 256 для максимальной производительности и 512 для максимального качества графики.</string>
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
<string name="antiflicker">Анти-мерцание</string>
<string name="antiflicker_description">Принудительно заставляет обратные вызовы ГПУ-фильтра ожидать выполнения отправленных задач на ГПУ. Используйте с Быстрым режимом ГПУ, что бы избежать мерцаний с меньшим влиянием на производительность.</string>
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
<string name="emulate_bgr565">Эмулировать BGR565</string>
@@ -571,12 +566,6 @@
<string name="gpu_log_level_description">Уровень детализации логов ГПУ (больше значение = больше деталей, выше нагрузка)</string>
<string name="gpu_log_vulkan_calls">Записывать вызовы Vulkan API</string>
<string name="gpu_log_vulkan_calls_description">Отслеживать все вызовы Vulkan API в кольцевом буфере</string>
<string name="gpu_log_shader_dumps">Выгрузить SPIR-V шейдеры</string>
<string name="gpu_log_shader_dumps_description">Сохранять перекомпилированные SPIR-V бинарные файлы (.spv) в папку дампа. Проверять с помощью spirv-dis/spirv-cross/spirv-val.</string>
<string name="dump_guest_shaders">Выгрузить гостевые (Maxwell) шейдеры</string>
<string name="dump_guest_shaders_description">Сохранять файлы байткода гостевых шейдеров Maxwell (*.ash) в папку дампа. Проверять с помощью nvdisasm.</string>
<string name="dump_macros">Выгрузить макросы Maxwell</string>
<string name="dump_macros_description">Сохранять файлы макропрограмм Maxwell (*.macro) в папку дампа. Проверять с помощью envydis.</string>
<string name="gpu_log_memory_tracking">Отслеживать память ГПУ</string>
<string name="gpu_log_memory_tracking_description">Мониторить выделение и освобождение памяти ГПУ</string>
<string name="gpu_log_driver_debug">Отладочная информация драйвера</string>
@@ -996,6 +985,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Быстрый</string>
<string name="renderer_accuracy_medium">Сбалансированный</string>
<string name="renderer_accuracy_high">Точный</string>
<!-- DMA Accuracy -->
@@ -1003,13 +993,6 @@
<string name="dma_accuracy_unsafe">Небезопасно</string>
<string name="dma_accuracy_safe">Безопасный</string>
<!-- GPU Fence Behavior -->
<string name="gpu_fence_behavior_default">По умолчанию</string>
<string name="gpu_fence_behavior_immediate">Мгновенный</string>
<string name="gpu_fence_behavior_balanced">Сбалансированный</string>
<string name="gpu_fence_behavior_accurate">Точный</string>
<string name="gpu_fence_behavior_strict">Строгий</string>
<string name="vram_usage_conservative">Консервативный</string>
<string name="vram_usage_aggressive">Агрессивный</string>
@@ -469,6 +469,7 @@
<string name="advanced">Додаткові</string>
<string name="renderer_accuracy">Режим ГП</string>
<string name="renderer_accuracy_description">Керує режимом емуляції ГП. Більшість ігор добре візуалізуються з режимами «Швидко» або «Збалансовано», але деякі ігри можуть потребувати режиму «Точно». Частинки зазвичай правильно візуалізуються лише з режимом «Точно».</string>
<string name="dma_accuracy">Точність DMA</string>
<string name="dma_accuracy_description">Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням.</string>
<string name="anisotropic_filtering">Анізотропне фільтрування</string>
@@ -501,6 +502,8 @@
<string name="fast_gpu_time_description">Примушує більшість ігор працювати на їхній максимальній нативній роздільності. Використовуйте 256 для максимальної продуктивності та 512 для найкращої якості.</string>
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
<string name="antiflicker">Антимерехтіння</string>
<string name="antiflicker_description">Змушує механізм синхронізації чекати, доки ГП завершить подані завдання. Використовуйте з режимом ГП «Швидко», щоб уникнути мерехтіння з меншими втратами продуктивності.</string>
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XXA7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
<string name="emulate_bgr565">Емулювати BGR565</string>
@@ -985,6 +988,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Швидко</string>
<string name="renderer_accuracy_medium">Збалансовано</string>
<string name="renderer_accuracy_high">Точно</string>
<!-- DMA Accuracy -->
@@ -67,7 +67,7 @@
<string name="show_shaders_building">显示着色器编译信息</string>
<string name="show_shaders_building_description">显示当前正在编译的着色器数量</string>
<string name="pipeline_worker_cores">管线工作线程</string>
<string name="pipeline_worker_cores_description">管理用于构建 Vulkan 管线的核心数量,较高的值可提升管线编译性能,但温度也会随之升高。</string>
<string name="pipeline_worker_cores_description">管理用于构建 Vulkan 管线的核心数量,数值越高则管线编译性能越好,但温度也会随之升高。</string>
<string name="overlay_position">叠加层位置</string>
<string name="overlay_position_description">选择叠加层在屏幕上显示的位置</string>
<string name="overlay_position_top_left">左上</string>
@@ -185,7 +185,7 @@
<string name="multiplayer_preferred_game_name">首选游戏</string>
<string name="multiplayer_lobby_type">游戏大厅类型</string>
<string name="multiplayer_room_name_error">长度需为3-20个字符</string>
<string name="multiplayer_required">需要</string>
<string name="multiplayer_required">必填</string>
<string name="multiplayer_token_required">需要Web令牌,请前往高级设置 -> 系统 -> 网络</string>
<string name="multiplayer_ip_error">IP格式无效</string>
<string name="multiplayer_username_error">必须为4至20个字符,且仅包含字母、数字、点号、连字符、下划线和空格</string>
@@ -287,7 +287,7 @@
<string name="warning_skip">跳过</string>
<string name="warning_cancel">取消</string>
<string name="install_amiibo_keys">安装 Amiibo 密钥文件</string>
<string name="install_amiibo_keys_description">在遊戏中使用 Amiibo 时需</string>
<string name="install_amiibo_keys_description">在遊戏中使用 Amiibo 时</string>
<string name="gpu_driver_fetcher">GPU驱动获取器</string>
<string name="gpu_driver_manager">GPU 驱动管理器</string>
<string name="install_gpu_driver_description">安装替代的驱动程序以获得更好的性能和精度</string>
@@ -463,13 +463,11 @@
<string name="advanced">高级</string>
<string name="renderer_accuracy">GPU 模式</string>
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”模式下渲染效果良好,但有些游戏仍需使用“精确”模式。粒子效果通常只有在“精确”模式下才能正确渲染。</string>
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”或“平衡”模式下都能正常渲染,但有些游戏仍需使用“精确”模式。粒子效果通常只有在“精确”模式下才能正确渲染。</string>
<string name="dma_accuracy">DMA 精度</string>
<string name="dma_accuracy_description">控制 DMA 的精准度。安全精度可以修复存在于某些游戏中的问题,但在某些情况下也会对性能造成影响。如不确定,请保持“默认”。</string>
<string name="gpu_fence_behavior">GPU 围栏行为</string>
<string name="gpu_fence_behavior_description">控制 GPU 围栏同步行为。“即时”是速度最快的选项,但可能会引入一些问题。“均衡”提供了更好的兼容性,可能修复某些游戏中的问题。“精确”在牺牲部分性能的前提下进一步提升兼容性。“严格”是速度最慢的选项,但可以修复那些要求更严格同步的问题。默认遵循 GPU “精确”设定。</string>
<string name="anisotropic_filtering">各向异性过滤</string>
<string name="anisotropic_filtering_description">升斜视角下的纹理质量</string>
<string name="anisotropic_filtering_description">高斜角的纹理质量</string>
<string name="vram_usage_mode">显存使用模式</string>
<string name="vram_usage_mode_description">控制显存分配与释放策略</string>
<string name="accelerate_astc">ASTC解码方式</string>
@@ -498,6 +496,8 @@
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。设置为 256 可获得最佳性能,设置为 512 可获得最佳画面保真度。</string>
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
<string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string>
<string name="antiflicker">防闪烁</string>
<string name="antiflicker_description">强制 GPU 围栏回调等待已提交的 GPU 任务。配合“快速 GPU 模式”一起使用,以牺牲少量性能为代价来避免画面闪烁现象。</string>
<string name="fix_bloom_effects">修复 Bloom 效果</string>
<string name="fix_bloom_effects_description">减少《智慧的再现》和《众神的三角力量2》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
<string name="emulate_bgr565">模拟 BGR565</string>
@@ -511,7 +511,7 @@
<string name="gpu_unswizzle_enable">启用 GPU Unswizzle</string>
<string name="gpu_unswizzle_disabled">禁用</string>
<string name="gpu_unswizzle_texture_size">GPU Unswizzle 最大纹理尺寸</string>
<string name="gpu_unswizzle_texture_size_description">设置基于 GPU 的纹理 unswizzling 的最大尺寸(MB)。虽然 GPU 处理中等和大型纹理的速度更快,但对于非常小的纹理,CPU 可能更为高效。通过调节此项设置,以平衡GPU 加速与 CPU 开销。</string>
<string name="gpu_unswizzle_texture_size_description">设置基于 GPU 的纹理 unswizzling 的最大尺寸(MB)。虽然 GPU 处理中等和大型纹理的速度更快,但对于非常小的纹理,CPU 可能更为高效。通过调节此项设置,以尝试在 GPU 加速与 CPU 开销之间找到平衡</string>
<string name="gpu_unswizzle_stream_size">GPU Unswizzle 流大小</string>
<string name="gpu_unswizzle_stream_size_description">设置用于 unswizzling 大型纹理时的每帧数据限制。较高的数值可以加速纹理的加载过程,但会带来更高的帧延迟。而较低的数值则可以降低 GPU 的开销,但也可能会导致可见的纹理闪现。</string>
<string name="gpu_unswizzle_chunk_size">GPU Unswizzle 块大小</string>
@@ -563,12 +563,6 @@
<string name="gpu_log_level_description">GPU 日志的详细级别(数值越高 = 细节越多,开销越大)</string>
<string name="gpu_log_vulkan_calls">记录 Vulkan API 调用</string>
<string name="gpu_log_vulkan_calls_description">在环形缓冲区中跟踪所有 Vulkan API 调用</string>
<string name="gpu_log_shader_dumps">转储 SPIR-V 着色器</string>
<string name="gpu_log_shader_dumps_description">将经过重编译的 SPIR-V 二进制文件(.spv)保存到 dump 文件夹中。使用 spirv-dis/spirv-cross/spirv-val 进行检查。</string>
<string name="dump_guest_shaders">转储 Guest (Maxwell) 着色器</string>
<string name="dump_guest_shaders_description">将 Maxwell guest 着色器字节码文件(*.ash)保存到 dump 文件夹。使用 nvdisasm 进行检查。</string>
<string name="dump_macros">转储 Maxwell 宏</string>
<string name="dump_macros_description">将 Maxwell 宏程序文件(*.macro)保存到 dump 文件夹。使用 envydis 进行检查。</string>
<string name="gpu_log_memory_tracking">追踪 GPU 内存</string>
<string name="gpu_log_memory_tracking_description">监控 GPU 内存的分配和释放</string>
<string name="gpu_log_driver_debug">驱动调试信息</string>
@@ -988,6 +982,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">快速</string>
<string name="renderer_accuracy_medium">平衡</string>
<string name="renderer_accuracy_high">精确</string>
<!-- DMA Accuracy -->
@@ -995,13 +990,6 @@
<string name="dma_accuracy_unsafe">不安全</string>
<string name="dma_accuracy_safe">安全</string>
<!-- GPU Fence Behavior -->
<string name="gpu_fence_behavior_default">默认</string>
<string name="gpu_fence_behavior_immediate">即时</string>
<string name="gpu_fence_behavior_balanced">均衡</string>
<string name="gpu_fence_behavior_accurate">精确</string>
<string name="gpu_fence_behavior_strict">严格</string>
<string name="vram_usage_conservative">保守式</string>
<string name="vram_usage_aggressive">主动式</string>
@@ -1025,7 +1013,7 @@
<string name="ratio_stretch">拉伸窗口</string>
<!-- CPU Accuracy -->
<string name="cpu_accuracy_accurate"></string>
<string name="cpu_accuracy_accurate"></string>
<string name="cpu_accuracy_unsafe">不安全</string>
<string name="cpu_accuracy_paranoid">极致</string>
<string name="cpu_accuracy_debugging">调试</string>
@@ -3,7 +3,7 @@
<string name="app_disclaimer">本軟體可執行Nintendo Switch主機的遊戲,軟體不提供遊戲和金鑰檔案。&lt;br/> &lt;br/>在開始之前,請先安裝您的 &lt;<![CDATA[ &lt;b>prod.keys&lt;/b> ]]> 檔案,&lt;br />&lt;br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">了解更多</a>]]></string>
<string name="notice_notification_channel_name">通知和錯誤</string>
<string name="notice_notification_channel_description">發生錯誤時顯示通知</string>
<string name="notice_notification_channel_description">發生錯誤時顯示通知</string>
<string name="notification_permission_not_granted">未授予通知權限!</string>
<string name="app_notification_channel_description">Eden模擬器通知</string>
<string name="app_notification_running">Eden正在執行</string>
@@ -16,7 +16,7 @@
<string name="value_too_high">範圍最大必須為%1$d</string>
<string name="invalid_value">無效的範圍</string>
<string name="using_per_game_config">使用個別設定</string>
<string name="using_per_game_config">使用自定義組態</string>
<!-- Input Overlay -->
<string name="show_input_overlay">顯示虛擬按鍵</string>
@@ -25,7 +25,7 @@
<string name="overlay_snap_to_grid_description">編輯時將虛擬按鍵與網格對齊</string>
<string name="overlay_grid_size">網格大小</string>
<string name="overlay_grid_size_description">調整網格格線間距</string>
<string name="input_overlay_behavior">隱藏</string>
<string name="input_overlay_behavior">行為模式</string>
<string name="overlay_auto_hide">自動隱藏虛擬按鍵</string>
<string name="overlay_auto_hide_description">在未使用虛擬按鍵幾秒後自動隱藏</string>
<string name="enable_input_overlay_auto_hide">啟用自動隱藏虛擬按鍵</string>
@@ -46,7 +46,7 @@
<string name="shaders_suffix">著色器</string>
<string name="charging">(充電中)</string>
<string name="system_info_label">系統</string>
<string name="system_info_label">系統:</string>
<string name="show_stats_overlay">顯示效能統計疊加層</string>
<string name="stats_overlay_customization">自訂</string>
<string name="stats_overlay_items">可見項目</string>
@@ -54,20 +54,18 @@
<string name="enable_stats_overlay_">啟用效能統計疊加層</string>
<string name="stats_overlay_options_description">設定疊加層中顯示的資訊</string>
<string name="show_fps">顯示FPS</string>
<string name="show_fps_description">顯示當前影格</string>
<string name="show_frametime">顯示影格時間</string>
<string name="show_fps_description">顯示當前</string>
<string name="show_frametime">顯示時間</string>
<string name="show_app_ram_usage">顯示應用程式的記憶體用量</string>
<string name="show_app_ram_usage_description">顯示模擬器的記憶體</string>
<string name="show_app_ram_usage_description">顯示模擬器正在使用的記憶體量</string>
<string name="show_system_ram_usage">顯示系統記憶體用量</string>
<string name="show_system_ram_usage_description">顯示系統的記憶體</string>
<string name="show_system_ram_usage_description">顯示系統使用的記憶體量</string>
<string name="show_bat_temperature">顯示電池溫度</string>
<string name="bat_temperature_unit">電池溫度單位</string>
<string name="show_power_info">顯示電池資訊</string>
<string name="show_power_info_description">顯示當前功耗和電池可續航時間</string>
<string name="show_shaders_building">當著色器在編譯時顯示</string>
<string name="show_shaders_building_description">顯示正在編譯的著色器數量</string>
<string name="pipeline_worker_cores">管線工作執行緒</string>
<string name="pipeline_worker_cores_description">設定用於建置 Vulkan 管線的 CPU 核心數量,設定的數值越大效能越好,但溫度也會上升更快</string>
<string name="overlay_position">疊加層位置</string>
<string name="overlay_position_description">選擇疊加層在畫面上的顯示位置</string>
<string name="overlay_position_top_left">左上</string>
@@ -80,10 +78,10 @@
<string name="perf_overlay_background_description">為疊加層添加背景以提高可讀性</string>
<!-- Device Overlay settings -->
<string name="show_soc_overlay">顯示裝置資訊疊加</string>
<string name="enable_soc_overlay">啟用裝置疊加</string>
<string name="soc_overlay_options">裝置疊加</string>
<string name="soc_overlay_options_description">設定裝置疊加層中顯示的資訊</string>
<string name="show_soc_overlay">顯示裝置資訊</string>
<string name="enable_soc_overlay">啟用裝置</string>
<string name="soc_overlay_options">裝置</string>
<string name="soc_overlay_options_description">設定裝置層中顯示的資訊</string>
<string name="show_build_id">顯示Eden的組建版本</string>
<string name="show_driver_version">顯示圖形驅動程式的版本</string>
@@ -94,10 +92,10 @@
<!-- Eden\'s Veil -->
<string name="buffer_reorder_disable">停用緩衝區重新排序</string>
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能</string>
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能</string>
<string name="use_sync_core">同步核心速度</string>
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
<string name="debug_knobs">偵錯開關</string>
@@ -173,7 +171,7 @@
<string name="multiplayer_ban">封鎖使用者</string>
<string name="multiplayer_room_browser">公開房間</string>
<string name="multiplayer_no_rooms_found">未找到公開房間</string>
<string name="multiplayer_password_required">輸入密碼</string>
<string name="multiplayer_password_required">需輸入密碼</string>
<string name="multiplayer_player_count">%1$d/%2$d</string>
<string name="multiplayer_game">遊戲</string>
<string name="multiplayer_no_game_info">任意遊戲</string>
@@ -192,7 +190,7 @@
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
<string name="multiplayer_port_error">埠號需為1-65535</string>
<string name="cancel">略過</string>
<string name="cancel">取消</string>
<string name="ok">確定</string>
<string name="refresh">重新整理</string>
<string name="room_list">房間列表</string>
@@ -246,21 +244,21 @@
<string name="home_search_games">搜尋遊戲</string>
<string name="search_settings">搜尋設定</string>
<string name="install_prod_keys">安裝 prod.keys</string>
<string name="install_prod_keys_description">需要用來解密零售遊戲</string>
<string name="install_prod_keys_description">需要解密零售遊戲</string>
<string name="install_prod_keys_warning">跳過安裝金鑰?</string>
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,如果不安裝將僅有自製遊戲可以運作</string>
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,若要繼續,將僅有自製遊戲可以運作</string>
<string name="install_prod_keys_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
<string name="install_firmware_warning">跳過安裝韌體?</string>
<string name="emulator_data">設定模擬器資料</string>
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動QLaunch小程式</string>
<string name="permissions">授予權限</string>
<string name="permissions_description">授予權限以使用模擬器的特定功能</string>
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
<string name="notifications">通知</string>
<string name="notifications_description">使用下方的按鈕授予通知權限</string>
<string name="notifications_description">使用下方的按鈕授予通知權限</string>
<string name="permission_denied">權限遭拒</string>
<string name="permission_denied_description">您多次拒絕了要求的權限,現在您需要在系統設定中手動授予</string>
<string name="permission_denied_description">多次拒絕了權限要求,現在您需要在系統設定中手動授予權限。</string>
<string name="about">關於</string>
<string name="about_description">組建版本、製作群、以及更多</string>
<string name="system_information">裝置資訊</string>
@@ -287,7 +285,7 @@
<string name="warning_skip">跳過</string>
<string name="warning_cancel">取消</string>
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
<string name="install_amiibo_keys_description">要在遊戲中使用 Amiibo 得先安裝</string>
<string name="install_amiibo_keys_description">要在遊戲中使用 Amiibo</string>
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
@@ -302,14 +300,14 @@
<string name="notification_no_directory_link">無法開啟 Eden 目錄</string>
<string name="notification_no_directory_link_description">請使用檔案管理員的側邊面板手動定位到使用者資料夾。</string>
<string name="manage_save_data">管理儲存資料</string>
<string name="manage_save_data_description">導入/導出遊戲的儲存資料</string>
<string name="manage_save_data_description">已找到儲存資料,請選取下方的選項。</string>
<string name="import_save_warning">導入儲存資料</string>
<string name="import_save_warning_description">這將會以提供的檔案覆寫現有的該遊戲儲存資料,您確定要繼續嗎?</string>
<string name="import_save_warning_description">這將會以提供的檔案覆寫所有現有的儲存資料,您確定要繼續嗎?</string>
<string name="save_files_importing">正在導入儲存資料…</string>
<string name="save_files_exporting">正在導出儲存資料…</string>
<string name="save_file_imported_success">已成功導入</string>
<string name="save_file_invalid_zip_structure">無效的儲存目錄結構</string>
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲 ID</string>
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲標題 ID</string>
<string name="install_firmware">安裝韌體</string>
<string name="install_firmware_description">韌體必須為 ZIP 壓縮檔,將會用於部分遊戲的啟動</string>
<string name="firmware_installing">正在安裝韌體</string>
@@ -319,15 +317,12 @@
<string name="share_log">分享偵錯記錄</string>
<string name="share_log_description">分享 Eden 的記錄檔以便對相關問題進行偵錯</string>
<string name="share_log_missing">找不到日誌檔案</string>
<string name="share_gpu_log">分享 GPU 日誌</string>
<string name="share_gpu_log_description">分享 Eden 的 GPU 日誌以對圖形問題進行偵錯</string>
<string name="share_gpu_log_missing">找不到 GPU 日誌檔案</string>
<string name="install_game_content">安裝遊戲內容</string>
<string name="install_game_content_description">安裝遊戲更新或 DLC</string>
<string name="installing_game_content">正在安裝內容…</string>
<string name="install_game_content_failure">安裝檔案至 NAND 時發生錯誤</string>
<string name="install_game_content_failure_description">請確保內容有效並且 prod.keys 檔案已安裝</string>
<string name="install_game_content_failure_base">為避免產生衝突,無法直接安裝遊戲本體</string>
<string name="install_game_content_failure_description">請確保內容有效並且 prod.keys 檔案已安裝</string>
<string name="install_game_content_failure_base">為避免可能的衝突,無法直接安裝遊戲本體</string>
<string name="install_game_content_failed_count">%1$d 安裝錯誤</string>
<string name="install_game_content_success">遊戲內容已成功安裝</string>
<string name="install_game_content_success_install">%1$d 安裝成功</string>
@@ -336,12 +331,12 @@
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式。\n請以後再來查看是否已新增支援!</string>
<string name="manage_yuzu_data">管理 Eden 資料</string>
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其項目!</string>
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其項目!</string>
<string name="game_folders">遊戲資料夾</string>
<string name="deep_scan">深度掃描</string>
<string name="add_game_folder">新增遊戲資料夾</string>
<string name="folder_already_added">這個資料夾已經新增過了!</string>
<string name="game_folder_properties">遊戲資料夾設定</string>
<string name="game_folder_properties">遊戲資料夾屬性</string>
<plurals name="saves_import_failed">
<item quantity="other">%d 個存檔導入失敗</item>
</plurals>
@@ -352,30 +347,28 @@
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
<string name="verify_installed_content_description">檢查所有已安裝的內容是否有損壞</string>
<string name="keys_missing">缺少 prod.keys</string>
<string name="keys_missing">缺少解密金鑰</string>
<string name="keys_missing_description">無法解密韌體和零售遊戲</string>
<string name="keys_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
<string name="uninstall_firmware">解除安裝韌體</string>
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性</string>
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性</string>
<string name="firmware_uninstalling">正在解除安裝韌體...</string>
<string name="firmware_uninstalled_success">韌體解除安裝成功</string>
<string name="keys_failed">金鑰安裝失敗</string>
<string name="keys_install_success">金鑰安裝成功</string>
<string name="error_keys_copy_failed">一個或多個金鑰安裝失敗</string>
<string name="error_keys_copy_failed">一個或多個金鑰複製失敗</string>
<string name="error_keys_invalid_filename">請確保金鑰檔案具有.keys副檔名後重試。</string>
<string name="error_keys_failed_init">金鑰初始化失敗。請檢查您的轉儲工具是否為最新版本並重新轉儲金鑰。</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>
<string name="qlaunch_description">Switch系統主畫面啟動應用程式(目前僅支援英文)</string>
<string name="qlaunch_description">從系統主畫面啟動應用程式</string>
<string name="applets">小程式啟動器</string>
<string name="applets_description">使用已安裝的韌體啟動系統小程式</string>
<string name="applets_error_firmware">未安裝韌體</string>
<string name="applets_error_applet">無法使用小程式</string>
<string name="applets_error_description"><![CDATA[請確定您的<a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a>檔案和<a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">韌體</a>已安裝並重試]]></string>
<string name="album_applet">相簿</string>
<string name="album_applet_description">使用系統相片檢視器查看儲存在使用者螢幕截圖資料夾中的影像</string>
<string name="mii_edit_applet">Mii 編輯</string>
@@ -384,58 +377,47 @@
<string name="cabinet_applet_description">編輯、刪除儲存在 amiibo 上的資料</string>
<string name="cabinet_launcher">Cabinet 啟動器</string>
<string name="cabinet_nickname_and_owner">暱稱和擁有者設定</string>
<string name="cabinet_game_data_eraser">刪除遊戲資料</string>
<string name="cabinet_game_data_eraser">遊戲資料橡皮擦</string>
<string name="cabinet_restorer">還原程式</string>
<string name="cabinet_formatter">格式化程式</string>
<!-- About screen strings -->
<string name="gaia_is_not_real">Gaia 不存在</string>
<string name="gaia_is_not_real">Gaia不是真的</string>
<string name="copied_to_clipboard">已複製到剪貼簿</string>
<string name="about_app_description">一個開放原始碼的 Switch 模擬器</string>
<string name="contributors">參與者</string>
<string name="contributors_description">這些人讓 Eden Android 版成為可能</string>
<string name="licenses_description">這些專案使 Eden Android 版成為可能</string>
<string name="build">組建版本</string>
<string name="user_data">使用者資料</string>
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入使用者資料可能會出現問題,建議手動導入所有所需資料。</string>
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入資料可能會出現問題,建議手動導入所有所需資料。</string>
<string name="exporting_user_data">正在導出使用者資料…</string>
<string name="importing_user_data">正在導入使用者資料…</string>
<string name="invalid_yuzu_backup">無效的 Eden 備份</string>
<string name="user_data_export_success">使用者資料導出成功</string>
<string name="user_data_import_success">使用者資料導入成功</string>
<string name="user_data_export_cancelled">導出已取消</string>
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次</string>
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次</string>
<!-- General settings strings -->
<string name="frame_limit_enable">限制模擬速度</string>
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比</string>
<string name="frame_limit_enable">限制速度</string>
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比</string>
<string name="frame_limit_slider">限制速度百分比</string>
<string name="frame_limit_slider_description">指定模擬速度的百分比。100% 為標準速度,更高或更低的值將會減少或增加速度限制</string>
<string name="turbo_speed_limit">加速模式</string>
<string name="turbo_speed_limit_description">當開啟加速模式時,模擬器將以此速度執行</string>
<string name="slow_speed_limit">慢速模式</string>
<string name="slow_speed_limit_description">當慢速模式開啟時,模擬器將會以此速度執行</string>
<string name="frame_limit_slider_description">指定限制模擬速度的百分比。100% 為標準速度,更高或更低的值將會增加或減少速度限制</string>
<string name="cpu_backend">CPU 後端</string>
<string name="cpu_accuracy">CPU 準確度</string>
<string name="value_with_units">%1$s%2$s</string>
<string name="program_args">Homebrew 參數</string>
<string name="program_args_description">在啟動時傳遞給 Homebrew 的命令列參數(例如:-noglsl)</string>
<!-- System settings strings -->
<string name="device_name">裝置名稱</string>
<string name="use_docked_mode">底座模式</string>
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能</string>
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能</string>
<string name="emulated_region">模擬區域</string>
<string name="emulated_language">模擬語言</string>
<string name="select_rtc_date">選擇 RTC 日期</string>
<string name="select_rtc_time">選擇 RTC 時間</string>
<string name="use_custom_rtc">自訂 RTC</string>
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
<string name="set_custom_rtc">設定自訂 RTC</string>
<!-- CPU -->
<string name="fast_cpu_time">CPU 超頻</string>
<string name="fast_cpu_time_description">強制模擬 CPU 以更高的時脈運作,減少某些 FPS 限制。使用 加速 (1700MHz) 以 Switch 的最高原生時脈執行,或 高速 (2000MHz) 以雙倍時脈執行</string>
<string name="custom_cpu_ticks">自訂CPU時脈</string>
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
<string name="cpu_ticks">時脈</string>
@@ -446,41 +428,33 @@
<!-- Network settings strings -->
<string name="web_token">網路令牌</string>
<string name="web_token_description">用於建立公開大廳的網路令牌。由48個小寫字母a-z組成</string>
<string name="web_token_description">用於建立公開大廳的網路令牌。它是由48個小寫字母a-z組成的字串。</string>
<string name="web_username">網路使用者名稱</string>
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)</string>
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)</string>
<string name="network">網路</string>
<!-- Graphics settings strings -->
<string name="renderer_resolution">解析度 (手提/底座)</string>
<string name="renderer_vsync">垂直同步</string>
<string name="renderer_scaling_filter">視窗適應濾</string>
<string name="fsr_sharpness">FSR/SGSR 銳化度</string>
<string name="fsr_sharpness_description">使用 FSR/SGSR 時圖片的銳化程度</string>
<string name="renderer_scaling_filter">視窗適應濾器</string>
<string name="renderer_anti_aliasing">抗鋸齒</string>
<string name="advanced">進階</string>
<string name="renderer_accuracy">GPU 模式</string>
<string name="renderer_accuracy_description">設定 GPU 模擬的準確度。大多數遊戲在設定為快速時即可正常渲染,但有些需要渲染粒子的遊戲仍需設為準確來避免圖形錯誤</string>
<string name="dma_accuracy">DMA 準確度</string>
<string name="dma_accuracy_description">控制 DMA 準確度。準確度設為穩定可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為預設</string>
<string name="gpu_fence_behavior">GPU 同步柵欄模式</string>
<string name="gpu_fence_behavior_description">控制 GPU 同步柵欄模式。即時是速度最快的選項,但可能會導致一些問題。使用平衡可以提供更好的相容性並修復某些遊戲中的錯誤。準確則是在犧牲部分效能的情況下進一步提升相容性。嚴格是最慢的選項,但可以修復那些對同步要求更嚴格的遊戲中的問題。預設則會依照 GPU 準確度設定</string>
<string name="dma_accuracy_description">控制 DMA 準確度。安全準確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為預設」。</string>
<string name="anisotropic_filtering">各向異性過濾</string>
<string name="anisotropic_filtering_description">改善斜角檢視時的紋理品質</string>
<string name="vram_usage_mode">VRAM使用模式</string>
<string name="vram_usage_mode_description">控制GPU記憶體的分配與釋放策略</string>
<string name="accelerate_astc">ASTC解碼方式</string>
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、穩定)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、安全)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
<string name="sync_memory_operations">同步記憶體操作</string>
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大</string>
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大</string>
<string name="use_disk_shader_cache">磁碟著色器快取</string>
<string name="use_disk_shader_cache_description">將產生的著色器快取儲存至硬碟以減少中斷</string>
<string name="use_disk_shader_cache_description">將產生的著色器快取儲存至硬碟以減少中斷</string>
<string name="renderer_force_max_clock">強制使用最大時脈 (僅限Adreno)</string>
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)</string>
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)</string>
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
@@ -629,7 +603,7 @@
<string name="import_complete">導入完成</string>
<string name="use_global_setting">使用全域設定</string>
<string name="operation_completed_successfully">操作已成功完成</string>
<string name="confirm">下載</string>
<string name="confirm">確定</string>
<string name="load">載入</string>
<string name="save">儲存</string>
@@ -847,8 +821,8 @@
<!-- Memory Layouts -->
<string name="memory_4gb">4GB (推薦)</string>
<string name="memory_6gb">6GB (不穩定)</string>
<string name="memory_8gb">8GB (不穩定)</string>
<string name="memory_6gb">6GB (不安全)</string>
<string name="memory_8gb">8GB (不安全)</string>
<!--CPU clock speeds-->
<string name="clock_boost">加速 (1700MHz)</string>
@@ -869,12 +843,13 @@
<string name="renderer_none"></string>
<string name="renderer_accuracy_medium">平衡</string>
<string name="renderer_accuracy_high">準確</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">預設</string>
<string name="dma_accuracy_unsafe">穩定</string>
<string name="dma_accuracy_safe">穩定</string>
<string name="dma_accuracy_unsafe">安全</string>
<string name="dma_accuracy_safe">安全</string>
<string name="vram_usage_conservative">保守</string>
<string name="vram_usage_aggressive">積極</string>
@@ -900,7 +875,7 @@
<!-- CPU Accuracy -->
<string name="cpu_accuracy_accurate">高準確度</string>
<string name="cpu_accuracy_unsafe">低準確度(不穩定</string>
<string name="cpu_accuracy_unsafe">低準確度(不安全</string>
<string name="cpu_accuracy_paranoid">不合理</string>
<string name="cpu_accuracy_debugging">偵錯</string>
+2 -15
View File
@@ -103,12 +103,14 @@
<string-array name="rendererAccuracyNames">
<item>@string/renderer_accuracy_low</item>
<item>@string/renderer_accuracy_medium</item>
<item>@string/renderer_accuracy_high</item>
</string-array>
<integer-array name="rendererAccuracyValues">
<item>0</item>
<item>1</item>
<item>2</item>
</integer-array>
<!-- VRAM USAGE MODE CHOICES -->
@@ -520,21 +522,6 @@
<item>2</item>
</integer-array>
<string-array name="gpuFenceBehaviorNames">
<item>@string/gpu_fence_behavior_default</item>
<item>@string/gpu_fence_behavior_immediate</item>
<item>@string/gpu_fence_behavior_balanced</item>
<item>@string/gpu_fence_behavior_accurate</item>
<item>@string/gpu_fence_behavior_strict</item>
</string-array>
<integer-array name="gpuFenceBehaviorValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</integer-array>
<string-array name="appletEntries">
<item>@string/applet_hle</item>
@@ -479,11 +479,9 @@
<string name="advanced">Advanced</string>
<string name="renderer_accuracy">GPU Mode</string>
<string name="renderer_accuracy_description">Controls the GPU emulation mode. Most games render fine with Fast, but Accurate is still required for some. Particles tend to only render correctly with Accurate mode.</string>
<string name="renderer_accuracy_description">Controls the GPU emulation mode. Most games render fine with Fast or Balanced modes, but Accurate is still required for some. Particles tend to only render correctly with Accurate mode.</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>
<string name="gpu_fence_behavior">GPU Fence Behavior</string>
<string name="gpu_fence_behavior_description">Controls the GPU fence synchronization behavior. Immediate is the fastest option, but can introduce some issues. Balanced offers better compatibility and may fix issues in some games. Accurate further improves compatibility at the cost of some performance. Strict is the slowest option, but can fix issues that require stricter synchronization. Default follows the GPU Accuracy setting.</string>
<string name="anisotropic_filtering">Anisotropic filtering</string>
<string name="anisotropic_filtering_description">Improves the quality of textures when viewed at oblique angles</string>
<string name="vram_usage_mode">VRAM Usage Mode</string>
@@ -514,6 +512,8 @@
<string name="fast_gpu_time_description">Forces most games to run at their highest native resolution. Use 256 for maximal performance and 512 for maximal graphics fidelity.</string>
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
<string name="antiflicker">Anti-Flicker</string>
<string name="antiflicker_description">Forces GPU fence callbacks to wait for submitted GPU work. Use with Fast GPU mode, to avoid flicker with lower performance impact.</string>
<string name="fix_bloom_effects">Fix Bloom Effects</string>
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
<string name="emulate_bgr565">Emulate BGR565</string>
@@ -1037,6 +1037,7 @@
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Fast</string>
<string name="renderer_accuracy_medium">Balanced</string>
<string name="renderer_accuracy_high">Accurate</string>
<!-- DMA Accuracy -->
@@ -1044,13 +1045,6 @@
<string name="dma_accuracy_unsafe">Unsafe</string>
<string name="dma_accuracy_safe">Safe</string>
<!-- GPU Fence Behavior -->
<string name="gpu_fence_behavior_default">Default</string>
<string name="gpu_fence_behavior_immediate">Immediate</string>
<string name="gpu_fence_behavior_balanced">Balanced</string>
<string name="gpu_fence_behavior_accurate">Accurate</string>
<string name="gpu_fence_behavior_strict">Strict</string>
<!-- ASTC Decoding Method Choices -->
<string name="accelerate_astc_cpu" translatable="false">CPU</string>
<string name="accelerate_astc_gpu" translatable="false">GPU</string>
@@ -29,8 +29,96 @@ void AudioRenderer::Start() {
CreateSinkStreams();
mailbox.Initialize(AppMailboxId::AudioRenderer);
// Main AudioRenderer thread, responsible for processing the command lists.
main_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("DSP_AudioRenderer_Main");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
main_thread = std::jthread([this](std::stop_token stop_token) { Main(stop_token); });
// TODO: Create buffer map/unmap thread + mailbox
// TODO: Create gMix devices, initialize them here
if (mailbox.Receive(Direction::DSP) != Message::InitializeOK) {
LOG_ERROR(Service_Audio, "ADSP Audio Renderer -- Failed to receive initialize message from host!");
return;
}
mailbox.Send(Direction::Host, Message::InitializeOK);
// 0.12 seconds (2,304,000 / 19,200,000)
constexpr u64 max_process_time{2'304'000ULL};
while (!stop_token.stop_requested()) {
auto msg{mailbox.Receive(Direction::DSP)};
switch (msg) {
case Message::Shutdown:
mailbox.Send(Direction::Host, Message::Shutdown);
return;
case Message::Render: {
if (system.IsShuttingDown()) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
mailbox.Send(Direction::Host, Message::RenderResponse);
continue;
}
std::array<bool, MaxRendererSessions> buffers_reset{};
std::array<u64, MaxRendererSessions> render_times_taken{};
const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()};
for (u32 index = 0; index < MaxRendererSessions; index++) {
auto& command_buffer{command_buffers[index]};
auto& command_list_processor{command_list_processors[index]};
// Check this buffer is valid, as it may not be used.
if (command_buffer.buffer != 0) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) {
command_list_processor.Initialize(system, *command_buffer.process,
command_buffer.buffer,
command_buffer.size, streams[index]);
}
if (command_buffer.reset_buffer && !buffers_reset[index]) {
streams[index]->ClearQueue();
buffers_reset[index] = true;
}
u64 max_time{max_process_time};
if (index == 1 && command_buffer.applet_resource_user_id ==
command_buffers[0].applet_resource_user_id) {
max_time = max_process_time - render_times_taken[0];
if (render_times_taken[0] > max_process_time) {
max_time = 0;
}
}
max_time = (std::min)(command_buffer.time_limit, max_time);
command_list_processor.SetProcessTimeMax(max_time);
if (index == 0) {
streams[index]->WaitFreeSpace(stop_token);
}
// Process the command list
{
render_times_taken[index] =
command_list_processor.Process(index) - start_time;
}
const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()};
command_buffer.remaining_command_count =
command_list_processor.GetRemainingCommandCount();
command_buffer.render_time_taken_us = end_time - start_time;
}
}
mailbox.Send(Direction::Host, Message::RenderResponse);
} break;
default:
LOG_WARNING(Service_Audio, "ADSP AudioRenderer received an invalid message, msg={:02X}!", msg);
break;
}
}
});
mailbox.Send(Direction::DSP, Message::InitializeOK);
if (mailbox.Receive(Direction::Host) != Message::InitializeOK) {
@@ -129,95 +217,4 @@ void AudioRenderer::CreateSinkStreams() {
}
}
void AudioRenderer::Main(std::stop_token stop_token) {
Common::SetCurrentThreadName("DSP_AudioRenderer_Main");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
// TODO: Create buffer map/unmap thread + mailbox
// TODO: Create gMix devices, initialize them here
if (mailbox.Receive(Direction::DSP) != Message::InitializeOK) {
LOG_ERROR(Service_Audio, "ADSP Audio Renderer -- Failed to receive initialize message from host!");
return;
}
mailbox.Send(Direction::Host, Message::InitializeOK);
// 0.12 seconds (2,304,000 / 19,200,000)
constexpr u64 max_process_time{2'304'000ULL};
while (!stop_token.stop_requested()) {
auto msg{mailbox.Receive(Direction::DSP)};
switch (msg) {
case Message::Shutdown:
mailbox.Send(Direction::Host, Message::Shutdown);
return;
case Message::Render: {
if (system.IsShuttingDown()) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
mailbox.Send(Direction::Host, Message::RenderResponse);
continue;
}
std::array<bool, MaxRendererSessions> buffers_reset{};
std::array<u64, MaxRendererSessions> render_times_taken{};
const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()};
for (u32 index = 0; index < MaxRendererSessions; index++) {
auto& command_buffer{command_buffers[index]};
auto& command_list_processor{command_list_processors[index]};
// Check this buffer is valid, as it may not be used.
if (command_buffer.buffer != 0) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) {
command_list_processor.Initialize(system, *command_buffer.process,
command_buffer.buffer,
command_buffer.size, streams[index]);
}
if (command_buffer.reset_buffer && !buffers_reset[index]) {
streams[index]->ClearQueue();
buffers_reset[index] = true;
}
u64 max_time{max_process_time};
if (index == 1 && command_buffer.applet_resource_user_id ==
command_buffers[0].applet_resource_user_id) {
max_time = max_process_time - render_times_taken[0];
if (render_times_taken[0] > max_process_time) {
max_time = 0;
}
}
max_time = (std::min)(command_buffer.time_limit, max_time);
command_list_processor.SetProcessTimeMax(max_time);
if (index == 0) {
streams[index]->WaitFreeSpace(stop_token);
}
// Process the command list
{
render_times_taken[index] =
command_list_processor.Process(index) - start_time;
}
const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()};
command_buffer.remaining_command_count =
command_list_processor.GetRemainingCommandCount();
command_buffer.render_time_taken_us = end_time - start_time;
}
}
mailbox.Send(Direction::Host, Message::RenderResponse);
} break;
default:
LOG_WARNING(Service_Audio, "ADSP AudioRenderer received an invalid message, msg={:02X}!", msg);
break;
}
}
}
} // namespace AudioCore::ADSP::AudioRenderer
@@ -82,11 +82,6 @@ public:
u64 GetRenderingStartTick(s32 session_id) const noexcept;
private:
/**
* Main AudioRenderer thread, responsible for processing the command lists.
*/
void Main(std::stop_token stop_token);
/**
* Creates the streams which will receive the processed samples.
*/
+194 -195
View File
@@ -37,7 +37,9 @@ bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 stereo_stream_co
} // namespace
OpusDecoder::OpusDecoder(Core::System& system_) : system{system_} {
init_thread = std::jthread([this](std::stop_token stop_token) { Init(stop_token); });
init_thread = std::jthread([this](std::stop_token stop_token) {
Init(stop_token);
});
}
OpusDecoder::~OpusDecoder() {
@@ -64,206 +66,203 @@ u32 OpusDecoder::Receive(Direction dir, std::stop_token stop_token) {
return mailbox.Receive(dir, stop_token);
}
void OpusDecoder::Init(std::stop_token stop_token) {
void OpusDecoder::Init(std::stop_token rc_stop_token) {
Common::SetCurrentThreadName("DSP_OpusDecoder_Init");
if (Receive(Direction::DSP, stop_token) != Message::Start) {
LOG_ERROR(Service_Audio,
"DSP OpusDecoder failed to receive Start message. Opus initialization failed.");
if (Receive(Direction::DSP, rc_stop_token) != Message::Start) {
LOG_ERROR(Service_Audio, "DSP OpusDecoder failed to receive Start message. Opus initialization failed.");
return;
}
main_thread = std::jthread([this](std::stop_token st) { Main(st); });
// Main OpusDecoder thread, responsible for processing the incoming Opus packets.
main_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("DSP_OpusDecoder_Main");
while (!stop_token.stop_requested()) {
auto msg = Receive(Direction::DSP, stop_token);
switch (msg) {
case Shutdown:
Send(Direction::Host, Message::ShutdownOK);
return;
case GetWorkBufferSize: {
auto channel_count = static_cast<s32>(shared_memory->host_send_data[0]);
ASSERT(IsValidChannelCount(channel_count));
shared_memory->dsp_return_data[0] = OpusDecodeObject::GetWorkBufferSize(channel_count);
Send(Direction::Host, Message::GetWorkBufferSizeOK);
} break;
case InitializeDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
auto channel_count = static_cast<s32>(shared_memory->host_send_data[3]);
ASSERT(sample_rate >= 0);
ASSERT(IsValidChannelCount(channel_count));
ASSERT(buffer_size >= OpusDecodeObject::GetWorkBufferSize(channel_count));
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] =
decoder_object.InitializeDecoder(sample_rate, channel_count);
Send(Direction::Host, Message::InitializeDecodeObjectOK);
} break;
case ShutdownDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.Shutdown();
Send(Direction::Host, Message::ShutdownDecodeObjectOK);
} break;
case DecodeInterleaved: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
auto input_data = shared_memory->host_send_data[1];
auto input_data_size = shared_memory->host_send_data[2];
auto output_data = shared_memory->host_send_data[3];
auto output_data_size = shared_memory->host_send_data[4];
auto final_range = static_cast<u32>(shared_memory->host_send_data[5]);
auto reset_requested = shared_memory->host_send_data[6];
u32 decoded_samples{0};
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
s32 error_code{OPUS_OK};
if (reset_requested) {
error_code = decoder_object.ResetDecoder();
}
if (error_code == OPUS_OK) {
error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size,
input_data, input_data_size);
}
if (error_code == OPUS_OK) {
if (final_range && decoder_object.GetFinalRange() != final_range) {
error_code = OPUS_INVALID_PACKET;
}
}
auto end_time = system.CoreTiming().GetGlobalTimeUs();
shared_memory->dsp_return_data[0] = error_code;
shared_memory->dsp_return_data[1] = decoded_samples;
shared_memory->dsp_return_data[2] = (end_time - start_time).count();
Send(Direction::Host, Message::DecodeInterleavedOK);
} break;
case MapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::MapMemoryOK);
} break;
case UnmapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::UnmapMemoryOK);
} break;
case GetWorkBufferSizeForMultiStream: {
auto total_stream_count = static_cast<s32>(shared_memory->host_send_data[0]);
auto stereo_stream_count = static_cast<s32>(shared_memory->host_send_data[1]);
ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count));
shared_memory->dsp_return_data[0] = OpusMultiStreamDecodeObject::GetWorkBufferSize(
total_stream_count, stereo_stream_count);
Send(Direction::Host, Message::GetWorkBufferSizeForMultiStreamOK);
} break;
case InitializeMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
auto channel_count = static_cast<s32>(shared_memory->host_send_data[3]);
auto total_stream_count = static_cast<s32>(shared_memory->host_send_data[4]);
auto stereo_stream_count = static_cast<s32>(shared_memory->host_send_data[5]);
// Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel
// mappings, but [6] is never set, and there is not enough room in the argument data for
// more than 40 channels, when 255 are possible.
// It also means the mapping values are undefined, though likely always 0,
// and the mappings given by the game are ignored. The mappings are copied to this
// dedicated buffer host side, so let's do as intended.
auto mappings = shared_memory->channel_mapping.data();
ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count));
ASSERT(sample_rate >= 0);
ASSERT(buffer_size >= OpusMultiStreamDecodeObject::GetWorkBufferSize(
total_stream_count, stereo_stream_count));
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.InitializeDecoder(
sample_rate, total_stream_count, channel_count, stereo_stream_count, mappings);
Send(Direction::Host, Message::InitializeMultiStreamDecodeObjectOK);
} break;
case ShutdownMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.Shutdown();
Send(Direction::Host, Message::ShutdownMultiStreamDecodeObjectOK);
} break;
case DecodeInterleavedForMultiStream: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
auto input_data = shared_memory->host_send_data[1];
auto input_data_size = shared_memory->host_send_data[2];
auto output_data = shared_memory->host_send_data[3];
auto output_data_size = shared_memory->host_send_data[4];
auto final_range = static_cast<u32>(shared_memory->host_send_data[5]);
auto reset_requested = shared_memory->host_send_data[6];
u32 decoded_samples{0};
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
s32 error_code{OPUS_OK};
if (reset_requested) {
error_code = decoder_object.ResetDecoder();
}
if (error_code == OPUS_OK) {
error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size,
input_data, input_data_size);
}
if (error_code == OPUS_OK) {
if (final_range && decoder_object.GetFinalRange() != final_range) {
error_code = OPUS_INVALID_PACKET;
}
}
auto end_time = system.CoreTiming().GetGlobalTimeUs();
shared_memory->dsp_return_data[0] = error_code;
shared_memory->dsp_return_data[1] = decoded_samples;
shared_memory->dsp_return_data[2] = (end_time - start_time).count();
Send(Direction::Host, Message::DecodeInterleavedForMultiStreamOK);
} break;
default:
LOG_ERROR(Service_Audio, "Invalid OpusDecoder command {}", msg);
continue;
}
}
});
running = true;
Send(Direction::Host, Message::StartOK);
}
void OpusDecoder::Main(std::stop_token stop_token) {
Common::SetCurrentThreadName("DSP_OpusDecoder_Main");
while (!stop_token.stop_requested()) {
auto msg = Receive(Direction::DSP, stop_token);
switch (msg) {
case Shutdown:
Send(Direction::Host, Message::ShutdownOK);
return;
case GetWorkBufferSize: {
auto channel_count = static_cast<s32>(shared_memory->host_send_data[0]);
ASSERT(IsValidChannelCount(channel_count));
shared_memory->dsp_return_data[0] = OpusDecodeObject::GetWorkBufferSize(channel_count);
Send(Direction::Host, Message::GetWorkBufferSizeOK);
} break;
case InitializeDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
auto channel_count = static_cast<s32>(shared_memory->host_send_data[3]);
ASSERT(sample_rate >= 0);
ASSERT(IsValidChannelCount(channel_count));
ASSERT(buffer_size >= OpusDecodeObject::GetWorkBufferSize(channel_count));
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] =
decoder_object.InitializeDecoder(sample_rate, channel_count);
Send(Direction::Host, Message::InitializeDecodeObjectOK);
} break;
case ShutdownDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.Shutdown();
Send(Direction::Host, Message::ShutdownDecodeObjectOK);
} break;
case DecodeInterleaved: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
auto input_data = shared_memory->host_send_data[1];
auto input_data_size = shared_memory->host_send_data[2];
auto output_data = shared_memory->host_send_data[3];
auto output_data_size = shared_memory->host_send_data[4];
auto final_range = static_cast<u32>(shared_memory->host_send_data[5]);
auto reset_requested = shared_memory->host_send_data[6];
u32 decoded_samples{0};
auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer);
s32 error_code{OPUS_OK};
if (reset_requested) {
error_code = decoder_object.ResetDecoder();
}
if (error_code == OPUS_OK) {
error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size,
input_data, input_data_size);
}
if (error_code == OPUS_OK) {
if (final_range && decoder_object.GetFinalRange() != final_range) {
error_code = OPUS_INVALID_PACKET;
}
}
auto end_time = system.CoreTiming().GetGlobalTimeUs();
shared_memory->dsp_return_data[0] = error_code;
shared_memory->dsp_return_data[1] = decoded_samples;
shared_memory->dsp_return_data[2] = (end_time - start_time).count();
Send(Direction::Host, Message::DecodeInterleavedOK);
} break;
case MapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::MapMemoryOK);
} break;
case UnmapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::UnmapMemoryOK);
} break;
case GetWorkBufferSizeForMultiStream: {
auto total_stream_count = static_cast<s32>(shared_memory->host_send_data[0]);
auto stereo_stream_count = static_cast<s32>(shared_memory->host_send_data[1]);
ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count));
shared_memory->dsp_return_data[0] = OpusMultiStreamDecodeObject::GetWorkBufferSize(
total_stream_count, stereo_stream_count);
Send(Direction::Host, Message::GetWorkBufferSizeForMultiStreamOK);
} break;
case InitializeMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
auto channel_count = static_cast<s32>(shared_memory->host_send_data[3]);
auto total_stream_count = static_cast<s32>(shared_memory->host_send_data[4]);
auto stereo_stream_count = static_cast<s32>(shared_memory->host_send_data[5]);
// Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel
// mappings, but [6] is never set, and there is not enough room in the argument data for
// more than 40 channels, when 255 are possible.
// It also means the mapping values are undefined, though likely always 0,
// and the mappings given by the game are ignored. The mappings are copied to this
// dedicated buffer host side, so let's do as intended.
auto mappings = shared_memory->channel_mapping.data();
ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count));
ASSERT(sample_rate >= 0);
ASSERT(buffer_size >= OpusMultiStreamDecodeObject::GetWorkBufferSize(
total_stream_count, stereo_stream_count));
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.InitializeDecoder(
sample_rate, total_stream_count, channel_count, stereo_stream_count, mappings);
Send(Direction::Host, Message::InitializeMultiStreamDecodeObjectOK);
} break;
case ShutdownMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
shared_memory->dsp_return_data[0] = decoder_object.Shutdown();
Send(Direction::Host, Message::ShutdownMultiStreamDecodeObjectOK);
} break;
case DecodeInterleavedForMultiStream: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
auto input_data = shared_memory->host_send_data[1];
auto input_data_size = shared_memory->host_send_data[2];
auto output_data = shared_memory->host_send_data[3];
auto output_data_size = shared_memory->host_send_data[4];
auto final_range = static_cast<u32>(shared_memory->host_send_data[5]);
auto reset_requested = shared_memory->host_send_data[6];
u32 decoded_samples{0};
auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer);
s32 error_code{OPUS_OK};
if (reset_requested) {
error_code = decoder_object.ResetDecoder();
}
if (error_code == OPUS_OK) {
error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size,
input_data, input_data_size);
}
if (error_code == OPUS_OK) {
if (final_range && decoder_object.GetFinalRange() != final_range) {
error_code = OPUS_INVALID_PACKET;
}
}
auto end_time = system.CoreTiming().GetGlobalTimeUs();
shared_memory->dsp_return_data[0] = error_code;
shared_memory->dsp_return_data[1] = decoded_samples;
shared_memory->dsp_return_data[2] = (end_time - start_time).count();
Send(Direction::Host, Message::DecodeInterleavedForMultiStreamOK);
} break;
default:
LOG_ERROR(Service_Audio, "Invalid OpusDecoder command {}", msg);
continue;
}
}
}
} // namespace AudioCore::ADSP::OpusDecoder
@@ -72,10 +72,6 @@ private:
* Initializing thread, launched at audio_core boot to avoid blocking the main emu boot thread.
*/
void Init(std::stop_token stop_token);
/**
* Main OpusDecoder thread, responsible for processing the incoming Opus packets.
*/
void Main(std::stop_token stop_token);
/// Core system
Core::System& system;
+2 -2
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 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
@@ -147,7 +147,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out
auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
OpusPacketHeader header{ReverseHeader(*header_p)};
LOG_TRACE(Service_Audio, "header size {:#x} input data size {:#x} in_data size {:#x}",
LOG_TRACE(Service_Audio, "header size {:#X} input data size 0x{:X} in_data size 0x{:X}",
header.size, input_data.size_bytes(), in_data.size_bytes());
R_UNLESS(in_data.size_bytes() >= header.size &&
@@ -369,7 +369,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
if (mix_count < 0 || mix_count > 0x100) {
LOG_ERROR(
Service_Audio,
"Invalid mix count from dirty parameter: count={}, magic={:#x}, expected_size={}",
"Invalid mix count from dirty parameter: count={}, magic=0x{:X}, expected_size={}",
mix_count, in_dirty_params->magic, in_header->mix_size);
return Service::Audio::ResultInvalidUpdateInfo;
}
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -184,9 +181,8 @@ MemoryPoolInfo::ResultState PoolMapper::Update(MemoryPoolInfo& pool,
return MemoryPoolInfo::ResultState::Success;
}
if (in_params.address == 0 || in_params.size == 0
|| !Common::IsAligned(in_params.address, Core::Memory::YUZU_PAGESIZE)
|| !Common::IsAligned(in_params.size, Core::Memory::YUZU_PAGESIZE)) {
if (in_params.address == 0 || in_params.size == 0 || !Common::Is4KBAligned(in_params.address) ||
!Common::Is4KBAligned(in_params.size)) {
return MemoryPoolInfo::ResultState::BadParam;
}

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