Compare commits

...

155 Commits

Author SHA1 Message Date
a9e31e7261 Android 268 2024-02-25 00:57:12 +00:00
7821ae4d43 Merge yuzu-emu#13154 2024-02-25 00:57:12 +00:00
d2ee9c6056 Merge yuzu-emu#13096 2024-02-25 00:57:12 +00:00
46668db138 Merge yuzu-emu#12749 2024-02-25 00:57:11 +00:00
f872f4c2b0 Merge yuzu-emu#12461 2024-02-25 00:57:11 +00:00
a93d249ac1 Merge pull request #13155 from german77/GetSettingsItemValue
service: set: Fix GetSettingsItemValue
2024-02-24 16:24:01 -05:00
9fccccedee service: set: Fix GetSettingsItemValue 2024-02-24 14:44:21 -06:00
05f94dc5fc Merge pull request #13153 from german77/defaultset
service: set: Enable nfc and others by default and bump version
2024-02-24 12:48:31 -05:00
dcf7698924 Merge pull request #13081 from FearlessTobi/aoc-ipc
aoc: Migrate to use cmif serialization
2024-02-24 12:48:26 -05:00
7b68d7d467 Merge pull request #13150 from liamwhite/region
set: fix region code for system settings
2024-02-24 11:40:31 -06:00
4741e50047 service: set: Enable nfc and others by default and bump version 2024-02-24 11:19:51 -06:00
7836c0867d set: fix region code for system settings 2024-02-24 00:48:44 -05:00
d1e0039bc8 Merge pull request #13142 from t895/vibration-queue
android: Play vibrations asynchronously
2024-02-24 00:38:13 -05:00
7a51eaa727 Merge pull request #13146 from wheremyfoodat/patch-1
common/ring_buffer: Include <limits> header
2024-02-23 20:32:40 -05:00
6c40d75e47 Merge pull request #13140 from german77/yet-more-qlaunch
service: Stub multiple function for qlaunch
2024-02-23 20:32:32 -05:00
0a0c257206 service: audio: Add missing logging properties of SetHeadphoneOutputLevelMode 2024-02-23 18:58:51 -06:00
7019023cbc service: btdrv: Add EnableRadio for Qlaunch 2024-02-23 18:58:51 -06:00
c48c182fe0 service: friend: Add GetFriendCount, GetNewlyFriendCount, GetReceivedFriendRequestCount, GetPlayHistoryStatistics, GetReceivedFriendInvitationCountCache for QLaunch 2024-02-23 18:58:51 -06:00
98be02898b service: hid: Add IsAnyCustomButtonConfigEnabled for QLaunch 2024-02-23 18:58:51 -06:00
e1bdeb2942 service: lbl: Add SaveCurrentSetting, LoadCurrentSetting and IsAutoBrightnessControlSupported for QLaunch 2024-02-23 18:58:50 -06:00
015d666a4d service: nfc: Implement SetNfcEnabled 2024-02-23 18:58:50 -06:00
624c90a439 service: npns: Add ListenTo and GetReceiveEvent for QLaunch 2024-02-23 18:58:39 -06:00
0fb26acccc service: set: Add default eula setting 2024-02-23 18:58:19 -06:00
ed315fb8a5 common/ring_buffer: Include <limits> header 2024-02-24 02:34:09 +02:00
0369c65870 android: Play vibrations asynchronously 2024-02-23 16:41:59 -05:00
975d6f1ec4 Merge pull request #13141 from liamwhite/swap
fs: fix argument order
2024-02-23 15:23:06 -05:00
7c9e2255be Merge pull request #13137 from liamwhite/mac-ci
ci: fix mac build
2024-02-23 15:21:18 -05:00
9f6818a6e5 Merge pull request #13136 from liamwhite/fs-launch
fs: add ISaveDataTransferProhibiter, stub FindSaveDataWithFilter
2024-02-23 15:21:12 -05:00
f1c16b487a fs: fix argument order 2024-02-23 15:10:35 -05:00
6512f39061 ci: fix mac build 2024-02-23 13:25:48 -05:00
22b91afa69 fs: add ISaveDataTransferProhibiter, stub FindSaveDataWithFilter 2024-02-23 12:17:24 -05:00
77107ba124 Merge pull request #13133 from liamwhite/libstdcxx-issue
vi: workaround conductor includes
2024-02-23 11:34:34 -05:00
fa4dec9fe9 Merge pull request #13115 from liamwhite/olsc-pctl
olsc, pctl: move to new ipc
2024-02-23 11:34:29 -05:00
215e887be0 Merge pull request #13100 from liamwhite/audio-ipc
audio: move to new ipc
2024-02-23 11:34:21 -05:00
0da6704fc2 Merge pull request #13073 from FearlessTobi/fsp-srv-ipc
fsp: Migrate remaining interfaces to cmif serialization
2024-02-23 11:34:06 -05:00
812754edec vi: workaround conductor includes 2024-02-23 10:34:49 -05:00
964e19ab56 oboe_sink: handle temporary stream creation failure 2024-02-23 10:30:52 -05:00
9dc624f5dc Merge pull request #13121 from german77/clean-shortcut
yuzu: Fix shortcut error message
2024-02-22 23:04:28 -05:00
dad9ea3e07 Merge pull request #13117 from liamwhite/ovln
psc: stub overlay notification channel
2024-02-22 20:26:03 -05:00
2c00599a53 audio: fix released buffer bounds check 2024-02-22 20:20:31 -05:00
2786d34dd7 aoc: Rename AOC_U to IAddOnContentManager 2024-02-23 01:19:18 +01:00
864b046500 yuzu: Fix shortcut error message 2024-02-22 17:52:30 -06:00
d12d9dad40 Merge pull request #12982 from FearlessTobi/fs-rewrite-part0
fs: Add FileSystemAccessor and use cmif serialization
2024-02-22 12:34:47 -05:00
2b3f1d3fc5 Merge pull request #13000 from liamwhite/skip-null-memory
device_memory_manager: skip unregistered interfaces on invalidate
2024-02-22 11:34:23 -06:00
984396a21a Merge pull request #13001 from liamwhite/scaled-availability
vulkan_device: don't use fixed cap for memory limits
2024-02-22 11:31:17 -06:00
4f95ee5209 Merge pull request #13075 from liamwhite/mali-having-a-bad-time
shader_recompiler: throw on missing geometry streams in geometry shaders
2024-02-22 11:30:26 -06:00
c04567fad4 audio: add NotifyHeadphoneVolumeWarningDisplayedEvent 2024-02-21 23:54:10 -05:00
89c2fd3d28 pctl: rewrite IParentalControlService 2024-02-21 23:42:33 -05:00
5ab49c833d pctl: rewrite IParentalControlServiceFactory 2024-02-21 23:00:01 -05:00
0e74204aad pctl: move IParentalControlServiceFactory 2024-02-21 23:00:01 -05:00
a37bd0b9a7 pctl: move IParentalControlService 2024-02-21 23:00:01 -05:00
01d89acd13 pctl: move types and results 2024-02-21 22:58:20 -05:00
e85466c1ae psc: stub overlay notification channel 2024-02-21 22:54:05 -05:00
352297d361 psc: rewrite IPmService 2024-02-21 22:26:32 -05:00
6c2d6cff19 psc: move IPmControl, IPmModule, IPmService 2024-02-21 22:26:12 -05:00
e540757279 olsc: rewrite IOlscServiceForSystemService 2024-02-21 20:02:00 -05:00
a8bca24292 olsc: add IRemoteStorageController 2024-02-21 19:47:54 -05:00
5f3c03d6a8 olsc: add IDaemonController 2024-02-21 19:05:19 -05:00
6b956a6951 olsc: rewrite ITransferTaskListController 2024-02-21 18:36:17 -05:00
8689370830 olsc: rewrite INativeHandleHolder 2024-02-21 18:19:48 -05:00
8ffa27b311 olsc: rewrite IOlscServiceForApplication 2024-02-21 18:19:12 -05:00
6334616b44 olsc: move INativeHandleHolder, IOlscServiceForApplication, IOlscServiceForSystemService, ITransferTaskListController 2024-02-21 16:13:01 -05:00
8bbc209950 Merge pull request #13105 from t895/connection-fix
android: Misc controller fixes
2024-02-21 10:43:46 -05:00
9e1a67b950 fs: add missing mutex header for member (#13106) 2024-02-21 16:43:05 +01:00
de5422b1fd android: Connect controllers with supported styles
If you tried to connect a controller that was previously configured with an unsupported style for your game, when you try to connect that controller, it will immediately disconnect. This ensures that the controller that is being connected will be changed to the first supported style index before being connected.
2024-02-21 08:37:55 -05:00
45f450fca5 android: Add additional check for hasMapping
Controls can have no mapping if they are either "[empty]" or and empty string. This was causing an issue if you reset mapping on all controllers and then tried to play a game. The check to determine whether auto mapping was required would fail and leave you will no mapped controllers. This feels a bit like user error but it smooths things out if you forget so I see it as necessary.
2024-02-21 08:17:30 -05:00
9a3fd76b25 android: Enable all controller styles on emulation shutdown 2024-02-21 08:13:54 -05:00
60fc6df407 Merge pull request #13099 from t895/default-fix
android: Fix extra stick setting default values
2024-02-21 07:02:58 -05:00
2e4a6b7f92 audio: format 2024-02-20 22:51:39 -05:00
5f90bd88da audio: rewrite IHardwareOpusDecoder 2024-02-20 22:15:38 -05:00
c575a85233 audio: rewrite IAudioDevice 2024-02-20 22:15:38 -05:00
ea4703cb31 audio: rewrite IHardwareOpusDecoderManager 2024-02-20 22:15:38 -05:00
0471e54e5a audio: rewrite IAudioRenderer 2024-02-20 22:15:38 -05:00
6012c9fe3a audio: rewrite IAudioRendererManager 2024-02-20 22:15:37 -05:00
f65539504f audio: split IHardwarweOpusDecoder, move IHardwareOpusDecoderManager 2024-02-20 22:15:37 -05:00
62083fcafd audio: split IAudioDevice, IAudioRenderer, move IAudioRendererManager 2024-02-20 22:15:37 -05:00
2e5a9cf119 audio: move IFinalOutputRecorderManager{,ForApplet} 2024-02-20 22:15:37 -05:00
a45b8bc9bc audio: rewrite IAudioOutManager 2024-02-20 22:15:37 -05:00
a05bd3c47e audio: rewrite IAudioOut 2024-02-20 22:15:37 -05:00
2a2c92f181 audio: rewrite IAudioInManager 2024-02-20 22:15:37 -05:00
f54277364c audio: rewrite IAudioIn 2024-02-20 22:15:37 -05:00
de2d496e71 android: Fix extra stick setting default values
The default value was accidentally hardcoded for all extra stick settings
2024-02-20 22:13:59 -05:00
7b5bdd076d Merge pull request #13095 from liamwhite/ns-oops
ns: fix alignment of uid type
2024-02-20 21:19:35 -05:00
e0c17a2113 Merge pull request #10529 from liamwhite/critical-spacing
caches: make critical reclamation less eager and possible in more cases
2024-02-20 23:19:27 -03:00
b107435a3f ns: fix alignment of uid type 2024-02-20 18:43:44 -05:00
4e1fcd4a63 Merge pull request #13091 from t895/device-renaming
android: Expose device name setting
2024-02-20 18:30:54 -05:00
ea4a96b45e Merge pull request #13079 from liamwhite/vi3
vi: misc fixes
2024-02-20 18:30:47 -05:00
6a90db8c19 android: Expose device name setting 2024-02-20 08:16:38 -05:00
0e5972b0b5 android: Add StringInputSetting settings item 2024-02-20 08:06:56 -05:00
5f7608a7c6 vi: ignore shared buffer destruction failure on termination 2024-02-20 00:02:56 -05:00
668ff0db3a vi: remove superfluous locking in shared buffer manager 2024-02-19 23:59:35 -05:00
9f159dd62c nvnflinger/vi: don't recreate buffer queue on open/close 2024-02-19 23:59:35 -05:00
d1eaeeed8c Import keys from filesystem. (#13056)
* Import keys, re-initialize KeyManager, re-scan vfs, re-populate game list.

* <.< spelling.

* Update based on feedback on #13047 and this PR

* Based on feedback: Don't delete existing files. There's legitimate reasons that someone may want to keep their retail keys and title key handling is resilient to mismatches.

* Update src/yuzu/main.cpp

Co-authored-by: Tobias <thm.frey@gmail.com>

* Remove translation of literal filename/filter format.

* clang-format.

---------

Co-authored-by: Tobias <thm.frey@gmail.com>
2024-02-19 19:18:13 -05:00
10e27a2902 Merge pull request #13086 from t895/clear-button-fix
android: Fix broken clear button check
2024-02-19 19:18:05 -05:00
f567a41f53 android: Have input overlay follow player 1 style index (#13085) 2024-02-19 22:47:21 +01:00
704c62ca01 android: Fix broken clear button check 2024-02-19 15:54:52 -05:00
8d5473e67c Merge pull request #13031 from german77/btm-interfcae
service: btm: Migrate service to new IPC
2024-02-19 14:49:42 -05:00
3b1b98c645 android: Fix overlay visibility reset (#13083) 2024-02-19 19:44:42 +01:00
daf350f5d3 android: Show done button when configuring input overlay (#13082) 2024-02-19 19:26:18 +01:00
ef50277124 Address review comments pt. 2 2024-02-19 19:22:51 +01:00
ba70dc4c13 Address review comments 2024-02-19 19:20:46 +01:00
934e420e36 fs: Refactor to use cmif serialization 2024-02-19 19:20:46 +01:00
d5e4617ab5 fs: Add FileSystemAccessor classes 2024-02-19 19:20:40 +01:00
b5a17b501b Address review comments 2024-02-19 19:11:07 +01:00
2b18957365 fs: Add and use fs_save_data_types.h 2024-02-19 19:06:31 +01:00
4c71bf3d90 fsp: Migrate remaining interfaces to cmif serialization 2024-02-19 19:06:31 +01:00
fdf4a5bc90 fsp-srv: Migrate to use cmif serialization 2024-02-19 19:06:31 +01:00
b7d9eba72b fsp: Move IMultiCommitManager to a seperate file 2024-02-19 19:06:31 +01:00
380475af32 fsp: Move ISaveDataInfoReader to a seperate file 2024-02-19 19:06:31 +01:00
a2a0be4246 aoc: Migrate to use cmif serialization 2024-02-19 17:20:02 +01:00
c9ef2e26ca Merge pull request #13080 from FearlessTobi/scope-exit
scope_exit: Make constexpr
2024-02-19 10:50:45 -05:00
aa6532cf34 core/aoc: Move IPurchaseEventManager to separate file 2024-02-19 16:36:24 +01:00
310c1f50be scope_exit: Make constexpr
Allows the use of the macro in constexpr-contexts.
Also avoids some potential problems when nesting braces inside it.
2024-02-19 16:00:46 +01:00
665fce871f core/CMakeLists: Sort alphabetically 2024-02-19 15:51:02 +01:00
58c7e846cb Merge pull request #13006 from liamwhite/a-hat-in-vram
buffer_cache: use mapped range with large vertex buffer size
2024-02-18 23:37:49 -06:00
8b0fb98a11 Merge pull request #13026 from liamwhite/scale-this-mf
shader_recompiler: fix non-const offset for arrayed image types
2024-02-18 23:37:25 -06:00
8615509c40 Merge pull request #13035 from liamwhite/vi2
vi: manage resources independently of nvnflinger and refactor
2024-02-18 23:36:53 -06:00
d0af52f28e Merge pull request #13048 from liamwhite/new-shell
ns: rewrite for new IPC
2024-02-18 23:36:29 -06:00
f46dc31683 shader_recompiler: throw on missing geometry streams in geometry shaders 2024-02-19 00:34:00 -05:00
d45a12826c ns: address review comments 2024-02-18 19:02:00 -05:00
56810541f0 vulkan_device: don't use fixed cap for memory limits 2024-02-18 18:59:13 -05:00
940a71422e nvnflinger: check for layers before compose 2024-02-18 11:25:52 -05:00
4cdf18095d ns: rewrite IQueryService 2024-02-18 10:35:39 -05:00
2d43831d1f ns: rewrite IServiceGetterInterface 2024-02-18 10:35:39 -05:00
2e96921f9c ns: rewrite IApplicationManagerInterface 2024-02-18 10:35:39 -05:00
cf0de18982 ns: move IDevelopInterface 2024-02-18 10:35:37 -05:00
ae83ee28a3 ns: rewrite ISystemUpdateInterface 2024-02-18 10:32:21 -05:00
306ed4984b ns: move ISystemUpdateControl 2024-02-18 10:32:21 -05:00
626f2e65b1 ns: rewrite IVulnerabilityManagerInterface 2024-02-18 10:32:21 -05:00
2eded86b4b ns: rewrite IReadOnlyApplicationControlDataInterface 2024-02-18 10:32:21 -05:00
786fc512e2 ns: rewrite IReadOnlyApplicationRecordInterface 2024-02-18 10:32:21 -05:00
c31ac45332 ns: add IDynamicRightsInterface 2024-02-18 10:32:21 -05:00
db172ba249 ns: rewrite IDownloadTaskInterface 2024-02-18 10:32:21 -05:00
bb59940b03 ns: rewrite IDocumentInterface 2024-02-18 10:32:21 -05:00
04887953ff ns: rewrite IContentManagementInterface 2024-02-18 10:32:21 -05:00
8ea72cc99d ns: move IFactoryResetInterface 2024-02-18 10:32:21 -05:00
44d2e90217 ns: move IECommerceInterface 2024-02-18 10:32:21 -05:00
12926eb5db ns: move IApplicationVersionInterface 2024-02-18 10:32:21 -05:00
ae114d2fa1 ns: move IAccountProxyInterface 2024-02-18 10:32:21 -05:00
270d07be2f ns: rewrite IPlatformServiceManager 2024-02-18 10:32:21 -05:00
947cdbe4b1 ns: rename results header 2024-02-18 10:32:21 -05:00
a07f0883b9 service: vi: Implement ListDisplayMode 2024-02-17 18:08:41 -05:00
812f23d05c vi: manage resources independently of nvnflinger and refactor 2024-02-17 18:08:38 -05:00
dcce9837d2 vi: move shared buffer management from nvnflinger 2024-02-17 18:01:41 -05:00
ee8eccc5fa nvnflinger: convert to process 2024-02-17 18:01:41 -05:00
7b79cddacd am: unify display layer management 2024-02-17 18:00:28 -05:00
110969e207 service: btm: Implement function needed by QLaunch 2024-02-17 12:39:36 -06:00
9c0724b270 service: btm: Migrate service to new IPC 2024-02-16 12:15:06 -06:00
462ea921e3 shader_recompiler: fix non-const offset for arrayed image types 2024-02-15 18:49:23 -05:00
cb29aa0473 Revert "shader_recompiler: use only ConstOffset for OpImageFetch"
This reverts commit f296a9ce9a.
2024-02-15 18:38:56 -05:00
3067bfd126 buffer_cache: use mapped range with large vertex buffer size 2024-02-13 08:27:33 -05:00
461eaca7e8 device_memory_manager: skip unregistered interfaces on invalidate 2024-02-12 20:02:59 -05:00
368bf2211f texture_cache: tweak iteration tracking change 2024-02-11 13:41:13 -05:00
de8a623932 texture_cache: avoid overestimation of ASTC texture sizes 2024-02-11 13:41:13 -05:00
865a0186b6 caches: make critical reclamation less eager and possible in more cases 2024-02-11 13:41:13 -05:00
434 changed files with 23675 additions and 9433 deletions

View File

@ -81,8 +81,7 @@ jobs:
fetch-depth: 0
- name: Install dependencies
run: |
# workaround for https://github.com/actions/setup-python/issues/577
brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd || brew link --overwrite python@3.12
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd
- name: Build
run: |
mkdir build

View File

@ -1,3 +1,15 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`2831f5dc6`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
| [12749](https://github.com/yuzu-emu/yuzu//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
| [13096](https://github.com/yuzu-emu/yuzu//pull/13096) | [`0a8759057`](https://github.com/yuzu-emu/yuzu//pull/13096/files) | texture_cache: use two-pass collection for costly load resources | [liamwhite](https://github.com/liamwhite/) | Yes |
| [13154](https://github.com/yuzu-emu/yuzu//pull/13154) | [`ca7f949ee`](https://github.com/yuzu-emu/yuzu//pull/13154/files) | core: hid: Reintroduce vibration filter | [german77](https://github.com/german77/) | Yes |
End of merge log. You can find the original README.md below the break.
-----
<!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later

View File

@ -314,3 +314,10 @@ endif()
if (NOT TARGET SimpleIni::SimpleIni)
add_subdirectory(simpleini)
endif()
# sse2neon
if (ARCHITECTURE_arm64 AND NOT TARGET sse2neon)
add_library(sse2neon INTERFACE)
target_include_directories(sse2neon INTERFACE sse2neon)
endif()

9282
externals/sse2neon/sse2neon.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -121,6 +121,7 @@ else()
-Wno-attributes
-Wno-invalid-offsetof
-Wno-unused-parameter
-Wno-missing-field-initializers
)
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
@ -164,6 +165,7 @@ else()
if (MINGW)
add_definitions(-DMINGW_HAS_SECURE_API)
add_compile_options("-msse4.1")
if (MINGW_STATIC_BUILD)
add_definitions(-DQT_STATICPLUGIN)

View File

@ -64,17 +64,17 @@ data class PlayerInput(
fun hasMapping(): Boolean {
var hasMapping = false
buttons.forEach {
if (it != "[empty]") {
if (it != "[empty]" && it.isNotEmpty()) {
hasMapping = true
}
}
analogs.forEach {
if (it != "[empty]") {
if (it != "[empty]" && it.isNotEmpty()) {
hasMapping = true
}
}
motions.forEach {
if (it != "[empty]") {
if (it != "[empty]" && it.isNotEmpty()) {
hasMapping = true
}
}

View File

@ -6,7 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.model
import org.yuzu.yuzu_emu.utils.NativeConfig
enum class StringSetting(override val key: String) : AbstractStringSetting {
DRIVER_PATH("driver_path");
DRIVER_PATH("driver_path"),
DEVICE_NAME("device_name");
override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal)

View File

@ -16,6 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ByteSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.utils.NativeConfig
/**
@ -75,6 +76,9 @@ abstract class SettingsItem(
get() = NativeLibrary.isRunning() && !setting.global &&
!NativeConfig.isPerGameConfigLoaded()
val clearable: Boolean
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
companion object {
const val TYPE_HEADER = 0
const val TYPE_SWITCH = 1
@ -87,6 +91,7 @@ abstract class SettingsItem(
const val TYPE_INPUT = 8
const val TYPE_INT_SINGLE_CHOICE = 9
const val TYPE_INPUT_PROFILE = 10
const val TYPE_STRING_INPUT = 11
const val FASTMEM_COMBINED = "fastmem_combined"
@ -105,6 +110,7 @@ abstract class SettingsItem(
// List of all general
val settingsItems = HashMap<String, SettingsItem>().apply {
put(StringInputSetting(StringSetting.DEVICE_NAME, titleId = R.string.device_name))
put(
SwitchSetting(
BooleanSetting.RENDERER_USE_SPEED_LIMIT,

View File

@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.features.settings.model.view
import androidx.annotation.StringRes
import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
class StringInputSetting(
setting: AbstractStringSetting,
@StringRes titleId: Int = 0,
titleString: String = "",
@StringRes descriptionId: Int = 0,
descriptionString: String = ""
) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) {
override val type = TYPE_STRING_INPUT
fun getSelectedValue(needsGlobal: Boolean = false) = setting.getValueAsString(needsGlobal)
fun setSelectedValue(selection: String) =
(setting as AbstractStringSetting).setString(selection)
}

View File

@ -85,6 +85,10 @@ class SettingsAdapter(
InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this)
}
SettingsItem.TYPE_STRING_INPUT -> {
StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this)
}
else -> {
HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)
}
@ -392,6 +396,15 @@ class SettingsAdapter(
popup.show()
}
fun onStringInputClick(item: StringInputSetting, position: Int) {
SettingsDialogFragment.newInstance(
settingsViewModel,
item,
SettingsItem.TYPE_STRING_INPUT,
position
).show(fragment.childFragmentManager, SettingsDialogFragment.TAG)
}
fun onLongClick(item: SettingsItem, position: Int): Boolean {
SettingsDialogFragment.newInstance(
settingsViewModel,

View File

@ -14,6 +14,7 @@ import androidx.fragment.app.activityViewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.slider.Slider
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding
import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
@ -23,6 +24,7 @@ import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
import org.yuzu.yuzu_emu.utils.ParamPackage
import org.yuzu.yuzu_emu.utils.collect
@ -37,6 +39,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
private val settingsViewModel: SettingsViewModel by activityViewModels()
private lateinit var sliderBinding: DialogSliderBinding
private lateinit var stringInputBinding: DialogEditTextBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -131,6 +134,18 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
.create()
}
SettingsItem.TYPE_STRING_INPUT -> {
stringInputBinding = DialogEditTextBinding.inflate(layoutInflater)
val item = settingsViewModel.clickedItem as StringInputSetting
stringInputBinding.editText.setText(item.getSelectedValue())
MaterialAlertDialogBuilder(requireContext())
.setTitle(item.title)
.setView(stringInputBinding.root)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
.create()
}
SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
val item = settingsViewModel.clickedItem as StringSingleChoiceSetting
MaterialAlertDialogBuilder(requireContext())
@ -158,6 +173,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
): View? {
return when (type) {
SettingsItem.TYPE_SLIDER -> sliderBinding.root
SettingsItem.TYPE_STRING_INPUT -> stringInputBinding.root
else -> super.onCreateView(inflater, container, savedInstanceState)
}
}
@ -200,6 +216,13 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
val sliderSetting = settingsViewModel.clickedItem as SliderSetting
sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value)
}
is StringInputSetting -> {
val stringInputSetting = settingsViewModel.clickedItem as StringInputSetting
stringInputSetting.setSelectedValue(
(stringInputBinding.editText.text ?: "").toString()
)
}
}
closeDialog()
}

View File

@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
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.InputHandler
import org.yuzu.yuzu_emu.utils.NativeConfig
@ -153,6 +154,7 @@ class SettingsFragmentPresenter(
private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
add(StringSetting.DEVICE_NAME.key)
add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
add(ShortSetting.RENDERER_SPEED_LIMIT.key)
add(BooleanSetting.USE_DOCKED_MODE.key)
@ -778,7 +780,7 @@ class SettingsFragmentPresenter(
playerIndex: Int,
paramName: String,
stick: NativeAnalog,
defaultValue: Int
defaultValue: Float
): AbstractIntSetting =
object : AbstractIntSetting {
val params get() = NativeInput.getStickParam(playerIndex, stick)
@ -786,7 +788,7 @@ class SettingsFragmentPresenter(
override val key = ""
override fun getInt(needsGlobal: Boolean): Int =
(params.get(paramName, 0.15f) * 100).toInt()
(params.get(paramName, defaultValue) * 100).toInt()
override fun setInt(value: Int) {
val tempParams = params
@ -794,12 +796,12 @@ class SettingsFragmentPresenter(
NativeInput.setStickParam(playerIndex, stick, tempParams)
}
override val defaultValue = defaultValue
override val defaultValue = (defaultValue * 100).toInt()
override fun getValueAsString(needsGlobal: Boolean): String =
getInt(needsGlobal).toString()
override fun reset() = setInt(defaultValue)
override fun reset() = setInt(this.defaultValue)
}
private fun getExtraStickSettings(
@ -809,11 +811,11 @@ class SettingsFragmentPresenter(
val stickIsController =
NativeInput.isController(NativeInput.getStickParam(playerIndex, nativeAnalog))
val modifierRangeSetting =
getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 50)
getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 0.5f)
val stickRangeSetting =
getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 95)
getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 0.95f)
val stickDeadzoneSetting =
getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 15)
getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 0.15f)
val out = mutableListOf<SettingsItem>().apply {
if (stickIsController) {

View File

@ -13,7 +13,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@ -32,9 +31,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
binding.textSettingValue.text = dateFormatter.format(zonedTime)
binding.buttonClear.setVisible(
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
)
binding.buttonClear.setVisible(setting.clearable)
binding.buttonClear.setOnClickListener {
adapter.onClearClick(setting, bindingAdapterPosition)
}

View File

@ -10,7 +10,6 @@ import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@ -48,9 +47,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
binding.textSettingValue.setVisible(false)
}
binding.buttonClear.setVisible(
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
)
binding.buttonClear.setVisible(setting.clearable)
binding.buttonClear.setOnClickListener {
adapter.onClearClick(setting, bindingAdapterPosition)
}

View File

@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@ -28,9 +27,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
setting.units
)
binding.buttonClear.setVisible(
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
)
binding.buttonClear.setVisible(setting.clearable)
binding.buttonClear.setOnClickListener {
adapter.onClearClick(setting, bindingAdapterPosition)
}

View File

@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
import android.view.View
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
SettingViewHolder(binding.root, adapter) {
private lateinit var setting: StringInputSetting
override fun bind(item: SettingsItem) {
setting = item as StringInputSetting
binding.textSettingName.text = setting.title
binding.textSettingDescription.setVisible(setting.description.isNotEmpty())
binding.textSettingDescription.text = setting.description
binding.textSettingValue.setVisible(true)
binding.textSettingValue.text = setting.getSelectedValue()
binding.buttonClear.setVisible(setting.clearable)
binding.buttonClear.setOnClickListener {
adapter.onClearClick(setting, bindingAdapterPosition)
}
setStyle(setting.isEditable, binding)
}
override fun onClick(clicked: View) {
if (setting.isEditable) {
adapter.onStringInputClick(setting, bindingAdapterPosition)
}
}
override fun onLongClick(clicked: View): Boolean {
if (setting.isEditable) {
return adapter.onLongClick(setting, bindingAdapterPosition)
}
return false
}
}

View File

@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) :
@ -29,9 +28,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)
}
binding.buttonClear.setVisible(
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
)
binding.buttonClear.setVisible(setting.clearable)
binding.buttonClear.setOnClickListener {
adapter.onClearClick(setting, bindingAdapterPosition)
}

View File

@ -810,7 +810,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
}
binding.doneControlConfig.setVisible(false)
binding.doneControlConfig.setVisible(true)
binding.surfaceInputOverlay.setIsInEditMode(true)
}

View File

@ -28,6 +28,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
import org.yuzu.yuzu_emu.features.input.model.NativeButton
import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.overlay.model.OverlayControl
@ -99,12 +100,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
}
var shouldUpdateView = false
val playerIndex =
if (NativeInput.isHandheldOnly()) {
NativeInput.ConsoleDevice
} else {
NativeInput.Player1Device
}
val playerIndex = when (NativeInput.getStyleIndex(0)) {
NpadStyleIndex.Handheld -> 8
else -> 0
}
for (button in overlayButtons) {
if (!button.updateStatus(event)) {
@ -664,7 +663,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
val overlayControlData = NativeConfig.getOverlayControlData()
overlayControlData.forEach {
it.enabled = OverlayControl.from(it.id)?.defaultVisibility == false
it.enabled = OverlayControl.from(it.id)?.defaultVisibility == true
}
NativeConfig.setOverlayControlData(overlayControlData)

View File

@ -292,6 +292,9 @@ void EmulationSession::ShutdownEmulation() {
// Unload user input.
m_system.HIDCore().UnloadInputDevices();
// Enable all controllers
m_system.HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
// Shutdown the main emulated process
if (m_load_result == Core::SystemResultStatus::Success) {
m_system.DetachDebugger();
@ -404,7 +407,9 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
const size_t program_index,
const bool frontend_initiated) {
MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); });
SCOPE_EXIT {
MicroProfileShutdown();
};
LOG_INFO(Frontend, "starting");
@ -413,7 +418,9 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
return Core::SystemResultStatus::ErrorLoader;
}
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
SCOPE_EXIT {
EmulationSession::GetInstance().ShutdownEmulation();
};
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
frontend_initiated);
@ -661,7 +668,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
ASSERT(user_id);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 1,
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, 1,
user_id->AsU128(), 0);
const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
@ -829,8 +836,8 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
FileSys::OpenMode::Read);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
program_id, user_id->AsU128(), 0);
{}, vfsNandDir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, program_id,
user_id->AsU128(), 0);
return Common::Android::ToJString(env, user_save_data_path);
}

View File

@ -102,8 +102,50 @@ void ApplyControllerConfig(size_t player_index,
}
}
std::vector<s32> GetSupportedStyles(int player_index) {
auto& hid_core = EmulationSession::GetInstance().System().HIDCore();
const auto npad_style_set = hid_core.GetSupportedStyleTag();
std::vector<s32> supported_indexes;
if (npad_style_set.fullkey == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Fullkey));
}
if (npad_style_set.joycon_dual == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconDual));
}
if (npad_style_set.joycon_left == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconLeft));
}
if (npad_style_set.joycon_right == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconRight));
}
if (player_index == 0 && npad_style_set.handheld == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Handheld));
}
if (npad_style_set.gamecube == 1) {
supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::GameCube));
}
return supported_indexes;
}
void ConnectController(size_t player_index, bool connected) {
auto& hid_core = EmulationSession::GetInstance().System().HIDCore();
ApplyControllerConfig(player_index, [&](Core::HID::EmulatedController* controller) {
auto supported_styles = GetSupportedStyles(player_index);
auto controller_style = controller->GetNpadStyleIndex(true);
auto style = std::find(supported_styles.begin(), supported_styles.end(),
static_cast<int>(controller_style));
if (style == supported_styles.end() && !supported_styles.empty()) {
controller->SetNpadStyleIndex(
static_cast<Core::HID::NpadStyleIndex>(supported_styles[0]));
}
});
if (player_index == 0) {
auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
auto* player_one = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
@ -522,36 +564,10 @@ jint Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getButtonNameImpl(JNIEnv
jintArray Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getSupportedStyleTagsImpl(
JNIEnv* env, jobject j_obj, jint j_player_index) {
auto& hid_core = EmulationSession::GetInstance().System().HIDCore();
const auto npad_style_set = hid_core.GetSupportedStyleTag();
std::vector<s32> supported_indexes;
if (npad_style_set.fullkey == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Fullkey));
}
if (npad_style_set.joycon_dual == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconDual));
}
if (npad_style_set.joycon_left == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconLeft));
}
if (npad_style_set.joycon_right == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconRight));
}
if (j_player_index == 0 && npad_style_set.handheld == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Handheld));
}
if (npad_style_set.gamecube == 1) {
supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::GameCube));
}
jintArray j_supported_indexes = env->NewIntArray(supported_indexes.size());
env->SetIntArrayRegion(j_supported_indexes, 0, supported_indexes.size(),
supported_indexes.data());
auto supported_styles = GetSupportedStyles(j_player_index);
jintArray j_supported_indexes = env->NewIntArray(supported_styles.size());
env->SetIntArrayRegion(j_supported_indexes, 0, supported_styles.size(),
supported_styles.data());
return j_supported_indexes;
}

View File

@ -209,6 +209,7 @@
<string name="value_with_units">%1$s%2$s</string>
<!-- System settings strings -->
<string name="device_name">Device name</string>
<string name="use_docked_mode">Docked Mode</string>
<string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string>
<string name="emulated_region">Emulated region</string>

View File

@ -73,16 +73,15 @@ void Manager::BufferReleaseAndRegister() {
}
}
u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names,
[[maybe_unused]] const u32 max_count,
u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
[[maybe_unused]] const bool filter) {
std::scoped_lock l{mutex};
LinkToManager();
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (input_devices.size() > 1) {
names.emplace_back("Uac");
if (!input_devices.empty() && !names.empty()) {
names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
return 1;
}
return 0;

View File

@ -60,13 +60,11 @@ public:
* Get a list of audio in device names.
*
* @param names - Output container to write names to.
* @param max_count - Maximum number of device names to write. Unused
* @param filter - Should the list be filtered? Unused.
*
* @return Number of names written.
*/
u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count,
bool filter);
u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
/// Core system
Core::System& system;

View File

@ -146,7 +146,11 @@ public:
break;
}
tags[released++] = tag;
if (released < tags.size()) {
tags[released] = tag;
}
released++;
if (released >= tags.size()) {
break;

View File

@ -28,8 +28,8 @@ OpusDecoder::~OpusDecoder() {
}
}
Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size) {
Result OpusDecoder::Initialize(const OpusParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
shared_buffer_size = transfer_memory_size;
shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
@ -59,7 +59,7 @@ Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory
R_SUCCEED();
}
Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params,
Result OpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
shared_buffer_size = transfer_memory_size;

View File

@ -22,10 +22,10 @@ public:
explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
~OpusDecoder();
Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size);
Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
Result Initialize(const OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size);
Result Initialize(const OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
std::span<const u8> input_data, std::span<u8> output_data, bool reset);
Result SetContext([[maybe_unused]] std::span<const u8> context);

View File

@ -38,7 +38,7 @@ OpusDecoderManager::OpusDecoderManager(Core::System& system_)
}
}
Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSize(const OpusParameters& params, u32& out_size) {
OpusParametersEx ex{
.sample_rate = params.sample_rate,
.channel_count = params.channel_count,
@ -47,11 +47,11 @@ Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_si
R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
}
Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size) {
R_RETURN(GetWorkBufferSizeExEx(params, out_size));
}
Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size) {
R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
@ -63,8 +63,8 @@ Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64&
R_SUCCEED();
}
Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params,
u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params,
u32& out_size) {
OpusMultiStreamParametersEx ex{
.sample_rate = params.sample_rate,
.channel_count = params.channel_count,
@ -76,13 +76,13 @@ Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParame
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
}
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params,
u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
const OpusMultiStreamParametersEx& params, u32& out_size) {
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
}
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params,
u64& out_size) {
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
const OpusMultiStreamParametersEx& params, u32& out_size) {
R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,

View File

@ -22,17 +22,19 @@ public:
return hardware_opus;
}
Result GetWorkBufferSize(OpusParameters& params, u64& out_size);
Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size);
Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size);
Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size);
Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size);
Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size);
Result GetWorkBufferSize(const OpusParameters& params, u32& out_size);
Result GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size);
Result GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size);
Result GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params, u32& out_size);
Result GetWorkBufferSizeForMultiStreamEx(const OpusMultiStreamParametersEx& params,
u32& out_size);
Result GetWorkBufferSizeForMultiStreamExEx(const OpusMultiStreamParametersEx& params,
u32& out_size);
private:
Core::System& system;
HardwareOpus hardware_opus;
std::array<u64, MaxChannels> required_workbuffer_sizes{};
std::array<u32, MaxChannels> required_workbuffer_sizes{};
};
} // namespace AudioCore::OpusDecoder

