mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-28 15:31:12 +02:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14cbcc2438 | |||
| 0a73fb5229 | |||
| 254250a83d | |||
| 83c727794e | |||
| a6c610cf26 | |||
| 0dafab4053 | |||
| 40b2fd0e6b | |||
| 610e9eb516 | |||
| d835cab32d | |||
| 46c2a81f4a | |||
| 1ebdef1a02 | |||
| bd80d603e2 | |||
| 76bb5fc18b | |||
| b1821cb60e | |||
| b1cc417c55 | |||
| 70620c245c | |||
| 8389a98648 | |||
| 7fe40a37ef | |||
| e05c74108f | |||
| cd7414814a | |||
| dfe1f39a4b | |||
| 3f1f20185c | |||
| 1845d5b222 | |||
| 1240268048 | |||
| a134ad3fbd | |||
| da30efbc55 | |||
| 2dbca791f6 | |||
| 74248bd35a | |||
| e715925d52 | |||
| 852b8e176f | |||
| b2b07abbc8 | |||
| ce2f2187bd | |||
| 8c077fc4cd | |||
| b88ca5b635 | |||
| 4755ec7a59 | |||
| e20875d8fc | |||
| 58bff28b04 | |||
| 570cd64c03 | |||
| b0a607539a | |||
| 64163f2d2a | |||
| 631ad933b2 | |||
| 6985aaf614 | |||
| d1466b0e9d | |||
| a02e8a5679 | |||
| e98280bee9 | |||
| 1d0a3e83fa | |||
| 4343874a69 | |||
| 11d5c0f96a | |||
| ca42578d4e | |||
| b7087a16ba | |||
| 1bdedc17ad | |||
| 32e63b5fa2 | |||
| 2e89bb890a | |||
| 842acf2c86 | |||
| 2d4c460011 | |||
| c42c67ab85 | |||
| 5bce1993e1 | |||
| 8c79a3a8de | |||
| ebb3cda782 | |||
| daf972b517 | |||
| cd25e61afa | |||
| 4a7aa1618a | |||
| 1aae75512b | |||
| 825b899bf8 | |||
| 73c16c3d45 | |||
| 124c97a88a | |||
| 02f9c5ffd2 | |||
| 042a10cf71 | |||
| d6a889828f | |||
| d06eb3f52f | |||
| 21c77d5dce | |||
| a80e0f10ba | |||
| ccb518dc05 | |||
| bb768ad570 | |||
| c028d925bc | |||
| 3557ff28b7 | |||
| 108bb3d28b | |||
| 5b12a7725d | |||
| 15d575aa31 | |||
| 47fe86be7b | |||
| 3db45f3c46 | |||
| 4481391474 | |||
| dee102cf92 | |||
| ad2f40b0e7 | |||
| d10080b757 | |||
| ce15cf7cd3 | |||
| 6b87b0052a | |||
| 9630da580d | |||
| 12fdd88a58 | |||
| 646aea7fbf | |||
| 186c0b0cc7 | |||
| ee1ffbaf2e | |||
| c931de0570 | |||
| 33f1fb1cf4 | |||
| aabc470314 | |||
| d82a6a273d | |||
| 4bb853d52a | |||
| 43ebdb1ffc | |||
| e310f0b151 | |||
| 9b915c8659 | |||
| 35ab33de6a | |||
| 5615ea9ced | |||
| d273fc4ad6 | |||
| e3e880e879 | |||
| 6b8115f27a | |||
| a24e7e8143 | |||
| 88b9393b44 | |||
| 2081d659d2 | |||
| 9eacaf2444 | |||
| c9eb764d2a | |||
| 72ced6b947 | |||
| ffae2350ca | |||
| 646542a397 | |||
| 1ae76d44c1 | |||
| 24d07ab28c | |||
| 651a999017 | |||
| 5c0e12fb0e | |||
| 712c505cd1 | |||
| 051522b54e | |||
| a1fdbef129 | |||
| ecd5c751f8 | |||
| 69678d02b6 | |||
| 8d031532d8 | |||
| c8e4818b01 | |||
| 2bac9cec32 | |||
| 6190fcaaef | |||
| 3272e1fcb5 | |||
| 8faeffdc7e |
@@ -115,7 +115,7 @@ for file in $FILES; do
|
||||
*.cmake|*.sh|*CMakeLists.txt)
|
||||
begin="#"
|
||||
;;
|
||||
*.kt*|*.cpp|*.h|*.qml)
|
||||
*.kt*|*.cpp|*.h)
|
||||
begin="//"
|
||||
;;
|
||||
*)
|
||||
@@ -193,7 +193,7 @@ if [ "$UPDATE" = "true" ]; then
|
||||
begin="#"
|
||||
shell=true
|
||||
;;
|
||||
*)
|
||||
*.kt*|*.cpp|*.h)
|
||||
begin="//"
|
||||
shell="false"
|
||||
;;
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
From 509be32bbfa6eb95014860f7c9ea6d45c8ddaa56 Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sun, 8 Mar 2026 15:11:12 -0400
|
||||
Subject: [PATCH] [cmake] Simplify zstd find logic, and support pre-existing
|
||||
zstd target
|
||||
|
||||
Some deduplication work on the zstd required/if-available logic. Also
|
||||
adds support for pre-existing `zstd::libzstd` which is useful for
|
||||
projects that bundle their own zstd in a way that doesn't get caught by
|
||||
`CONFIG`
|
||||
|
||||
Signed-off-by: crueter <crueter@eden-emu.dev>
|
||||
---
|
||||
CMakeLists.txt | 46 ++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 26 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 1874e36be0..8d31198006 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -241,28 +241,34 @@ endif()
|
||||
# NOTE:
|
||||
# zstd < 1.5.6 does not provide the CMake imported target `zstd::libzstd`.
|
||||
# Older versions must be consumed via their pkg-config file.
|
||||
-if(HTTPLIB_REQUIRE_ZSTD)
|
||||
- find_package(zstd 1.5.6 CONFIG)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig REQUIRED)
|
||||
- pkg_check_modules(zstd REQUIRED IMPORTED_TARGET libzstd)
|
||||
- add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
- endif()
|
||||
- set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
-elseif(HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
- find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig QUIET)
|
||||
- if(PKG_CONFIG_FOUND)
|
||||
- pkg_check_modules(zstd QUIET IMPORTED_TARGET libzstd)
|
||||
-
|
||||
- if(TARGET PkgConfig::zstd)
|
||||
+if (HTTPLIB_REQUIRE_ZSTD)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED REQUIRED)
|
||||
+elseif (HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED QUIET)
|
||||
+endif()
|
||||
+
|
||||
+if (HTTPLIB_ZSTD_REQUESTED)
|
||||
+ if (TARGET zstd::libzstd)
|
||||
+ set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
+ else()
|
||||
+ find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
+
|
||||
+ if (NOT zstd_FOUND)
|
||||
+ find_package(PkgConfig ${HTTPLIB_ZSTD_REQUIRED})
|
||||
+ pkg_check_modules(zstd ${HTTPLIB_ZSTD_REQUIRED} IMPORTED_TARGET libzstd)
|
||||
+
|
||||
+ if (TARGET PkgConfig::zstd)
|
||||
add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
endif()
|
||||
endif()
|
||||
+
|
||||
+ # This will always be true if zstd is required.
|
||||
+ # If zstd *isn't* found when zstd is set to required,
|
||||
+ # CMake will error out earlier in this block.
|
||||
+ set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
- # Both find_package and PkgConf set a XXX_FOUND var
|
||||
- set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
@@ -317,13 +323,13 @@ if(HTTPLIB_COMPILE)
|
||||
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
|
||||
)
|
||||
-
|
||||
+
|
||||
# Add C++20 module support if requested
|
||||
# Include from separate file to prevent parse errors on older CMake versions
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.28")
|
||||
include(cmake/modules.cmake)
|
||||
endif()
|
||||
-
|
||||
+
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
@@ -61,10 +61,6 @@ 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
|
||||
|
||||
We have a user manual! See our [User Handbook](./docs/user/README.md).
|
||||
|
||||
## Building
|
||||
|
||||
See the [General Build Guide](docs/Build.md)
|
||||
@@ -73,9 +69,7 @@ For information on provided development tooling, see the [Tools directory](./too
|
||||
|
||||
## Download
|
||||
|
||||
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.
|
||||
You can download the latest releases from [here](https://github.com/eden-emulator/Releases/releases).
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
+4
-4
@@ -46,9 +46,9 @@
|
||||
"package": "ZLIB",
|
||||
"repo": "madler/zlib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4",
|
||||
"hash": "06eaa3a1eaaeb31f461a2283b03a91ed8eb2406e62cd97ea1c69836324909edeecd93edd03ff0bf593d9dde223e3376149134c5b1fe2e8688c258cadf8cd60ff",
|
||||
"version": "1.2",
|
||||
"git_version": "1.3.2",
|
||||
"git_version": "1.3.1.2",
|
||||
"options": [
|
||||
"ZLIB_BUILD_SHARED OFF",
|
||||
"ZLIB_INSTALL OFF"
|
||||
@@ -98,9 +98,9 @@
|
||||
"package": "VVL",
|
||||
"repo": "KhronosGroup/Vulkan-ValidationLayers",
|
||||
"tag": "vulkan-sdk-%VERSION%",
|
||||
"git_version": "1.4.341.0",
|
||||
"git_version": "1.4.335.0",
|
||||
"artifact": "android-binaries-%VERSION%.zip",
|
||||
"hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753"
|
||||
"hash": "48167c4a17736301bd08f9290f41830443e1f18cce8ad867fc6f289b49e18b40e93c9850b377951af82f51b5b6d7313aa6a884fc5df79f5ce3df82696c1c1244"
|
||||
},
|
||||
"quazip": {
|
||||
"package": "QuaZip-Qt6",
|
||||
|
||||
+2
-8
@@ -91,7 +91,7 @@ After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-
|
||||
|
||||
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`. Builds are currently not working due to lack of `std::jthread` and such, either compile libc++ manually or wait for ports to catch up.
|
||||
|
||||
If clang has errors, try using `g++11`.
|
||||
If clang has errors, try using `g++-11`.
|
||||
|
||||
## FreeBSD
|
||||
|
||||
@@ -107,8 +107,6 @@ hw.usb.usbhid.enable="0"
|
||||
|
||||
## NetBSD
|
||||
|
||||
2026-02-07: `vulkan-headers` must not be installed, since the version found in `pkgsrc` is older than required. Either wait for binary packages to update or build newer versions from source.
|
||||
|
||||
Install `pkgin` if not already `pkg_add pkgin`, see also the general [pkgsrc guide](https://www.netbsd.org/docs/pkgsrc/using.html). For NetBSD 10.1 provide `echo 'PKG_PATH="https://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/10.1/All/"' >/etc/pkg_install.conf`. If `pkgin` is taking too much time consider adding the following to `/etc/rc.conf`:
|
||||
|
||||
```sh
|
||||
@@ -118,7 +116,7 @@ ip6addrctl_policy=ipv4_prefer
|
||||
|
||||
System provides a default `g++-10` which doesn't support the current C++ codebase; install `clang-19` with `pkgin install clang-19`. Or install `gcc14` (or `gcc15` with current pkgsrc). Provided that, the following CMake commands may work:
|
||||
|
||||
- `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -Bbuild` (Recommended)
|
||||
- `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -Bbuild`
|
||||
- `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/pkg/gcc14/bin/gcc -DCMAKE_CXX_COMPILER=/usr/pkg/gcc14/bin/g++ -Bbuild`
|
||||
- `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/pkg/gcc15/bin/gcc -DCMAKE_CXX_COMPILER=/usr/pkg/gcc15/bin/g++ -Bbuild`
|
||||
|
||||
@@ -140,12 +138,8 @@ cmake --install build
|
||||
|
||||
However, pkgsrc is highly recommended, see [getting pkgsrc](https://iso.us.netbsd.org/pub/pkgsrc/current/pkgsrc/doc/pkgsrc.html#getting). You must get `current` not the `2025Q2` version.
|
||||
|
||||
`QtCore` on NetBSD is included, but due to misconfigurations(!) we MUST include one of the standard headers that include `bits/c++config.h`, since source_location (required by `QtCore`) isn't properly configured to intake `bits/c++config.h` (none of the experimental library is). This is a bug with NetBSD packaging and not our fault, but alas.
|
||||
|
||||
## DragonFlyBSD
|
||||
|
||||
2026-02-07: `vulkan-headers` and `vulkan-utility-libraries` must NOT be uninstalled, since they're too old: `1.3.289`. Either wait for binary packages to update or build newer versions from source.
|
||||
|
||||
If `libstdc++.so.6` is not found (`GLIBCXX_3.4.30`) then attempt:
|
||||
|
||||
```sh
|
||||
|
||||
+1
-2
@@ -1,7 +1,5 @@
|
||||
# Eden Build Documentation
|
||||
|
||||
Are you just a casual user? Take a look at our [User Handbook](./user) then!
|
||||
|
||||
This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](./CPMUtil), and more.
|
||||
|
||||
- **[General Build Instructions](Build.md)**
|
||||
@@ -13,6 +11,7 @@ This contains documentation created by developers. This contains build instructi
|
||||
- **[CPM - CMake Package Manager](./CPMUtil)**
|
||||
- **[Platform-Specific Caveats](Caveats.md)**
|
||||
- **[The NVIDIA SM86 (Maxwell) GPU](./NvidiaGpu.md)**
|
||||
- **[User Handbook](./user)**
|
||||
- **[Dynarmic](./dynarmic)**
|
||||
- **[Cross compilation](./CrossCompile.md)**
|
||||
- **[Driver Bugs](./DriverBugs.md)**
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# User Handbook - Configuring Steam ROM Manager
|
||||
|
||||
## Importing Eden into Steam with Steam Rom Manager
|
||||
# Importing Eden into Steam with Steam Rom Manager
|
||||
|
||||
Use this when you want to import the Eden AppImage into your Steam Library along with artwork using *Steam ROM Manager.*
|
||||
|
||||
@@ -8,7 +6,7 @@ Use this when you want to import the Eden AppImage into your Steam Library along
|
||||
|
||||
---
|
||||
|
||||
#### Pre-Requisites
|
||||
### Pre-Requisites
|
||||
|
||||
- Eden set up and configured
|
||||
- Internet Connection
|
||||
@@ -16,9 +14,9 @@ Use this when you want to import the Eden AppImage into your Steam Library along
|
||||
|
||||
---
|
||||
|
||||
### Steps
|
||||
## Steps
|
||||
|
||||
#### Initial Setup
|
||||
### Initial Setup
|
||||
|
||||
1. Press the **STEAM** button and then go to *Power → Switch to Desktop* to enter the Desktop mode.
|
||||
|
||||
@@ -26,14 +24,14 @@ Use this when you want to import the Eden AppImage into your Steam Library along
|
||||
|
||||
---
|
||||
|
||||
#### Manual Installation
|
||||
### Manual Installation
|
||||
|
||||
1. Open the *Discover Store* and search for *Steam ROM Manager.*
|
||||
2. Select the **Install** button to install the program.
|
||||
|
||||
---
|
||||
|
||||
#### Installing Through *EmuDeck*
|
||||
### Installing Through *EmuDeck*
|
||||
|
||||
<aside>
|
||||
|
||||
@@ -47,9 +45,9 @@ Use this when you want to import the Eden AppImage into your Steam Library along
|
||||
|
||||
---
|
||||
|
||||
#### Adding Eden into *Steam ROM Manager*
|
||||
### Adding Eden into *Steam ROM Manager*
|
||||
|
||||
#### EmuDeck Users
|
||||
### EmuDeck Users
|
||||
|
||||
EmuDeck will automatically create an *Emulators - Emulators* parser for ***Steam ROM Manager*** that uses shell scripts to launch them. We will follow this convention.
|
||||
|
||||
@@ -89,7 +87,7 @@ EmuDeck will automatically create an *Emulators - Emulators* parser for ***Steam
|
||||
|
||||
---
|
||||
|
||||
#### Non-EmuDeck Users
|
||||
### Non-EmuDeck Users
|
||||
|
||||
We will need to create a new parser for the Emulators. Unlike with the EmuDeck model, we will have the parser look for AppImages.
|
||||
|
||||
@@ -128,7 +126,7 @@ We will need to create a new parser for the Emulators. Unlike with the EmuDeck
|
||||
|
||||
---
|
||||
|
||||
#### Adding Eden to Steam
|
||||
### Adding Eden to Steam
|
||||
|
||||
Now that we have the parser or shell script created, we can actually add it to Steam.
|
||||
|
||||
@@ -139,7 +137,7 @@ Now that we have the parser or shell script created, we can actually add it to S
|
||||
|
||||
---
|
||||
|
||||
#### Correcting a Mismatch
|
||||
### Correcting a Mismatch
|
||||
|
||||
If the emulator is not identified correctly, you may need to tell *Steam ROM Manager* what the game is manually.
|
||||
|
||||
@@ -149,7 +147,7 @@ Now that we have the parser or shell script created, we can actually add it to S
|
||||
|
||||
---
|
||||
|
||||
#### Excluding Matches
|
||||
### Excluding Matches
|
||||
|
||||
You may want to tell Steam ROM Manager to ignore some files that it finds in the directory. This is how you do so.
|
||||
|
||||
@@ -161,105 +159,4 @@ Now that we have the parser or shell script created, we can actually add it to S
|
||||
|
||||
5. The program will now start writing the entries into the Steam Library. You should get pop up notifications of the progress, but you can monitor the progress by selecting the **Log** on the left-hand side if needed.
|
||||
6. Restart Steam to have the changes take effect. Check your library to ensure that your games are there, in a category if you defined one in the parser.
|
||||
7. Try to launch the Emulator from Steam and ensure everything is working. You are now good to go.
|
||||
|
||||
## Importing Games into Steam with Steam Rom Manager
|
||||
|
||||
Use this when you want to import your games inside Eden into Steam to launch with artwork from Steam Game Mode without needing to launch Eden first.
|
||||
|
||||
**Click [Here](https://evilperson1337.notion.site/Importing-Games-into-Steam-with-Steam-Rom-Manager-2b757c2edaf680d7a491c92b138f1fcc) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
#### Pre-Requisites
|
||||
|
||||
- Steam Deck Set up and Configured
|
||||
- Eden set up and Configured
|
||||
- Internet Access
|
||||
|
||||
---
|
||||
|
||||
### Steps
|
||||
|
||||
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).
|
||||
|
||||
---
|
||||
|
||||
#### Manual Installation
|
||||
|
||||
1. Open the *Discover Store* and search for *Steam ROM Manager.*
|
||||
2. Select the **Install** button to install the program.
|
||||
|
||||
---
|
||||
|
||||
#### Installing Through *EmuDeck*
|
||||
|
||||
<aside>
|
||||
|
||||
***NOTE***: This assumes you have already set up EmuDeck, if not - just run through the guided installation and select *Steam ROM Manager* as one of the options.
|
||||
|
||||
</aside>
|
||||
|
||||
1. Open **EmuDeck**, then navigate to *Manage Emulators.*
|
||||
2. Scroll down to the bottom of the page to the *Manage your Tools & Frontends* section. Click **Steam ROM Manager**.
|
||||
|
||||
3. Click the **Install** button on the right hand side to install it.
|
||||
|
||||
---
|
||||
|
||||
2. Open the Start Menu and Launch ***Steam ROM Manager***
|
||||
|
||||
1. The program will now launch and show you a window with parsers.
|
||||
|
||||
<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.
|
||||
|
||||
</aside>
|
||||
|
||||
2. Switch off all Parsers by hitting the *Toggle Parsers* switch.
|
||||
3. Scroll down the list on the left-hand side and look for a parser called *Nintendo Switch - Eden* and switch it on. This parser may not exist depending on how you installed *Steam ROM Manager* (EmuDeck creates it for you). Follow these steps to create it if it is missing.
|
||||
|
||||
---
|
||||
#### Creating the Eden Parser
|
||||
|
||||
1. Select Create Parser and in the *Community Presets* option look for **Nintendo Switch - Yuzu**.
|
||||
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.
|
||||
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. 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.
|
||||
|
||||
---
|
||||
|
||||
#### Correcting a Mismatch
|
||||
|
||||
If the game is not identified correctly, you may need to tell *Steam ROM Manager* what the game is manually.
|
||||
|
||||
1. Hover over the game card and click the magnifying glass icon.
|
||||
2. Search for the game on the *Search SteamGridDB* section and scroll through the results, selecting the one you want.
|
||||
3. Ensure the *Name* and *Game ID* update in the **Per-App Exceptions** and press **Save and close**. The game should now update.
|
||||
|
||||
---
|
||||
|
||||
#### Excluding Matches
|
||||
|
||||
You may want to tell Steam ROM Manager to ignore some files (updates/DLC/etc.) that it finds in the directory. This is how you do so.
|
||||
|
||||
1. Hit the **Exclude Games** button in the bottom right.
|
||||
2. Deselect the game you want to exclude, the poster artwork should go dim and the **Number Excluded** number should increment up. Repeat with any other exclusions you want to add.
|
||||
3. Hit **Save Excludes** when you are happy with your selections.
|
||||
---
|
||||
3. When you are happy with the results, select **Save to Steam** to save the results.
|
||||
1. The program will now start writing the entries into the Steam Library. You should get pop up notifications of the progress, but you can monitor the progress by selecting the **Log** on the left-hand side if needed.
|
||||
2. Restart Steam to have the changes take effect. Check your library to ensure that your games are there, in a category if you defined one in the parser.
|
||||
3. Try to launch a game and ensure everything is working. You are now good to go.
|
||||
7. Try to launch the Emulator from Steam and ensure everything is working. You are now good to go.
|
||||
@@ -0,0 +1,100 @@
|
||||
# Importing Games into Steam with Steam Rom Manager
|
||||
|
||||
Use this when you want to import your games inside Eden into Steam to launch with artwork from Steam Game Mode without needing to launch Eden first.
|
||||
|
||||
**Click [Here](https://evilperson1337.notion.site/Importing-Games-into-Steam-with-Steam-Rom-Manager-2b757c2edaf680d7a491c92b138f1fcc) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
### Pre-Requisites
|
||||
|
||||
- Steam Deck Set up and Configured
|
||||
- Eden set up and Configured
|
||||
- Internet Access
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
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).
|
||||
|
||||
---
|
||||
|
||||
### Manual Installation
|
||||
|
||||
1. Open the *Discover Store* and search for *Steam ROM Manager.*
|
||||
2. Select the **Install** button to install the program.
|
||||
|
||||
---
|
||||
|
||||
### Installing Through *EmuDeck*
|
||||
|
||||
<aside>
|
||||
|
||||
***NOTE***: This assumes you have already set up EmuDeck, if not - just run through the guided installation and select *Steam ROM Manager* as one of the options.
|
||||
|
||||
</aside>
|
||||
|
||||
1. Open **EmuDeck**, then navigate to *Manage Emulators.*
|
||||
2. Scroll down to the bottom of the page to the *Manage your Tools & Frontends* section. Click **Steam ROM Manager**.
|
||||
|
||||
3. Click the **Install** button on the right hand side to install it.
|
||||
|
||||
---
|
||||
|
||||
2. Open the Start Menu and Launch ***Steam ROM Manager***
|
||||
|
||||
1. The program will now launch and show you a window with parsers.
|
||||
|
||||
<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.
|
||||
|
||||
</aside>
|
||||
|
||||
2. Switch off all Parsers by hitting the *Toggle Parsers* switch.
|
||||
3. Scroll down the list on the left-hand side and look for a parser called *Nintendo Switch - Eden* and switch it on. This parser may not exist depending on how you installed *Steam ROM Manager* (EmuDeck creates it for you). Follow these steps to create it if it is missing.
|
||||
|
||||
---
|
||||
### Creating the Eden Parser
|
||||
|
||||
1. Select Create Parser and in the *Community Presets* option look for **Nintendo Switch - Yuzu**.
|
||||
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.
|
||||
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. 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.
|
||||
|
||||
---
|
||||
|
||||
### Correcting a Mismatch
|
||||
|
||||
If the game is not identified correctly, you may need to tell *Steam ROM Manager* what the game is manually.
|
||||
|
||||
1. Hover over the game card and click the magnifying glass icon.
|
||||
2. Search for the game on the *Search SteamGridDB* section and scroll through the results, selecting the one you want.
|
||||
3. Ensure the *Name* and *Game ID* update in the **Per-App Exceptions** and press **Save and close**. The game should now update.
|
||||
|
||||
---
|
||||
|
||||
### Excluding Matches
|
||||
|
||||
You may want to tell Steam ROM Manager to ignore some files (updates/DLC/etc.) that it finds in the directory. This is how you do so.
|
||||
|
||||
1. Hit the **Exclude Games** button in the bottom right.
|
||||
2. Deselect the game you want to exclude, the poster artwork should go dim and the **Number Excluded** number should increment up. Repeat with any other exclusions you want to add.
|
||||
3. Hit **Save Excludes** when you are happy with your selections.
|
||||
---
|
||||
3. When you are happy with the results, select **Save to Steam** to save the results.
|
||||
1. The program will now start writing the entries into the Steam Library. You should get pop up notifications of the progress, but you can monitor the progress by selecting the **Log** on the left-hand side if needed.
|
||||
2. Restart Steam to have the changes take effect. Check your library to ensure that your games are there, in a category if you defined one in the parser.
|
||||
3. Try to launch a game and ensure everything is working. You are now good to go.
|
||||
@@ -1,11 +0,0 @@
|
||||
# User Handbook - Custom Firmware (CFW)
|
||||
|
||||
At the moment of writing, we do not support CFW such as Atmosphere, due to:
|
||||
|
||||
- Lacking the required LLE emulation capabilities to properly emulate the full firmware.
|
||||
- Lack of implementation on some of the key internals.
|
||||
- Nobody has bothered to do it (PRs always welcome!)
|
||||
|
||||
We do however, maintain HLE compatibility with the former mentioned CFW, applications that require Atmosphere to run will run fine in the emulator without any adjustments.
|
||||
|
||||
If they don't run - then that's a bug!
|
||||
@@ -1,7 +1,5 @@
|
||||
# User Handbook - Graphics
|
||||
|
||||
Graphical enhancements and visual quality improvments. This doesn't cover texture mods.
|
||||
|
||||
## Visual Enhancements
|
||||
|
||||
### Anti-aliasing
|
||||
@@ -91,7 +89,7 @@ The OpenGL backend would invoke behaviour that would result in swarst/LLVMpipe w
|
||||
|
||||
### HaikuOS compatibility
|
||||
|
||||
HaikuOS bundles a Mesa library that doesn't support full core OpenGL 4.6 (required by the emulator). This leads to HaikuOS being one of the few computer platforms where Vulkan is the only available option for users. If OpenGL is desired, Mesa has to be built manually from source. For debugging purposes `lavapipe` is recommended over the GPU driver; there is in-kernel support for NVIDIA cards through.
|
||||
HaikuOS bundles a Mesa library that doesn't support full core OpenGL 4.6 (required by the emulator). This leads to HaikuOS being one of the few computer platforms where Vulkan is the only available option for users. If OpenGL is desired, Mesa has to be built manually from source. For debugging purpouses `lavapipe` is recommended over the GPU driver; there is in-kernel support for NVIDIA cards through.
|
||||
|
||||
### Fixes for Windows 10 and above having "Device loss"
|
||||
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
# User Handbook - Installing Mods
|
||||
|
||||
## General Notes
|
||||
|
||||
**Note:** When installing a mod, always read the mod's installation instructions.
|
||||
|
||||
This is especially important if a mod uses a framework such as **ARCropolis**, **Skyline**, or **Atmosphere plugins**. In those cases, follow the framework's instructions instead of using Eden's normal mod folder.
|
||||
|
||||
For example, **Super Smash Bros. Ultimate** uses such a framework. See the related section below for details.
|
||||
|
||||
---
|
||||
|
||||
# Installing Mods for Most Games
|
||||
|
||||
1. Right click a game in the game list.
|
||||
2. Click **"Open Mod Data Location"**.
|
||||
3. Extract the mod into that folder.
|
||||
|
||||
Each mod should be placed inside **its own subfolder**.
|
||||
|
||||
---
|
||||
|
||||
# Enabling or Disabling Mods
|
||||
|
||||
1. Right click the game in the game list.
|
||||
2. Click **Configure Game**.
|
||||
3. In the **Add-Ons** tab, enable or disable mods, updates, and DLC by ticking or unticking their boxes.
|
||||
|
||||
---
|
||||
|
||||
# Important Note About SD Card Paths
|
||||
|
||||
Some mods are designed for real Nintendo Switch consoles and refer to the **SD card root**.
|
||||
|
||||
The emulated SD card is located at:
|
||||
|
||||
```
|
||||
%AppData%\eden\sdmc
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Switch instruction: sd:/ultimate/mods
|
||||
Eden equivalent: sdmc/ultimate/mods
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Framework-Based Mods (Super Smash Bros. Ultimate)
|
||||
|
||||
Some games require external mod frameworks instead of the built-in mod loader.
|
||||
|
||||
The most common example is **Super Smash Bros. Ultimate**.
|
||||
|
||||
These mods are installed directly to the **emulated SD card**, not the normal Eden mod folder.
|
||||
|
||||
---
|
||||
|
||||
# Installing the ARCropolis Modding Framework
|
||||
|
||||
**Note:** Some mod packs bundle ARCropolis with their installer (for example, Smash Ult-S).
|
||||
|
||||
---
|
||||
|
||||
## 1. Download ARCropolis
|
||||
|
||||
Download the latest release:
|
||||
|
||||
https://github.com/Raytwo/ARCropolis/releases/
|
||||
|
||||
---
|
||||
|
||||
## 2. Install ARCropolis
|
||||
|
||||
Extract the **`atmosphere`** folder into:
|
||||
|
||||
```
|
||||
%AppData%\eden\sdmc
|
||||
```
|
||||
|
||||
This is the **emulated SD card directory**.
|
||||
|
||||
Verify installation by checking that the following file exists:
|
||||
|
||||
```
|
||||
sdmc\atmosphere\contents\01006A800016E000\romfs\skyline\plugins\libarcropolis.nro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Download Skyline
|
||||
|
||||
Download the latest Skyline release:
|
||||
|
||||
https://github.com/skyline-dev/skyline/releases
|
||||
|
||||
Skyline used to be bundled with ARCropolis but is now distributed separately to avoid compatibility issues caused by outdated bundled versions.
|
||||
|
||||
---
|
||||
|
||||
## 4. Install Skyline
|
||||
|
||||
Extract the **`exefs`** folder into:
|
||||
|
||||
```
|
||||
sdmc\atmosphere\contents\01006A800016E000
|
||||
```
|
||||
|
||||
The `exefs` folder should be **next to the `romfs` folder**.
|
||||
|
||||
Verify installation by checking that the following file exists:
|
||||
|
||||
```
|
||||
%AppData%\eden\sdmc\atmosphere\contents\01006A800016E000\exefs\subsdk9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Launch the Game Once
|
||||
|
||||
Start the game and make sure you see the **ARCropolis version text on the title screen**.
|
||||
|
||||
This will also create the folders required for installing mods.
|
||||
|
||||
---
|
||||
|
||||
## 6. Install Smash Ultimate Mods
|
||||
|
||||
Install mods inside:
|
||||
|
||||
```
|
||||
sdmc\ultimate\mods
|
||||
```
|
||||
|
||||
Each mod must be placed inside **its own subfolder**.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
sdmc\ultimate\mods\ExampleMod
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## ARCropolis text does not appear on startup
|
||||
|
||||
Check the following:
|
||||
|
||||
- `libarcropolis.nro` exists in:
|
||||
|
||||
```
|
||||
sdmc\atmosphere\contents\01006A800016E000\romfs\skyline\plugins
|
||||
```
|
||||
|
||||
- `subsdk9` exists in:
|
||||
|
||||
```
|
||||
sdmc\atmosphere\contents\01006A800016E000\exefs
|
||||
```
|
||||
|
||||
- Files were extracted to:
|
||||
|
||||
```
|
||||
%AppData%\eden\sdmc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mods are not loading
|
||||
|
||||
Make sure mods are installed inside:
|
||||
|
||||
```
|
||||
sdmc\ultimate\mods
|
||||
```
|
||||
|
||||
Each mod must have its **own subfolder**.
|
||||
|
||||
Correct example:
|
||||
|
||||
```
|
||||
sdmc\ultimate\mods\ExampleMod
|
||||
```
|
||||
|
||||
Incorrect example:
|
||||
|
||||
```
|
||||
sdmc\ultimate\mods\ExampleMod\ExampleMod
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Installing mods in the wrong folder
|
||||
|
||||
ARCropolis mods **do not go in Eden's normal mod folder**.
|
||||
|
||||
Do **not** install Smash mods here:
|
||||
|
||||
```
|
||||
user\load\01006A800016E000
|
||||
```
|
||||
|
||||
That folder is only used for traditional **RomFS mods**, not ARCropolis.
|
||||
+4
-15
@@ -4,14 +4,10 @@ The "FAQ".
|
||||
|
||||
This handbook is primarily aimed at the end-user - baking useful knowledge for enhancing their emulation experience.
|
||||
|
||||
A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/user/README.md).
|
||||
|
||||
## Basics
|
||||
|
||||
- **[The Basics](Basics.md)**
|
||||
- **[Quickstart](./QuickStart.md)**
|
||||
- **[Settings](./Settings.md)**
|
||||
- **[Installing Mods](./Mods.md)**
|
||||
- **[Run On macOS](./RunOnMacOS.md)**
|
||||
- **[Audio](Audio.md)**
|
||||
- **[Graphics](Graphics.md)**
|
||||
@@ -21,29 +17,22 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
||||
- **[Using Amiibo](./UsingAmiibo.md)**
|
||||
- **[Using Cheats](./UsingCheats.md)**
|
||||
- **[Importing Saves](./ImportingSaves.md)**
|
||||
- **[Add Eden to Steam ROM Manager](./AddEdenToSRM.md)**
|
||||
- **[Add Games to Steam ROM Manager](./AddGamesToSRM.md)**
|
||||
- **[Installing Atmosphere Mods](./InstallingAtmosphereMods.md)**
|
||||
- **[Installing Updates & DLCs](./InstallingUpdatesDLC.md)**
|
||||
- **[Controller Profiles](./ControllerProfiles.md)**
|
||||
- **[Alter Date & Time](./AlterDateTime.md)**
|
||||
|
||||
## 3rd-party Integration
|
||||
|
||||
- **[Configuring Steam ROM Manager](./SteamROM.md)**
|
||||
- **[Server hosting](ServerHosting.md)**
|
||||
- **[Syncthing Guide](./SyncthingGuide.md)**
|
||||
- **[Third Party](./ThirdParty.md)**
|
||||
- **[Obtainium](./ThirdParty.md#configuring-obtainium)**
|
||||
- **[ES-DE](./ThirdParty.md#configuring-es-de)**
|
||||
- **[Mirrors](./ThirdParty.md#mirrors)**
|
||||
|
||||
## Advanced
|
||||
|
||||
- **[Custom Firmware](./CFW.md)**
|
||||
- **[How To Access Logs](./HowToAccessLogs.md)**
|
||||
- **[Gyro Controls](./GyroControls.md)**
|
||||
- **[Platforms and Architectures](Architectures.md)**
|
||||
- **[Server hosting](ServerHosting.md)**
|
||||
- **[Command Line](CommandLine.md)**
|
||||
- **[Native Application Development](Native.md)**
|
||||
- **[Adding Boolean Settings Toggles](AddingBooleanToggles.md)**
|
||||
- **[Adding Debug Knobs](./AddingDebugKnobs.md)**
|
||||
- **[Syncthing Guide](./SyncthingGuide.md)**
|
||||
- **[Testing](Testing.md)**
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# User Handbook - Settings
|
||||
|
||||
As the emulator continues to grow, so does the number of settings that come and go.
|
||||
|
||||
Most of the development adds new settings that enhance performance/compatibility, only to be removed later in newer versions due to newfound discoveries or because they were "a hacky workaround".
|
||||
|
||||
As such, this guide will NOT mention those kind of settings, we'd rather mention settings which have a long shelf time (i.e won't get removed in future releases) and are likely to be unchanged.
|
||||
|
||||
Some of the options are self explainatory, and they do exactly what they say they do (i.e "Pause when not in focus"); such options will be also skipped due to triviality.
|
||||
|
||||
## Foreword
|
||||
|
||||
Before touching the settings, please see the game boots with stock options. We try our best to ensure users can boot any game using the default settings. If they don't work, then you may try fiddling with options - but please, first use stock options.
|
||||
|
||||
## General
|
||||
|
||||
- `General/Force X11 as Graphics Backend`: Wayland on *NIX has prominent issues that are unlikely to be resolved; the kind that are "not our fault, it's Wayland issue", this "temporary" hack forces X11 as the backend, regardless of the desktop manager's default.
|
||||
- `General/Enable Gamemode`: This only does anything when you have Feral Interactive's Gamemode library installed somewhere, if you do, this will help boost FPS by telling the OS to explicitly prioritize *this* application for "gaming" - only for *NIX systems.
|
||||
- `Hotkeys`: Deceptively to remove a hotkey you must right click and a menu will appear to remove that specific hotkey.
|
||||
- `UI/Language`: Changes language *of the interface* NOT the emulated program!
|
||||
- `Debug/Enable Auto Stub`: May help to "fix" some games by just lying and saying that everything they do returns "success" instead of outright crashing for any function/service that is NOT implemented.
|
||||
- `Debug/Show log in console`: Does as said, note that the program may need to be reopened (Windows) for changes to take effect.
|
||||
- `Debug/Flush log output`: Classically, every write to the log is "buffered", that is, changes aren't written to the disk UNTIL the program has decided it is time to write, until then it keeps data in a buffer which resides on RAM. If the program crashes, the OS will automatically discard said buffer (any RAM associated with a dead process is automatically discarded/reused for some other purpose); this means critical data may not be logged to the disk on time, which may lead to missing log lines. Use this if you're wanting to remove that factor when debugging, sometimes a hard crash may "eat" some of the log lines IF this option isn't enabled.
|
||||
- `Debug/Disable Macro HLE:` The emulator has HLE emulation of macro programs for Maxwell, this means that some details are purpousefully skipped; this option forces all macro programs to be ran without skipping anything.
|
||||
|
||||
## System
|
||||
|
||||
- `System/RNG Seed`: Set to 0 (and uncheck) to disable ASLR systemwide (this makes mods like CTGP to stop working); by default it enables ASLR to replicate console behaviour.
|
||||
- `Network/Enable Airplane Mode`: Enable this if a game is crashing before loading AND the logs mention anything related to "web" or "internet" services.
|
||||
|
||||
## CPU
|
||||
|
||||
- `CPU/Virtual table bouncing`: Some games have the tendency to crash on loading due to an indirect bad jump (Pokemon ZA being the worst offender); this option lies to the game and tells it to just pretend it never executed a given function. This is fine for most casual users, but developers of switch applications **must** disable this. This temporary "hack" should hopefully be gone in 6-7 months from now on.
|
||||
- `Fastmem`, aka. `CPU/Enable Host MMU`: Enables "fastmem"; a detailed description of fastmem can be found [here](../dynarmic/Design.md#fast-memory-fastmem).
|
||||
- `CPU/Unsafe FMA`: Enables deliberate innacurate FMA behaviour which may affect how FMA returns any given operation - this may introduce tiny floating point errors which can cascade in sensitive code (i.e FFmpeg).
|
||||
- `CPU/Faster FRSQRTE and FRECPE`: Introduces accuracy errors on square root and reciprocals in exchange for less checks - this introduces inaccuracies with some cases but it's mostly safe.
|
||||
- `CPU/Faster ASIMD Instructions`: Skips rounding mode checks for ARM ASIMD instructions - this means some code dpeending on these rounding modes may misbehave.
|
||||
- `CPU/Disable address space checks`: Before each memory access, the emulator checks the address is in range, if not it faults; this option makes it so the emulator skips the check entirely (which may be expensive for a myriad of reasons). However at the same time this allows the guest program to "break out" of the emulation context by writing to arbitrary addresses.
|
||||
- `CPU/Ignore global monitor`: This relies on a quirk present on x86 to avoid the ARM global monitor emulation, this may increase performance in mutex-heavy contexts (i.e games waiting for next frames or such); but also can cause deadlocks and fun to debug issues.
|
||||
|
||||
It is important to note the majority of precision-reducing instructions do not benefit cases where they are not used, which means the performance gains will vary per game.
|
||||
|
||||
# Graphics
|
||||
|
||||
See also [an extended breakdown of some options](./Graphics.md).
|
||||
|
||||
- `Extras/Extended Dynamic State` and `Extras/Vertex Input Dynamic State`: These Vulkan extensions essentially allow you to reuse the same pipeline but just change the state between calls (so called "dynamic state"); the "extended" levels signifies how much state can be placed on this "dynamic" range, for example the amount of depth culling to use can be placed on the dynamic state, avoiding costly reloads and flushes. While this by itself is a fine option, SOME vendors (notably PowerVR and Mali) have problems with anything related to EDS3. EDS3 contains EDS2, and EDS2 contains EDS1. Essentially this means more extended data the driver has to keep track of, at the benefit of avoiding costly flushes.
|
||||
- `Advanced/Use persistent cache`: This saves compiled shaders onto the disk, independent of any driver's own disk saved shaders (yes, some drivers, notably NVIDIA, save a secondary shader cache onto disk) - disable this only if you're debugging or working on the GPU backend. This option is meant to massively help to reduce shader stutters (after playing for one session that compiles them).
|
||||
- `Advanced/Use Vulkan pipeline cache`: This is NOT the same as `Use persistent cache`; it's a separate flag that tells the Vulkan backend to create pipeline caches, which are a detail that can be used to massively improve performance and remove pipeline creation overhead. This is a Vulkan feature.
|
||||
|
||||
## Controls
|
||||
|
||||
Most of the controls should work out of the box. If not, please use a joystick calibrator to ensure it's not an issue with your own controller, for example:
|
||||
- https://github.com/dkosmari/calibrate-joystick
|
||||
@@ -7,62 +7,3 @@ While most of the links mentioned in this guide are relatively "safe"; we urge u
|
||||
- [Nightly Eden builds](https://github.com/pflyly/eden-nightly)
|
||||
- [NixOS Eden Flake](https://github.com/Grantimatter/eden-flake)
|
||||
- [ES-DE Frontend Support](https://github.com/GlazedBelmont/es-de-android-custom-systems)
|
||||
|
||||
## Mirrors
|
||||
|
||||
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://collective.taymaerz.de/eden/eden
|
||||
|
||||
Other mirrors obviously exist on the internet, but we can't guarantee their reliability and/or availability.
|
||||
|
||||
If you're someone wanting to make a mirror, simply setup forgejo and automatically mirror from the origin repository. Or you could mirror a mirror to save us bandwidth... your choice!
|
||||
|
||||
## Configuring Obtainium
|
||||
|
||||
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)
|
||||
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)`.
|
||||
5. Click `Add:` Obtainium should now be able to parse the releases and find the APK files.
|
||||
|
||||
Note: Even though the site isn't Codeberg, it uses the same Forgejo/Gitea backend, and this setting tells Obtainium how to read the release data.
|
||||
|
||||
## Configuring ES-DE
|
||||
|
||||
### Method 1
|
||||
|
||||
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).
|
||||
|
||||
### Method 2
|
||||
|
||||
1. Navigate to `\Odin2\Internal shared storage\ES-DE\custom_systems`.
|
||||
2. Add this to your `es_find_rules.xml`:
|
||||
|
||||
```xml
|
||||
<!-- Standard aka. normal release -->
|
||||
<emulator name="EDEN">
|
||||
<rule type="androidpackage">
|
||||
<entry>dev.eden.eden_emulator/org.yuzu.yuzu_emu.activities.EmulationActivity</entry>
|
||||
</rule>
|
||||
</emulator>
|
||||
|
||||
<!-- Optimized -->
|
||||
<emulator name="EDEN">
|
||||
<rule type="androidpackage">
|
||||
<entry>com.miHoYo.Yuanshen/org.yuzu.yuzu_emu.activities.EmulationActivity</entry>
|
||||
</rule>
|
||||
</emulator>
|
||||
```
|
||||
|
||||
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>
|
||||
```
|
||||
|
||||
Vendored
+12
-13
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"sirit": {
|
||||
"repo": "eden-emulator/sirit",
|
||||
"git_version": "1.0.4",
|
||||
"git_version": "1.0.3",
|
||||
"tag": "v%VERSION%",
|
||||
"artifact": "sirit-source-%VERSION%.tar.zst",
|
||||
"hash_suffix": "sha512sum",
|
||||
@@ -28,12 +28,11 @@
|
||||
"httplib": {
|
||||
"repo": "yhirose/cpp-httplib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
|
||||
"git_version": "0.37.0",
|
||||
"hash": "a229e24cca4afe78e5c0aa2e482f15108ac34101fd8dbd927365f15e8c37dec4de38c5277d635017d692a5b320e1b929f8bfcc076f52b8e4dcdab8fe53bfdf2e",
|
||||
"git_version": "0.30.1",
|
||||
"find_args": "MODULE GLOBAL",
|
||||
"patches": [
|
||||
"0001-mingw.patch",
|
||||
"0002-fix-zstd.patch"
|
||||
"0001-mingw.patch"
|
||||
],
|
||||
"options": [
|
||||
"HTTPLIB_REQUIRE_OPENSSL ON"
|
||||
@@ -56,8 +55,8 @@
|
||||
"package": "xbyak",
|
||||
"repo": "herumi/xbyak",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a",
|
||||
"git_version": "7.35.2"
|
||||
"hash": "ac333d7bea1d61865bebebb116201a58db431946aa2f11aa042ef5795c390ff30af4d6c90ed3b3d24443a1d430703b08f14fc13b2fa405c155a241456ed78a47",
|
||||
"git_version": "7.33.2"
|
||||
},
|
||||
"oaknut": {
|
||||
"repo": "eden-emulator/oaknut",
|
||||
@@ -147,9 +146,9 @@
|
||||
"package": "Catch2",
|
||||
"repo": "catchorg/Catch2",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "7eea385d79d88a5690cde131fe7ccda97d5c54ea09d6f515000d7bf07c828809d61c1ac99912c1ee507cf933f61c1c47ecdcc45df7850ffa82714034b0fccf35",
|
||||
"hash": "acb3f463a7404d6a3bce52e474075cdadf9bb241d93feaf147c182d756e5a2f8bd412f4658ca186d15ab8fed36fc587d79ec311f55642d8e4ded16df9e213656",
|
||||
"version": "3.0.1",
|
||||
"git_version": "3.13.0",
|
||||
"git_version": "3.12.0",
|
||||
"patches": [
|
||||
"0001-solaris-isnan-fix.patch"
|
||||
]
|
||||
@@ -257,15 +256,15 @@
|
||||
"repo": "KhronosGroup/Vulkan-Headers",
|
||||
"package": "VulkanHeaders",
|
||||
"version": "1.4.317",
|
||||
"hash": "d2846ea228415772645eea4b52a9efd33e6a563043dd3de059e798be6391a8f0ca089f455ae420ff22574939ed0f48ed7c6ff3d5a9987d5231dbf3b3f89b484b",
|
||||
"git_version": "1.4.345",
|
||||
"hash": "26e0ad8fa34ab65a91ca62ddc54cc4410d209a94f64f2817dcdb8061dc621539a4262eab6387e9b9aa421db3dbf2cf8e2a4b041b696d0d03746bae1f25191272",
|
||||
"git_version": "1.4.342",
|
||||
"tag": "v%VERSION%"
|
||||
},
|
||||
"vulkan-utility-libraries": {
|
||||
"repo": "KhronosGroup/Vulkan-Utility-Libraries",
|
||||
"package": "VulkanUtilityLibraries",
|
||||
"hash": "114f6b237a6dcba923ccc576befb5dea3f1c9b3a30de7dc741f234a831d1c2d52d8a224afb37dd57dffca67ac0df461eaaab6a5ab5e503b393f91c166680c3e1",
|
||||
"git_version": "1.4.345",
|
||||
"hash": "8147370f964fd82c315d6bb89adeda30186098427bf3efaa641d36282d42a263f31e96e4586bfd7ae0410ff015379c19aa4512ba160630444d3d8553afd1ec14",
|
||||
"git_version": "1.4.342",
|
||||
"tag": "v%VERSION%"
|
||||
},
|
||||
"frozen": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -242,6 +241,7 @@ if (YUZU_CMD)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT)
|
||||
add_definitions(-DYUZU_QT_WIDGETS)
|
||||
add_subdirectory(qt_common)
|
||||
add_subdirectory(yuzu)
|
||||
endif()
|
||||
|
||||
@@ -40,21 +40,11 @@ class AddonAdapter(val addonViewModel: AddonViewModel) :
|
||||
}
|
||||
}
|
||||
|
||||
val canDelete = model.isRemovable
|
||||
binding.deleteCard.isEnabled = canDelete
|
||||
binding.buttonDelete.isEnabled = canDelete
|
||||
binding.deleteCard.alpha = if (canDelete) 1f else 0.38f
|
||||
|
||||
if (canDelete) {
|
||||
val deleteAction = {
|
||||
addonViewModel.setAddonToDelete(model)
|
||||
}
|
||||
binding.deleteCard.setOnClickListener { deleteAction() }
|
||||
binding.buttonDelete.setOnClickListener { deleteAction() }
|
||||
} else {
|
||||
binding.deleteCard.setOnClickListener(null)
|
||||
binding.buttonDelete.setOnClickListener(null)
|
||||
val deleteAction = {
|
||||
addonViewModel.setAddonToDelete(model)
|
||||
}
|
||||
binding.deleteCard.setOnClickListener { deleteAction() }
|
||||
binding.buttonDelete.setOnClickListener { deleteAction() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: 2023 yuzu Emulator Project
|
||||
@@ -10,8 +10,6 @@ import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.CardInstallableIconBinding
|
||||
import org.yuzu.yuzu_emu.databinding.CardSimpleOutlinedBinding
|
||||
import org.yuzu.yuzu_emu.model.GameProperty
|
||||
@@ -91,33 +89,29 @@ class GamePropertiesAdapter(
|
||||
|
||||
|
||||
val hasVisibleActions = submenuProperty.secondaryActions?.any { it.isShown } == true
|
||||
binding.layoutSecondaryActions.removeAllViews()
|
||||
binding.dividerSecondaryActions.setVisible(false)
|
||||
|
||||
if (hasVisibleActions) {
|
||||
binding.dividerSecondaryActions.setVisible(true)
|
||||
binding.layoutSecondaryActions.setVisible(true)
|
||||
|
||||
val visibleActions = submenuProperty.secondaryActions!!.filter { it.isShown }
|
||||
val inflater = LayoutInflater.from(binding.root.context)
|
||||
visibleActions.forEachIndexed { index, secondaryAction ->
|
||||
val button = inflater.inflate(
|
||||
R.layout.item_secondary_action_button,
|
||||
binding.layoutSecondaryActions,
|
||||
false
|
||||
) as MaterialButton
|
||||
button.setIconResource(secondaryAction.iconId)
|
||||
button.text = ""
|
||||
button.contentDescription = binding.root.context
|
||||
.getString(secondaryAction.descriptionId)
|
||||
button.tooltipText = binding.root.context
|
||||
.getString(secondaryAction.descriptionId)
|
||||
if (index == visibleActions.lastIndex) {
|
||||
(button.layoutParams as ViewGroup.MarginLayoutParams).marginEnd = 0
|
||||
submenuProperty.secondaryActions!!.forEach { secondaryAction ->
|
||||
if (secondaryAction.isShown) {
|
||||
val button = com.google.android.material.button.MaterialButton(
|
||||
binding.root.context,
|
||||
null,
|
||||
com.google.android.material.R.attr.materialButtonOutlinedStyle
|
||||
).apply {
|
||||
setIconResource(secondaryAction.iconId)
|
||||
iconSize = (18 * binding.root.context.resources.displayMetrics.density).toInt()
|
||||
text = binding.root.context.getString(secondaryAction.descriptionId)
|
||||
contentDescription = binding.root.context.getString(secondaryAction.descriptionId)
|
||||
setOnClickListener { secondaryAction.action.invoke() }
|
||||
}
|
||||
binding.layoutSecondaryActions.addView(button)
|
||||
}
|
||||
button.setOnClickListener { secondaryAction.action.invoke() }
|
||||
binding.layoutSecondaryActions.addView(button)
|
||||
}
|
||||
} else {
|
||||
binding.dividerSecondaryActions.setVisible(false)
|
||||
binding.layoutSecondaryActions.setVisible(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
package org.yuzu.yuzu_emu.dialogs
|
||||
@@ -14,7 +14,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
@@ -59,30 +58,6 @@ class LobbyBrowser(context: Context) : BottomSheetDialog(context) {
|
||||
setupSearchBar()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
window?.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
|
||||
val bottomSheet =
|
||||
findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
|
||||
if (bottomSheet != null) {
|
||||
bottomSheet.layoutParams = bottomSheet.layoutParams.apply {
|
||||
width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
bottomSheet.requestLayout()
|
||||
}
|
||||
|
||||
behavior.isFitToContents = false
|
||||
behavior.expandedOffset = 0
|
||||
behavior.skipCollapsed = true
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
adapter = LobbyRoomAdapter { room -> handleRoomSelection(room) }
|
||||
|
||||
|
||||
-2
@@ -30,8 +30,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
|
||||
RENDERER_DEBUG("debug"),
|
||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
||||
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
||||
|
||||
@@ -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
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model
|
||||
@@ -27,7 +27,7 @@ object Settings {
|
||||
SECTION_APP_SETTINGS(R.string.app_settings),
|
||||
SECTION_CUSTOM_PATHS(R.string.preferences_custom_paths),
|
||||
SECTION_DEBUG(R.string.preferences_debug),
|
||||
SECTION_FREEDRENO(R.string.freedreno_settings_title),
|
||||
SECTION_FREEDRENO(R.string.gpu_driver_settings),
|
||||
SECTION_APPLETS(R.string.applets_menu);
|
||||
}
|
||||
|
||||
|
||||
-32
@@ -141,20 +141,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.dynaStateValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_PROVOKING_VERTEX,
|
||||
titleId = R.string.provoking_vertex,
|
||||
descriptionId = R.string.provoking_vertex_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
|
||||
titleId = R.string.vertex_input_dynamic_state,
|
||||
descriptionId = R.string.vertex_input_dynamic_state_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
|
||||
@@ -349,15 +335,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.astcDecodingMethodValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_ASTC_RECOMPRESSION,
|
||||
titleId = R.string.astc_recompression,
|
||||
descriptionId = R.string.astc_recompression_description,
|
||||
choicesId = R.array.astcRecompressionMethodNames,
|
||||
valuesId = R.array.astcRecompressionMethodValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_VRAM_USAGE_MODE,
|
||||
@@ -670,15 +647,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.dmaAccuracyValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.FRAME_PACING_MODE,
|
||||
titleId = R.string.frame_pacing_mode,
|
||||
descriptionId = R.string.frame_pacing_mode_description,
|
||||
choicesId = R.array.framePacingModeNames,
|
||||
valuesId = R.array.framePacingModeValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
|
||||
|
||||
+3
-11
@@ -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: 2023 yuzu Emulator Project
|
||||
@@ -111,18 +111,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||
if (navHostFragment.childFragmentManager.backStackEntryCount > 0) {
|
||||
navHostFragment.navController.popBackStack()
|
||||
} else {
|
||||
finishWithFragmentLikeAnimation()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun finishWithFragmentLikeAnimation() {
|
||||
finish()
|
||||
overridePendingTransition(
|
||||
androidx.navigation.ui.R.anim.nav_default_pop_enter_anim,
|
||||
androidx.navigation.ui.R.anim.nav_default_pop_exit_anim
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (!DirectoryInitialization.areDirectoriesReady) {
|
||||
@@ -178,7 +170,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
getString(R.string.settings_reset),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
finishWithFragmentLikeAnimation()
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
|
||||
+21
-25
@@ -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: 2023 yuzu Emulator Project
|
||||
@@ -98,8 +98,23 @@ class SettingsFragment : Fragment() {
|
||||
activity
|
||||
)
|
||||
|
||||
val toolbarTitle = resolveToolbarTitle()
|
||||
configureToolbar(toolbarTitle)
|
||||
binding.toolbarSettingsLayout.title = if (args.menuTag == Settings.MenuTag.SECTION_ROOT &&
|
||||
args.game != null
|
||||
) {
|
||||
args.game!!.title
|
||||
} else {
|
||||
when (args.menuTag) {
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_ONE -> Settings.getPlayerString(1)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_TWO -> Settings.getPlayerString(2)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_THREE -> Settings.getPlayerString(3)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_FOUR -> Settings.getPlayerString(4)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_FIVE -> Settings.getPlayerString(5)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_SIX -> Settings.getPlayerString(6)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_SEVEN -> Settings.getPlayerString(7)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_EIGHT -> Settings.getPlayerString(8)
|
||||
else -> getString(args.menuTag.titleId)
|
||||
}
|
||||
}
|
||||
|
||||
binding.listSettings.apply {
|
||||
adapter = settingsAdapter
|
||||
@@ -178,9 +193,11 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
presenter.onViewCreated()
|
||||
|
||||
setInsets()
|
||||
}
|
||||
private fun getPlayerIndex(): Int =
|
||||
|
||||
private fun getPlayerIndex(): Int =
|
||||
when (args.menuTag) {
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_ONE -> 0
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_TWO -> 1
|
||||
@@ -193,27 +210,6 @@ private fun getPlayerIndex(): Int =
|
||||
else -> -1
|
||||
}
|
||||
|
||||
private fun resolveToolbarTitle(): String {
|
||||
if (args.menuTag == Settings.MenuTag.SECTION_ROOT && args.game != null) {
|
||||
return args.game!!.title
|
||||
}
|
||||
return when (args.menuTag) {
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_ONE -> Settings.getPlayerString(1)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_TWO -> Settings.getPlayerString(2)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_THREE -> Settings.getPlayerString(3)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_FOUR -> Settings.getPlayerString(4)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_FIVE -> Settings.getPlayerString(5)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_SIX -> Settings.getPlayerString(6)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_SEVEN -> Settings.getPlayerString(7)
|
||||
Settings.MenuTag.SECTION_INPUT_PLAYER_EIGHT -> Settings.getPlayerString(8)
|
||||
else -> getString(args.menuTag.titleId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureToolbar(title: String) {
|
||||
binding.toolbarSettings.title = title
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
|
||||
+43
-33
@@ -6,6 +6,7 @@ package org.yuzu.yuzu_emu.features.settings.ui
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
@@ -26,9 +27,11 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
|
||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import androidx.core.content.edit
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||
|
||||
@@ -180,6 +183,16 @@ class SettingsFragmentPresenter(
|
||||
menuKey = MenuTag.SECTION_DEBUG
|
||||
)
|
||||
)
|
||||
if (GpuDriverHelper.isAdrenoGpu() && !NativeConfig.isPerGameConfigLoaded()) {
|
||||
add(
|
||||
SubmenuSetting(
|
||||
titleId = R.string.gpu_driver_settings,
|
||||
descriptionId = R.string.freedreno_settings_title,
|
||||
iconId = R.drawable.ic_graphics,
|
||||
menuKey = MenuTag.SECTION_FREEDRENO
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
SubmenuSetting(
|
||||
titleId = R.string.applets_menu,
|
||||
@@ -254,11 +267,9 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(IntSetting.RENDERER_ACCURACY.key)
|
||||
add(IntSetting.DMA_ACCURACY.key)
|
||||
add(IntSetting.FRAME_PACING_MODE.key)
|
||||
add(IntSetting.MAX_ANISOTROPY.key)
|
||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
|
||||
|
||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
||||
@@ -278,8 +289,6 @@ class SettingsFragmentPresenter(
|
||||
add(HeaderSetting(R.string.extensions))
|
||||
|
||||
add(IntSetting.RENDERER_DYNA_STATE.key)
|
||||
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
|
||||
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
||||
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
||||
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
|
||||
|
||||
@@ -1071,35 +1080,6 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(HeaderSetting(R.string.theme_and_color))
|
||||
|
||||
val themeMode: AbstractIntSetting = object : AbstractIntSetting {
|
||||
override fun getInt(needsGlobal: Boolean): Int = IntSetting.THEME_MODE.getInt()
|
||||
override fun setInt(value: Int) {
|
||||
IntSetting.THEME_MODE.setInt(value)
|
||||
settingsViewModel.setShouldRecreate(true)
|
||||
}
|
||||
|
||||
override val key: String = IntSetting.THEME_MODE.key
|
||||
override val isRuntimeModifiable: Boolean =
|
||||
IntSetting.THEME_MODE.isRuntimeModifiable
|
||||
|
||||
override fun getValueAsString(needsGlobal: Boolean): String =
|
||||
IntSetting.THEME_MODE.getValueAsString()
|
||||
|
||||
override val defaultValue: Int = IntSetting.THEME_MODE.defaultValue
|
||||
override fun reset() {
|
||||
IntSetting.THEME_MODE.setInt(defaultValue)
|
||||
settingsViewModel.setShouldRecreate(true)
|
||||
}
|
||||
}
|
||||
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
themeMode,
|
||||
titleId = R.string.change_theme_mode,
|
||||
choicesId = R.array.themeModeEntries,
|
||||
valuesId = R.array.themeModeValues
|
||||
)
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
add(
|
||||
@@ -1121,6 +1101,27 @@ class SettingsFragmentPresenter(
|
||||
)
|
||||
}
|
||||
|
||||
val themeMode: AbstractIntSetting = object : AbstractIntSetting {
|
||||
override fun getInt(needsGlobal: Boolean): Int = IntSetting.THEME_MODE.getInt()
|
||||
override fun setInt(value: Int) {
|
||||
IntSetting.THEME_MODE.setInt(value)
|
||||
settingsViewModel.setShouldRecreate(true)
|
||||
}
|
||||
|
||||
override val key: String = IntSetting.THEME_MODE.key
|
||||
override val isRuntimeModifiable: Boolean =
|
||||
IntSetting.THEME_MODE.isRuntimeModifiable
|
||||
|
||||
override fun getValueAsString(needsGlobal: Boolean): String =
|
||||
IntSetting.THEME_MODE.getValueAsString()
|
||||
|
||||
override val defaultValue: Int = IntSetting.THEME_MODE.defaultValue
|
||||
override fun reset() {
|
||||
IntSetting.THEME_MODE.setInt(defaultValue)
|
||||
settingsViewModel.setShouldRecreate(true)
|
||||
}
|
||||
}
|
||||
|
||||
val staticThemeColor: AbstractIntSetting = object : AbstractIntSetting {
|
||||
override fun getInt(needsGlobal: Boolean): Int =
|
||||
IntSetting.STATIC_THEME_COLOR.getInt(needsGlobal)
|
||||
@@ -1144,6 +1145,15 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
themeMode,
|
||||
titleId = R.string.change_theme_mode,
|
||||
choicesId = R.array.themeModeEntries,
|
||||
valuesId = R.array.themeModeValues
|
||||
)
|
||||
)
|
||||
|
||||
if (IntSetting.THEME.getInt() != 1) {
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
@@ -51,8 +54,8 @@ class AboutFragment : Fragment() {
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = false)
|
||||
|
||||
binding.toolbarAbout.setNavigationOnClickListener {
|
||||
binding.root.findNavController().popBackStack()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
@@ -19,6 +19,7 @@ import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import kotlinx.coroutines.launch
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.adapters.AddonAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentAddonsBinding
|
||||
@@ -41,7 +42,7 @@ class AddonsFragment : Fragment() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
addonViewModel.onAddonsViewCreated(args.game)
|
||||
addonViewModel.onOpenAddons(args.game)
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
@@ -121,14 +122,12 @@ class AddonsFragment : Fragment() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
addonViewModel.onAddonsViewStarted(args.game)
|
||||
addonViewModel.refreshAddons()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (activity?.isChangingConfigurations != true) {
|
||||
addonViewModel.onCloseAddons()
|
||||
}
|
||||
super.onDestroy()
|
||||
addonViewModel.onCloseAddons()
|
||||
}
|
||||
|
||||
val installAddon =
|
||||
@@ -168,7 +167,7 @@ class AddonsFragment : Fragment() {
|
||||
} catch (_: Exception) {
|
||||
return@newInstance errorMessage
|
||||
}
|
||||
addonViewModel.refreshAddons(force = true)
|
||||
addonViewModel.refreshAddons()
|
||||
return@newInstance getString(R.string.addon_installed_successfully)
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
} else {
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentDriverFetcherBinding
|
||||
import org.yuzu.yuzu_emu.features.fetcher.DriverGroupAdapter
|
||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
import java.io.IOException
|
||||
@@ -88,7 +87,6 @@ class DriverFetcherFragment : Fragment() {
|
||||
|
||||
private lateinit var driverGroupAdapter: DriverGroupAdapter
|
||||
private val driverViewModel: DriverViewModel by activityViewModels()
|
||||
private val homeViewModel: HomeViewModel by activityViewModels()
|
||||
|
||||
private fun parseAdrenoModel(): Int {
|
||||
if (gpuModel == null) {
|
||||
@@ -140,7 +138,7 @@ class DriverFetcherFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = false)
|
||||
|
||||
binding.toolbarDrivers.setNavigationOnClickListener {
|
||||
binding.root.findNavController().popBackStack()
|
||||
}
|
||||
|
||||
+12
-20
@@ -22,7 +22,6 @@ import org.yuzu.yuzu_emu.databinding.FragmentFreedrenoSettingsBinding
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.utils.NativeFreedrenoConfig
|
||||
import org.yuzu.yuzu_emu.utils.FreedrenoPresets
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
|
||||
|
||||
class FreedrenoSettingsFragment : Fragment() {
|
||||
@@ -75,15 +74,10 @@ class FreedrenoSettingsFragment : Fragment() {
|
||||
binding.toolbarFreedreno.setNavigationOnClickListener {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
binding.toolbarFreedreno.title = getString(
|
||||
if (isPerGameConfig) {
|
||||
R.string.freedreno_per_game_title
|
||||
} else {
|
||||
R.string.freedreno_settings_title
|
||||
}
|
||||
)
|
||||
binding.toolbarFreedreno.subtitle = null
|
||||
if (isPerGameConfig) {
|
||||
binding.toolbarFreedreno.title = getString(R.string.freedreno_per_game_title)
|
||||
binding.toolbarFreedreno.subtitle = game!!.title
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAdapters() {
|
||||
@@ -181,19 +175,17 @@ class FreedrenoSettingsFragment : Fragment() {
|
||||
|
||||
private fun setupWindowInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets ->
|
||||
val barInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
val leftInsets = barInsets.left + cutoutInsets.left
|
||||
val rightInsets = barInsets.right + cutoutInsets.right
|
||||
|
||||
binding.appbarFreedreno.updateMargins(left = leftInsets, right = rightInsets)
|
||||
binding.scrollFreedreno.updateMargins(left = leftInsets, right = rightInsets)
|
||||
binding.scrollFreedreno.updatePadding(bottom = barInsets.bottom)
|
||||
val systemInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
binding.root.updatePadding(
|
||||
left = systemInsets.left,
|
||||
right = systemInsets.right,
|
||||
bottom = systemInsets.bottom
|
||||
)
|
||||
insets
|
||||
}
|
||||
}
|
||||
private fun showSnackbar(message: String) {
|
||||
|
||||
private fun showSnackbar(message: String) {
|
||||
Snackbar.make(binding.root, message, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
|
||||
+13
-16
@@ -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
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
@@ -310,21 +310,6 @@ class GamePropertiesFragment : Fragment() {
|
||||
)
|
||||
)
|
||||
|
||||
if (!args.game.isHomebrew) {
|
||||
add(
|
||||
SubmenuProperty(
|
||||
R.string.add_ons,
|
||||
R.string.add_ons_description,
|
||||
R.drawable.ic_edit,
|
||||
action = {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToAddonsFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (GpuDriverHelper.supportsCustomDriverLoading()) {
|
||||
add(
|
||||
SubmenuProperty(
|
||||
@@ -356,6 +341,18 @@ class GamePropertiesFragment : Fragment() {
|
||||
}
|
||||
|
||||
if (!args.game.isHomebrew) {
|
||||
add(
|
||||
SubmenuProperty(
|
||||
R.string.add_ons,
|
||||
R.string.add_ons_description,
|
||||
R.drawable.ic_edit,
|
||||
action = {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToAddonsFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
InstallableProperty(
|
||||
R.string.save_data,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.Manifest
|
||||
@@ -41,9 +44,7 @@ import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
|
||||
class HomeSettingsFragment : Fragment() {
|
||||
private var _binding: FragmentHomeSettingsBinding? = null
|
||||
@@ -70,12 +71,8 @@ class HomeSettingsFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = false)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = true)
|
||||
mainActivity = requireActivity() as MainActivity
|
||||
binding.toolbarHomeSettings.setNavigationOnClickListener {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
binding.toolbarHomeSettings.title = getString(R.string.preferences_settings)
|
||||
|
||||
val optionsList: MutableList<HomeSetting> = mutableListOf<HomeSetting>().apply {
|
||||
add(
|
||||
@@ -147,18 +144,6 @@ class HomeSettingsFragment : Fragment() {
|
||||
driverViewModel.selectedDriverTitle
|
||||
)
|
||||
)
|
||||
if (GpuDriverHelper.isAdrenoGpu()) {
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.freedreno_settings_title,
|
||||
R.string.gpu_driver_settings,
|
||||
R.drawable.ic_graphics,
|
||||
{
|
||||
binding.root.findNavController().navigate(R.id.freedrenoSettingsFragment)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.multiplayer,
|
||||
@@ -480,22 +465,19 @@ class HomeSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
binding.appbarHomeSettings.updateMargins(
|
||||
left = barInsets.left + cutoutInsets.left,
|
||||
right = barInsets.right + cutoutInsets.right
|
||||
)
|
||||
|
||||
binding.scrollViewSettings.updatePadding(
|
||||
bottom = barInsets.bottom
|
||||
top = barInsets.top
|
||||
)
|
||||
|
||||
binding.homeSettingsList.updatePadding(
|
||||
left = barInsets.left + cutoutInsets.left,
|
||||
right = barInsets.right + cutoutInsets.right
|
||||
top = cutoutInsets.top,
|
||||
right = barInsets.right + cutoutInsets.right,
|
||||
bottom = barInsets.bottom
|
||||
)
|
||||
|
||||
windowInsets
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class AddonViewModel : ViewModel() {
|
||||
private val _patchList = MutableStateFlow<List<Patch>>(emptyList())
|
||||
private val _patchList = MutableStateFlow(mutableListOf<Patch>())
|
||||
val addonList get() = _patchList.asStateFlow()
|
||||
|
||||
private val _showModInstallPicker = MutableStateFlow(false)
|
||||
@@ -31,62 +31,34 @@ class AddonViewModel : ViewModel() {
|
||||
val addonToDelete = _addonToDelete.asStateFlow()
|
||||
|
||||
var game: Game? = null
|
||||
private var loadedGameKey: String? = null
|
||||
|
||||
private val isRefreshing = AtomicBoolean(false)
|
||||
private val pendingRefresh = AtomicBoolean(false)
|
||||
|
||||
fun onAddonsViewCreated(game: Game) {
|
||||
fun onOpenAddons(game: Game) {
|
||||
this.game = game
|
||||
refreshAddons(commitEmpty = false)
|
||||
refreshAddons()
|
||||
}
|
||||
|
||||
fun onAddonsViewStarted(game: Game) {
|
||||
this.game = game
|
||||
val hasLoadedCurrentGame = loadedGameKey == gameKey(game)
|
||||
refreshAddons(force = !hasLoadedCurrentGame)
|
||||
}
|
||||
|
||||
fun refreshAddons(force: Boolean = false, commitEmpty: Boolean = true) {
|
||||
val currentGame = game ?: return
|
||||
val currentGameKey = gameKey(currentGame)
|
||||
if (!force && loadedGameKey == currentGameKey) {
|
||||
fun refreshAddons() {
|
||||
if (isRefreshing.get() || game == null) {
|
||||
return
|
||||
}
|
||||
if (!isRefreshing.compareAndSet(false, true)) {
|
||||
if (force) {
|
||||
pendingRefresh.set(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
isRefreshing.set(true)
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val patches = withContext(Dispatchers.IO) {
|
||||
NativeLibrary.getPatchesForFile(currentGame.path, currentGame.programId)
|
||||
} ?: return@launch
|
||||
|
||||
val patchList = patches.toMutableList()
|
||||
withContext(Dispatchers.IO) {
|
||||
val patchList = (
|
||||
NativeLibrary.getPatchesForFile(game!!.path, game!!.programId)
|
||||
?: emptyArray()
|
||||
).toMutableList()
|
||||
patchList.sortBy { it.name }
|
||||
|
||||
// Ensure only one update is enabled
|
||||
ensureSingleUpdateEnabled(patchList)
|
||||
|
||||
removeDuplicates(patchList)
|
||||
if (patchList.isEmpty() && !commitEmpty) {
|
||||
return@launch
|
||||
}
|
||||
if (gameKey(game ?: return@launch) != currentGameKey) {
|
||||
return@launch
|
||||
}
|
||||
|
||||
_patchList.value = patchList.toList()
|
||||
loadedGameKey = currentGameKey
|
||||
} finally {
|
||||
_patchList.value = patchList
|
||||
isRefreshing.set(false)
|
||||
if (pendingRefresh.compareAndSet(true, false)) {
|
||||
refreshAddons(force = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,26 +119,17 @@ class AddonViewModel : ViewModel() {
|
||||
PatchType.DLC -> NativeLibrary.removeDLC(patch.programId)
|
||||
PatchType.Mod -> NativeLibrary.removeMod(patch.programId, patch.name)
|
||||
}
|
||||
refreshAddons(force = true)
|
||||
refreshAddons()
|
||||
}
|
||||
|
||||
fun onCloseAddons() {
|
||||
val currentGame = game ?: run {
|
||||
_patchList.value = emptyList()
|
||||
loadedGameKey = null
|
||||
return
|
||||
}
|
||||
val currentList = _patchList.value
|
||||
if (currentList.isEmpty()) {
|
||||
_patchList.value = emptyList()
|
||||
loadedGameKey = null
|
||||
game = null
|
||||
if (_patchList.value.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
NativeConfig.setDisabledAddons(
|
||||
currentGame.programId,
|
||||
currentList.mapNotNull {
|
||||
game!!.programId,
|
||||
_patchList.value.mapNotNull {
|
||||
if (it.enabled) {
|
||||
null
|
||||
} else {
|
||||
@@ -185,8 +148,7 @@ class AddonViewModel : ViewModel() {
|
||||
}.toTypedArray()
|
||||
)
|
||||
NativeConfig.saveGlobalConfig()
|
||||
_patchList.value = emptyList()
|
||||
loadedGameKey = null
|
||||
_patchList.value.clear()
|
||||
game = null
|
||||
}
|
||||
|
||||
@@ -197,8 +159,4 @@ class AddonViewModel : ViewModel() {
|
||||
fun showModNoticeDialog(show: Boolean) {
|
||||
_showModNoticeDialog.value = show
|
||||
}
|
||||
|
||||
private fun gameKey(game: Game): String {
|
||||
return "${game.programId}|${game.path}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,5 @@ data class Patch(
|
||||
val type: Int,
|
||||
val programId: String,
|
||||
val titleId: String,
|
||||
val numericVersion: Long = 0,
|
||||
val source: Int = 0
|
||||
) {
|
||||
companion object {
|
||||
const val SOURCE_UNKNOWN = 0
|
||||
const val SOURCE_NAND = 1
|
||||
const val SOURCE_SDMC = 2
|
||||
const val SOURCE_EXTERNAL = 3
|
||||
const val SOURCE_PACKED = 4
|
||||
}
|
||||
|
||||
val isRemovable: Boolean
|
||||
get() = source != SOURCE_EXTERNAL && source != SOURCE_PACKED
|
||||
}
|
||||
val numericVersion: Long = 0
|
||||
)
|
||||
|
||||
@@ -94,8 +94,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
|
||||
// Since Android 15, google automatically forces "games" to be 60 hrz
|
||||
// This ensures the display's max refresh rate is actually used
|
||||
display?.let {
|
||||
val supportedModes = it.supportedModes
|
||||
val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate }
|
||||
@@ -642,7 +640,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
addonViewModel.refreshAddons(force = true)
|
||||
addonViewModel.refreshAddons()
|
||||
|
||||
val separator = System.lineSeparator() ?: "\n"
|
||||
val installResult = StringBuilder()
|
||||
|
||||
@@ -6,8 +6,15 @@
|
||||
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "input_common/drivers/android.h"
|
||||
#include "input_common/drivers/touch_screen.h"
|
||||
#include "input_common/drivers/virtual_amiibo.h"
|
||||
@@ -22,6 +29,12 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||
m_window_width = 0;
|
||||
m_window_height = 0;
|
||||
window_info.render_surface = nullptr;
|
||||
m_last_frame_rate_hint = -1.0f;
|
||||
m_pending_frame_rate_hint = -1.0f;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_smoothed_present_rate = 0.0f;
|
||||
m_last_frame_display_time = {};
|
||||
m_pending_frame_rate_since = {};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,6 +45,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||
UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
|
||||
|
||||
window_info.render_surface = reinterpret_cast<void*>(surface);
|
||||
UpdateFrameRateHint();
|
||||
}
|
||||
|
||||
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
||||
@@ -51,6 +65,9 @@ void EmuWindow_Android::OnTouchReleased(int id) {
|
||||
}
|
||||
|
||||
void EmuWindow_Android::OnFrameDisplayed() {
|
||||
UpdateObservedFrameRate();
|
||||
UpdateFrameRateHint();
|
||||
|
||||
if (!m_first_frame) {
|
||||
Common::Android::RunJNIOnFiber<void>(
|
||||
[&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); });
|
||||
@@ -58,6 +75,175 @@ void EmuWindow_Android::OnFrameDisplayed() {
|
||||
}
|
||||
}
|
||||
|
||||
void EmuWindow_Android::UpdateObservedFrameRate() {
|
||||
const auto now = Clock::now();
|
||||
if (m_last_frame_display_time.time_since_epoch().count() != 0) {
|
||||
const auto frame_time = std::chrono::duration<float>(now - m_last_frame_display_time);
|
||||
const float seconds = frame_time.count();
|
||||
if (seconds > 0.0f) {
|
||||
const float instantaneous_rate = 1.0f / seconds;
|
||||
if (std::isfinite(instantaneous_rate) && instantaneous_rate >= 1.0f &&
|
||||
instantaneous_rate <= 240.0f) {
|
||||
constexpr float SmoothingFactor = 0.15f;
|
||||
if (m_smoothed_present_rate <= 0.0f) {
|
||||
m_smoothed_present_rate = instantaneous_rate;
|
||||
} else {
|
||||
m_smoothed_present_rate +=
|
||||
(instantaneous_rate - m_smoothed_present_rate) * SmoothingFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_last_frame_display_time = now;
|
||||
}
|
||||
|
||||
float EmuWindow_Android::QuantizeFrameRateHint(float frame_rate) {
|
||||
if (!std::isfinite(frame_rate) || frame_rate <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
frame_rate = std::clamp(frame_rate, 1.0f, 240.0f);
|
||||
|
||||
constexpr float Step = 0.5f;
|
||||
return std::round(frame_rate / Step) * Step;
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
|
||||
if (!EmulationSession::GetInstance().IsRunning()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const double frame_time_scale =
|
||||
EmulationSession::GetInstance().System().GetPerfStats().GetLastFrameTimeScale();
|
||||
if (!std::isfinite(frame_time_scale) || frame_time_scale <= 0.0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float verified_rate =
|
||||
std::clamp(60.0f / static_cast<float>(frame_time_scale), 0.0f, 240.0f);
|
||||
return QuantizeFrameRateHint(verified_rate);
|
||||
}
|
||||
|
||||
float EmuWindow_Android::GetFrameRateHint() const {
|
||||
const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f);
|
||||
const float frame_time_verified_hint = GetFrameTimeVerifiedHint();
|
||||
|
||||
if (m_last_frame_rate_hint > 0.0f && observed_rate > 0.0f) {
|
||||
const float tolerance = std::max(m_last_frame_rate_hint * 0.12f, 4.0f);
|
||||
if (std::fabs(observed_rate - m_last_frame_rate_hint) <= tolerance) {
|
||||
return m_last_frame_rate_hint;
|
||||
}
|
||||
}
|
||||
|
||||
const float observed_hint = QuantizeFrameRateHint(observed_rate);
|
||||
if (observed_hint > 0.0f) {
|
||||
if (frame_time_verified_hint > 0.0f) {
|
||||
const float tolerance = std::max(observed_hint * 0.20f, 3.0f);
|
||||
if (std::fabs(observed_hint - frame_time_verified_hint) <= tolerance) {
|
||||
return QuantizeFrameRateHint((observed_hint + frame_time_verified_hint) * 0.5f);
|
||||
}
|
||||
}
|
||||
return observed_hint;
|
||||
}
|
||||
|
||||
if (frame_time_verified_hint > 0.0f) {
|
||||
return frame_time_verified_hint;
|
||||
}
|
||||
|
||||
constexpr float NominalFrameRate = 60.0f;
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
return NominalFrameRate;
|
||||
}
|
||||
|
||||
const u16 speed_limit = Settings::SpeedLimit();
|
||||
if (speed_limit == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float speed_limited_rate =
|
||||
NominalFrameRate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
|
||||
return QuantizeFrameRateHint(speed_limited_rate);
|
||||
}
|
||||
|
||||
void EmuWindow_Android::UpdateFrameRateHint() {
|
||||
auto* const surface = reinterpret_cast<ANativeWindow*>(window_info.render_surface);
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = Clock::now();
|
||||
const float frame_rate_hint = GetFrameRateHint();
|
||||
if (std::fabs(frame_rate_hint - m_last_frame_rate_hint) < 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame_rate_hint == 0.0f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = now;
|
||||
} else if (m_last_frame_rate_hint >= 0.0f) {
|
||||
if (std::fabs(frame_rate_hint - m_pending_frame_rate_hint) >= 0.01f) {
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 1;
|
||||
m_pending_frame_rate_since = now;
|
||||
return;
|
||||
}
|
||||
|
||||
++m_pending_frame_rate_hint_votes;
|
||||
if (m_pending_frame_rate_since.time_since_epoch().count() == 0) {
|
||||
m_pending_frame_rate_since = now;
|
||||
}
|
||||
|
||||
const auto stable_for = now - m_pending_frame_rate_since;
|
||||
const float reference_rate = std::max(frame_rate_hint, 1.0f);
|
||||
const auto stable_duration = std::chrono::duration_cast<Clock::duration>(
|
||||
std::chrono::duration<float>(std::clamp(3.0f / reference_rate, 0.15f, 0.40f)));
|
||||
constexpr std::uint32_t MinStableVotes = 3;
|
||||
|
||||
if (m_pending_frame_rate_hint_votes < MinStableVotes || stable_for < stable_duration) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_pending_frame_rate_since = now;
|
||||
}
|
||||
|
||||
using SetFrameRateWithChangeStrategyFn =
|
||||
int32_t (*)(ANativeWindow*, float, int8_t, int8_t);
|
||||
using SetFrameRateFn = int32_t (*)(ANativeWindow*, float, int8_t);
|
||||
static const auto set_frame_rate_with_change_strategy =
|
||||
reinterpret_cast<SetFrameRateWithChangeStrategyFn>(
|
||||
dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRateWithChangeStrategy"));
|
||||
static const auto set_frame_rate = reinterpret_cast<SetFrameRateFn>(
|
||||
dlsym(RTLD_DEFAULT, "ANativeWindow_setFrameRate"));
|
||||
|
||||
constexpr int8_t FrameRateCompatibilityDefault = 0;
|
||||
constexpr int8_t ChangeFrameRateOnlyIfSeamless = 0;
|
||||
|
||||
int32_t result = -1;
|
||||
if (set_frame_rate_with_change_strategy) {
|
||||
result = set_frame_rate_with_change_strategy(surface, frame_rate_hint,
|
||||
FrameRateCompatibilityDefault,
|
||||
ChangeFrameRateOnlyIfSeamless);
|
||||
} else if (set_frame_rate) {
|
||||
result = set_frame_rate(surface, frame_rate_hint, FrameRateCompatibilityDefault);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
LOG_DEBUG(Frontend, "Failed to update Android surface frame rate hint: {}", result);
|
||||
return;
|
||||
}
|
||||
|
||||
m_last_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint = frame_rate_hint;
|
||||
m_pending_frame_rate_hint_votes = 0;
|
||||
m_pending_frame_rate_since = {};
|
||||
}
|
||||
|
||||
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface,
|
||||
std::shared_ptr<Common::DynamicLibrary> driver_library)
|
||||
: m_driver_library{driver_library} {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
@@ -50,10 +55,24 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
void UpdateFrameRateHint();
|
||||
void UpdateObservedFrameRate();
|
||||
[[nodiscard]] float GetFrameRateHint() const;
|
||||
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
|
||||
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
|
||||
|
||||
float m_window_width{};
|
||||
float m_window_height{};
|
||||
|
||||
std::shared_ptr<Common::DynamicLibrary> m_driver_library;
|
||||
|
||||
bool m_first_frame = false;
|
||||
float m_last_frame_rate_hint = -1.0f;
|
||||
float m_pending_frame_rate_hint = -1.0f;
|
||||
float m_smoothed_present_rate = 0.0f;
|
||||
Clock::time_point m_last_frame_display_time{};
|
||||
Clock::time_point m_pending_frame_rate_since{};
|
||||
std::uint32_t m_pending_frame_rate_hint_votes = 0;
|
||||
};
|
||||
|
||||
@@ -1407,7 +1407,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env
|
||||
Common::Android::ToJString(env, patch.version), static_cast<jint>(patch.type),
|
||||
Common::Android::ToJString(env, std::to_string(patch.program_id)),
|
||||
Common::Android::ToJString(env, std::to_string(patch.title_id)),
|
||||
static_cast<jlong>(patch.numeric_version), static_cast<jint>(patch.source));
|
||||
static_cast<jlong>(patch.numeric_version));
|
||||
env->SetObjectArrayElement(jpatchArray, i, jpatch);
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<solid android:color="?attr/colorSurface" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="?attr/colorOutline" />
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:text="@string/multiplayer_room_browser"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/search_background"
|
||||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
app:cardBackgroundColor="?attr/colorSurfaceVariant"
|
||||
app:cardCornerRadius="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/search_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@string/home_search"
|
||||
android:src="@drawable/ic_search"
|
||||
app:tint="?attr/colorOnSurfaceVariant" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:autofillHints=""
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="@string/multiplayer_search_public_lobbies"
|
||||
android:imeOptions="flagNoFullscreen"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/clear_button"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/clear"
|
||||
android:src="@drawable/ic_clear"
|
||||
android:visibility="invisible"
|
||||
app:tint="?attr/colorOnSurfaceVariant"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btn_submit"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/submit"
|
||||
android:src="@drawable/ic_send"
|
||||
app:tint="?attr/colorOnSurfaceVariant"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/refresh_button"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/refresh"
|
||||
app:icon="@drawable/ic_refresh" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/horizontalScrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:fadingEdge="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_hide_empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:checkable="true"
|
||||
android:checked="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:text="@string/multiplayer_hide_empty_rooms"
|
||||
app:chipCornerRadius="16dp"
|
||||
app:chipIconSize="18dp"
|
||||
app:chipIconTint="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip_hide_full"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:checkable="true"
|
||||
android:checked="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:text="@string/multiplayer_hide_full_rooms"
|
||||
app:chipCornerRadius="16dp"
|
||||
app:chipIconSize="18dp"
|
||||
app:chipIconTint="?attr/colorOnSurface" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/room_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:contentDescription="@string/room_list"
|
||||
android:paddingBottom="16dp"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/empty_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:alpha="0.5"
|
||||
android:contentDescription="@string/refresh"
|
||||
android:src="@drawable/ic_refresh"
|
||||
app:tint="?attr/colorOnSurface" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/multiplayer_no_rooms_found"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/multiplayer_tap_refresh_to_check_again"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/empty_refresh_button"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/refresh"
|
||||
app:icon="@drawable/ic_refresh" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -1,112 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/theme_dialog_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_weight="0.75">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/multiplayer"
|
||||
android:src="@drawable/ic_network"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.25"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/multiplayer"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_lobby_browser"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:minHeight="56dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/multiplayer_public_room"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:cornerRadius="16dp"
|
||||
app:icon="@drawable/ic_search"
|
||||
app:iconPadding="12dp"
|
||||
app:iconTint="?attr/colorOnPrimary" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_join"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:minHeight="56dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/multiplayer_join_room"
|
||||
app:cornerRadius="16dp"
|
||||
app:icon="@drawable/ic_install"
|
||||
app:iconPadding="12dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_create"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:minHeight="56dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/multiplayer_create_room"
|
||||
app:cornerRadius="16dp"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:iconPadding="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -44,12 +44,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="4dp"
|
||||
>
|
||||
|
||||
@@ -108,12 +103,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
@@ -137,12 +127,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
@@ -166,12 +151,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
|
||||
@@ -12,83 +12,70 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
tools:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
tools:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
android:text="@string/user_data"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/user_data"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/user_data_description"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/user_data_description"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<Button
|
||||
android:id="@+id/button_export"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:layout_gravity="center_vertical"
|
||||
android:contentDescription="@string/export"
|
||||
android:tooltipText="@string/export"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_export"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_install"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/string_import"
|
||||
android:tooltipText="@string/string_import"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_import"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_export"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:contentDescription="@string/export"
|
||||
android:tooltipText="@string/export"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_export"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:id="@+id/button_install"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:contentDescription="@string/string_import"
|
||||
android:tooltipText="@string/string_import"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_import"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
android:id="@+id/coordinator_about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
|
||||
@@ -7,13 +7,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
android:focusable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -2,15 +2,11 @@
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="?attr/materialCardViewOutlinedStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
android:layout_marginVertical="12dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingBottom="2dp">
|
||||
android:paddingTop="14dp"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/image_game_screen"
|
||||
@@ -48,14 +48,11 @@
|
||||
style="@style/SynthwaveText.Body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="8dp"
|
||||
android:requiresFadingEdge="horizontal"
|
||||
android:textAlignment="center"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintEnd_toEndOf="@+id/image_game_screen"
|
||||
app:layout_constraintStart_toStartOf="@+id/image_game_screen"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_game_screen"
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingBottom="3dp">
|
||||
android:paddingTop="14dp"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/image_container"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
android:transitionName="card_game"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardBackgroundColor="@color/eden_card_background"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
@@ -27,8 +27,6 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.Medium"
|
||||
app:strokeColor="@color/eden_card_background"
|
||||
app:strokeWidth="4dp"
|
||||
tools:src="@drawable/default_icon" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
|
||||
@@ -8,14 +8,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
app:cardCornerRadius="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/option_layout"
|
||||
@@ -65,7 +60,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorPrimary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:singleLine="true"
|
||||
|
||||
@@ -2,15 +2,11 @@
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
android:layout_marginVertical="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -46,37 +42,30 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<Button
|
||||
android:id="@+id/button_export"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
android:contentDescription="@string/export"
|
||||
android:tooltipText="@string/export"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_export"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_export"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/export"
|
||||
android:tooltipText="@string/export"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_export"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_install"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:contentDescription="@string/string_import"
|
||||
android:tooltipText="@string/string_import"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_import"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:id="@+id/button_install"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:contentDescription="@string/string_import"
|
||||
android:tooltipText="@string/string_import"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_import"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -6,75 +6,63 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
android:layout_marginVertical="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
tools:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
tools:src="@drawable/ic_settings" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
android:text="@string/user_data"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/user_data"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/user_data_description"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/user_data_description"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_install"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:contentDescription="@string/string_import"
|
||||
android:tooltipText="@string/string_import"
|
||||
android:visibility="gone"
|
||||
@@ -83,10 +71,11 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_export"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginTop="8dp"
|
||||
android:contentDescription="@string/export"
|
||||
android:tooltipText="@string/export"
|
||||
android:visibility="gone"
|
||||
|
||||
@@ -7,13 +7,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
android:focusable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -85,15 +81,14 @@
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/layoutSecondaryActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:visibility="gone"
|
||||
app:singleLine="false"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:elevation="0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
app:layout_scrollFlags="scroll|enterAlways|snap">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -59,11 +59,8 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/multiplayer_public_room"
|
||||
app:cornerRadius="16dp"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:icon="@drawable/ic_search"
|
||||
app:iconPadding="12dp"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
android:textColor="?attr/colorOnPrimary" />
|
||||
app:iconPadding="12dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="20dp"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
android:id="@+id/coordinator_about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@@ -52,15 +51,12 @@
|
||||
android:src="@drawable/ic_yuzu" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
app:cardCornerRadius="16dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -88,17 +84,14 @@
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/button_contributors"
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
app:cardCornerRadius="16dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -126,17 +119,14 @@
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/button_licenses"
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp">
|
||||
app:cardCornerRadius="16dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -171,7 +161,7 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardBackgroundColor="?attr/colorSurface"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_addons"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
@@ -19,7 +18,6 @@
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_addons"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_applets"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
@@ -16,7 +15,6 @@
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_applets"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -7,22 +7,19 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_drivers"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
||||
app:liftOnScrollTargetViewId="@id/list_drivers">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_drivers"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -13,15 +13,14 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_drivers"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false">
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:liftOnScrollTargetViewId="@id/list_drivers">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_drivers"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -12,15 +12,14 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_folders"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false">
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:liftOnScrollTargetViewId="@id/list_folders">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_folders"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -8,24 +8,35 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_freedreno"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false">
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_freedreno"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/toolbar_freedreno_layout"
|
||||
style="?attr/collapsingToolbarLayoutMediumStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:navigationIcon="@drawable/ic_back" />
|
||||
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:contentScrim="?attr/colorSurface"
|
||||
app:scrimVisibleHeightTrigger="100dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_freedreno"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:layout_collapseMode="pin"
|
||||
app:navigationIcon="@drawable/ic_back"
|
||||
app:title="@string/gpu_driver_settings" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/scroll_freedreno"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
@@ -52,12 +63,8 @@
|
||||
android:id="@+id/list_freedreno_presets"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="8dp"
|
||||
android:scrollbars="horizontal"
|
||||
android:scrollbarStyle="outsideInset"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
|
||||
<!-- Current Settings Section -->
|
||||
@@ -128,23 +135,22 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="horizontal">
|
||||
android:spacing="8dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_clear_all"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_weight="1"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:text="@string/freedreno_clear_all" />
|
||||
android:text="@string/freedreno_clear_all"
|
||||
style="?attr/materialButtonOutlinedStyle" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_save"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/save" />
|
||||
|
||||
@@ -155,7 +161,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="?attr/colorOutline">
|
||||
|
||||
@@ -33,12 +33,9 @@
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
app:icon="@drawable/ic_back"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorOnSurface"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@@ -47,12 +44,9 @@
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
app:icon="@drawable/ic_shortcut"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorOnSurface"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
@@ -37,12 +37,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
@@ -66,12 +61,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
@@ -95,12 +85,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="21dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="8dp"
|
||||
>
|
||||
|
||||
@@ -132,12 +117,7 @@
|
||||
style="@style/EdenCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
android:padding="4dp"
|
||||
>
|
||||
|
||||
|
||||
@@ -1,64 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/scroll_view_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface">
|
||||
android:scrollbars="vertical"
|
||||
android:fadeScrollbars="false"
|
||||
android:clipToPadding="false"
|
||||
android:background="?attr/colorSurface"
|
||||
android:defaultFocusHighlightEnabled="false">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_home_settings"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/linear_layout_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_home_settings"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:navigationIcon="@drawable/ic_back"
|
||||
app:title="@string/preferences_settings" />
|
||||
<ImageView
|
||||
android:id="@+id/logo_image"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/ic_yuzu" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/scroll_view_settings"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:defaultFocusHighlightEnabled="false"
|
||||
android:fadeScrollbars="false"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/appbar_home_settings">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/linear_layout_settings"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_settings_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="16dp">
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_settings_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_installables"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
@@ -16,7 +15,6 @@
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_installables"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_profiles"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/profile_manager"
|
||||
|
||||
@@ -8,19 +8,30 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_settings"
|
||||
style="@style/Widget.Eden.TransparentTopAppBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:touchscreenBlocksFocus="false">
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_settings"
|
||||
style="@style/Widget.Eden.TransparentTopToolbar"
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/toolbar_settings_layout"
|
||||
style="?attr/collapsingToolbarLayoutMediumStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:navigationIcon="@drawable/ic_back" />
|
||||
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:contentScrim="?attr/colorSurface"
|
||||
app:scrimVisibleHeightTrigger="100dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
app:layout_collapseMode="pin"
|
||||
app:navigationIcon="@drawable/ic_back" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.button.MaterialButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp" />
|
||||
@@ -11,11 +11,8 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardElevation="2dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
@@ -81,11 +78,8 @@
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="10dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="?attr/colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
app:cardElevation="2dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
@@ -106,7 +100,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:background="@null"
|
||||
android:src="@drawable/ic_delete"
|
||||
app:tint="?attr/colorPrimary"
|
||||
app:tint="@color/eden_border_gradient_end"
|
||||
android:contentDescription="@string/delete" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_settingsActivity"
|
||||
app:destination="@id/settingsActivity"
|
||||
app:enterAnim="@anim/nav_default_enter_anim"
|
||||
app:exitAnim="@anim/nav_default_exit_anim"
|
||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||
app:destination="@id/settingsActivity" />
|
||||
|
||||
</navigation>
|
||||
|
||||
@@ -101,11 +101,7 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_settingsActivity"
|
||||
app:destination="@id/settingsActivity"
|
||||
app:enterAnim="@anim/nav_default_enter_anim"
|
||||
app:exitAnim="@anim/nav_default_exit_anim"
|
||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||
app:destination="@id/settingsActivity" />
|
||||
<fragment
|
||||
android:id="@+id/installableFragment"
|
||||
android:name="org.yuzu.yuzu_emu.fragments.InstallableFragment"
|
||||
|
||||
@@ -506,8 +506,6 @@
|
||||
<string name="dyna_state">الحالة الديناميكية الموسعة</string>
|
||||
<string name="dyna_state_description">يتحكم هذا الخيار في عدد الميزات التي يمكن استخدامها في حالة الديناميكية الموسعة. تسمح الأرقام الأعلى بمزيد من الميزات ويمكن أن تزيد من الأداء، ولكنها قد تسبب مشاكل مع بعض برامج التشغيل والأجهزة.</string>
|
||||
<string name="disabled">معطل</string>
|
||||
<string name="vertex_input_dynamic_state">حالة ديناميكية لإدخال الرأس</string>
|
||||
<string name="vertex_input_dynamic_state_description">يتيح ميزة الحالة الديناميكية لإدخال الرأس لتحسين الجودة والأداء.</string>
|
||||
<string name="provoking_vertex">الرأس المثير</string>
|
||||
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">فهرسة الوصف</string>
|
||||
|
||||
@@ -488,8 +488,6 @@
|
||||
<string name="dyna_state">Úroveň EDS</string>
|
||||
<string name="dyna_state_description">Určuje počet funkcí využívaných v rámci rozšířeného dynamického stavu API Vulkan (Extended Dynamic State). Vyšší hodnoty umožňují využít více funkcí a mohou zvýšit výkon, ale u některých ovladačů a výrobců grafických karet mohou způsobovat problémy s kompatibilitou.</string>
|
||||
<string name="disabled">Vypnuto</string>
|
||||
<string name="vertex_input_dynamic_state">Dynamický stav vstupu vrcholů (Vertex Input)</string>
|
||||
<string name="vertex_input_dynamic_state_description">Aktivuje funkci dynamického stavu vstupu vrcholů (Vertex Input Dynamic State) pro lepší kvalitu a výkon.</string>
|
||||
<string name="provoking_vertex">Určující vrchol</string>
|
||||
<string name="provoking_vertex_description">Zlepšuje osvětlení a zpracování vrcholů v některých hrách. Podporováno pouze na GPU s API Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexování deskriptorů</string>
|
||||
|
||||
@@ -486,8 +486,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
||||
<string name="dyna_state">Erweiterter dynamischer Status</string>
|
||||
<string name="dyna_state_description">Steuert die Anzahl der Funktionen, die im \"Vertex Input Dynamic State\" werden können. Höhere Werte ermöglichen mehr Funktionen und können die Leistung steigern, können aber bei einigen Treibern und Anbietern zu Problemen führen.</string>
|
||||
<string name="disabled">Deaktiviert</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Aktiviert die Funktion \"Vertex Input Dynamic State\" für bessere Qualität und Leistung.</string>
|
||||
<string name="provoking_vertex">Provokanter Vertex</string>
|
||||
<string name="provoking_vertex_description">Verbessert die Beleuchtung und die Vertex-Verarbeitung in einigen Spielen. Wird nur von GPUs mit Vulkan 1.0+ unterstützt.</string>
|
||||
<string name="descriptor_indexing">Deskriptor-Indizierung</string>
|
||||
|
||||
@@ -436,8 +436,6 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Compile les shaders de manière asynchrone. Cela peut réduire les saccades mais peut aussi provoquer des problèmes graphiques.</string>
|
||||
<string name="dyna_state">État dynamique étendu</string>
|
||||
<string name="disabled">Désactivé</string>
|
||||
<string name="vertex_input_dynamic_state">État dynamique d\'entrée de sommet</string>
|
||||
<string name="vertex_input_dynamic_state_description">Active la fonctionnalité d\'état dynamique des entrées de sommets pour une meilleure qualité et de meilleures performances.</string>
|
||||
<string name="provoking_vertex">Provoque des Vertex</string>
|
||||
<string name="provoking_vertex_description">Améliore l`éclairage et la gestion des vertex dans certains jeux. Pris en charge uniquement par les GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexation des descripteurs</string>
|
||||
|
||||
@@ -488,8 +488,6 @@
|
||||
<string name="dyna_state">Rozszerzony stan dynamiczny</string>
|
||||
<string name="dyna_state_description">Kontroluje liczbę funkcji, które mogą być używane w Extended Dynamic State. Wyższe wartości pozwalają na użycie większej liczby funkcji i mogą zwiększyć wydajność, ale mogą powodować problemy z niektórymi sterownikami i u niektórych producentów.</string>
|
||||
<string name="disabled">Wyłączone</string>
|
||||
<string name="vertex_input_dynamic_state">Dynamiczny stan wejścia wierzchołków</string>
|
||||
<string name="vertex_input_dynamic_state_description">Włącza funkcję dynamicznego stanu wejścia wierzchołków, poprawiając jakość i wydajność.</string>
|
||||
<string name="provoking_vertex">Wierzchołek prowokujący</string>
|
||||
<string name="provoking_vertex_description">Poprawia oświetlenie i obsługę wierzchołków w niektórych grach. Obsługiwane tylko przez GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indeksowanie deskryptorów</string>
|
||||
|
||||
@@ -471,8 +471,6 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Compila shaders de forma assíncrona. Isso pode reduzir engasgos, mas também pode introduzir falhas gráficas.</string>
|
||||
<string name="dyna_state">Extended Dynamic State</string>
|
||||
<string name="disabled">Desativado</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Ativa o recurso de vertex input dynamic state para melhor qualidade e desempenho.</string>
|
||||
<string name="provoking_vertex">Provoking Vertex</string>
|
||||
<string name="provoking_vertex_description">Vértice Provocante: Melhora a iluminação e o processamento de vértices em certos jogos. Suportado apenas em GPUs com Vulkan 1.0 ou superior.</string>
|
||||
<string name="descriptor_indexing">Descriptor Indexing</string>
|
||||
|
||||
@@ -498,8 +498,6 @@
|
||||
<string name="dyna_state">Расширенное динамическое состояние</string>
|
||||
<string name="dyna_state_description">Управляет количеством функций, доступных в режиме «Расширенное динамическое состояние». Большее число позволяет задействовать больше функций и может повысить производительность, но способно вызывать проблемы с некоторыми драйверами и графикой.</string>
|
||||
<string name="disabled">Отключено</string>
|
||||
<string name="vertex_input_dynamic_state">Динамическое состояние ввода вершин</string>
|
||||
<string name="vertex_input_dynamic_state_description">Включает функцию динамического состояния ввода вершин для повышения качества и производительности</string>
|
||||
<string name="provoking_vertex">Определяющая вершина</string>
|
||||
<string name="provoking_vertex_description">Улучшает освещение и обработку вершин в некоторых играх. Поддерживается только ГПУ с Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Индексирование дескрипторов</string>
|
||||
|
||||
@@ -502,8 +502,6 @@
|
||||
<string name="dyna_state">Розширений динамічний стан</string>
|
||||
<string name="dyna_state_description">Керує кількістю функцій, які можна використовувати в «Розширеному динамічному стані». Вище число дозволяє більше функцій і може покращити продуктивність, але може спричинити проблеми з деякими драйверами й виробниками.</string>
|
||||
<string name="disabled">Вимкнено</string>
|
||||
<string name="vertex_input_dynamic_state">Динамічний стан введення вершин</string>
|
||||
<string name="vertex_input_dynamic_state_description">Вмикає можливість динамічного стану введення вершин для кращих якості й продуктивності.</string>
|
||||
<string name="provoking_vertex">Провокативна вершина</string>
|
||||
<string name="provoking_vertex_description">Покращує освітлення та взаємодію з вершинами у деяких іграх. Лише для ГП з підтримкою Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Індексація дескрипторів</string>
|
||||
|
||||
@@ -496,8 +496,6 @@
|
||||
<string name="dyna_state">扩展动态状态</string>
|
||||
<string name="dyna_state_description">控制在扩展动态状态中可使用的函数数量。更高的数值允许启用更多功能,并可能提升性能,但同时也可能导致额外的图形问题。</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="vertex_input_dynamic_state">顶点输入动态状态</string>
|
||||
<string name="vertex_input_dynamic_state_description">开启顶点输入动态状态功能来获得更好的质量和性能。</string>
|
||||
<string name="provoking_vertex">引发顶点</string>
|
||||
<string name="provoking_vertex_description">改善某些游戏中的光照和顶点处理。仅支持Vulkan 1.0+ GPU。</string>
|
||||
<string name="descriptor_indexing">描述符索引</string>
|
||||
|
||||
@@ -467,8 +467,6 @@
|
||||
<string name="renderer_asynchronous_shaders_description">非同步編譯著色器。這可能會減少卡頓,但也可能導致圖形錯誤。</string>
|
||||
<string name="dyna_state">擴展動態狀態</string>
|
||||
<string name="disabled">已停用</string>
|
||||
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
||||
<string name="vertex_input_dynamic_state_description">啟用頂點輸入動態狀態以取得更佳的品質及性能</string>
|
||||
<string name="provoking_vertex">引發頂點</string>
|
||||
<string name="provoking_vertex_description">改善某些遊戲中的光照和頂點處理。僅支援Vulkan 1.0+ GPU。</string>
|
||||
<string name="descriptor_indexing">描述符索引</string>
|
||||
|
||||
@@ -632,14 +632,12 @@
|
||||
<item>@string/disabled</item>
|
||||
<item>ExtendedDynamicState 1</item>
|
||||
<item>ExtendedDynamicState 2</item>
|
||||
<item>ExtendedDynamicState 3</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="dynaStateValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="installKeysResults">
|
||||
|
||||
@@ -531,8 +531,6 @@
|
||||
<string name="dyna_state">Extended Dynamic State</string>
|
||||
<string name="dyna_state_description">Controls the number of features that can be used in Extended Dynamic State. Higher numbers allow for more features and can increase performance, but may cause issues with some drivers and vendors.</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Enables vertex input dynamic state feature for better quality and performance.</string>
|
||||
<string name="provoking_vertex">Provoking Vertex</string>
|
||||
<string name="provoking_vertex_description">Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs.</string>
|
||||
<string name="descriptor_indexing">Descriptor Indexing</string>
|
||||
|
||||
@@ -191,22 +191,6 @@
|
||||
<item name="android:textColor">@color/eden_primary</item>
|
||||
<item name="rippleColor">@color/eden_glow_pink</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Eden.TransparentTopAppBarLayout" parent="">
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
<item name="android:elevation">0dp</item>
|
||||
<item name="android:stateListAnimator">@null</item>
|
||||
<item name="elevation">0dp</item>
|
||||
<item name="liftOnScroll">false</item>
|
||||
<item name="statusBarForeground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Eden.TransparentTopToolbar" parent="">
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
<item name="android:elevation">0dp</item>
|
||||
<item name="backgroundTint">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="EdenPopupMenu" parent="Widget.Material3.PopupMenu">
|
||||
<item name="android:popupBackground">@drawable/popup_menu_background</item>
|
||||
</style>
|
||||
|
||||
@@ -516,7 +516,7 @@ namespace Common::Android {
|
||||
s_patch_class = reinterpret_cast<jclass>(env->NewGlobalRef(patch_class));
|
||||
s_patch_constructor = env->GetMethodID(
|
||||
patch_class, "<init>",
|
||||
"(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JI)V");
|
||||
"(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;J)V");
|
||||
s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z");
|
||||
s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;");
|
||||
s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;");
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/time_zone.h"
|
||||
|
||||
#if defined(__linux__ ) && defined(ARCHITECTURE_arm64)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace Settings {
|
||||
|
||||
// Clang 14 and earlier have errors when explicitly instantiating these classes
|
||||
@@ -182,11 +178,7 @@ bool IsFastmemEnabled() {
|
||||
return bool(values.cpuopt_fastmem);
|
||||
else if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe)
|
||||
return bool(values.cpuopt_unsafe_host_mmu);
|
||||
#if defined(__linux__) && defined(ARCHITECTURE_arm64)
|
||||
// Only 4kb systems support host MMU right now
|
||||
// TODO: Support this
|
||||
return getpagesize() == 4096;
|
||||
#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__)
|
||||
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
|
||||
+2
-12
@@ -453,7 +453,7 @@ struct Values {
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||
#ifdef ANDROID
|
||||
AstcDecodeMode::Cpu,
|
||||
AstcDecodeMode::Gpu,
|
||||
#else
|
||||
AstcDecodeMode::Gpu,
|
||||
#endif
|
||||
@@ -586,7 +586,7 @@ struct Values {
|
||||
|
||||
SwitchableSetting<ExtendedDynamicState> dyna_state{linkage,
|
||||
#if defined (ANDROID) || defined (__APPLE__)
|
||||
ExtendedDynamicState::Disabled,
|
||||
ExtendedDynamicState::EDS1,
|
||||
#else
|
||||
ExtendedDynamicState::EDS2,
|
||||
#endif
|
||||
@@ -601,14 +601,6 @@ struct Values {
|
||||
Category::RendererExtensions,
|
||||
Specialization::Scalar};
|
||||
|
||||
SwitchableSetting<bool> vertex_input_dynamic_state{linkage,
|
||||
#if defined (ANDROID)
|
||||
false,
|
||||
#else
|
||||
true,
|
||||
#endif
|
||||
"vertex_input_dynamic_state", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
|
||||
|
||||
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
||||
@@ -706,7 +698,6 @@ struct Values {
|
||||
Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls};
|
||||
Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls};
|
||||
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
||||
Setting<bool> tas_show_recording_dialog{linkage, true, "tas_show_recording_dialog", Category::Controls};
|
||||
|
||||
Setting<bool> mouse_panning{
|
||||
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
||||
@@ -777,7 +768,6 @@ struct Values {
|
||||
Setting<bool> reporting_services{
|
||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Debugging};
|
||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
||||
|
||||
@@ -154,7 +154,7 @@ ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
|
||||
ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(TemperatureUnits, Celsius, Fahrenheit)
|
||||
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
|
||||
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2);
|
||||
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
|
||||
ENUM(GameListMode, TreeView, GridView);
|
||||
ENUM(SpeedMode, Standard, Turbo, Slow);
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
#include <windows.h>
|
||||
#include "common/string_util.h"
|
||||
#else
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_cpuset.h>
|
||||
#include <pthread_np.h>
|
||||
#elif defined(__DragonFly__) || defined(__OpenBSD__) || defined(__Bitrig__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
@@ -1220,7 +1220,7 @@ target_link_libraries(core PRIVATE
|
||||
RenderDoc::API
|
||||
ZLIB::ZLIB)
|
||||
|
||||
target_link_libraries(core PUBLIC httplib::httplib zstd::zstd)
|
||||
target_link_libraries(core PRIVATE httplib::httplib)
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE)
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/crypto/aes_util.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
@@ -643,15 +642,8 @@ void KeyManager::ReloadKeys() {
|
||||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
if (!Common::FS::CreateDir(keys_dir))
|
||||
LOG_ERROR(Core, "Failed to create the keys directory.");
|
||||
if (Settings::values.use_dev_keys.GetValue()) {
|
||||
dev_mode = true;
|
||||
LoadFromFile(keys_dir / "dev.keys_autogenerated", false);
|
||||
LoadFromFile(keys_dir / "dev.keys", false);
|
||||
} else {
|
||||
dev_mode = false;
|
||||
LoadFromFile(keys_dir / "prod.keys_autogenerated", false);
|
||||
LoadFromFile(keys_dir / "prod.keys", false);
|
||||
}
|
||||
LoadFromFile(keys_dir / "prod.keys_autogenerated", false);
|
||||
LoadFromFile(keys_dir / "prod.keys", false);
|
||||
LoadFromFile(keys_dir / "title.keys_autogenerated", true);
|
||||
LoadFromFile(keys_dir / "title.keys", true);
|
||||
LoadFromFile(keys_dir / "console.keys_autogenerated", false);
|
||||
@@ -846,7 +838,7 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
|
||||
|
||||
std::string filename = "title.keys_autogenerated";
|
||||
if (category == KeyCategory::Standard) {
|
||||
filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated";
|
||||
filename = "prod.keys_autogenerated";
|
||||
} else if (category == KeyCategory::Console) {
|
||||
filename = "console.keys_autogenerated";
|
||||
}
|
||||
@@ -944,8 +936,6 @@ bool KeyManager::KeyFileExists(bool title) {
|
||||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
if (title)
|
||||
return Common::FS::Exists(keys_dir / "title.keys");
|
||||
if (Settings::values.use_dev_keys.GetValue())
|
||||
return Common::FS::Exists(keys_dir / "dev.keys");
|
||||
return Common::FS::Exists(keys_dir / "prod.keys");
|
||||
}
|
||||
|
||||
|
||||
@@ -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 2018 yuzu Emulator Project
|
||||
@@ -314,7 +314,6 @@ private:
|
||||
std::array<u8, 576> eticket_extended_kek{};
|
||||
RSAKeyPair<2048> eticket_rsa_keypair{};
|
||||
|
||||
bool dev_mode;
|
||||
void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys);
|
||||
|
||||
template <size_t Size>
|
||||
|
||||
@@ -76,16 +76,16 @@ public:
|
||||
|
||||
template <typename Func>
|
||||
void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
|
||||
DAddr subbits = DAddr(address & page_mask);
|
||||
DAddr subbits = static_cast<DAddr>(address & page_mask);
|
||||
const u32 base = compressed_device_addr[(address >> page_bits)];
|
||||
if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||
const DAddr d_address = (DAddr(base) << page_bits) + subbits;
|
||||
const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits;
|
||||
operation(d_address);
|
||||
return;
|
||||
}
|
||||
InnerGatherDeviceAddresses(buffer, address);
|
||||
for (u32 value : buffer) {
|
||||
operation((DAddr(value) << page_bits) + subbits);
|
||||
operation((static_cast<DAddr>(value) << page_bits) + subbits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,12 +96,12 @@ public:
|
||||
}
|
||||
|
||||
PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const {
|
||||
PAddr subbits = PAddr(address & page_mask);
|
||||
auto paddr = tracked_entries[(address >> page_bits)].compressed_physical_ptr;
|
||||
PAddr subbits = static_cast<PAddr>(address & page_mask);
|
||||
auto paddr = compressed_physical_ptr[(address >> page_bits)];
|
||||
if (paddr == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (PAddr(paddr - 1) << page_bits) + subbits;
|
||||
return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -172,14 +172,9 @@ private:
|
||||
|
||||
const uintptr_t physical_base;
|
||||
DeviceInterface* device_inter;
|
||||
|
||||
struct TrackedEntry {
|
||||
VAddr cpu_backing_address;
|
||||
u32 continuity_tracker;
|
||||
u32 compressed_physical_ptr;
|
||||
};
|
||||
Common::VirtualBuffer<u32> compressed_physical_ptr;
|
||||
Common::VirtualBuffer<u32> compressed_device_addr;
|
||||
Common::VirtualBuffer<TrackedEntry> tracked_entries;
|
||||
Common::VirtualBuffer<u32> continuity_tracker;
|
||||
|
||||
// Process memory interfaces
|
||||
|
||||
@@ -194,16 +189,17 @@ private:
|
||||
static constexpr size_t asid_start_bit = guest_max_as_bits;
|
||||
|
||||
std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
|
||||
auto content = tracked_entries[page_index].cpu_backing_address;
|
||||
auto content = cpu_backing_address[page_index];
|
||||
const VAddr address = content & guest_mask;
|
||||
const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
|
||||
return std::make_pair(asid, address);
|
||||
}
|
||||
|
||||
void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
|
||||
tracked_entries[page_index].cpu_backing_address = address | (asid.id << asid_start_bit);
|
||||
cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
std::array<TranslationEntry, 4> t_slot{};
|
||||
u32 cache_cursor = 0;
|
||||
using CounterType = u8;
|
||||
|
||||
@@ -166,21 +166,29 @@ struct DeviceMemoryManagerAllocator {
|
||||
|
||||
template <typename Traits>
|
||||
DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
|
||||
: physical_base{uintptr_t(device_memory_.buffer.BackingBasePointer())}
|
||||
, device_inter{nullptr}
|
||||
, compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS))
|
||||
, tracked_entries(device_as_size >> Memory::YUZU_PAGEBITS)
|
||||
{
|
||||
: physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
|
||||
device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||
compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||
Settings::MemoryLayout::Memory_4Gb
|
||||
? physical_min_bits
|
||||
: physical_max_bits) -
|
||||
Memory::YUZU_PAGEBITS)),
|
||||
continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||
cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
|
||||
impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
|
||||
cached_pages = std::make_unique<CachedPages>();
|
||||
|
||||
const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS;
|
||||
for (size_t i = 0; i < total_virtual; i++) {
|
||||
tracked_entries[i].compressed_physical_ptr = 0;
|
||||
tracked_entries[i].continuity_tracker = 1;
|
||||
tracked_entries[i].cpu_backing_address = 0;
|
||||
compressed_physical_ptr[i] = 0;
|
||||
continuity_tracker[i] = 1;
|
||||
cpu_backing_address[i] = 0;
|
||||
}
|
||||
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS);
|
||||
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||
Settings::MemoryLayout::Memory_4Gb
|
||||
? physical_min_bits
|
||||
: physical_max_bits) -
|
||||
Memory::YUZU_PAGEBITS);
|
||||
for (size_t i = 0; i < total_phys; i++) {
|
||||
compressed_device_addr[i] = 0;
|
||||
}
|
||||
@@ -220,11 +228,11 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
|
||||
const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE;
|
||||
auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress));
|
||||
if (ptr == nullptr) [[unlikely]] {
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
|
||||
compressed_physical_ptr[start_page_d + i] = 0;
|
||||
continue;
|
||||
}
|
||||
auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = phys_addr;
|
||||
compressed_physical_ptr[start_page_d + i] = phys_addr;
|
||||
InsertCPUBacking(start_page_d + i, new_vaddress, asid);
|
||||
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||
const u32 new_dev = static_cast<u32>(start_page_d + i);
|
||||
@@ -252,9 +260,9 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
|
||||
device_inter->InvalidateRegion(address, size);
|
||||
std::scoped_lock lk(mapping_guard);
|
||||
for (size_t i = 0; i < num_pages; i++) {
|
||||
auto phys_addr = tracked_entries[start_page_d + i].compressed_physical_ptr;
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
|
||||
tracked_entries[start_page_d + i].cpu_backing_address = 0;
|
||||
auto phys_addr = compressed_physical_ptr[start_page_d + i];
|
||||
compressed_physical_ptr[start_page_d + i] = 0;
|
||||
cpu_backing_address[start_page_d + i] = 0;
|
||||
if (phys_addr != 0) [[likely]] {
|
||||
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||
if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||
@@ -292,14 +300,14 @@ void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtu
|
||||
page_count = 1;
|
||||
}
|
||||
last_ptr = new_ptr;
|
||||
tracked_entries[start_page_d + index].continuity_tracker = static_cast<u32>(page_count);
|
||||
continuity_tracker[start_page_d + index] = static_cast<u32>(page_count);
|
||||
}
|
||||
}
|
||||
template <typename Traits>
|
||||
u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) {
|
||||
size_t page_index = src_addr >> page_bits;
|
||||
size_t subbits = src_addr & page_mask;
|
||||
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
|
||||
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||
return GetPointer<u8>(src_addr);
|
||||
}
|
||||
return nullptr;
|
||||
@@ -309,7 +317,7 @@ template <typename Traits>
|
||||
const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const {
|
||||
size_t page_index = src_addr >> page_bits;
|
||||
size_t subbits = src_addr & page_mask;
|
||||
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
|
||||
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||
return GetPointer<u8>(src_addr);
|
||||
}
|
||||
return nullptr;
|
||||
@@ -334,10 +342,12 @@ template <typename T>
|
||||
T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) {
|
||||
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
|
||||
if (phys_addr == 0) [[unlikely]]
|
||||
auto phys_addr = compressed_physical_ptr[index];
|
||||
if (phys_addr == 0) [[unlikely]] {
|
||||
return nullptr;
|
||||
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
|
||||
}
|
||||
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||
offset);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
@@ -345,10 +355,12 @@ template <typename T>
|
||||
const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const {
|
||||
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
|
||||
if (phys_addr == 0)
|
||||
auto phys_addr = compressed_physical_ptr[index];
|
||||
if (phys_addr == 0) [[unlikely]] {
|
||||
return nullptr;
|
||||
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
|
||||
}
|
||||
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||
offset);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
@@ -374,14 +386,18 @@ T DeviceMemoryManager<Traits>::Read(DAddr address) const {
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped, auto on_memory, auto increment) {
|
||||
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped,
|
||||
auto on_memory, auto increment) {
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = addr >> Memory::YUZU_PAGEBITS;
|
||||
std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
|
||||
|
||||
while (remaining_size) {
|
||||
const size_t next_pages = std::size_t(tracked_entries[page_index].continuity_tracker);
|
||||
const std::size_t copy_amount = (std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
|
||||
const auto current_vaddr = u64((page_index << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
|
||||
const std::size_t copy_amount =
|
||||
(std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
|
||||
const auto current_vaddr =
|
||||
static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
SCOPE_EXIT{
|
||||
page_index += next_pages;
|
||||
page_offset = 0;
|
||||
@@ -389,12 +405,13 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
|
||||
remaining_size -= copy_amount;
|
||||
};
|
||||
|
||||
auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
auto phys_addr = compressed_physical_ptr[page_index];
|
||||
if (phys_addr == 0) {
|
||||
on_unmapped(copy_amount, current_vaddr);
|
||||
continue;
|
||||
}
|
||||
auto* mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
auto* mem_ptr = GetPointerFromRaw<u8>(
|
||||
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
on_memory(copy_amount, mem_ptr);
|
||||
}
|
||||
}
|
||||
@@ -413,7 +430,7 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s
|
||||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
@@ -471,7 +488,7 @@ void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_poin
|
||||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
|
||||
@@ -123,39 +123,6 @@ bool IsVersionedExternalUpdateDisabled(const std::vector<std::string>& disabled,
|
||||
return std::find(disabled.cbegin(), disabled.cend(), disabled_key) != disabled.cend() ||
|
||||
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
|
||||
}
|
||||
|
||||
std::string GetUpdateVersionStringFromSlot(const ContentProvider* provider, u64 update_tid) {
|
||||
if (provider == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto control_nca = provider->GetEntry(update_tid, ContentRecordType::Control);
|
||||
if (control_nca == nullptr ||
|
||||
control_nca->GetStatus() != Loader::ResultStatus::Success) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto romfs = control_nca->GetRomFS();
|
||||
if (romfs == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto extracted = ExtractRomFS(romfs);
|
||||
if (extracted == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto nacp_file = extracted->GetFile("control.nacp");
|
||||
if (nacp_file == nullptr) {
|
||||
nacp_file = extracted->GetFile("Control.nacp");
|
||||
}
|
||||
if (nacp_file == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
NACP nacp{nacp_file};
|
||||
return nacp.GetVersionString();
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
PatchManager::PatchManager(u64 title_id_,
|
||||
@@ -804,7 +771,6 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
||||
std::nullopt, std::nullopt, ContentRecordType::Program, update_tid);
|
||||
|
||||
for (const auto& [slot, entry] : all_updates) {
|
||||
(void)entry;
|
||||
if (slot == ContentProviderUnionSlot::External ||
|
||||
slot == ContentProviderUnionSlot::FrontendManual) {
|
||||
continue;
|
||||
@@ -820,7 +786,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
||||
source_suffix = " (NAND)";
|
||||
break;
|
||||
case ContentProviderUnionSlot::SDMC:
|
||||
source_type = PatchSource::SDMC;
|
||||
source_type = PatchSource::NAND;
|
||||
source_suffix = " (SDMC)";
|
||||
break;
|
||||
default:
|
||||
@@ -829,16 +795,19 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
||||
|
||||
std::string version_str;
|
||||
u32 numeric_ver = 0;
|
||||
const auto* slot_provider = content_union->GetSlotProvider(slot);
|
||||
version_str = GetUpdateVersionStringFromSlot(slot_provider, update_tid);
|
||||
PatchManager update{update_tid, fs_controller, content_provider};
|
||||
const auto metadata = update.GetControlMetadata();
|
||||
const auto& nacp = metadata.first;
|
||||
|
||||
if (slot_provider != nullptr) {
|
||||
const auto slot_ver = slot_provider->GetEntryVersion(update_tid);
|
||||
if (slot_ver.has_value()) {
|
||||
numeric_ver = *slot_ver;
|
||||
if (version_str.empty() && numeric_ver != 0) {
|
||||
version_str = FormatTitleVersion(numeric_ver);
|
||||
}
|
||||
if (nacp != nullptr) {
|
||||
version_str = nacp->GetVersionString();
|
||||
}
|
||||
|
||||
const auto meta_ver = content_provider.GetEntryVersion(update_tid);
|
||||
if (meta_ver.has_value()) {
|
||||
numeric_ver = *meta_ver;
|
||||
if (version_str.empty() && numeric_ver != 0) {
|
||||
version_str = FormatTitleVersion(numeric_ver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,60 +956,37 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
||||
}
|
||||
|
||||
// DLC
|
||||
const auto dlc_entries =
|
||||
content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
|
||||
|
||||
std::vector<ContentProviderEntry> dlc_match;
|
||||
bool has_external_dlc = false;
|
||||
bool has_nand_dlc = false;
|
||||
bool has_sdmc_dlc = false;
|
||||
bool has_other_dlc = false;
|
||||
const auto dlc_entries_with_origin =
|
||||
content_union->ListEntriesFilterOrigin(std::nullopt, TitleType::AOC, ContentRecordType::Data);
|
||||
dlc_match.reserve(dlc_entries.size());
|
||||
std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
|
||||
[this](const ContentProviderEntry& entry) {
|
||||
const auto base_tid = GetBaseTitleID(entry.title_id);
|
||||
const bool matches_base = base_tid == title_id;
|
||||
|
||||
dlc_match.reserve(dlc_entries_with_origin.size());
|
||||
for (const auto& [slot, entry] : dlc_entries_with_origin) {
|
||||
const auto base_tid = GetBaseTitleID(entry.title_id);
|
||||
const bool matches_base = base_tid == title_id;
|
||||
if (!matches_base) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} base {:016X} doesn't match title {:016X}",
|
||||
entry.title_id, base_tid, title_id);
|
||||
continue;
|
||||
}
|
||||
if (!matches_base) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} base {:016X} doesn't match title {:016X}",
|
||||
entry.title_id, base_tid, title_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* slot_provider = content_union->GetSlotProvider(slot);
|
||||
if (slot_provider == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto nca = content_provider.GetEntry(entry);
|
||||
if (!nca) {
|
||||
LOG_DEBUG(Loader, "Failed to get NCA for DLC {:016X}", entry.title_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto nca = slot_provider->GetEntry(entry);
|
||||
if (!nca) {
|
||||
LOG_DEBUG(Loader, "Failed to get NCA for DLC {:016X}", entry.title_id);
|
||||
continue;
|
||||
}
|
||||
const auto status = nca->GetStatus();
|
||||
if (status != Loader::ResultStatus::Success) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} NCA has status {}",
|
||||
entry.title_id, static_cast<int>(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto status = nca->GetStatus();
|
||||
if (status != Loader::ResultStatus::Success) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} NCA has status {}", entry.title_id,
|
||||
static_cast<int>(status));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (slot) {
|
||||
case ContentProviderUnionSlot::External:
|
||||
case ContentProviderUnionSlot::FrontendManual:
|
||||
has_external_dlc = true;
|
||||
break;
|
||||
case ContentProviderUnionSlot::UserNAND:
|
||||
case ContentProviderUnionSlot::SysNAND:
|
||||
has_nand_dlc = true;
|
||||
break;
|
||||
case ContentProviderUnionSlot::SDMC:
|
||||
has_sdmc_dlc = true;
|
||||
break;
|
||||
default:
|
||||
has_other_dlc = true;
|
||||
break;
|
||||
}
|
||||
dlc_match.push_back(entry);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!dlc_match.empty()) {
|
||||
// Ensure sorted so DLC IDs show in order.
|
||||
@@ -1054,22 +1000,13 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
||||
|
||||
const auto dlc_disabled =
|
||||
std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end();
|
||||
PatchSource dlc_source = PatchSource::Unknown;
|
||||
if (has_external_dlc && !has_nand_dlc && !has_sdmc_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::External;
|
||||
} else if (has_nand_dlc && !has_external_dlc && !has_sdmc_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::NAND;
|
||||
} else if (has_sdmc_dlc && !has_external_dlc && !has_nand_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::SDMC;
|
||||
}
|
||||
|
||||
out.push_back({.enabled = !dlc_disabled,
|
||||
.name = "DLC",
|
||||
.version = std::move(list),
|
||||
.type = PatchType::DLC,
|
||||
.program_id = title_id,
|
||||
.title_id = dlc_match.back().title_id,
|
||||
.source = dlc_source});
|
||||
.source = PatchSource::Unknown});
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
@@ -34,7 +34,6 @@ enum class PatchType { Update, DLC, Mod };
|
||||
enum class PatchSource {
|
||||
Unknown,
|
||||
NAND,
|
||||
SDMC,
|
||||
External,
|
||||
Packed,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -21,14 +18,17 @@ namespace Service::Audio {
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
|
||||
server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
|
||||
server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
|
||||
// Depends on audout:u and audin:u on ctor!
|
||||
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
|
||||
server_manager->RegisterNamedService("audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
|
||||
server_manager->RegisterNamedService("audrec:u", std::make_shared<IFinalOutputRecorderManager>(system));
|
||||
server_manager->RegisterNamedService("audren:u", std::make_shared<IAudioRendererManager>(system));
|
||||
server_manager->RegisterNamedService("hwopus", std::make_shared<IHardwareOpusDecoderManager>(system));
|
||||
server_manager->RegisterNamedService(
|
||||
"audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
|
||||
server_manager->RegisterNamedService("audrec:u",
|
||||
std::make_shared<IFinalOutputRecorderManager>(system));
|
||||
server_manager->RegisterNamedService("audren:u",
|
||||
std::make_shared<IAudioRendererManager>(system));
|
||||
server_manager->RegisterNamedService("hwopus",
|
||||
std::make_shared<IHardwareOpusDecoderManager>(system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -107,8 +104,7 @@ Result TimeZoneService::LoadLocationNameList(
|
||||
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
|
||||
index, *out_count, out_names.size() > 0 ? out_names[0] : Service::PSC::Time::LocationName{},
|
||||
out_names.size() > 1 ? out_names[1] : Service::PSC::Time::LocationName{});
|
||||
index, *out_count, out_names[0], out_names[1]);
|
||||
};
|
||||
|
||||
std::scoped_lock l{m_mutex};
|
||||
@@ -212,8 +208,7 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
};
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
|
||||
@@ -225,8 +220,7 @@ Result TimeZoneService::ToPosixTimeWithMyRule(
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
};
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -151,8 +148,7 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
};
|
||||
|
||||
R_RETURN(
|
||||
@@ -165,8 +161,7 @@ Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
};
|
||||
|
||||
R_RETURN(
|
||||
|
||||
@@ -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 2018 yuzu Emulator Project
|
||||
@@ -29,13 +29,10 @@ namespace Service {
|
||||
return function_string;
|
||||
}
|
||||
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_)
|
||||
, system{system_}
|
||||
, service_name{service_name_}
|
||||
, handler_invoker{handler_invoker_}
|
||||
, max_sessions{max_sessions_}
|
||||
{}
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
||||
u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
|
||||
service_name{service_name_}, handler_invoker{handler_invoker_}, max_sessions{max_sessions_} {}
|
||||
|
||||
ServiceFrameworkBase::~ServiceFrameworkBase() {
|
||||
// Wait for other threads to release access before destroying
|
||||
@@ -53,7 +50,8 @@ void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* func
|
||||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
handlers_tipc.reserve(handlers_tipc.size() + n);
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]);
|
||||
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header,
|
||||
functions[i]);
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user