View File

@ -42,7 +42,7 @@ HardwareOpus::HardwareOpus(Core::System& system_)
opus_decoder.SetSharedMemory(shared_memory);
}
u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
u32 HardwareOpus::GetWorkBufferSize(u32 channel) {
if (!opus_decoder.IsRunning()) {
return 0;
}
@ -55,10 +55,10 @@ u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
return 0;
}
return shared_memory.dsp_return_data[0];
return static_cast<u32>(shared_memory.dsp_return_data[0]);
}
u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
u32 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
std::scoped_lock l{mutex};
shared_memory.host_send_data[0] = total_stream_count;
shared_memory.host_send_data[1] = stereo_stream_count;
@ -70,7 +70,7 @@ u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 st
ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
return 0;
}
return shared_memory.dsp_return_data[0];
return static_cast<u32>(shared_memory.dsp_return_data[0]);
}
Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
@ -94,8 +94,9 @@ Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count,
Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
u32 total_stream_count,
u32 stereo_stream_count, void* mappings,
void* buffer, u64 buffer_size) {
u32 stereo_stream_count,
const void* mappings, void* buffer,
u64 buffer_size) {
std::scoped_lock l{mutex};
shared_memory.host_send_data[0] = (u64)buffer;
shared_memory.host_send_data[1] = buffer_size;

View File

@ -16,14 +16,14 @@ class HardwareOpus {
public:
HardwareOpus(Core::System& system);
u64 GetWorkBufferSize(u32 channel);
u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
u32 GetWorkBufferSize(u32 channel);
u32 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
u64 buffer_size);
Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
u32 totaL_stream_count, u32 stereo_stream_count,
void* mappings, void* buffer, u64 buffer_size);
const void* mappings, void* buffer, u64 buffer_size);
Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,

View File

@ -20,7 +20,7 @@ struct OpusParametersEx {
/* 0x00 */ u32 sample_rate;
/* 0x04 */ u32 channel_count;
/* 0x08 */ bool use_large_frame_size;
/* 0x09 */ INSERT_PADDING_BYTES(7);
/* 0x09 */ INSERT_PADDING_BYTES_NOINIT(7);
}; // size = 0x10
static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!");
@ -40,7 +40,7 @@ struct OpusMultiStreamParametersEx {
/* 0x08 */ u32 total_stream_count;
/* 0x0C */ u32 stereo_stream_count;
/* 0x10 */ bool use_large_frame_size;
/* 0x11 */ INSERT_PADDING_BYTES(7);
/* 0x11 */ INSERT_PADDING_BYTES_NOINIT(7);
/* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings;
}; // size = 0x118
static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,

View File

@ -36,8 +36,7 @@ AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id
: output_sink{system.AudioCore().GetOutputSink()},
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) const {
u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const {
std::span<const AudioDeviceName> names{};
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
@ -46,19 +45,18 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
names = device_names;
}
const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(names[i]);
out_buffer[i] = names[i];
}
return out_count;
}
u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) const {
const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const {
const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), output_device_names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(output_device_names[i]);
out_buffer[i] = output_device_names[i];
}
return out_count;
}

View File

@ -36,20 +36,18 @@ public:
* Get a list of the available output devices.
*
* @param out_buffer - Output buffer to write the available device names.
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
u32 ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const;
/**
* Get a list of the available output devices.
* Different to above somehow...
*
* @param out_buffer - Output buffer to write the available device names.
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
u32 ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const;
/**
* Set the volume of all streams in the backend sink.

View File

@ -17,9 +17,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, const u32 process_handle,
Kernel::KProcess& process, const u64 applet_resource_user_id,
const s32 session_id) {
const u64 transfer_memory_size, Kernel::KProcess* process_handle,
const u64 applet_resource_user_id, const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio,
@ -30,7 +29,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
}
initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
applet_resource_user_id, session_id);
return ResultSuccess;

View File

@ -38,14 +38,14 @@ public:
* @param params - Input parameters to initialize the system with.
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
* @param transfer_memory_size - Size of the transfer memory. Unused.
* @param process_handle - Process handle, also used for memory. Unused.
* @param process_handle - Process handle, also used for memory.
* @param applet_resource_user_id - Applet id for this renderer. Unused.
* @param session_id - Session id of this renderer.
* @return Result code.
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
Kernel::KProcess* process_handle, u64 applet_resource_user_id,
s32 session_id);
/**

View File

@ -18,7 +18,7 @@
namespace AudioCore::Renderer {
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
const u32 process_handle_, BehaviorInfo& behaviour_)
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
: input{input_.data() + sizeof(UpdateDataHeader)},
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(

View File

@ -8,6 +8,10 @@
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::Renderer {
class BehaviorInfo;
class VoiceContext;
@ -39,8 +43,8 @@ class InfoUpdater {
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!");
public:
explicit InfoUpdater(std::span<const u8> input, std::span<u8> output, u32 process_handle,
BehaviorInfo& behaviour);
explicit InfoUpdater(std::span<const u8> input, std::span<u8> output,
Kernel::KProcess* process_handle, BehaviorInfo& behaviour);
/**
* Update the voice channel resources.
@ -197,7 +201,7 @@ private:
/// Expected output size, see CheckConsumedSize
u64 expected_output_size;
/// Unused
u32 process_handle;
Kernel::KProcess* process_handle;
/// Behaviour
BehaviorInfo& behaviour;
};

View File

@ -8,11 +8,11 @@
namespace AudioCore::Renderer {
PoolMapper::PoolMapper(u32 process_handle_, bool force_map_)
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
: process_handle{process_handle_}, force_map{force_map_} {}
PoolMapper::PoolMapper(u32 process_handle_, std::span<MemoryPoolInfo> pool_infos_, u32 pool_count_,
bool force_map_)
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
u32 pool_count_, bool force_map_)
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
pool_count{pool_count_}, force_map{force_map_} {}
@ -106,15 +106,17 @@ bool PoolMapper::IsForceMapEnabled() const {
return force_map;
}
u32 PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
Kernel::KProcess* PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
switch (pool->GetLocation()) {
case MemoryPoolInfo::Location::CPU:
return process_handle;
case MemoryPoolInfo::Location::DSP:
return Kernel::Svc::CurrentProcess;
// return Kernel::Svc::CurrentProcess;
return nullptr;
}
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
return Kernel::Svc::CurrentProcess;
// return Kernel::Svc::CurrentProcess;
return nullptr;
}
bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
@ -147,14 +149,14 @@ bool PoolMapper::Unmap([[maybe_unused]] const u32 handle, [[maybe_unused]] const
}
bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
[[maybe_unused]] u32 handle{0};
[[maybe_unused]] Kernel::KProcess* handle{};
switch (pool.GetLocation()) {
case MemoryPoolInfo::Location::CPU:
handle = process_handle;
break;
case MemoryPoolInfo::Location::DSP:
handle = Kernel::Svc::CurrentProcess;
// handle = Kernel::Svc::CurrentProcess;
break;
}
// nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);

View File

@ -10,6 +10,10 @@
#include "common/common_types.h"
#include "core/hle/service/audio/errors.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::Renderer {
class AddressInfo;
@ -18,9 +22,9 @@ class AddressInfo;
*/
class PoolMapper {
public:
explicit PoolMapper(u32 process_handle, bool force_map);
explicit PoolMapper(u32 process_handle, std::span<MemoryPoolInfo> pool_infos, u32 pool_count,
bool force_map);
explicit PoolMapper(Kernel::KProcess* process_handle, bool force_map);
explicit PoolMapper(Kernel::KProcess* process_handle, std::span<MemoryPoolInfo> pool_infos,
u32 pool_count, bool force_map);
/**
* Clear the usage state for all given pools.
@ -98,7 +102,7 @@ public:
* @return CurrentProcessHandle if location == DSP,
* the PoolMapper's process_handle if location == CPU
*/
u32 GetProcessHandle(const MemoryPoolInfo* pool) const;
Kernel::KProcess* GetProcessHandle(const MemoryPoolInfo* pool) const;
/**
* Map the given region with the given handle. This is a no-op.
@ -167,7 +171,7 @@ public:
private:
/// Process handle for this mapper, used when location == CPU
u32 process_handle;
Kernel::KProcess* process_handle{};
/// List of memory pools assigned to this mapper
MemoryPoolInfo* pool_infos{};
/// The number of pools

View File

@ -102,8 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle_, Kernel::KProcess& process_,
u64 applet_resource_user_id_, s32 session_id_) {
Kernel::KProcess* process_handle_, u64 applet_resource_user_id_,
s32 session_id_) {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision;
}
@ -119,7 +119,6 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
behavior.SetUserLibRevision(params.revision);
process_handle = process_handle_;
process = &process_;
applet_resource_user_id = applet_resource_user_id_;
session_id = session_id_;
@ -132,7 +131,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
process_handle->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(),
transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for.
// Allocate the memory normally instead and hope the game doesn't try to read anything back
@ -616,7 +616,7 @@ void System::SendCommandToDsp() {
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, process,
applet_resource_user_id, process_handle,
reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;

View File

@ -74,14 +74,14 @@ public:
* @param params - Input parameters to initialize the system with.
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
* @param transfer_memory_size - Size of the transfer memory. Unused.
* @param process_handle - Process handle, also used for memory. Unused.
* @param process_handle - Process handle, also used for memory.
* @param applet_resource_user_id - Applet id for this renderer. Unused.
* @param session_id - Session id of this renderer.
* @return Result code.
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
Kernel::KProcess* process_handle, u64 applet_resource_user_id,
s32 session_id);
/**
@ -278,9 +278,7 @@ private:
/// Does what locks do
std::mutex lock{};
/// Process this audio render is operating within, used for memory reads/writes.
Kernel::KProcess* process{};
/// Handle for the process for this system, unused
u32 process_handle{};
Kernel::KProcess* process_handle{};
/// Applet resource id for this system, unused
u64 applet_resource_user_id{};
/// Controls performance input and output

View File

@ -357,7 +357,9 @@ bool IsCubebSuitable() {
return false;
}
SCOPE_EXIT({ cubeb_destroy(ctx); });
SCOPE_EXIT {
cubeb_destroy(ctx);
};
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {

View File

@ -67,9 +67,13 @@ public:
oboe::AudioStreamBuilder builder;
const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream);
ASSERT(result == oboe::Result::OK);
if (result == oboe::Result::OK) {
return temp_stream->getChannelCount() >= 6 ? 6 : 2;
}
return temp_stream->getChannelCount() >= 6 ? 6 : 2;
LOG_ERROR(Audio_Sink, "Failed to open {} stream. Using default channel count 2",
direction == oboe::Direction::Output ? "output" : "input");
return 2;
}
protected:

View File

@ -20,10 +20,10 @@
namespace AudioCore::Sink {
void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
SCOPE_EXIT({
SCOPE_EXIT {
queue.enqueue(buffer);
++queued_buffers;
});
};
if (type == StreamType::In) {
return;

View File

@ -20,7 +20,9 @@ std::string DemangleSymbol(const std::string& mangled) {
}
char* demangled = nullptr;
SCOPE_EXIT({ std::free(demangled); });
SCOPE_EXIT {
std::free(demangled);
};
if (is_itanium(mangled)) {
demangled = llvm::itaniumDemangle(mangled.c_str());

View File

@ -430,11 +430,11 @@ public:
explicit Impl(size_t backing_size_, size_t virtual_size_)
: backing_size{backing_size_}, virtual_size{virtual_size_} {
bool good = false;
SCOPE_EXIT({
SCOPE_EXIT {
if (!good) {
Release();
}
});
};
long page_size = sysconf(_SC_PAGESIZE);
if (page_size != 0x1000) {

View File

@ -24,10 +24,10 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c
out_entry->block_size = page_size;
// Regardless of whether the page was mapped, advance on exit.
SCOPE_EXIT({
SCOPE_EXIT {
context->next_page += 1;
context->next_offset += page_size;
});
};
// Validate that we can read the actual entry.
const auto page = context->next_page;

View File

@ -8,6 +8,7 @@
#include <atomic>
#include <cstddef>
#include <cstring>
#include <limits>
#include <new>
#include <span>
#include <type_traits>

View File

@ -7,29 +7,61 @@
#include "common/common_funcs.h"
namespace detail {
template <typename Func>
struct ScopeExitHelper {
explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {}
~ScopeExitHelper() {
template <class F>
class ScopeGuard {
YUZU_NON_COPYABLE(ScopeGuard);
private:
F f;
bool active;
public:
constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {}
constexpr ~ScopeGuard() {
if (active) {
func();
f();
}
}
void Cancel() {
constexpr void Cancel() {
active = false;
}
Func func;
bool active{true};
constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) {
rhs.Cancel();
}
ScopeGuard& operator=(ScopeGuard&& rhs) = delete;
};
template <typename Func>
ScopeExitHelper<Func> ScopeExit(Func&& func) {
return ScopeExitHelper<Func>(std::forward<Func>(func));
template <class F>
constexpr ScopeGuard<F> MakeScopeGuard(F f) {
return ScopeGuard<F>(std::move(f));
}
enum class ScopeGuardOnExit {};
template <typename F>
constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
return ScopeGuard<F>(std::forward<F>(f));
}
} // namespace detail
#define CONCATENATE_IMPL(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__)
#else
#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__)
#endif
/**
* This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
* used when the caller might want to cancel the ScopeExit.
*/
#define SCOPE_GUARD detail::ScopeGuardOnExit() + [&]()
/**
* This macro allows you to conveniently specify a block of code that will run on scope exit. Handy
* for doing ad-hoc clean-up tasks in a function with multiple returns.
@ -38,7 +70,7 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
* \code
* const int saved_val = g_foo;
* g_foo = 55;
* SCOPE_EXIT({ g_foo = saved_val; });
* SCOPE_EXIT{ g_foo = saved_val; };
*
* if (Bar()) {
* return 0;
@ -47,10 +79,4 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
* }
* \endcode
*/
#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
/**
* This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
* used when the caller might want to cancel the ScopeExit.
*/
#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)
#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD

View File

@ -384,6 +384,12 @@ struct Values {
AstcRecompression::Bc3,
"astc_recompression",
Category::RendererAdvanced};
SwitchableSetting<VramUsageMode, true> vram_usage_mode{linkage,
VramUsageMode::Conservative,
VramUsageMode::Conservative,
VramUsageMode::Aggressive,
"vram_usage_mode",
Category::RendererAdvanced};
SwitchableSetting<bool> async_presentation{linkage,
#ifdef ANDROID
true,

View File

@ -122,6 +122,8 @@ ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
ENUM(VramUsageMode, Conservative, Aggressive);
ENUM(RendererBackend, OpenGL, Vulkan, Null);
ENUM(ShaderBackend, Glsl, Glasm, SpirV);

View File

@ -38,6 +38,10 @@ std::string StringFromBuffer(std::span<const u8> data) {
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
}
std::string StringFromBuffer(std::span<const char> data) {
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
}
// Turns " hej " into "hej". Also handles tabs.
std::string StripSpaces(const std::string& str) {
const std::size_t s = str.find_first_not_of(" \t\r\n");

View File

@ -19,6 +19,7 @@ namespace Common {
[[nodiscard]] std::string ToUpper(std::string str);
[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
[[nodiscard]] std::string StringFromBuffer(std::span<const char> data);
[[nodiscard]] std::string StripSpaces(const std::string& s);
[[nodiscard]] std::string StripQuotes(const std::string& s);

View File

@ -2,8 +2,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
arm/arm_interface.h
arm/debug.cpp
arm/debug.h
arm/exclusive_monitor.cpp
@ -37,10 +37,10 @@ add_library(core STATIC
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
device_memory_manager.h
device_memory_manager.inc
device_memory.cpp
device_memory.h
device_memory_manager.h
device_memory_manager.inc
file_sys/bis_factory.cpp
file_sys/bis_factory.h
file_sys/card_image.cpp
@ -58,9 +58,14 @@ add_library(core STATIC
file_sys/fs_operate_range.h
file_sys/fs_path.h
file_sys/fs_path_utility.h
file_sys/fs_save_data_types.h
file_sys/fs_string_util.h
file_sys/fsa/fs_i_directory.h
file_sys/fsa/fs_i_file.h
file_sys/fsa/fs_i_filesystem.h
file_sys/fsmitm_romfsbuild.cpp
file_sys/fsmitm_romfsbuild.h
file_sys/fssrv/fssrv_sf_path.h
file_sys/fssystem/fs_i_storage.h
file_sys/fssystem/fs_types.h
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
@ -390,6 +395,20 @@ add_library(core STATIC
hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h
hle/service/am/am.cpp
hle/service/am/am.h
hle/service/am/am_results.h
hle/service/am/am_types.h
hle/service/am/applet.cpp
hle/service/am/applet.h
hle/service/am/applet_data_broker.cpp
hle/service/am/applet_data_broker.h
hle/service/am/applet_manager.cpp
hle/service/am/applet_manager.h
hle/service/am/applet_message_queue.cpp
hle/service/am/applet_message_queue.h
hle/service/am/display_layer_manager.cpp
hle/service/am/display_layer_manager.h
hle/service/am/frontend/applet_cabinet.cpp
hle/service/am/frontend/applet_cabinet.h
hle/service/am/frontend/applet_controller.cpp
@ -411,24 +430,10 @@ add_library(core STATIC
hle/service/am/frontend/applet_web_browser_types.h
hle/service/am/frontend/applets.cpp
hle/service/am/frontend/applets.h
hle/service/am/am.cpp
hle/service/am/am.h
hle/service/am/am_results.h
hle/service/am/am_types.h
hle/service/am/applet.cpp
hle/service/am/applet.h
hle/service/am/applet_manager.cpp
hle/service/am/applet_data_broker.cpp
hle/service/am/applet_data_broker.h
hle/service/am/applet_manager.h
hle/service/am/applet_message_queue.cpp
hle/service/am/applet_message_queue.h
hle/service/am/hid_registration.cpp
hle/service/am/hid_registration.h
hle/service/am/library_applet_storage.cpp
hle/service/am/library_applet_storage.h
hle/service/am/managed_layer_holder.cpp
hle/service/am/managed_layer_holder.h
hle/service/am/process.cpp
hle/service/am/process.h
hle/service/am/service/all_system_applet_proxies_service.cpp
@ -441,10 +446,10 @@ add_library(core STATIC
hle/service/am/service/application_creator.h
hle/service/am/service/application_functions.cpp
hle/service/am/service/application_functions.h
hle/service/am/service/application_proxy_service.cpp
hle/service/am/service/application_proxy_service.h
hle/service/am/service/application_proxy.cpp
hle/service/am/service/application_proxy.h
hle/service/am/service/application_proxy_service.cpp
hle/service/am/service/application_proxy_service.h
hle/service/am/service/audio_controller.cpp
hle/service/am/service/audio_controller.h
hle/service/am/service/common_state_getter.cpp
@ -473,55 +478,53 @@ add_library(core STATIC
hle/service/am/service/process_winding_controller.h
hle/service/am/service/self_controller.cpp
hle/service/am/service/self_controller.h
hle/service/am/service/storage_accessor.cpp
hle/service/am/service/storage_accessor.h
hle/service/am/service/storage.cpp
hle/service/am/service/storage.h
hle/service/am/service/storage_accessor.cpp
hle/service/am/service/storage_accessor.h
hle/service/am/service/system_applet_proxy.cpp
hle/service/am/service/system_applet_proxy.h
hle/service/am/service/window_controller.cpp
hle/service/am/service/window_controller.h
hle/service/am/system_buffer_manager.cpp
hle/service/am/system_buffer_manager.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/aoc/addon_content_manager.cpp
hle/service/aoc/addon_content_manager.h
hle/service/aoc/purchase_event_manager.cpp
hle/service/aoc/purchase_event_manager.h
hle/service/apm/apm.cpp
hle/service/apm/apm.h
hle/service/apm/apm_controller.cpp
hle/service/apm/apm_controller.h
hle/service/apm/apm_interface.cpp
hle/service/apm/apm_interface.h
hle/service/audio/audin_u.cpp
hle/service/audio/audin_u.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audio_controller.cpp
hle/service/audio/audio_controller.h
hle/service/audio/audout_u.cpp
hle/service/audio/audout_u.h
hle/service/audio/audrec_a.cpp
hle/service/audio/audrec_a.h
hle/service/audio/audrec_u.cpp
hle/service/audio/audrec_u.h
hle/service/audio/audren_u.cpp
hle/service/audio/audren_u.h
hle/service/audio/audio_device.cpp
hle/service/audio/audio_device.h
hle/service/audio/audio_in_manager.cpp
hle/service/audio/audio_in_manager.h
hle/service/audio/audio_in.cpp
hle/service/audio/audio_in.h
hle/service/audio/audio_out_manager.cpp
hle/service/audio/audio_out_manager.h
hle/service/audio/audio_out.cpp
hle/service/audio/audio_out.h
hle/service/audio/audio_renderer_manager.cpp
hle/service/audio/audio_renderer_manager.h
hle/service/audio/audio_renderer.cpp
hle/service/audio/audio_renderer.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/errors.h
hle/service/audio/hwopus.cpp
hle/service/audio/hwopus.h
hle/service/audio/final_output_recorder_manager_for_applet.cpp
hle/service/audio/final_output_recorder_manager_for_applet.h
hle/service/audio/final_output_recorder_manager.cpp
hle/service/audio/final_output_recorder_manager.h
hle/service/audio/hardware_opus_decoder_manager.cpp
hle/service/audio/hardware_opus_decoder_manager.h
hle/service/audio/hardware_opus_decoder.cpp
hle/service/audio/hardware_opus_decoder.h
hle/service/bcat/backend/backend.cpp
hle/service/bcat/backend/backend.h
hle/service/bcat/news/newly_arrived_event_holder.cpp
hle/service/bcat/news/newly_arrived_event_holder.h
hle/service/bcat/news/news_data_service.cpp
hle/service/bcat/news/news_data_service.h
hle/service/bcat/news/news_database_service.cpp
hle/service/bcat/news/news_database_service.h
hle/service/bcat/news/news_service.cpp
hle/service/bcat/news/news_service.h
hle/service/bcat/news/overwrite_event_holder.cpp
hle/service/bcat/news/overwrite_event_holder.h
hle/service/bcat/news/service_creator.cpp
hle/service/bcat/news/service_creator.h
hle/service/bcat/bcat.cpp
hle/service/bcat/bcat.h
hle/service/bcat/bcat_result.h
@ -537,6 +540,18 @@ add_library(core STATIC
hle/service/bcat/delivery_cache_progress_service.h
hle/service/bcat/delivery_cache_storage_service.cpp
hle/service/bcat/delivery_cache_storage_service.h
hle/service/bcat/news/newly_arrived_event_holder.cpp
hle/service/bcat/news/newly_arrived_event_holder.h
hle/service/bcat/news/news_data_service.cpp
hle/service/bcat/news/news_data_service.h
hle/service/bcat/news/news_database_service.cpp
hle/service/bcat/news/news_database_service.h
hle/service/bcat/news/news_service.cpp
hle/service/bcat/news/news_service.h
hle/service/bcat/news/overwrite_event_holder.cpp
hle/service/bcat/news/overwrite_event_holder.h
hle/service/bcat/news/service_creator.cpp
hle/service/bcat/news/service_creator.h
hle/service/bcat/service_creator.cpp
hle/service/bcat/service_creator.h
hle/service/bpc/bpc.cpp
@ -545,6 +560,16 @@ add_library(core STATIC
hle/service/btdrv/btdrv.h
hle/service/btm/btm.cpp
hle/service/btm/btm.h
hle/service/btm/btm_debug.cpp
hle/service/btm/btm_debug.h
hle/service/btm/btm_system.cpp
hle/service/btm/btm_system.h
hle/service/btm/btm_system_core.cpp
hle/service/btm/btm_system_core.h
hle/service/btm/btm_user.cpp
hle/service/btm/btm_user.h
hle/service/btm/btm_user_core.cpp
hle/service/btm/btm_user_core.h
hle/service/caps/caps.cpp
hle/service/caps/caps.h
hle/service/caps/caps_a.cpp
@ -587,6 +612,10 @@ add_library(core STATIC
hle/service/filesystem/fsp/fs_i_file.h
hle/service/filesystem/fsp/fs_i_filesystem.cpp
hle/service/filesystem/fsp/fs_i_filesystem.h
hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
hle/service/filesystem/fsp/fs_i_storage.cpp
hle/service/filesystem/fsp/fs_i_storage.h
hle/service/filesystem/fsp/fsp_ldr.cpp
@ -595,13 +624,13 @@ add_library(core STATIC
hle/service/filesystem/fsp/fsp_pr.h
hle/service/filesystem/fsp/fsp_srv.cpp
hle/service/filesystem/fsp/fsp_srv.h
hle/service/filesystem/fsp/fsp_util.h
hle/service/filesystem/fsp/fsp_types.h
hle/service/filesystem/fsp/save_data_transfer_prohibiter.cpp
hle/service/filesystem/fsp/save_data_transfer_prohibiter.h
hle/service/filesystem/romfs_controller.cpp
hle/service/filesystem/romfs_controller.h
hle/service/filesystem/save_data_controller.cpp
hle/service/filesystem/save_data_controller.h
hle/service/fgm/fgm.cpp
hle/service/fgm/fgm.h
hle/service/friend/friend.cpp
hle/service/friend/friend.h
hle/service/friend/friend_interface.cpp
@ -739,15 +768,48 @@ add_library(core STATIC
hle/service/nim/nim.h
hle/service/npns/npns.cpp
hle/service/npns/npns.h
hle/service/ns/errors.h
hle/service/ns/iplatform_service_manager.cpp
hle/service/ns/iplatform_service_manager.h
hle/service/ns/account_proxy_interface.cpp
hle/service/ns/account_proxy_interface.h
hle/service/ns/application_manager_interface.cpp
hle/service/ns/application_manager_interface.h
hle/service/ns/application_version_interface.cpp
hle/service/ns/application_version_interface.h
hle/service/ns/content_management_interface.cpp
hle/service/ns/content_management_interface.h
hle/service/ns/develop_interface.cpp
hle/service/ns/develop_interface.h
hle/service/ns/document_interface.cpp
hle/service/ns/document_interface.h
hle/service/ns/download_task_interface.cpp
hle/service/ns/download_task_interface.h
hle/service/ns/dynamic_rights_interface.cpp
hle/service/ns/dynamic_rights_interface.h
hle/service/ns/ecommerce_interface.cpp
hle/service/ns/ecommerce_interface.h
hle/service/ns/factory_reset_interface.cpp
hle/service/ns/factory_reset_interface.h
hle/service/ns/language.cpp
hle/service/ns/language.h
hle/service/ns/ns.cpp
hle/service/ns/ns.h
hle/service/ns/pdm_qry.cpp
hle/service/ns/pdm_qry.h
hle/service/ns/ns_results.h
hle/service/ns/ns_types.h
hle/service/ns/platform_service_manager.cpp
hle/service/ns/platform_service_manager.h
hle/service/ns/query_service.cpp
hle/service/ns/query_service.h
hle/service/ns/read_only_application_control_data_interface.cpp
hle/service/ns/read_only_application_control_data_interface.h
hle/service/ns/read_only_application_record_interface.cpp
hle/service/ns/read_only_application_record_interface.h
hle/service/ns/service_getter_interface.cpp
hle/service/ns/service_getter_interface.h
hle/service/ns/system_update_control.cpp
hle/service/ns/system_update_control.h
hle/service/ns/system_update_interface.cpp
hle/service/ns/system_update_interface.h
hle/service/ns/vulnerability_manager_interface.cpp
hle/service/ns/vulnerability_manager_interface.h
hle/service/nvdrv/core/container.cpp
hle/service/nvdrv/core/container.h
hle/service/nvdrv/core/heap_mapper.cpp
@ -800,14 +862,14 @@ add_library(core STATIC
hle/service/nvnflinger/consumer_base.cpp
hle/service/nvnflinger/consumer_base.h
hle/service/nvnflinger/consumer_listener.h
hle/service/nvnflinger/fb_share_buffer_manager.cpp
hle/service/nvnflinger/fb_share_buffer_manager.h
hle/service/nvnflinger/graphic_buffer_producer.cpp
hle/service/nvnflinger/graphic_buffer_producer.h
hle/service/nvnflinger/hos_binder_driver_server.cpp
hle/service/nvnflinger/hos_binder_driver_server.h
hle/service/nvnflinger/hardware_composer.cpp
hle/service/nvnflinger/hardware_composer.h
hle/service/nvnflinger/hos_binder_driver.cpp
hle/service/nvnflinger/hos_binder_driver.h
hle/service/nvnflinger/hos_binder_driver_server.cpp
hle/service/nvnflinger/hos_binder_driver_server.h
hle/service/nvnflinger/hwc_layer.h
hle/service/nvnflinger/nvnflinger.cpp
hle/service/nvnflinger/nvnflinger.h
@ -815,12 +877,26 @@ add_library(core STATIC
hle/service/nvnflinger/pixel_format.h
hle/service/nvnflinger/producer_listener.h
hle/service/nvnflinger/status.h
hle/service/nvnflinger/surface_flinger.cpp
hle/service/nvnflinger/surface_flinger.h
hle/service/nvnflinger/ui/fence.h
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h
hle/service/olsc/daemon_controller.cpp
hle/service/olsc/daemon_controller.h
hle/service/olsc/native_handle_holder.cpp
hle/service/olsc/native_handle_holder.h
hle/service/olsc/olsc_service_for_application.cpp
hle/service/olsc/olsc_service_for_application.h
hle/service/olsc/olsc_service_for_system_service.cpp
hle/service/olsc/olsc_service_for_system_service.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
hle/service/olsc/remote_storage_controller.cpp
hle/service/olsc/remote_storage_controller.h
hle/service/olsc/transfer_task_list_controller.cpp
hle/service/olsc/transfer_task_list_controller.h
hle/service/omm/omm.cpp
hle/service/omm/omm.h
hle/service/omm/operation_mode_manager.cpp
@ -831,25 +907,44 @@ add_library(core STATIC
hle/service/omm/power_state_interface.h
hle/service/os/event.cpp
hle/service/os/event.h
hle/service/os/multi_wait.cpp
hle/service/os/multi_wait.h
hle/service/os/multi_wait_holder.cpp
hle/service/os/multi_wait_holder.h
hle/service/os/multi_wait_utils.h
hle/service/os/multi_wait.cpp
hle/service/os/multi_wait.h
hle/service/os/mutex.cpp
hle/service/os/mutex.h
hle/service/pcie/pcie.cpp
hle/service/pcie/pcie.h
hle/service/pctl/parental_control_service_factory.cpp
hle/service/pctl/parental_control_service_factory.h
hle/service/pctl/parental_control_service.cpp
hle/service/pctl/parental_control_service.h
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h
hle/service/pctl/pctl_module.cpp
hle/service/pctl/pctl_module.h
hle/service/pctl/pctl_results.h
hle/service/pctl/pctl_types.h
hle/service/pcv/pcv.cpp
hle/service/pcv/pcv.h
hle/service/pm/pm.cpp
hle/service/pm/pm.h
hle/service/prepo/prepo.cpp
hle/service/prepo/prepo.h
hle/service/psc/ovln/ovln_types.h
hle/service/psc/ovln/receiver_service.cpp
hle/service/psc/ovln/receiver_service.h
hle/service/psc/ovln/receiver.cpp
hle/service/psc/ovln/receiver.h
hle/service/psc/ovln/sender_service.cpp
hle/service/psc/ovln/sender_service.h
hle/service/psc/ovln/sender.cpp
hle/service/psc/ovln/sender.h
hle/service/psc/pm_control.cpp
hle/service/psc/pm_control.h
hle/service/psc/pm_module.cpp
hle/service/psc/pm_module.h
hle/service/psc/pm_service.cpp
hle/service/psc/pm_service.h
hle/service/psc/psc.cpp
hle/service/psc/psc.h
hle/service/psc/time/alarms.cpp
@ -873,15 +968,17 @@ add_library(core STATIC
hle/service/psc/time/common.cpp
hle/service/psc/time/common.h
hle/service/psc/time/errors.h
hle/service/psc/time/shared_memory.cpp
hle/service/psc/time/shared_memory.h
hle/service/psc/time/static.cpp
hle/service/psc/time/static.h
hle/service/psc/time/manager.h
hle/service/psc/time/power_state_request_manager.cpp
hle/service/psc/time/power_state_request_manager.h
hle/service/psc/time/power_state_service.cpp
hle/service/psc/time/power_state_service.h
hle/service/psc/time/service_manager.cpp
hle/service/psc/time/service_manager.h
hle/service/psc/time/shared_memory.cpp
hle/service/psc/time/shared_memory.h
hle/service/psc/time/static.cpp
hle/service/psc/time/static.h
hle/service/psc/time/steady_clock.cpp
hle/service/psc/time/steady_clock.h
hle/service/psc/time/system_clock.cpp
@ -890,8 +987,6 @@ add_library(core STATIC
hle/service/psc/time/time_zone.h
hle/service/psc/time/time_zone_service.cpp
hle/service/psc/time/time_zone_service.h
hle/service/psc/time/power_state_request_manager.cpp
hle/service/psc/time/power_state_request_manager.h
hle/service/ptm/psm.cpp
hle/service/ptm/psm.h
hle/service/ptm/ptm.cpp
@ -908,19 +1003,21 @@ add_library(core STATIC
hle/service/server_manager.h
hle/service/service.cpp
hle/service/service.h
hle/service/set/setting_formats/appln_settings.cpp
hle/service/set/setting_formats/appln_settings.h
hle/service/set/setting_formats/device_settings.cpp
hle/service/set/setting_formats/device_settings.h
hle/service/set/setting_formats/system_settings.cpp
hle/service/set/setting_formats/system_settings.h
hle/service/set/setting_formats/private_settings.cpp
hle/service/set/setting_formats/private_settings.h
hle/service/services.cpp
hle/service/services.h
hle/service/set/factory_settings_server.cpp
hle/service/set/factory_settings_server.h
hle/service/set/firmware_debug_settings_server.cpp
hle/service/set/firmware_debug_settings_server.h
hle/service/set/key_code_map.h
hle/service/set/setting_formats/appln_settings.cpp
hle/service/set/setting_formats/appln_settings.h
hle/service/set/setting_formats/device_settings.cpp
hle/service/set/setting_formats/device_settings.h
hle/service/set/setting_formats/private_settings.cpp
hle/service/set/setting_formats/private_settings.h
hle/service/set/setting_formats/system_settings.cpp
hle/service/set/setting_formats/system_settings.h
hle/service/set/settings.cpp
hle/service/set/settings.h
hle/service/set/settings_server.cpp
@ -955,30 +1052,36 @@ add_library(core STATIC
hle/service/ssl/ssl_backend.h
hle/service/usb/usb.cpp
hle/service/usb/usb.h
hle/service/vi/display/vi_display.cpp
hle/service/vi/display/vi_display.h
hle/service/vi/layer/vi_layer.cpp
hle/service/vi/layer/vi_layer.h
hle/service/vi/application_display_service.cpp
hle/service/vi/application_display_service.h
hle/service/vi/application_root_service.cpp
hle/service/vi/application_root_service.h
hle/service/vi/hos_binder_driver.cpp
hle/service/vi/hos_binder_driver.h
hle/service/vi/conductor.cpp
hle/service/vi/conductor.h
hle/service/vi/container.cpp
hle/service/vi/container.h
hle/service/vi/display.h
hle/service/vi/display_list.h
hle/service/vi/layer.h
hle/service/vi/layer_list.h
hle/service/vi/manager_display_service.cpp
hle/service/vi/manager_display_service.h
hle/service/vi/manager_root_service.cpp
hle/service/vi/manager_root_service.h
hle/service/vi/service_creator.cpp
hle/service/vi/service_creator.h
hle/service/vi/shared_buffer_manager.cpp
hle/service/vi/shared_buffer_manager.h
hle/service/vi/system_display_service.cpp
hle/service/vi/system_display_service.h
hle/service/vi/system_root_service.cpp
hle/service/vi/system_root_service.h
hle/service/vi/vi_results.h
hle/service/vi/vi_types.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
hle/service/vi/vi_results.h
hle/service/vi/vi_types.h
hle/service/vi/vsync_manager.cpp
hle/service/vi/vsync_manager.h
internal_network/network.cpp
internal_network/network.h
internal_network/network_interface.cpp

View File

@ -47,6 +47,7 @@
#include "core/hle/service/psc/time/system_clock.h"
#include "core/hle/service/psc/time/time_zone_service.h"
#include "core/hle/service/service.h"
#include "core/hle/service/services.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"
#include "core/internal_network/network.h"
@ -310,7 +311,8 @@ struct System::Impl {
audio_core = std::make_unique<AudioCore::AudioCore>(system);
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
services = std::make_unique<Service::Services>(service_manager, system);
services =
std::make_unique<Service::Services>(service_manager, system, stop_event.get_token());
is_powered_on = true;
exit_locked = false;
@ -458,11 +460,10 @@ struct System::Impl {
gpu_core->NotifyShutdown();
}
stop_event.request_stop();
core_timing.SyncPause(false);
Network::CancelPendingSocketOperations();
kernel.SuspendEmulation(true);
if (services) {
services->KillNVNFlinger();
}
kernel.CloseServices();
kernel.ShutdownCores();
applet_manager.Reset();
@ -480,6 +481,7 @@ struct System::Impl {
cpu_manager.Shutdown();
debugger.reset();
kernel.Shutdown();
stop_event = {};
Network::RestartSocketOperations();
if (auto room_member = room_network.GetRoomMember().lock()) {
@ -615,6 +617,7 @@ struct System::Impl {
ExecuteProgramCallback execute_program_callback;
ExitCallback exit_callback;
std::stop_source stop_event;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};

View File

@ -199,10 +199,10 @@ void CpuManager::RunThread(std::stop_token token, std::size_t core) {
data.host_context = Common::Fiber::ThreadToFiber();
// Cleanup
SCOPE_EXIT({
SCOPE_EXIT {
data.host_context->Exit();
MicroProfileOnThreadExit();
});
};
// Running
if (!gpu_barrier->Sync(token)) {

View File

@ -43,6 +43,8 @@ public:
DeviceMemoryManager(const DeviceMemory& device_memory);
~DeviceMemoryManager();
static constexpr bool HAS_FLUSH_INVALIDATION = true;
void BindInterface(DeviceInterface* device_inter);
DAddr Allocate(size_t size);

View File

@ -391,12 +391,12 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
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({
SCOPE_EXIT{
page_index += next_pages;
page_offset = 0;
increment(copy_amount);
remaining_size -= copy_amount;
});
};
auto phys_addr = compressed_physical_ptr[page_index];
if (phys_addr == 0) {
@ -522,13 +522,17 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
auto* memory_device_inter = registered_processes[asid.id];
const auto release_pending = [&] {
if (uncache_bytes > 0) {
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
uncache_bytes, false);
if (memory_device_inter != nullptr) {
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
uncache_bytes, false);
}
uncache_bytes = 0;
}
if (cache_bytes > 0) {
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
cache_bytes, true);
if (memory_device_inter != nullptr) {
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
cache_bytes, true);
}
cache_bytes = 0;
}
};

View File

@ -3,6 +3,10 @@
#pragma once
#include <string_view>
#include "common/common_funcs.h"
#include "common/common_types.h"
namespace FileSys {
constexpr inline size_t EntryNameLengthMax = 0x300;

View File

@ -23,6 +23,8 @@ enum class OpenDirectoryMode : u64 {
File = (1 << 1),
All = (Directory | File),
NotRequireFileSize = (1ULL << 31),
};
DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode)
@ -36,4 +38,29 @@ enum class CreateOption : u8 {
BigFile = (1 << 0),
};
struct FileSystemAttribute {
u8 dir_entry_name_length_max_defined;
u8 file_entry_name_length_max_defined;
u8 dir_path_name_length_max_defined;
u8 file_path_name_length_max_defined;
INSERT_PADDING_BYTES_NOINIT(0x5);
u8 utf16_dir_entry_name_length_max_defined;
u8 utf16_file_entry_name_length_max_defined;
u8 utf16_dir_path_name_length_max_defined;
u8 utf16_file_path_name_length_max_defined;
INSERT_PADDING_BYTES_NOINIT(0x18);
s32 dir_entry_name_length_max;
s32 file_entry_name_length_max;
s32 dir_path_name_length_max;
s32 file_path_name_length_max;
INSERT_PADDING_WORDS_NOINIT(0x5);
s32 utf16_dir_entry_name_length_max;
s32 utf16_file_entry_name_length_max;
s32 utf16_dir_path_name_length_max;
s32 utf16_file_path_name_length_max;
INSERT_PADDING_WORDS_NOINIT(0x18);
INSERT_PADDING_WORDS_NOINIT(0x1);
};
static_assert(sizeof(FileSystemAttribute) == 0xC0, "FileSystemAttribute has incorrect size");
} // namespace FileSys

View File

@ -10,7 +10,7 @@ namespace FileSys {
constexpr size_t RequiredAlignment = alignof(u64);
void* AllocateUnsafe(size_t size) {
inline void* AllocateUnsafe(size_t size) {
// Allocate
void* const ptr = ::operator new(size, std::align_val_t{RequiredAlignment});
@ -21,16 +21,16 @@ void* AllocateUnsafe(size_t size) {
return ptr;
}
void DeallocateUnsafe(void* ptr, size_t size) {
inline void DeallocateUnsafe(void* ptr, size_t size) {
// Deallocate the pointer
::operator delete(ptr, std::align_val_t{RequiredAlignment});
}
void* Allocate(size_t size) {
inline void* Allocate(size_t size) {
return AllocateUnsafe(size);
}
void Deallocate(void* ptr, size_t size) {
inline void Deallocate(void* ptr, size_t size) {
// If the pointer is non-null, deallocate it
if (ptr != nullptr) {
DeallocateUnsafe(ptr, size);

View File

@ -381,7 +381,7 @@ public:
// Check that it's possible for us to remove a child
auto* p = m_write_buffer.Get();
s32 len = std::strlen(p);
s32 len = static_cast<s32>(std::strlen(p));
R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), ResultNotImplemented);
// Handle a trailing separator

View File

@ -426,9 +426,10 @@ public:
R_SUCCEED();
}
static Result Normalize(char* dst, size_t* out_len, const char* path, size_t max_out_size,
bool is_windows_path, bool is_drive_relative_path,
bool allow_all_characters = false) {
static constexpr Result Normalize(char* dst, size_t* out_len, const char* path,
size_t max_out_size, bool is_windows_path,
bool is_drive_relative_path,
bool allow_all_characters = false) {
// Use StringTraits names for remainder of scope
using namespace StringTraits;
@ -447,7 +448,7 @@ public:
char* replacement_path = nullptr;
size_t replacement_path_size = 0;
SCOPE_EXIT({
SCOPE_EXIT {
if (replacement_path != nullptr) {
if (std::is_constant_evaluated()) {
delete[] replacement_path;
@ -455,7 +456,7 @@ public:
Deallocate(replacement_path, replacement_path_size);
}
}
});
};
// Perform path replacement, if necessary
if (IsParentDirectoryPathReplacementNeeded(cur_path)) {
@ -1102,8 +1103,8 @@ public:
R_SUCCEED();
}
static Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len,
const PathFlags& flags) {
static constexpr Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len,
const PathFlags& flags) {
// Use StringTraits names for remainder of scope
using namespace StringTraits;
@ -1199,7 +1200,7 @@ public:
const size_t replaced_src_len = path_len - (src - path);
char* replaced_src = nullptr;
SCOPE_EXIT({
SCOPE_EXIT {
if (replaced_src != nullptr) {
if (std::is_constant_evaluated()) {
delete[] replaced_src;
@ -1207,7 +1208,7 @@ public:
Deallocate(replaced_src, replaced_src_len);
}
}
});
};
if (std::is_constant_evaluated()) {
replaced_src = new char[replaced_src_len];

View File

@ -0,0 +1,188 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <fmt/format.h>
#include "common/common_funcs.h"
#include "common/common_types.h"
namespace FileSys {
using SaveDataId = u64;
using SystemSaveDataId = u64;
using SystemBcatSaveDataId = SystemSaveDataId;
using ProgramId = u64;
enum class SaveDataSpaceId : u8 {
System = 0,
User = 1,
SdSystem = 2,
Temporary = 3,
SdUser = 4,
ProperSystem = 100,
SafeMode = 101,
};
enum class SaveDataType : u8 {
System = 0,
Account = 1,
Bcat = 2,
Device = 3,
Temporary = 4,
Cache = 5,
SystemBcat = 6,
};
enum class SaveDataRank : u8 {
Primary = 0,
Secondary = 1,
};
struct SaveDataSize {
u64 normal;
u64 journal;
};
static_assert(sizeof(SaveDataSize) == 0x10, "SaveDataSize has invalid size.");
using UserId = u128;
static_assert(std::is_trivially_copyable_v<UserId>, "Data type must be trivially copyable.");
static_assert(sizeof(UserId) == 0x10, "UserId has invalid size.");
constexpr inline SystemSaveDataId InvalidSystemSaveDataId = 0;
constexpr inline UserId InvalidUserId = {};
enum class SaveDataFlags : u32 {
None = (0 << 0),
KeepAfterResettingSystemSaveData = (1 << 0),
KeepAfterRefurbishment = (1 << 1),
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
NeedsSecureDelete = (1 << 3),
};
enum class SaveDataMetaType : u8 {
None = 0,
Thumbnail = 1,
ExtensionContext = 2,
};
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
INSERT_PADDING_BYTES(0xB);
};
static_assert(std::is_trivially_copyable_v<SaveDataMetaInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataMetaInfo) == 0x10, "SaveDataMetaInfo has invalid size.");
struct SaveDataCreationInfo {
s64 size;
s64 journal_size;
s64 block_size;
u64 owner_id;
u32 flags;
SaveDataSpaceId space_id;
bool pseudo;
INSERT_PADDING_BYTES(0x1A);
};
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataCreationInfo) == 0x40, "SaveDataCreationInfo has invalid size.");
struct SaveDataAttribute {
ProgramId program_id;
UserId user_id;
SystemSaveDataId system_save_data_id;
SaveDataType type;
SaveDataRank rank;
u16 index;
INSERT_PADDING_BYTES(0x1C);
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id, u16 index,
SaveDataRank rank) {
return {
.program_id = program_id,
.user_id = user_id,
.system_save_data_id = system_save_data_id,
.type = type,
.rank = rank,
.index = index,
};
}
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id, u16 index) {
return Make(program_id, type, user_id, system_save_data_id, index, SaveDataRank::Primary);
}
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id) {
return Make(program_id, type, user_id, system_save_data_id, 0, SaveDataRank::Primary);
}
std::string DebugInfo() const {
return fmt::format(
"[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
"rank={}, index={}]",
program_id, user_id[1], user_id[0], system_save_data_id, static_cast<u8>(type),
static_cast<u8>(rank), index);
}
};
static_assert(sizeof(SaveDataAttribute) == 0x40);
static_assert(std::is_trivially_destructible<SaveDataAttribute>::value);
constexpr inline bool operator<(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.index, lhs.rank) <
std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.index, rhs.rank);
}
constexpr inline bool operator==(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.type, lhs.rank,
lhs.index) == std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id,
rhs.type, rhs.rank, rhs.index);
}
constexpr inline bool operator!=(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return !(lhs == rhs);
}
struct SaveDataExtraData {
SaveDataAttribute attr;
u64 owner_id;
s64 timestamp;
u32 flags;
INSERT_PADDING_BYTES(4);
s64 available_size;
s64 journal_size;
s64 commit_id;
INSERT_PADDING_BYTES(0x190);
};
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has invalid size.");
static_assert(std::is_trivially_copyable_v<SaveDataExtraData>,
"Data type must be trivially copyable.");
struct SaveDataFilter {
bool use_program_id;
bool use_save_data_type;
bool use_user_id;
bool use_save_data_id;
bool use_index;
SaveDataRank rank;
SaveDataAttribute attribute;
};
static_assert(sizeof(SaveDataFilter) == 0x48, "SaveDataFilter has invalid size.");
static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
"Data type must be trivially copyable.");
struct HashSalt {
static constexpr size_t Size = 32;
std::array<u8, Size> value;
};
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(HashSalt) == HashSalt::Size);
} // namespace FileSys

View File

@ -19,6 +19,11 @@ constexpr int Strlen(const T* str) {
return length;
}
template <typename T>
constexpr int Strnlen(const T* str, std::size_t count) {
return Strnlen(str, static_cast<int>(count));
}
template <typename T>
constexpr int Strnlen(const T* str, int count) {
ASSERT(str != nullptr);
@ -32,6 +37,11 @@ constexpr int Strnlen(const T* str, int count) {
return length;
}
template <typename T>
constexpr int Strncmp(const T* lhs, const T* rhs, std::size_t count) {
return Strncmp(lhs, rhs, static_cast<int>(count));
}
template <typename T>
constexpr int Strncmp(const T* lhs, const T* rhs, int count) {
ASSERT(lhs != nullptr);
@ -51,6 +61,11 @@ constexpr int Strncmp(const T* lhs, const T* rhs, int count) {
return l - r;
}
template <typename T>
static constexpr int Strlcpy(T* dst, const T* src, std::size_t count) {
return Strlcpy<T>(dst, src, static_cast<int>(count));
}
template <typename T>
static constexpr int Strlcpy(T* dst, const T* src, int count) {
ASSERT(dst != nullptr);

View File

@ -0,0 +1,91 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fs_directory.h"
#include "core/file_sys/fs_file.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/hle/result.h"
namespace FileSys::Fsa {
class IDirectory {
public:
explicit IDirectory(VirtualDir backend_, OpenDirectoryMode mode)
: backend(std::move(backend_)) {
// TODO(DarkLordZach): Verify that this is the correct behavior.
// Build entry index now to save time later.
if (True(mode & OpenDirectoryMode::Directory)) {
BuildEntryIndex(backend->GetSubdirectories(), DirectoryEntryType::Directory);
}
if (True(mode & OpenDirectoryMode::File)) {
BuildEntryIndex(backend->GetFiles(), DirectoryEntryType::File);
}
}
virtual ~IDirectory() {}
Result Read(s64* out_count, DirectoryEntry* out_entries, s64 max_entries) {
R_UNLESS(out_count != nullptr, ResultNullptrArgument);
if (max_entries == 0) {
*out_count = 0;
R_SUCCEED();
}
R_UNLESS(out_entries != nullptr, ResultNullptrArgument);
R_UNLESS(max_entries > 0, ResultInvalidArgument);
R_RETURN(this->DoRead(out_count, out_entries, max_entries));
}
Result GetEntryCount(s64* out) {
R_UNLESS(out != nullptr, ResultNullptrArgument);
R_RETURN(this->DoGetEntryCount(out));
}
private:
Result DoRead(s64* out_count, DirectoryEntry* out_entries, s64 max_entries) {
const u64 actual_entries =
std::min(static_cast<u64>(max_entries), entries.size() - next_entry_index);
const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index);
const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries);
const auto range_size = static_cast<std::size_t>(std::distance(begin, end));
next_entry_index += actual_entries;
*out_count = actual_entries;
std::memcpy(out_entries, begin, range_size);
R_SUCCEED();
}
Result DoGetEntryCount(s64* out) {
*out = entries.size() - next_entry_index;
R_SUCCEED();
}
// TODO: Remove this when VFS is gone
template <typename T>
void BuildEntryIndex(const std::vector<T>& new_data, DirectoryEntryType type) {
entries.reserve(entries.size() + new_data.size());
for (const auto& new_entry : new_data) {
auto name = new_entry->GetName();
if (type == DirectoryEntryType::File && name == GetSaveDataSizeFileName()) {
continue;
}
entries.emplace_back(name, static_cast<s8>(type),
type == DirectoryEntryType::Directory ? 0 : new_entry->GetSize());
}
}
VirtualDir backend;
std::vector<DirectoryEntry> entries;
u64 next_entry_index = 0;
};
} // namespace FileSys::Fsa

View File

@ -0,0 +1,167 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/overflow.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fs_file.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/fs_operate_range.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "core/hle/result.h"
namespace FileSys::Fsa {
class IFile {
public:
explicit IFile(VirtualFile backend_) : backend(std::move(backend_)) {}
virtual ~IFile() {}
Result Read(size_t* out, s64 offset, void* buffer, size_t size, const ReadOption& option) {
// Check that we have an output pointer
R_UNLESS(out != nullptr, ResultNullptrArgument);
// If we have nothing to read, just succeed
if (size == 0) {
*out = 0;
R_SUCCEED();
}
// Check that the read is valid
R_UNLESS(buffer != nullptr, ResultNullptrArgument);
R_UNLESS(offset >= 0, ResultOutOfRange);
R_UNLESS(Common::CanAddWithoutOverflow<s64>(offset, size), ResultOutOfRange);
// Do the read
R_RETURN(this->DoRead(out, offset, buffer, size, option));
}
Result Read(size_t* out, s64 offset, void* buffer, size_t size) {
R_RETURN(this->Read(out, offset, buffer, size, ReadOption::None));
}
Result GetSize(s64* out) {
R_UNLESS(out != nullptr, ResultNullptrArgument);
R_RETURN(this->DoGetSize(out));
}
Result Flush() {
R_RETURN(this->DoFlush());
}
Result Write(s64 offset, const void* buffer, size_t size, const WriteOption& option) {
// Handle the zero-size case
if (size == 0) {
if (option.HasFlushFlag()) {
R_TRY(this->Flush());
}
R_SUCCEED();
}
// Check the write is valid
R_UNLESS(buffer != nullptr, ResultNullptrArgument);
R_UNLESS(offset >= 0, ResultOutOfRange);
R_UNLESS(Common::CanAddWithoutOverflow<s64>(offset, size), ResultOutOfRange);
R_RETURN(this->DoWrite(offset, buffer, size, option));
}
Result SetSize(s64 size) {
R_UNLESS(size >= 0, ResultOutOfRange);
R_RETURN(this->DoSetSize(size));
}
Result OperateRange(void* dst, size_t dst_size, OperationId op_id, s64 offset, s64 size,
const void* src, size_t src_size) {
R_RETURN(this->DoOperateRange(dst, dst_size, op_id, offset, size, src, src_size));
}
Result OperateRange(OperationId op_id, s64 offset, s64 size) {
R_RETURN(this->DoOperateRange(nullptr, 0, op_id, offset, size, nullptr, 0));
}
protected:
Result DryRead(size_t* out, s64 offset, size_t size, const ReadOption& option,
OpenMode open_mode) {
// Check that we can read
R_UNLESS(static_cast<u32>(open_mode & OpenMode::Read) != 0, ResultReadNotPermitted);
// Get the file size, and validate our offset
s64 file_size = 0;
R_TRY(this->DoGetSize(std::addressof(file_size)));
R_UNLESS(offset <= file_size, ResultOutOfRange);
*out = static_cast<size_t>(std::min(file_size - offset, static_cast<s64>(size)));
R_SUCCEED();
}
Result DrySetSize(s64 size, OpenMode open_mode) {
// Check that we can write
R_UNLESS(static_cast<u32>(open_mode & OpenMode::Write) != 0, ResultWriteNotPermitted);
R_SUCCEED();
}
Result DryWrite(bool* out_append, s64 offset, size_t size, const WriteOption& option,
OpenMode open_mode) {
// Check that we can write
R_UNLESS(static_cast<u32>(open_mode & OpenMode::Write) != 0, ResultWriteNotPermitted);
// Get the file size
s64 file_size = 0;
R_TRY(this->DoGetSize(&file_size));
// Determine if we need to append
*out_append = false;
if (file_size < offset + static_cast<s64>(size)) {
R_UNLESS(static_cast<u32>(open_mode & OpenMode::AllowAppend) != 0,
ResultFileExtensionWithoutOpenModeAllowAppend);
*out_append = true;
}
R_SUCCEED();
}
private:
Result DoRead(size_t* out, s64 offset, void* buffer, size_t size, const ReadOption& option) {
const auto read_size = backend->Read(static_cast<u8*>(buffer), size, offset);
*out = read_size;
R_SUCCEED();
}
Result DoGetSize(s64* out) {
*out = backend->GetSize();
R_SUCCEED();
}
Result DoFlush() {
// Exists for SDK compatibiltity -- No need to flush file.
R_SUCCEED();
}
Result DoWrite(s64 offset, const void* buffer, size_t size, const WriteOption& option) {
const std::size_t written = backend->Write(static_cast<const u8*>(buffer), size, offset);
ASSERT_MSG(written == size,
"Could not write all bytes to file (requested={:016X}, actual={:016X}).", size,
written);
R_SUCCEED();
}
Result DoSetSize(s64 size) {
backend->Resize(size);
R_SUCCEED();
}
Result DoOperateRange(void* dst, size_t dst_size, OperationId op_id, s64 offset, s64 size,
const void* src, size_t src_size) {
R_THROW(ResultNotImplemented);
}
VirtualFile backend;
};
} // namespace FileSys::Fsa

View File

@ -0,0 +1,206 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/errors.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/fs_path.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "core/hle/result.h"
#include "core/hle/service/filesystem/filesystem.h"
namespace FileSys::Fsa {
class IFile;
class IDirectory;
enum class QueryId : u32 {
SetConcatenationFileAttribute = 0,
UpdateMac = 1,
IsSignedSystemPartitionOnSdCardValid = 2,
QueryUnpreparedFileInformation = 3,
};
class IFileSystem {
public:
explicit IFileSystem(VirtualDir backend_) : backend{std::move(backend_)} {}
virtual ~IFileSystem() {}
Result CreateFile(const Path& path, s64 size, CreateOption option) {
R_UNLESS(size >= 0, ResultOutOfRange);
R_RETURN(this->DoCreateFile(path, size, static_cast<int>(option)));
}
Result CreateFile(const Path& path, s64 size) {
R_RETURN(this->CreateFile(path, size, CreateOption::None));
}
Result DeleteFile(const Path& path) {
R_RETURN(this->DoDeleteFile(path));
}
Result CreateDirectory(const Path& path) {
R_RETURN(this->DoCreateDirectory(path));
}
Result DeleteDirectory(const Path& path) {
R_RETURN(this->DoDeleteDirectory(path));
}
Result DeleteDirectoryRecursively(const Path& path) {
R_RETURN(this->DoDeleteDirectoryRecursively(path));
}
Result RenameFile(const Path& old_path, const Path& new_path) {
R_RETURN(this->DoRenameFile(old_path, new_path));
}
Result RenameDirectory(const Path& old_path, const Path& new_path) {
R_RETURN(this->DoRenameDirectory(old_path, new_path));
}
Result GetEntryType(DirectoryEntryType* out, const Path& path) {
R_RETURN(this->DoGetEntryType(out, path));
}
Result OpenFile(VirtualFile* out_file, const Path& path, OpenMode mode) {
R_UNLESS(out_file != nullptr, ResultNullptrArgument);
R_UNLESS(static_cast<u32>(mode & OpenMode::ReadWrite) != 0, ResultInvalidOpenMode);
R_UNLESS(static_cast<u32>(mode & ~OpenMode::All) == 0, ResultInvalidOpenMode);
R_RETURN(this->DoOpenFile(out_file, path, mode));
}
Result OpenDirectory(VirtualDir* out_dir, const Path& path, OpenDirectoryMode mode) {
R_UNLESS(out_dir != nullptr, ResultNullptrArgument);
R_UNLESS(static_cast<u64>(mode & OpenDirectoryMode::All) != 0, ResultInvalidOpenMode);
R_UNLESS(static_cast<u64>(
mode & ~(OpenDirectoryMode::All | OpenDirectoryMode::NotRequireFileSize)) == 0,
ResultInvalidOpenMode);
R_RETURN(this->DoOpenDirectory(out_dir, path, mode));
}
Result Commit() {
R_RETURN(this->DoCommit());
}
Result GetFreeSpaceSize(s64* out, const Path& path) {
R_UNLESS(out != nullptr, ResultNullptrArgument);
R_RETURN(this->DoGetFreeSpaceSize(out, path));
}
Result GetTotalSpaceSize(s64* out, const Path& path) {
R_UNLESS(out != nullptr, ResultNullptrArgument);
R_RETURN(this->DoGetTotalSpaceSize(out, path));
}
Result CleanDirectoryRecursively(const Path& path) {
R_RETURN(this->DoCleanDirectoryRecursively(path));
}
Result GetFileTimeStampRaw(FileTimeStampRaw* out, const Path& path) {
R_UNLESS(out != nullptr, ResultNullptrArgument);
R_RETURN(this->DoGetFileTimeStampRaw(out, path));
}
Result QueryEntry(char* dst, size_t dst_size, const char* src, size_t src_size, QueryId query,
const Path& path) {
R_RETURN(this->DoQueryEntry(dst, dst_size, src, src_size, query, path));
}
// These aren't accessible as commands
Result CommitProvisionally(s64 counter) {
R_RETURN(this->DoCommitProvisionally(counter));
}
Result Rollback() {
R_RETURN(this->DoRollback());
}
Result Flush() {
R_RETURN(this->DoFlush());
}
private:
Result DoCreateFile(const Path& path, s64 size, int flags) {
R_RETURN(backend.CreateFile(path.GetString(), size));
}
Result DoDeleteFile(const Path& path) {
R_RETURN(backend.DeleteFile(path.GetString()));
}
Result DoCreateDirectory(const Path& path) {
R_RETURN(backend.CreateDirectory(path.GetString()));
}
Result DoDeleteDirectory(const Path& path) {
R_RETURN(backend.DeleteDirectory(path.GetString()));
}
Result DoDeleteDirectoryRecursively(const Path& path) {
R_RETURN(backend.DeleteDirectoryRecursively(path.GetString()));
}
Result DoRenameFile(const Path& old_path, const Path& new_path) {
R_RETURN(backend.RenameFile(old_path.GetString(), new_path.GetString()));
}
Result DoRenameDirectory(const Path& old_path, const Path& new_path) {
R_RETURN(backend.RenameDirectory(old_path.GetString(), new_path.GetString()));
}
Result DoGetEntryType(DirectoryEntryType* out, const Path& path) {
R_RETURN(backend.GetEntryType(out, path.GetString()));
}
Result DoOpenFile(VirtualFile* out_file, const Path& path, OpenMode mode) {
R_RETURN(backend.OpenFile(out_file, path.GetString(), mode));
}
Result DoOpenDirectory(VirtualDir* out_directory, const Path& path, OpenDirectoryMode mode) {
R_RETURN(backend.OpenDirectory(out_directory, path.GetString()));
}
Result DoCommit() {
R_THROW(ResultNotImplemented);
}
Result DoGetFreeSpaceSize(s64* out, const Path& path) {
R_THROW(ResultNotImplemented);
}
Result DoGetTotalSpaceSize(s64* out, const Path& path) {
R_THROW(ResultNotImplemented);
}
Result DoCleanDirectoryRecursively(const Path& path) {
R_RETURN(backend.CleanDirectoryRecursively(path.GetString()));
}
Result DoGetFileTimeStampRaw(FileTimeStampRaw* out, const Path& path) {
R_RETURN(backend.GetFileTimeStampRaw(out, path.GetString()));
}
Result DoQueryEntry(char* dst, size_t dst_size, const char* src, size_t src_size, QueryId query,
const Path& path) {
R_THROW(ResultNotImplemented);
}
// These aren't accessible as commands
Result DoCommitProvisionally(s64 counter) {
R_THROW(ResultNotImplemented);
}
Result DoRollback() {
R_THROW(ResultNotImplemented);
}
Result DoFlush() {
R_THROW(ResultNotImplemented);
}
Service::FileSystem::VfsDirectoryServiceWrapper backend;
};
} // namespace FileSys::Fsa

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/fs_directory.h"
namespace FileSys::Sf {
struct Path {
char str[EntryNameLengthMax + 1];
static constexpr Path Encode(const char* p) {
Path path = {};
for (size_t i = 0; i < sizeof(path) - 1; i++) {
path.str[i] = p[i];
if (p[i] == '\x00') {
break;
}
}
return path;
}
static constexpr size_t GetPathLength(const Path& path) {
size_t len = 0;
for (size_t i = 0; i < sizeof(path) - 1 && path.str[i] != '\x00'; i++) {
len++;
}
return len;
}
};
static_assert(std::is_trivially_copyable_v<Path>, "Path must be trivially copyable.");
using FspPath = Path;
} // namespace FileSys::Sf

View File

@ -3,6 +3,7 @@
#pragma once
#include <mutex>
#include <optional>
#include "core/crypto/aes_util.h"

View File

@ -36,7 +36,9 @@ Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 lay
// Get the base storage size.
m_base_storage_size = base_storages[2]->GetSize();
{
auto size_guard = SCOPE_GUARD({ m_base_storage_size = 0; });
auto size_guard = SCOPE_GUARD {
m_base_storage_size = 0;
};
R_UNLESS(m_base_storage_size <= static_cast<s64>(HashSize)
<< m_log_size_ratio << m_log_size_ratio,
ResultHierarchicalSha256BaseStorageTooLarge);

View File

@ -98,7 +98,9 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
Loader::ResultStatus ProgramMetadata::Reload(VirtualFile file) {
const u64 original_program_id = aci_header.title_id;
SCOPE_EXIT({ aci_header.title_id = original_program_id; });
SCOPE_EXIT {
aci_header.title_id = original_program_id;
};
return this->Load(file);
}

View File

@ -14,48 +14,11 @@ namespace FileSys {
namespace {
void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) {
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
if (meta.zero_1 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).",
meta.zero_1);
}
if (meta.zero_2 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).",
meta.zero_2);
}
if (meta.zero_3 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).",
meta.zero_3);
}
}
if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is SystemSaveData but title_id is "
"non-zero ({:016X}).",
meta.title_id);
}
if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is DeviceSaveData but user_id is "
"non-zero ({:016X}{:016X})",
meta.user_id[1], meta.user_id[0]);
}
}
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) {
return attr.type == SaveDataType::CacheStorage || attr.type == SaveDataType::TemporaryStorage ||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
(attr.type == SaveDataType::SaveData || attr.type == SaveDataType::DeviceSaveData) &&
attr.title_id == 0 && attr.save_id == 0);
return attr.type == SaveDataType::Cache || attr.type == SaveDataType::Temporary ||
(space == SaveDataSpaceId::User && ///< Normal Save Data -- Current Title & User
(attr.type == SaveDataType::Account || attr.type == SaveDataType::Device) &&
attr.program_id == 0 && attr.system_save_data_id == 0);
}
std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
@ -63,7 +26,7 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
// Only detect nand user saves.
const auto space_id_path = [space_id]() -> std::string_view {
switch (space_id) {
case SaveDataSpaceId::NandUser:
case SaveDataSpaceId::User:
return "/user/save";
default:
return "";
@ -79,9 +42,9 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
// Only detect account/device saves from the future location.
switch (type) {
case SaveDataType::SaveData:
case SaveDataType::Account:
return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id);
case SaveDataType::DeviceSaveData:
case SaveDataType::Device:
return fmt::format("{}/device/{:016X}/0", space_id_path, title_id);
default:
return "";
@ -90,13 +53,6 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
} // Anonymous namespace
std::string SaveDataAttribute::DebugInfo() const {
return fmt::format("[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
"rank={}, index={}]",
title_id, user_id[1], user_id[0], save_id, static_cast<u8>(type),
static_cast<u8>(rank), index);
}
SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
VirtualDir save_directory_)
: system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} {
@ -108,18 +64,16 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
SaveDataFactory::~SaveDataFactory() = default;
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
PrintSaveDataAttributeWarnings(meta);
const auto save_directory =
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
meta.user_id, meta.system_save_data_id);
return dir->CreateDirectoryRelative(save_directory);
}
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
const auto save_directory =
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
meta.user_id, meta.system_save_data_id);
auto out = dir->GetDirectoryRelative(save_directory);
@ -136,11 +90,11 @@ VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) con
std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
switch (space) {
case SaveDataSpaceId::NandSystem:
case SaveDataSpaceId::System:
return "/system/";
case SaveDataSpaceId::NandUser:
case SaveDataSpaceId::User:
return "/user/";
case SaveDataSpaceId::TemporaryStorage:
case SaveDataSpaceId::Temporary:
return "/temp/";
default:
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
@ -153,7 +107,7 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
u128 user_id, u64 save_id) {
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
// be interpreted as the title id of the current process.
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
if (type == SaveDataType::Account || type == SaveDataType::Device) {
if (title_id == 0) {
title_id = program_id;
}
@ -173,16 +127,16 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
std::string out = GetSaveDataSpaceIdPath(space);
switch (type) {
case SaveDataType::SystemSaveData:
case SaveDataType::System:
return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]);
case SaveDataType::SaveData:
case SaveDataType::DeviceSaveData:
case SaveDataType::Account:
case SaveDataType::Device:
return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
title_id);
case SaveDataType::TemporaryStorage:
case SaveDataType::Temporary:
return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
title_id);
case SaveDataType::CacheStorage:
case SaveDataType::Cache:
return fmt::format("{}save/cache/{:016X}", out, title_id);
default:
ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type));
@ -202,7 +156,7 @@ std::string SaveDataFactory::GetUserGameSaveDataRoot(u128 user_id, bool future)
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
u128 user_id) const {
const auto path =
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
@ -221,7 +175,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
SaveDataSize new_value) const {
const auto path =
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());

View File

@ -7,6 +7,7 @@
#include <string>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/file_sys/fs_save_data_types.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/hle/result.h"
@ -16,73 +17,6 @@ class System;
namespace FileSys {
enum class SaveDataSpaceId : u8 {
NandSystem = 0,
NandUser = 1,
SdCardSystem = 2,
TemporaryStorage = 3,
SdCardUser = 4,
ProperSystem = 100,
SafeMode = 101,
};
enum class SaveDataType : u8 {
SystemSaveData = 0,
SaveData = 1,
BcatDeliveryCacheStorage = 2,
DeviceSaveData = 3,
TemporaryStorage = 4,
CacheStorage = 5,
SystemBcat = 6,
};
enum class SaveDataRank : u8 {
Primary = 0,
Secondary = 1,
};
enum class SaveDataFlags : u32 {
None = (0 << 0),
KeepAfterResettingSystemSaveData = (1 << 0),
KeepAfterRefurbishment = (1 << 1),
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
NeedsSecureDelete = (1 << 3),
};
struct SaveDataAttribute {
u64 title_id;
u128 user_id;
u64 save_id;
SaveDataType type;
SaveDataRank rank;
u16 index;
INSERT_PADDING_BYTES_NOINIT(4);
u64 zero_1;
u64 zero_2;
u64 zero_3;
std::string DebugInfo() const;
};
static_assert(sizeof(SaveDataAttribute) == 0x40, "SaveDataAttribute has incorrect size.");
struct SaveDataExtraData {
SaveDataAttribute attr;
u64 owner_id;
s64 timestamp;
SaveDataFlags flags;
INSERT_PADDING_BYTES_NOINIT(4);
s64 available_size;
s64 journal_size;
s64 commit_id;
std::array<u8, 0x190> unused;
};
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has incorrect size.");
struct SaveDataSize {
u64 normal;
u64 journal;
};
constexpr const char* GetSaveDataSizeFileName() {
return ".yuzu_save_size";
}

View File

@ -9,7 +9,7 @@
#include "core/file_sys/system_archive/data/font_standard.h"
#include "core/file_sys/system_archive/shared_font.h"
#include "core/file_sys/vfs/vfs_vector.h"
#include "core/hle/service/ns/iplatform_service_manager.h"
#include "core/hle/service/ns/platform_service_manager.h"
namespace FileSys::SystemArchive {

View File

@ -44,15 +44,32 @@ public:
GuestMemory() = delete;
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
Common::ScratchBuffer<T>* backup = nullptr)
: m_memory{memory}, m_addr{addr}, m_size{size} {
: m_memory{&memory}, m_addr{addr}, m_size{size} {
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
if constexpr (FLAGS & GuestMemoryFlags::Read) {
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
if (!this->TrySetSpan()) {
if (backup) {
backup->resize_destructive(this->size());
m_data_span = *backup;
m_span_valid = true;
m_is_data_copy = true;
} else {
m_data_copy.resize(this->size());
m_data_span = std::span(m_data_copy);
m_span_valid = true;
m_is_data_copy = true;
}
}
} else if constexpr (FLAGS & GuestMemoryFlags::Read) {
Read(addr, size, backup);
}
}
~GuestMemory() = default;
GuestMemory(GuestMemory&& rhs) = default;
GuestMemory& operator=(GuestMemory&& rhs) = default;
T* data() noexcept {
return m_data_span.data();
}
@ -109,8 +126,8 @@ public:
}
if (this->TrySetSpan()) {
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
m_memory.FlushRegion(m_addr, this->size_bytes());
if constexpr (FLAGS & GuestMemoryFlags::Safe && M::HAS_FLUSH_INVALIDATION) {
m_memory->FlushRegion(m_addr, this->size_bytes());
}
} else {
if (backup) {
@ -123,9 +140,9 @@ public:
m_is_data_copy = true;
m_span_valid = true;
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
m_memory->ReadBlock(m_addr, this->data(), this->size_bytes());
} else {
m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
m_memory->ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
}
}
return m_data_span;
@ -133,18 +150,19 @@ public:
void Write(std::span<T> write_data) noexcept {
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
m_memory->WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
m_memory->WriteBlock(m_addr, write_data.data(), this->size_bytes());
} else {
m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
m_memory->WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
}
}
bool TrySetSpan() noexcept {
if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
if (u8* ptr = m_memory->GetSpan(m_addr, this->size_bytes()); ptr) {
m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
m_span_valid = true;
m_is_data_copy = false;
return true;
}
return false;
@ -159,7 +177,7 @@ protected:
return m_addr_changed;
}
M& m_memory;
M* m_memory;
u64 m_addr{};
size_t m_size{};
std::span<T> m_data_span{};
@ -175,17 +193,7 @@ public:
GuestMemoryScoped() = delete;
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
Common::ScratchBuffer<T>* backup = nullptr)
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
if (!this->TrySetSpan()) {
if (backup) {
this->m_data_span = *backup;
this->m_span_valid = true;
this->m_is_data_copy = true;
}
}
}
}
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {}
~GuestMemoryScoped() {
if constexpr (FLAGS & GuestMemoryFlags::Write) {
@ -196,15 +204,17 @@ public:
if (this->AddressChanged() || this->IsDataCopy()) {
ASSERT(this->m_span_valid);
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
this->m_memory->WriteBlockCached(this->m_addr, this->data(),
this->size_bytes());
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes());
} else {
this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(),
this->size_bytes());
}
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
(FLAGS & GuestMemoryFlags::Cached)) {
this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
this->m_memory->InvalidateRegion(this->m_addr, this->size_bytes());
}
}
}

View File

@ -24,7 +24,9 @@ Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) {
// Create a session request.
KSessionRequest* request = KSessionRequest::Create(m_kernel);
R_UNLESS(request != nullptr, ResultOutOfResource);
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// Initialize the request.
request->Initialize(nullptr, address, size);
@ -37,7 +39,9 @@ Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t
// Create a session request.
KSessionRequest* request = KSessionRequest::Create(m_kernel);
R_UNLESS(request != nullptr, ResultOutOfResource);
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// Initialize the request.
request->Initialize(event, address, size);

View File

@ -1305,11 +1305,11 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
// Ensure that we maintain the instruction cache.
bool reprotected_pages = false;
SCOPE_EXIT({
SCOPE_EXIT {
if (reprotected_pages && any_code_pages) {
InvalidateInstructionCache(m_kernel, this, dst_address, size);
}
});
};
// Unmap.
{
@ -1397,7 +1397,9 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// Close the opened pages when we're done with them.
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically.
SCOPE_EXIT({ pg.Close(); });
SCOPE_EXIT {
pg.Close();
};
// Clear all the newly allocated pages.
for (const auto& it : pg) {
@ -1603,7 +1605,9 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option));
// Ensure that the page group is closed when we're done working with it.
SCOPE_EXIT({ pg.Close(); });
SCOPE_EXIT {
pg.Close();
};
// Clear all pages.
for (const auto& it : pg) {
@ -2191,7 +2195,9 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
// Close the opened pages when we're done with them.
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically.
SCOPE_EXIT({ pg.Close(); });
SCOPE_EXIT {
pg.Close();
};
// Clear all the newly allocated pages.
for (const auto& it : pg) {
@ -2592,7 +2598,9 @@ Result KPageTableBase::UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddre
// Temporarily unlock ourselves, so that other operations can occur while we flush the
// region.
m_general_lock.Unlock();
SCOPE_EXIT({ m_general_lock.Lock(); });
SCOPE_EXIT {
m_general_lock.Lock();
};
// Flush the region.
R_ASSERT(FlushDataCache(dst_address, size));
@ -3311,10 +3319,10 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre
// Ensure we unmap the io memory when we're done with it.
const KPageProperties unmap_properties =
KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None};
SCOPE_EXIT({
SCOPE_EXIT {
R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,
unmap_properties, OperationType::Unmap, true));
});
};
// Read the memory.
const KProcessAddress read_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1));
@ -3347,10 +3355,10 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd
// Ensure we unmap the io memory when we're done with it.
const KPageProperties unmap_properties =
KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None};
SCOPE_EXIT({
SCOPE_EXIT {
R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,
unmap_properties, OperationType::Unmap, true));
});
};
// Write the memory.
const KProcessAddress write_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1));
@ -4491,14 +4499,14 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// If the partial pages are mapped, an extra reference will have been opened. Otherwise, they'll
// free on scope exit.
SCOPE_EXIT({
SCOPE_EXIT {
if (start_partial_page != 0) {
m_kernel.MemoryManager().Close(start_partial_page, 1);
}
if (end_partial_page != 0) {
m_kernel.MemoryManager().Close(end_partial_page, 1);
}
});
};
ON_RESULT_FAILURE {
if (cur_mapped_addr != dst_addr) {
@ -5166,10 +5174,10 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value));
// If we fail in the next bit (or retry), we need to cleanup the pages.
auto pg_guard = SCOPE_GUARD({
auto pg_guard = SCOPE_GUARD {
pg.OpenFirst();
pg.Close();
});
};
// Map the memory.
{
@ -5694,7 +5702,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
// Ensure that any pages we track are closed on exit.
KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager());
SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
SCOPE_EXIT {
pages_to_close.CloseAndReset();
};
// Make a page group representing the region to unmap.
this->MakePageGroup(pages_to_close, virt_addr, num_pages);

View File

@ -77,7 +77,9 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process,
}
// Terminate and close the thread.
SCOPE_EXIT({ cur_child->Close(); });
SCOPE_EXIT {
cur_child->Close();
};
if (const Result terminate_result = cur_child->Terminate();
ResultTerminationRequested == terminate_result) {
@ -466,11 +468,11 @@ void KProcess::DoWorkerTaskImpl() {
Result KProcess::StartTermination() {
// Finalize the handle table when we're done, if the process isn't immortal.
SCOPE_EXIT({
SCOPE_EXIT {
if (!m_is_immortal) {
this->FinalizeHandleTable();
}
});
};
// Terminate child threads other than the current one.
R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel)));
@ -964,7 +966,9 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
// Create a new thread for the process.
KThread* main_thread = KThread::Create(m_kernel);
R_UNLESS(main_thread != nullptr, ResultOutOfResource);
SCOPE_EXIT({ main_thread->Close(); });
SCOPE_EXIT {
main_thread->Close();
};
// Initialize the thread.
R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0,
@ -1155,7 +1159,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
// Ensure we maintain a clean state on exit.
SCOPE_EXIT({ res_limit->Close(); });
SCOPE_EXIT {
res_limit->Close();
};
// Declare flags and code address.
Svc::CreateProcessFlag flag{};

View File

@ -651,11 +651,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any special data.
if (src_header.GetHasSpecialHeader()) {
// After we process, make sure we track whether the receive list is broken.
SCOPE_EXIT({
SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
});
};
// Process special data.
R_TRY(ProcessMessageSpecialData<false>(offset, dst_process, src_process, src_thread,
@ -665,11 +665,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any pointer buffers.
for (auto i = 0; i < src_header.GetPointerCount(); ++i) {
// After we process, make sure we track whether the receive list is broken.
SCOPE_EXIT({
SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
});
};
R_TRY(ProcessReceiveMessagePointerDescriptors(
offset, pointer_key, dst_page_table, src_page_table, dst_msg, src_msg, dst_recv_list,
@ -680,11 +680,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any map alias buffers.
for (auto i = 0; i < src_header.GetMapAliasCount(); ++i) {
// After we process, make sure we track whether the receive list is broken.
SCOPE_EXIT({
SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
});
};
// We process in order send, recv, exch. Buffers after send (recv/exch) are ReadWrite.
const KMemoryPermission perm = (i >= src_header.GetSendCount())
@ -702,11 +702,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any raw data.
if (const auto raw_count = src_header.GetRawCount(); raw_count != 0) {
// After we process, make sure we track whether the receive list is broken.
SCOPE_EXIT({
SCOPE_EXIT {
if (offset + raw_count > dst_recv_list_idx) {
recv_list_broken = true;
}
});
};
// Get the offset and size.
const size_t offset_words = offset * sizeof(u32);
@ -1124,7 +1124,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server
client_thread->Open();
}
SCOPE_EXIT({ client_thread->Close(); });
SCOPE_EXIT {
client_thread->Close();
};
// Set the request as our current.
m_current_request = request;
@ -1174,7 +1176,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server
// Reply to the client.
{
// After we reply, close our reference to the request.
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// Get the event to check whether the request is async.
if (KEvent* event = request->GetEvent(); event != nullptr) {
@ -1236,7 +1240,9 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff
}
// Close reference to the request once we're done processing it.
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// Extract relevant information from the request.
const uint64_t client_message = request->GetAddress();
@ -1394,7 +1400,9 @@ void KServerSession::CleanupRequests() {
}
// Close a reference to the request once it's cleaned up.
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// Extract relevant information from the request.
const uint64_t client_message = request->GetAddress();
@ -1491,7 +1499,9 @@ void KServerSession::OnClientClosed() {
ASSERT(thread != nullptr);
// Ensure that we close the request when done.
SCOPE_EXIT({ request->Close(); });
SCOPE_EXIT {
request->Close();
};
// If we're terminating, close a reference to the thread and event.
if (terminate) {

View File

@ -21,7 +21,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
// Allocate a new page.
KPageBuffer* page_buf = KPageBuffer::Allocate(kernel);
R_UNLESS(page_buf != nullptr, ResultOutOfMemory);
auto page_buf_guard = SCOPE_GUARD({ KPageBuffer::Free(kernel, page_buf); });
auto page_buf_guard = SCOPE_GUARD {
KPageBuffer::Free(kernel, page_buf);
};
// Map the address in.
const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);

View File

@ -24,7 +24,9 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size,
// Construct the page group, guarding to make sure our state is valid on exit.
m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
auto pg_guard = SCOPE_GUARD({ m_page_group.reset(); });
auto pg_guard = SCOPE_GUARD {
m_page_group.reset();
};
// Lock the memory.
R_TRY(page_table.LockForTransferMemory(std::addressof(*m_page_group), addr, size,

View File

@ -109,7 +109,9 @@ struct KernelCore::Impl {
void Shutdown() {
is_shutting_down.store(true, std::memory_order_relaxed);
SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); });
SCOPE_EXIT {
is_shutting_down.store(false, std::memory_order_relaxed);
};
CloseServices();
@ -1080,7 +1082,9 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
// Ensure that we don't hold onto any extra references.
SCOPE_EXIT({ process->Close(); });
SCOPE_EXIT {
process->Close();
};
// Register the new process.
KProcess::Register(*this, process);
@ -1108,7 +1112,9 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function
process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
// Ensure that we don't hold onto any extra references.
SCOPE_EXIT({ process->Close(); });
SCOPE_EXIT {
process->Close();
};
// Register the new process.
KProcess::Register(*this, process);

View File

@ -45,7 +45,9 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t
KCodeMemory* code_mem = KCodeMemory::Create(kernel);
R_UNLESS(code_mem != nullptr, ResultOutOfResource);
SCOPE_EXIT({ code_mem->Close(); });
SCOPE_EXIT {
code_mem->Close();
};
// Verify that the region is in range.
R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size),

View File

@ -28,7 +28,9 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_
// Create the device address space.
KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel());
R_UNLESS(das != nullptr, ResultOutOfResource);
SCOPE_EXIT({ das->Close(); });
SCOPE_EXIT {
das->Close();
};
// Initialize the device address space.
R_TRY(das->Initialize(das_address, das_size));

View File

@ -72,10 +72,10 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
event_reservation.Commit();
// Ensure that we clean up the event (and its only references are handle table) on function end.
SCOPE_EXIT({
SCOPE_EXIT {
event->GetReadableEvent().Close();
event->Close();
});
};
// Register the event.
KEvent::Register(kernel, event);

View File

@ -129,11 +129,11 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
SCOPE_EXIT {
for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
};
R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs,
num_handles, reply_target, timeout_ns));
@ -208,10 +208,10 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
event_reservation.Commit();
// At end of scope, kill the standing references to the sub events.
SCOPE_EXIT({
SCOPE_EXIT {
event->GetReadableEvent().Close();
event->Close();
});
};
// Register the event.
KEvent::Register(system.Kernel(), event);

View File

@ -68,10 +68,10 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
port->Initialize(max_sessions, is_light, name);
// Ensure that we clean up the port (and its only references are handle table) on function end.
SCOPE_EXIT({
SCOPE_EXIT {
port->GetServerPort().Close();
port->GetClientPort().Close();
});
};
// Register the port.
KPort::Register(kernel, port);
@ -150,10 +150,10 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t
KPort::Register(system.Kernel(), port);
// Ensure that our only reference to the port is in the handle table when we're done.
SCOPE_EXIT({
SCOPE_EXIT {
port->GetClientPort().Close();
port->GetServerPort().Close();
});
};
// Register the handle in the table.
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));

View File

@ -18,7 +18,9 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
R_UNLESS(resource_limit != nullptr, ResultOutOfResource);
// Ensure we don't leak a reference to the limit.
SCOPE_EXIT({ resource_limit->Close(); });
SCOPE_EXIT {
resource_limit->Close();
};
// Initialize the resource limit.
resource_limit->Initialize();

View File

@ -69,10 +69,10 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
// Ensure that we clean up the session (and its only references are handle table) on function
// end.
SCOPE_EXIT({
SCOPE_EXIT {
session->GetClientSession().Close();
session->GetServerSession().Close();
});
};
// Register the session.
T::Register(system.Kernel(), session);

View File

@ -78,11 +78,11 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
SCOPE_EXIT {
for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
};
// Convert the timeout from nanoseconds to ticks.
s64 timeout;

View File

@ -51,7 +51,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
// Create the thread.
KThread* thread = KThread::Create(kernel);
R_UNLESS(thread != nullptr, ResultOutOfResource)
SCOPE_EXIT({ thread->Close(); });
SCOPE_EXIT {
thread->Close();
};
// Initialize the thread.
{

View File

@ -52,7 +52,9 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
R_UNLESS(trmem != nullptr, ResultOutOfResource);
// Ensure the only reference is in the handle table when we're done.
SCOPE_EXIT({ trmem->Close(); });
SCOPE_EXIT {
trmem->Close();
};
// Ensure that the region is in range.
R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory);

View File

@ -8,13 +8,13 @@
namespace Service::AM {
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService(
"appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
server_manager->RegisterNamedService(
"appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
server_manager->RegisterNamedService("appletAE",
std::make_shared<IAllSystemAppletProxiesService>(system));
server_manager->RegisterNamedService("appletOE",
std::make_shared<IApplicationProxyService>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -7,12 +7,8 @@ namespace Core {
class System;
}
namespace Service::Nvnflinger {
class Nvnflinger;
}
namespace Service::AM {
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
void LoopProcess(Core::System& system);
} // namespace Service::AM

View File

@ -14,10 +14,9 @@
#include "core/hle/service/am/am_types.h"
#include "core/hle/service/am/applet_message_queue.h"
#include "core/hle/service/am/display_layer_manager.h"
#include "core/hle/service/am/hid_registration.h"
#include "core/hle/service/am/managed_layer_holder.h"
#include "core/hle/service/am/process.h"
#include "core/hle/service/am/system_buffer_manager.h"
namespace Service::AM {
@ -54,8 +53,7 @@ struct Applet {
HidRegistration hid_registration;
// vi state
SystemBufferManager system_buffer_manager{};
ManagedLayerHolder managed_layer_holder{};
DisplayLayerManager display_layer_manager{};
// Applet common functions
Result terminate_result{};

View File

@ -24,11 +24,11 @@ void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) {
Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) {
std::scoped_lock lk{m_lock};
SCOPE_EXIT({
SCOPE_EXIT {
if (m_data.empty()) {
m_event.Clear();
}
});
};
R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel);

View File

@ -0,0 +1,151 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/am/display_layer_manager.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/application_display_service.h"
#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/manager_display_service.h"
#include "core/hle/service/vi/manager_root_service.h"
#include "core/hle/service/vi/shared_buffer_manager.h"
#include "core/hle/service/vi/vi_results.h"
#include "core/hle/service/vi/vi_types.h"
namespace Service::AM {
DisplayLayerManager::DisplayLayerManager() = default;
DisplayLayerManager::~DisplayLayerManager() {
this->Finalize();
}
void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process,
AppletId applet_id, LibraryAppletMode mode) {
R_ASSERT(system.ServiceManager()
.GetService<VI::IManagerRootService>("vi:m", true)
->GetDisplayService(&m_display_service, VI::Policy::Compositor));
R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service));
m_process = process;
m_system_shared_buffer_id = 0;
m_system_shared_layer_id = 0;
m_applet_id = applet_id;
m_buffer_sharing_enabled = false;
m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
}
void DisplayLayerManager::Finalize() {
if (!m_manager_display_service) {
return;
}
// Clean up managed layers.
for (const auto& layer : m_managed_display_layers) {
m_manager_display_service->DestroyManagedLayer(layer);
}
for (const auto& layer : m_managed_display_recording_layers) {
m_manager_display_service->DestroyManagedLayer(layer);
}
// Clean up shared layers.
if (m_buffer_sharing_enabled) {
m_manager_display_service->DestroySharedLayerSession(m_process);
}
m_manager_display_service = nullptr;
m_display_service = nullptr;
}
Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
u64 display_id;
R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
R_TRY(m_manager_display_service->CreateManagedLayer(
out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
m_managed_display_layers.emplace(*out_layer_id);
R_SUCCEED();
}
Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id,
u64* out_recording_layer_id) {
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
// side effects.
*out_recording_layer_id = 0;
R_RETURN(this->CreateManagedDisplayLayer(out_layer_id));
}
Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
// Succeed if already enabled.
R_SUCCEED_IF(m_buffer_sharing_enabled);
// Ensure we can access shared layers.
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied);
// Create the shared layer.
u64 display_id;
R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id,
&m_system_shared_layer_id, display_id,
m_blending_enabled));
// We succeeded, so set up remaining state.
m_buffer_sharing_enabled = true;
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
R_SUCCEED();
}
Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
u64* out_system_shared_layer_id) {
R_TRY(this->IsSystemBufferSharingEnabled());
*out_system_shared_buffer_id = m_system_shared_buffer_id;
*out_system_shared_layer_id = m_system_shared_layer_id;
R_SUCCEED();
}
void DisplayLayerManager::SetWindowVisibility(bool visible) {
if (m_visible == visible) {
return;
}
m_visible = visible;
if (m_manager_display_service) {
if (m_system_shared_layer_id) {
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
}
for (const auto layer_id : m_managed_display_layers) {
m_manager_display_service->SetLayerVisibility(m_visible, layer_id);
}
}
}
bool DisplayLayerManager::GetWindowVisibility() const {
return m_visible;
}
Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
s32* out_fbshare_layer_index) {
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
out_was_written, out_fbshare_layer_index));
}
} // namespace Service::AM

View File

@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <set>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "core/hle/service/am/am_types.h"
namespace Core {
class System;
}
namespace Kernel {
class KProcess;
}
namespace Service::VI {
class IApplicationDisplayService;
class IManagerDisplayService;
} // namespace Service::VI
namespace Service::AM {
class DisplayLayerManager {
public:
explicit DisplayLayerManager();
~DisplayLayerManager();
void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id,
LibraryAppletMode mode);
void Finalize();
Result CreateManagedDisplayLayer(u64* out_layer_id);
Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id);
Result IsSystemBufferSharingEnabled();
Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
u64* out_system_shared_layer_id);
void SetWindowVisibility(bool visible);
bool GetWindowVisibility() const;
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
private:
Kernel::KProcess* m_process{};
std::shared_ptr<VI::IApplicationDisplayService> m_display_service{};
std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{};
std::set<u64> m_managed_display_layers{};
std::set<u64> m_managed_display_recording_layers{};
u64 m_system_shared_buffer_id{};
u64 m_system_shared_layer_id{};
AppletId m_applet_id{};
bool m_buffer_sharing_enabled{};
bool m_blending_enabled{};
bool m_visible{true};
};
} // namespace Service::AM

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