Compare commits

...

125 Commits

Author SHA1 Message Date
fbf15f5058 Android 222 2024-02-01 01:00:39 +00:00
f10157485d Merge yuzu-emu#12875 2024-02-01 01:00:39 +00:00
89f733a518 Merge yuzu-emu#12874 2024-02-01 01:00:39 +00:00
95802bc5b5 Merge yuzu-emu#12848 2024-02-01 01:00:39 +00:00
680fcdac60 Merge yuzu-emu#12749 2024-02-01 01:00:39 +00:00
386325553b Merge yuzu-emu#12461 2024-02-01 01:00:39 +00:00
c98d0e185f Merge pull request #12870 from liamwhite/mac-ci
ci: bump mac to macos-14
2024-01-31 11:52:27 -05:00
7cc7d027f7 Merge pull request #12760 from liamwhite/mp-am
am: rewrite for multiprocess support
2024-01-31 10:25:28 -06:00
12e5293c73 Merge pull request #12858 from liamwhite/non-blocking
internal_network: only poll for accept on blocking sockets
2024-01-31 10:24:30 -06:00
22492b68b7 Merge pull request #12869 from FernandoS27/smmu-fixes
SMMU: A set of different fixes.
2024-01-31 11:22:29 -05:00
a12a26e19b Merge pull request #12864 from Kelebek1/small_time_fixes
Small time fixes
2024-01-31 11:22:16 -05:00
2a2a1d98b3 Merge pull request #12868 from t895/engine-per-game
settings: Allow audio sink, input, and output to be set per game
2024-01-31 11:22:04 -05:00
6e92a7a149 aoc: fix DLC listing (#12867) 2024-01-31 17:21:34 +01:00
4dfe9dd038 ci: bump mac to macos-14 2024-01-31 11:17:09 -05:00
d57165df45 Device Memory Manager: ensure raster protection only within mapped device addresses. 2024-01-31 16:38:51 +01:00
738e9a79a0 DeviceMemory: Make counter types configurable 2024-01-31 16:38:51 +01:00
aaab11e36f NVDRV: Join the heaper optimization blocks 2024-01-31 16:38:51 +01:00
8f848f43e9 smmu: use new range mutex construction for protecting counters 2024-01-31 16:38:51 +01:00
a7c1306e2d Texture Cache: make sparse texture table per channel 2024-01-31 16:38:51 +01:00
e8be665f11 settings: Allow audio sink, input, and output to be set per game 2024-01-31 09:31:19 -05:00
9ed82a280e Remove a few hacks for clock setups, which seem to no longer be needed, but fix network clock to local clock on every boot. Also fix some logging strings. 2024-01-31 01:41:59 +00:00
817d916233 am: push storage from error applet with non-zero size 2024-01-30 20:13:48 -05:00
ffe3984353 Merge pull request #12860 from liamwhite/serialization2
cmif_serialization: fix LargeData types
2024-01-30 14:29:41 -05:00
ec734cb06c Merge pull request #12859 from german77/led
service: hid: Implement GetPlayerLedPattern accurately
2024-01-30 14:29:33 -05:00
8292ba7ad6 cmif_serialization: fix LargeData types 2024-01-30 12:26:32 -05:00
2e65616761 Merge pull request #12856 from liamwhite/serialization
cmif_serialization: fix out layout calculation
2024-01-30 11:59:00 -05:00
07aa1a99fa Merge pull request #12849 from LotP1/patch-1
Add support for the CONNREFUSED socket error
2024-01-30 11:58:55 -05:00
6524f20de4 Merge pull request #12847 from abouvier/cmake-oaknut
cmake: prefer system oaknut library
2024-01-30 11:58:48 -05:00
a0f7f2b309 service: hid: Implement GetPlayerLedPattern accurately 2024-01-30 10:57:03 -06:00
5510b31972 internal_network: only poll for accept on blocking sockets 2024-01-30 10:29:05 -05:00
ecea5ef757 Update sockets.h
forgot to realign the enum
2024-01-30 12:24:47 +01:00
a1ce45b0b1 Update src/core/hle/service/sockets/sockets.h
Co-authored-by: liamwhite <liamwhite@users.noreply.github.com>
2024-01-30 11:01:04 +01:00
9ba9780a96 cmif_serialization: fix out layout calculation 2024-01-30 02:22:45 -05:00
73e7a259fd cmake: prefer system oaknut library 2024-01-30 02:57:50 +01:00
8e0a40434c am: stop emulation when all applets are closed 2024-01-29 20:17:33 -05:00
68303ed601 core: support offline web applet 2024-01-29 20:17:33 -05:00
8a146469c0 am: return AppletDataBroker and use for frontend applets 2024-01-29 20:17:33 -05:00
b1c2f791af am: rework IStorage for transfer storage 2024-01-29 20:17:33 -05:00
182137a9a4 am: migrate global state to per-applet state structure 2024-01-29 20:17:33 -05:00
3155f4e96d am: retrieve main applet creation info from frontend 2024-01-29 20:17:09 -05:00
dfb9fa0144 am: re-namespace frontend applets to frontend directory 2024-01-29 18:43:45 -05:00
a7e9d7842d am: add new datatypes for per-applet state 2024-01-29 18:43:45 -05:00
7de6b41030 service: split am into components 2024-01-29 18:43:45 -05:00
2cc5c517cf Update sockets_translate.cpp
Align the error case with it's index in the Errno enum
2024-01-30 00:34:07 +01:00
c0775e74ec Update sockets.h
Add the CONNREFUSED error to the Service::Sockets::Errno enum
2024-01-30 00:27:11 +01:00
3acf35bb98 Update sockets_translate.cpp
Add support for the CONNREFUSED Errno.
Without this Connect() will return SUCCESS when a connection is refused, instead of an error code. This causes code, that relies on the result of Connect() being SUCCESS, to execute when it shouldn't.
2024-01-30 00:23:43 +01:00
8ddfecfbae Merge pull request #12846 from german77/mii_const
service: mii: Set arguments as const
2024-01-29 15:27:12 -05:00
51f5a6f1f8 Merge pull request #12830 from merryhime/dynamic-dual_code_block
externals/dynarmic: Update to 6.6.1
2024-01-29 15:27:04 -05:00
64fca24b32 service: mii: Set arguments as const 2024-01-29 11:22:44 -06:00
ba4cee1812 Merge pull request #12843 from t895/system-driver-whoops
android: Don't show delete button for system driver
2024-01-29 09:09:38 -05:00
06abf3205a Merge pull request #12837 from german77/cat
service: am: Focus state changed goes last
2024-01-29 09:09:00 -05:00
adfdc9520a Merge pull request #12836 from german77/im_home
service: hid: Implement home, capture and sleep buttons
2024-01-29 09:08:52 -05:00
90cb852908 Merge pull request #12814 from Kelebek1/time_new_ipc
Move time services to new IPC and add debug printing
2024-01-29 09:08:46 -05:00
278dd589ec Merge pull request #12439 from FireBurn/vkresult
Simplify VkResult lookup
2024-01-29 09:08:32 -05:00
15e8791f9d android: Don't show delete button for system driver 2024-01-29 06:59:34 -05:00
498c9bd96a Merge pull request #12840 from amazingfate/fix-gcc11
fix build for gcc 11
2024-01-29 04:36:57 -06:00
6c8df6af44 fix build for gcc 11 2024-01-29 14:00:56 +08:00
8e93537266 service: am: Focus state changed goes last 2024-01-28 22:02:01 -06:00
b8f16f3538 service: hid: Implement home, capture and sleep buttons 2024-01-28 19:28:37 -06:00
6a2532fe17 Merge pull request #12555 from flodavid/fix-gamemode-setting
Save gamemode configuration and add per-game config
2024-01-28 15:02:34 -05:00
3655115105 Merge pull request #12821 from merryhime/atomic_ops
atomic_ops: Reduce code duplication with templates
2024-01-28 15:02:28 -05:00
5561a08d59 Merge pull request #12831 from Kelebek1/audren_multi
Use the input process handle to get the correct application's memory
2024-01-28 15:02:22 -05:00
e687ca8735 Merge pull request #12833 from merryhime/vsync-crash
configure_graphics: Avoid crash when vsync_mode_combobox is empty
2024-01-28 15:02:15 -05:00
0bf46cb1ee configure_graphics: Avoid crash when vsync_mode_combobox is empty (occurs when renderer backend is Null) 2024-01-28 19:14:38 +00:00
19a2f12692 Use the input process handle to get the correct application's memory 2024-01-28 18:51:43 +00:00
6cc82fd430 externals/dynarmic: Update to 6.6.1 2024-01-28 17:04:01 +00:00
72c897c49d Merge pull request #12826 from t895/system-driver-version
android: Show system driver information
2024-01-28 11:57:58 -05:00
077a50a547 Merge pull request #12825 from liamwhite/why
kernel: clear pinned waiter list on unpin
2024-01-28 11:57:53 -05:00
820f1c8a16 Merge pull request #12823 from german77/set-audio
service: set: Implement more Qlaunch Settings
2024-01-28 11:57:47 -05:00
b163757e1f Merge pull request #12802 from german77/mii_interface
service: mii: Migrate service to new interface
2024-01-28 11:57:40 -05:00
2bc0132d0c externals/oaknut: Update to 2.0.1 2024-01-28 16:50:14 +00:00
b75401a2cb service: set: Increase settings version 2024-01-28 09:32:54 -06:00
12e7ee2357 service: set: Implement more Qlaunch Settings 2024-01-28 09:32:46 -06:00
3ec41503e3 Merge pull request #12827 from t895/focus-color
android: Disable focus on loading card
2024-01-28 08:52:57 -05:00
c770af9b12 android: Disable focus on loading card
Additionally de-emphasize the ripple that I can't disable
2024-01-28 00:25:07 -05:00
2d8f80b65e android: Show system driver information 2024-01-27 23:59:02 -05:00
6c4eb2733d kernel: clear pinned waiter list on unpin 2024-01-27 22:53:49 -05:00
d5e8c9d04f Merge pull request #12824 from t895/multi-boot
android: Multi-program app switching
2024-01-27 21:48:54 -05:00
3f1290cee3 android: Multi-program app switching 2024-01-27 20:05:51 -05:00
5a20d07c21 atomic_ops: Fix MSVC 2024-01-27 21:42:16 +00:00
9f91d310c6 atomic_ops: Remove volatile qualifier 2024-01-27 21:36:39 +00:00
6527c0d2fc atomic_ops: Reduce code duplication with templates
Also fixes builds on unusual toolchains where:
- u32 is unsigned int
- u64 is unsigned long long
- uintptr_t is unsigned long
2024-01-27 21:12:12 +00:00
ce2eb6e8ee Merge pull request #12818 from K900/small-fixes
A few small fixes
2024-01-27 12:13:46 -05:00
8b47465586 input: add a missing null pointer check
There's a few other places where the result of GetAruidData is accessed without a null check,
but I couldn't find a code path that hits those.
2024-01-27 17:32:49 +03:00
3065ab0fd8 nx_tzdb: add another safety assertion 2024-01-27 17:28:04 +03:00
a2407a2964 nx_tzdb: check for unpacked directory
Otherwise things get funny if the archive is downloaded, but the unpacking was interrupted.
2024-01-27 17:25:52 +03:00
16b79df836 Merge pull request #12815 from t895/visual-driver-silly
android: Reload global settings on closing emulation
2024-01-27 01:36:26 -05:00
6a4b25699d android: Reload global settings on closing emulation
UI like the driver manager expects the global settings to be loaded when in the MainActivity so we reload global config to properly reset state on exit.
2024-01-26 23:05:02 -05:00
da410506a4 Move time services to new IPC.
Add some fixes/improvements to usage with the new IPC
2024-01-27 03:30:09 +00:00
c5e88c654e service: mii: Migrate service to new interface 2024-01-26 10:43:34 -06:00
bd8635e26a Merge pull request #12808 from t895/uri-moment
vfs: Fix getting URI filename
2024-01-26 10:23:08 -05:00
4349cdba07 Merge pull request #12769 from german77/no-log
core: hid: Reduce controller requests
2024-01-26 09:57:40 -05:00
f2fb761bac vfs: Fix getting URI filename 2024-01-26 09:57:22 -05:00
59aee2b461 Merge pull request #12809 from t895/error-message
android: Add cancel condition to installed content check
2024-01-26 09:56:01 -05:00
4d206d849e Merge pull request #12765 from german77/sys-hid
service: set: Implement more settings functions for Qlaunch
2024-01-26 09:55:47 -05:00
744c0173d1 Merge pull request #12801 from german77/vibration-fix
service: hid: Don't try to vibrate if device isn't initialized
2024-01-26 09:55:37 -05:00
55482ab5dc Merge pull request #12707 from FearlessTobi/fs-housekeeping
fs: Various cleanups & add path class for later use
2024-01-26 09:55:25 -05:00
e56b44dee6 android: Add cancel condition to installed content check 2024-01-26 09:29:51 -05:00
f2012e5aff service: hid: Don't try to vibrate if device isn't initialized 2024-01-25 23:46:46 -06:00
4526fdaf64 Merge pull request #12796 from t895/controller-optimizations
android: Controller focus optimizations
2024-01-25 23:01:44 -05:00
bc22b4e782 Merge pull request #12798 from liamwhite/cmif-fixes
cmif_serialization: fixes
2024-01-25 23:01:10 -05:00
f70821ce0d Merge pull request #12794 from abouvier/cmake-simpleini-module
cmake: support simpleini config and pc file
2024-01-25 23:01:04 -05:00
a774ff935c cmif_serialization: support non-domain sessions on domain servers 2024-01-25 22:18:42 -05:00
431df5ae93 cmif_types: improve ergonomics of types 2024-01-25 22:18:37 -05:00
677c2c2cd2 android: Disable default focus highlight on views that shouldn't be selected 2024-01-25 20:49:57 -05:00
ee540c712c android: Allow controller to focus on toolbar menu items
Workaround for this
https://issuetracker.google.com/issues/256948272
2024-01-25 20:48:58 -05:00
d23c4393fd android: Add 600dp layout for GameInfoFragment 2024-01-25 20:46:03 -05:00
b24a111136 android: Fix button click listener for build version name
Was set to the text instead of the parent view by mistake
2024-01-25 20:43:12 -05:00
91636deaaf android: Disable focus for the root of cards that contain buttons 2024-01-25 20:42:23 -05:00
68cbf67f4c android: Focus on the in game menu when opened 2024-01-25 20:39:52 -05:00
645961613f cmake: support simpleini cmake config and pc file 2024-01-26 01:13:47 +01:00
53b321c945 service: set: Implement more settings functions for Qlaunch 2024-01-25 17:14:18 -06:00
975deb7528 Address review comments and fix compilation problems 2024-01-25 16:43:53 -05:00
2c049ae06d fs: Add path class 2024-01-25 16:42:06 -05:00
54372fdff5 result: Make fully constexpr, add ON_RESULT_INCLUDED 2024-01-25 16:42:06 -05:00
c60ab6bbf6 fs/errors: Unify naming of result codes 2024-01-25 16:42:06 -05:00
cc09c265e1 fs: Replace Mode enum by OpenMode enum 2024-01-25 16:42:05 -05:00
0f9288e38d vfs: Move vfs files to their own directory 2024-01-25 16:40:42 -05:00
06fb7f90da fs: Move fsp_srv subclasses to separate files
fs: Move additional files to the fsp directory
2024-01-25 16:40:42 -05:00
ad4622da2c core: hid: Skip duplicated vibrations 2024-01-23 11:33:08 -06:00
3b1c2896d9 core: hid: Only set polling mode if needed 2024-01-23 11:11:09 -06:00
23e074ff14 Simplify VkResult lookup 2024-01-22 03:10:43 +00:00
f854ffd015 Add Vulkan-Utility-Libraries dependency 2024-01-22 01:30:44 +00:00
e231b8b6f5 yuzu: Add per-game linux gamemode configuration 2024-01-02 21:21:40 +01:00
68fe1e3476 fix linux config values not saved 2024-01-02 21:21:40 +01:00
479 changed files with 17203 additions and 10568 deletions

View File

@ -73,7 +73,7 @@ jobs:
build-mac:
name: 'test build (macos)'
needs: format
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v3
with:
@ -87,7 +87,7 @@ jobs:
run: |
mkdir build
cd build
export Qt5_DIR="/usr/local/opt/qt@5/lib/cmake"
export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake"
cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF
ninja
build-msvc:

3
.gitmodules vendored
View File

@ -64,3 +64,6 @@
[submodule "oaknut"]
path = externals/oaknut
url = https://github.com/merryhime/oaknut
[submodule "Vulkan-Utility-Libraries"]
path = externals/Vulkan-Utility-Libraries
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git

View File

@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
find_package(Vulkan 1.3.274 REQUIRED)
endif()
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
find_package(VulkanUtilityLibraries REQUIRED)
endif()
if (ENABLE_LIBUSB)
find_package(libusb 1.0.24 MODULE)
endif()
@ -316,6 +322,10 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
find_package(xbyak 6 CONFIG)
endif()
if (ARCHITECTURE_arm64)
find_package(oaknut 2.0.1 CONFIG)
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
find_package(dynarmic 6.4.0 CONFIG)
endif()

View File

@ -2,18 +2,20 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_path(SimpleIni_INCLUDE_DIR SimpleIni.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SimpleIni
REQUIRED_VARS SimpleIni_INCLUDE_DIR
)
if (SimpleIni_FOUND AND NOT TARGET SimpleIni::SimpleIni)
add_library(SimpleIni::SimpleIni INTERFACE IMPORTED)
set_target_properties(SimpleIni::SimpleIni PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${SimpleIni_INCLUDE_DIR}"
find_package(SimpleIni QUIET CONFIG)
if (SimpleIni_CONSIDERED_CONFIGS)
find_package_handle_standard_args(SimpleIni CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(SIMPLEINI QUIET IMPORTED_TARGET simpleini)
find_package_handle_standard_args(SimpleIni
REQUIRED_VARS SIMPLEINI_INCLUDEDIR
VERSION_VAR SIMPLEINI_VERSION
)
endif()
mark_as_advanced(SimpleIni_INCLUDE_DIR)
if (SimpleIni_FOUND AND NOT TARGET SimpleIni::SimpleIni)
add_library(SimpleIni::SimpleIni ALIAS PkgConfig::SIMPLEINI)
endif()

View File

@ -1,3 +1,16 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12461](https://github.com/yuzu-emu/yuzu-android//pull/12461) | [`e1f31cfe5`](https://github.com/yuzu-emu/yuzu-android//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-android//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12848](https://github.com/yuzu-emu/yuzu-android//pull/12848) | [`4afca6bf5`](https://github.com/yuzu-emu/yuzu-android//pull/12848/files) | service: capsrv: Migrate to new IPC | [german77](https://github.com/german77/) | Yes |
| [12874](https://github.com/yuzu-emu/yuzu-android//pull/12874) | [`f410cf681`](https://github.com/yuzu-emu/yuzu-android//pull/12874/files) | Revert "shader_recompiler: fix Offset operand usage for non-OpImage*Gather" | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12875](https://github.com/yuzu-emu/yuzu-android//pull/12875) | [`5cb9fe781`](https://github.com/yuzu-emu/yuzu-android//pull/12875/files) | SwBlitter: Fix Pitch linear reading/writting | [FernandoS27](https://github.com/FernandoS27/) | 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

@ -14,16 +14,17 @@ set(BUILD_SHARED_LIBS OFF)
# Skip install rules for all externals
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
# xbyak
# Xbyak (also used by Dynarmic, so needs to be added first)
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
add_subdirectory(xbyak)
endif()
# Dynarmic
# Oaknut (also used by Dynarmic, so needs to be added first)
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
add_subdirectory(oaknut)
endif()
# Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
set(DYNARMIC_IGNORE_ASSERTS ON)
add_subdirectory(dynarmic)
@ -154,6 +155,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
add_subdirectory(Vulkan-Headers)
endif()
# Vulkan-Utility-Libraries
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
add_subdirectory(Vulkan-Utility-Libraries)
endif()
# TZDB (Time Zone Database)
add_subdirectory(nx_tzdb)

View File

@ -32,7 +32,7 @@ set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ARCHIVE})
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")

View File

@ -11,6 +11,10 @@ execute_process(
WORKING_DIRECTORY ${ZONE_PATH}
OUTPUT_VARIABLE FILE_LIST)
if (NOT FILE_LIST)
message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?")
endif()
set(DIRECTORY_NAME ${HEADER_NAME})
set(FILE_DATA "")

View File

@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) {
return 0;
}
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) {
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) {
return localsub(sp, timep, 0, tmp) == nullptr;
}
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) {
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) {
return time1(out_time, tmp, localsub, sp, 0);
}

View File

@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th
s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep);
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp);
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep);
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp);
} // namespace Tz

View File

@ -261,7 +261,7 @@ object NativeLibrary {
/**
* Begins emulation.
*/
external fun run(path: String?)
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
// Surface Handling
external fun surfaceChanged(surf: Surface?)
@ -489,6 +489,12 @@ object NativeLibrary {
sEmulationActivity.get()!!.onEmulationStopped(status)
}
@Keep
@JvmStatic
fun onProgramChanged(programIndex: Int) {
sEmulationActivity.get()!!.onProgramChanged(programIndex)
}
/**
* Logs the Yuzu version, Android version and, CPU.
*/

View File

@ -76,7 +76,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
override fun onDestroy() {
stopForegroundService(this)
emulationViewModel.clear()
super.onDestroy()
}
@ -193,6 +192,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
return super.dispatchKeyEvent(event)
}
if (emulationViewModel.drawerOpen.value) {
return super.dispatchKeyEvent(event)
}
return InputHandler.dispatchKeyEvent(event)
}
@ -203,6 +206,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
return super.dispatchGenericMotionEvent(event)
}
if (emulationViewModel.drawerOpen.value) {
return super.dispatchGenericMotionEvent(event)
}
// Don't attempt to do anything if we are disconnecting a device.
if (event.actionMasked == MotionEvent.ACTION_CANCEL) {
return true
@ -438,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
}
fun onEmulationStopped(status: Int) {
if (status == 0) {
if (status == 0 && emulationViewModel.programChanged.value == -1) {
finish()
}
emulationViewModel.setEmulationStopped(true)
}
fun onProgramChanged(programIndex: Int) {
emulationViewModel.setProgramChanged(programIndex)
}
private fun startMotionSensorListener() {

View File

@ -7,6 +7,7 @@ import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.model.Driver
@ -57,13 +58,9 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) :
title.text = model.title
version.text = model.version
description.text = model.description
if (model.description.isNotEmpty()) {
version.visibility = View.VISIBLE
description.visibility = View.VISIBLE
if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) {
buttonDelete.visibility = View.VISIBLE
} else {
version.visibility = View.GONE
description.visibility = View.GONE
buttonDelete.visibility = View.GONE
}
}

View File

@ -77,7 +77,7 @@ class AboutFragment : Fragment() {
}
binding.textVersionName.text = BuildConfig.VERSION_NAME
binding.textVersionName.setOnClickListener {
binding.buttonVersionName.setOnClickListener {
val clipBoard =
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(getString(R.string.build), BuildConfig.GIT_HASH)

View File

@ -38,6 +38,7 @@ import androidx.window.layout.WindowLayoutInfo
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.slider.Slider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.yuzu.yuzu_emu.HomeNavigationDirections
@ -184,10 +185,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
override fun onDrawerOpened(drawerView: View) {
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
binding.inGameMenu.requestFocus()
emulationViewModel.setDrawerOpen(true)
}
override fun onDrawerClosed(drawerView: View) {
binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
emulationViewModel.setDrawerOpen(false)
}
override fun onDrawerStateChanged(newState: Int) {
@ -239,6 +243,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
requireContext().theme
)
}
binding.inGameMenu.requestFocus()
true
}
@ -247,6 +252,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
null,
Settings.MenuTag.SECTION_ROOT
)
binding.inGameMenu.requestFocus()
binding.root.findNavController().navigate(action)
true
}
@ -256,6 +262,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
args.game,
Settings.MenuTag.SECTION_ROOT
)
binding.inGameMenu.requestFocus()
binding.root.findNavController().navigate(action)
true
}
@ -287,15 +294,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
)
}
}
binding.inGameMenu.requestFocus()
NativeConfig.saveGlobalConfig()
true
}
R.id.menu_exit -> {
emulationState.stop()
NativeConfig.reloadGlobalConfig()
emulationViewModel.setIsEmulationStopping(true)
binding.drawerLayout.close()
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
binding.inGameMenu.requestFocus()
true
}
@ -312,12 +321,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (!NativeLibrary.isRunning()) {
return
}
if (binding.drawerLayout.isOpen) {
binding.drawerLayout.close()
} else {
binding.drawerLayout.open()
}
emulationViewModel.setDrawerOpen(!binding.drawerLayout.isOpen)
}
}
)
@ -408,10 +412,50 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
}
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.drawerOpen.collect {
if (it) {
binding.drawerLayout.open()
binding.inGameMenu.requestFocus()
} else {
binding.drawerLayout.close()
}
}
}
}
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.programChanged.collect {
if (it != 0) {
emulationViewModel.setEmulationStarted(false)
binding.drawerLayout.close()
binding.drawerLayout
.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
ViewUtils.hideView(binding.surfaceInputOverlay)
ViewUtils.showView(binding.loadingIndicator)
}
}
}
}
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.emulationStopped.collect {
if (it && emulationViewModel.programChanged.value != -1) {
if (perfStatsUpdater != null) {
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
}
emulationState.changeProgram(emulationViewModel.programChanged.value)
emulationViewModel.setProgramChanged(-1)
emulationViewModel.setEmulationStopped(false)
}
}
}
}
}
}
private fun startEmulation() {
private fun startEmulation(programIndex: Int = 0) {
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
@ -419,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
updateScreenLayout()
emulationState.run(emulationActivity!!.isActivityRecreated)
emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
}
}
@ -817,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
) {
private var state: State
private var surface: Surface? = null
lateinit var emulationThread: Thread
init {
// Starting state is stopped.
@ -862,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
@Synchronized
fun run(isActivityRecreated: Boolean) {
fun run(isActivityRecreated: Boolean, programIndex: Int = 0) {
if (isActivityRecreated) {
if (NativeLibrary.isRunning()) {
state = State.PAUSED
@ -873,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// If the surface is set, run now. Otherwise, wait for it to get set.
if (surface != null) {
runWithValidSurface()
runWithValidSurface(programIndex)
}
}
@Synchronized
fun changeProgram(programIndex: Int) {
emulationThread.join()
emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath, programIndex, false)
}, "NativeEmulation")
emulationThread.start()
}
// Surface callbacks
@Synchronized
fun newSurface(surface: Surface?) {
@ -916,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
private fun runWithValidSurface() {
private fun runWithValidSurface(programIndex: Int = 0) {
NativeLibrary.surfaceChanged(surface)
if (!emulationCanStart.invoke()) {
return
@ -924,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
when (state) {
State.STOPPED -> {
val emulationThread = Thread({
emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath)
NativeLibrary.run(gamePath, programIndex, true)
}, "NativeEmulation")
emulationThread.start()
}

View File

@ -153,7 +153,13 @@ class HomeSettingsFragment : Fragment() {
cancellable = true
) { progressCallback, _ ->
val result = NativeLibrary.verifyInstalledContents(progressCallback)
return@newInstance if (result.isEmpty()) {
return@newInstance if (progressCallback.invoke(100, 100)) {
// Invoke the progress callback to check if the process was cancelled
MessageDialogFragment.newInstance(
titleId = R.string.verify_no_result,
descriptionId = R.string.verify_no_result_description
)
} else if (result.isEmpty()) {
MessageDialogFragment.newInstance(
titleId = R.string.verify_success,
descriptionId = R.string.operation_completed_successfully

View File

@ -66,10 +66,13 @@ class DriverViewModel : ViewModel() {
fun updateDriverList() {
val selectedDriver = GpuDriverHelper.customDriverSettingData
val systemDriverData = GpuDriverHelper.getSystemDriverInfo()
val newDriverList = mutableListOf(
Driver(
selectedDriver == GpuDriverMetadata(),
YuzuApplication.appContext.getString(R.string.system_gpu_driver)
YuzuApplication.appContext.getString(R.string.system_gpu_driver),
systemDriverData?.get(0) ?: "",
systemDriverData?.get(1) ?: ""
)
)
driverData.forEach {

View File

@ -6,6 +6,7 @@ package org.yuzu.yuzu_emu.model
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class EmulationViewModel : ViewModel() {
val emulationStarted: StateFlow<Boolean> get() = _emulationStarted
@ -14,6 +15,12 @@ class EmulationViewModel : ViewModel() {
val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
private val _isEmulationStopping = MutableStateFlow(false)
private val _emulationStopped = MutableStateFlow(false)
val emulationStopped = _emulationStopped.asStateFlow()
private val _programChanged = MutableStateFlow(-1)
val programChanged = _programChanged.asStateFlow()
val shaderProgress: StateFlow<Int> get() = _shaderProgress
private val _shaderProgress = MutableStateFlow(0)
@ -23,6 +30,9 @@ class EmulationViewModel : ViewModel() {
val shaderMessage: StateFlow<String> get() = _shaderMessage
private val _shaderMessage = MutableStateFlow("")
private val _drawerOpen = MutableStateFlow(false)
val drawerOpen = _drawerOpen.asStateFlow()
fun setEmulationStarted(started: Boolean) {
_emulationStarted.value = started
}
@ -31,6 +41,17 @@ class EmulationViewModel : ViewModel() {
_isEmulationStopping.value = value
}
fun setEmulationStopped(value: Boolean) {
if (value) {
_emulationStarted.value = false
}
_emulationStopped.value = value
}
fun setProgramChanged(programIndex: Int) {
_programChanged.value = programIndex
}
fun setShaderProgress(progress: Int) {
_shaderProgress.value = progress
}
@ -49,19 +70,7 @@ class EmulationViewModel : ViewModel() {
setTotalShaders(max)
}
fun clear() {
setEmulationStarted(false)
setIsEmulationStopping(false)
setShaderProgress(0)
setTotalShaders(0)
setShaderMessage("")
}
companion object {
const val KEY_EMULATION_STARTED = "EmulationStarted"
const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting"
const val KEY_SHADER_PROGRESS = "ShaderProgress"
const val KEY_TOTAL_SHADERS = "TotalShaders"
const val KEY_SHADER_MESSAGE = "ShaderMessage"
fun setDrawerOpen(value: Boolean) {
_drawerOpen.value = value
}
}

View File

@ -3,8 +3,10 @@
package org.yuzu.yuzu_emu.utils
import android.graphics.SurfaceTexture
import android.net.Uri
import android.os.Build
import android.view.Surface
import java.io.File
import java.io.IOException
import org.yuzu.yuzu_emu.NativeLibrary
@ -195,6 +197,11 @@ object GpuDriverHelper {
external fun supportsCustomDriverLoading(): Boolean
external fun getSystemDriverInfo(
surface: Surface = Surface(SurfaceTexture(true)),
hookLibPath: String = GpuDriverHelper.hookLibPath!!
): Array<String>?
// Parse the custom driver metadata to retrieve the name.
val installedCustomDriverData: GpuDriverMetadata
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))

View File

@ -22,7 +22,7 @@ add_library(yuzu-android SHARED
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers)
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools)

View File

@ -82,7 +82,7 @@ AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobj
const jstring string = reinterpret_cast<jstring>(env->GetObjectField(
object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;")));
return ResultData{GetJString(env, string),
static_cast<Service::AM::Applets::SwkbdResult>(env->GetIntField(
static_cast<Service::AM::Frontend::SwkbdResult>(env->GetIntField(
object, env->GetFieldID(s_keyboard_data_class, "result", "I")))};
}
@ -149,7 +149,7 @@ void AndroidKeyboard::ShowNormalKeyboard() const {
}
void AndroidKeyboard::ShowTextCheckDialog(
Service::AM::Applets::SwkbdTextCheckResult text_check_result,
Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
std::u16string text_check_message) const {
LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog.");
}
@ -204,7 +204,7 @@ void AndroidKeyboard::InlineTextChanged(
"\ncursor_position={}",
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString,
text_parameters.input_text, text_parameters.cursor_position);
}
@ -219,7 +219,7 @@ void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) {
m_current_text += submitted_text;
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text,
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
m_current_text.size());
}
@ -236,12 +236,12 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) {
case KEYCODE_BACK:
case KEYCODE_ENTER:
m_is_inline_active = false;
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, m_current_text,
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, m_current_text,
static_cast<s32>(m_current_text.size()));
break;
case KEYCODE_DEL:
m_current_text.pop_back();
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text,
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
m_current_text.size());
break;
}

View File

@ -24,7 +24,7 @@ public:
void ShowNormalKeyboard() const override;
void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
std::u16string text_check_message) const override;
void ShowInlineKeyboard(
@ -45,7 +45,7 @@ private:
static ResultData CreateFromFrontend(jobject object);
std::string text;
Service::AM::Applets::SwkbdResult result{};
Service::AM::Frontend::SwkbdResult result{};
};
void SubmitNormalText(const ResultData& result) const;

View File

@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <core/core.h>
#include <core/file_sys/mode.h>
#include <core/file_sys/patch_manager.h>
#include <core/loader/nro.h>
#include <jni.h>
#include "core/core.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/patch_manager.h"
#include "core/loader/loader.h"
#include "core/loader/nro.h"
#include "jni.h"
#include "jni/android_common/android_common.h"
#include "native.h"
@ -79,7 +79,7 @@ extern "C" {
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj,
jstring jpath) {
const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
GetJString(env, jpath), FileSys::Mode::Read);
GetJString(env, jpath), FileSys::OpenMode::Read);
if (!file) {
return false;
}

View File

@ -19,6 +19,7 @@ static jmethodID s_exit_emulation_activity;
static jmethodID s_disk_cache_load_progress;
static jmethodID s_on_emulation_started;
static jmethodID s_on_emulation_stopped;
static jmethodID s_on_program_changed;
static jclass s_game_class;
static jmethodID s_game_constructor;
@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() {
return s_on_emulation_stopped;
}
jmethodID GetOnProgramChanged() {
return s_on_program_changed;
}
jclass GetGameClass() {
return s_game_class;
}
@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
s_on_emulation_stopped =
env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
s_on_program_changed =
env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V");
const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class));

View File

@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity();
jmethodID GetDiskCacheLoadProgress();
jmethodID GetOnEmulationStarted();
jmethodID GetOnEmulationStopped();
jmethodID GetOnProgramChanged();
jclass GetGameClass();
jmethodID GetGameConstructor();

View File

@ -35,20 +35,22 @@
#include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/submission_package.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_real.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_real.h"
#include "core/frontend/applets/cabinet.h"
#include "core/frontend/applets/controller.h"
#include "core/frontend/applets/error.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/frontend/applets/general.h"
#include "core/frontend/applets/mii_edit.h"
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
#include "frontend_common/config.h"
@ -59,6 +61,9 @@
#include "jni/id_cache.h"
#include "jni/native.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#define jconst [[maybe_unused]] const auto
#define jauto [[maybe_unused]] auto
@ -154,7 +159,7 @@ void EmulationSession::SurfaceChanged() {
}
void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) {
const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read);
const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::OpenMode::Read);
if (!file) {
return;
}
@ -207,7 +212,15 @@ void EmulationSession::InitializeSystem(bool reload) {
m_system.GetFileSystemController().CreateFactories(*m_vfs);
}
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
void EmulationSession::SetAppletId(int applet_id) {
m_applet_id = applet_id;
m_system.GetFrontendAppletHolder().SetCurrentAppletId(
static_cast<Service::AM::AppletId>(m_applet_id));
}
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
const std::size_t program_index,
const bool frontend_initiated) {
std::scoped_lock lock(m_mutex);
// Create the render window.
@ -221,7 +234,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.ApplySettings();
Settings::LogSettings();
m_system.HIDCore().ReloadInputDevices();
m_system.SetAppletFrontendSet({
m_system.SetFrontendAppletSet({
nullptr, // Amiibo Settings
nullptr, // Controller Selector
nullptr, // Error Display
@ -237,7 +250,13 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath);
// Load the ROM.
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
Service::AM::FrontendAppletParameters params{
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
: Service::AM::LaunchType::ApplicationInitiated,
.program_index = static_cast<s32>(program_index),
};
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
if (m_load_result != Core::SystemResultStatus::Success) {
return m_load_result;
}
@ -247,6 +266,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); });
// Register an ExecuteProgram callback such that Core can execute a sub-program
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
m_next_program_index = program_index_;
EmulationSession::GetInstance().HaltEmulation();
});
OnEmulationStarted();
return Core::SystemResultStatus::Success;
}
@ -254,6 +279,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
void EmulationSession::ShutdownEmulation() {
std::scoped_lock lock(m_mutex);
if (m_next_program_index != -1) {
ChangeProgram(m_next_program_index);
m_next_program_index = -1;
}
m_is_running = false;
// Unload user input.
@ -322,6 +352,9 @@ void EmulationSession::RunEmulation() {
}
}
}
// Reset current applet ID.
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
}
bool EmulationSession::IsHandheldOnly() {
@ -401,6 +434,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
static_cast<jint>(result));
}
void EmulationSession::ChangeProgram(std::size_t program_index) {
JNIEnv* env = IDCache::GetEnvForThread();
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(),
static_cast<jint>(program_index));
}
u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
auto program_id_string = GetJString(env, jprogramId);
try {
@ -410,7 +449,9 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
}
}
static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
const size_t program_index,
const bool frontend_initiated) {
MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); });
@ -423,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath);
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
frontend_initiated);
if (result != Core::SystemResultStatus::Success) {
return result;
}
@ -475,8 +517,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* en
u64 program_id = EmulationSession::GetProgramId(env, jprogramId);
std::string updatePath = GetJString(env, jupdatePath);
std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>(
EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(updatePath,
FileSys::Mode::Read));
EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
updatePath, FileSys::OpenMode::Read));
for (const auto& item : nsp->GetNCAs()) {
for (const auto& nca_details : item.second) {
if (nca_details.second->GetName().ends_with(".cnmt.nca")) {
@ -520,6 +562,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
#endif
}
jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
const char* file_redirect_dir_{};
int featureFlags{};
std::string hook_lib_dir = GetJString(env, j_hook_lib_dir);
auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
nullptr, nullptr, file_redirect_dir_, nullptr);
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
InputCommon::InputSubsystem input_subsystem;
auto m_window = std::make_unique<EmuWindow_Android>(
&input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library);
Vulkan::vk::InstanceDispatch dld;
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo());
auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
auto driver_version = device.GetDriverVersion();
auto version_string =
fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
jobjectArray j_driver_info =
env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string));
env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName()));
return j_driver_info;
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
Core::Crypto::KeyManager::Instance().ReloadKeys();
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
@ -688,11 +761,13 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
Settings::LogSettings();
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz,
jstring j_path) {
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
jint j_program_index,
jboolean j_frontend_initiated) {
const std::string path = GetJString(env, j_path);
const Core::SystemResultStatus result{RunEmulation(path)};
const Core::SystemResultStatus result{
RunEmulation(path, j_program_index, j_frontend_initiated)};
if (result != Core::SystemResultStatus::Success) {
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
@ -719,7 +794,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
jobject instance) {
const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory(
Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read);
Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read);
const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser(
static_cast<std::size_t>(0));
@ -754,13 +829,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
jint jappletId) {
EmulationSession::GetInstance().System().GetAppletManager().SetCurrentAppletId(
static_cast<Service::AM::Applets::AppletId>(jappletId));
EmulationSession::GetInstance().SetAppletId(jappletId);
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
jint jcabinetMode) {
EmulationSession::GetInstance().System().GetAppletManager().SetCabinetMode(
EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode(
static_cast<Service::NFP::CabinetMode>(jcabinetMode));
}
@ -889,7 +963,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(nandDir),
FileSys::Mode::Read);
FileSys::OpenMode::Read);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,

View File

@ -45,7 +45,10 @@ public:
const Core::PerfStatsResults& PerfStats();
void ConfigureFilesystemProvider(const std::string& filepath);
void InitializeSystem(bool reload);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
void SetAppletId(int applet_id);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
const std::size_t program_index,
const bool frontend_initiated);
bool IsHandheldOnly();
void SetDeviceType([[maybe_unused]] int index, int type);
@ -60,6 +63,7 @@ public:
private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
static void OnEmulationStopped(Core::SystemResultStatus result);
static void ChangeProgram(std::size_t program_index);
private:
// Window management
@ -77,6 +81,7 @@ private:
std::atomic<bool> m_is_paused = false;
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
int m_applet_id{1};
// GPU driver parameters
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
@ -84,4 +89,7 @@ private:
// Synchronization
std::condition_variable_any m_cv;
mutable std::mutex m_mutex;
// Program index for next boot
std::atomic<s32> m_next_program_index = -1;
};

View File

@ -11,12 +11,14 @@
android:id="@+id/appbar_about"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_about"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/about" />
@ -28,6 +30,7 @@
android:layout_height="match_parent"
android:fadeScrollbars="false"
android:scrollbars="vertical"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinator_about"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_info"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/content_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:baselineAligned="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="3"
android:gravity="top|center_horizontal"
android:paddingHorizontal="16dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_copy"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/copy_details" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_verify_integrity"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/verify_integrity" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/path_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:importantForAutofill="no"
android:inputType="none"
android:minHeight="48dp"
android:textAlignment="viewStart"
tools:text="1.0.0" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/program_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/program_id_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:importantForAutofill="no"
android:inputType="none"
android:minHeight="48dp"
android:textAlignment="viewStart"
tools:text="1.0.0" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/developer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/developer_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:importantForAutofill="no"
android:inputType="none"
android:minHeight="48dp"
android:textAlignment="viewStart"
tools:text="1.0.0" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/version_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:importantForAutofill="no"
android:inputType="none"
android:minHeight="48dp"
android:textAlignment="viewStart"
tools:text="1.0.0" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -14,6 +14,7 @@
android:clipToPadding="false"
android:fadeScrollbars="false"
android:scrollbars="vertical"
android:defaultFocusHighlightEnabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/icon_layout"
app:layout_constraintTop_toTopOf="parent">

View File

@ -23,6 +23,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:focusable="false"
android:clickable="false"
android:checked="false" />

View File

@ -6,16 +6,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="12dp"
android:focusable="true">
android:layout_marginVertical="12dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:layout_gravity="center_vertical"
android:animateLayoutChanges="true">
android:layout_gravity="center_vertical">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/path"

View File

@ -11,12 +11,14 @@
android:id="@+id/appbar_about"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_about"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:title="@string/about"
app:navigationIcon="@drawable/ic_back" />
@ -28,6 +30,7 @@
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout

View File

@ -11,6 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
@ -19,6 +20,7 @@
android:id="@+id/toolbar_addons"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back" />
</com.google.android.material.appbar.AppBarLayout>
@ -28,6 +30,8 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false"
android:nextFocusDown="@id/button_install"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

View File

@ -10,12 +10,14 @@
android:id="@+id/appbar_applets"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_applets"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/applets" />

View File

@ -15,12 +15,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
app:liftOnScrollTargetViewId="@id/list_drivers">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_drivers"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/gpu_driver_manager" />

View File

@ -11,12 +11,14 @@
android:id="@+id/appbar_ea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_about"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/early_access" />
@ -30,6 +32,7 @@
android:paddingBottom="20dp"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout

View File

@ -5,6 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:defaultFocusHighlightEnabled="false"
tools:context="org.yuzu.yuzu_emu.fragments.EmulationFragment"
tools:openDrawer="start">
@ -24,7 +25,8 @@
android:layout_height="match_parent"
android:layout_gravity="center"
android:focusable="false"
android:focusableInTouchMode="false" />
android:focusableInTouchMode="false"
android:defaultFocusHighlightEnabled="false" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/loading_indicator"
@ -33,7 +35,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="false"
android:clickable="false">
android:defaultFocusHighlightEnabled="false"
android:clickable="false"
app:rippleColor="@android:color/transparent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/loading_layout"
@ -118,6 +122,7 @@
android:layout_gravity="center"
android:focusable="true"
android:focusableInTouchMode="true"
android:defaultFocusHighlightEnabled="false"
android:visibility="invisible" />
<Button
@ -160,6 +165,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:focusedByDefault="true"
app:headerLayout="@layout/header_in_game"
app:menu="@menu/menu_in_game"
tools:visibility="gone" />

View File

@ -15,12 +15,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
app:liftOnScrollTargetViewId="@id/list_folders">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_folders"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/game_folders" />
@ -31,6 +33,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -11,12 +11,14 @@
android:id="@+id/appbar_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:touchscreenBlocksFocus="false"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_info"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back" />
</com.google.android.material.appbar.AppBarLayout>
@ -25,6 +27,7 @@
android:id="@+id/scroll_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:defaultFocusHighlightEnabled="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout

View File

@ -12,7 +12,8 @@
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:clipToPadding="false">
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false">
<LinearLayout
android:id="@+id/layout_all"
@ -86,7 +87,7 @@
android:id="@+id/list_properties"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/card_simple_outlined" />
android:defaultFocusHighlightEnabled="false" />
</LinearLayout>

View File

@ -27,6 +27,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false"
tools:listitem="@layout/card_game" />
</RelativeLayout>

View File

@ -7,7 +7,8 @@
android:background="?attr/colorSurface"
android:scrollbars="vertical"
android:fadeScrollbars="false"
android:clipToPadding="false">
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/linear_layout_settings"

View File

@ -10,12 +10,14 @@
android:id="@+id/appbar_installables"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_installables"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:title="@string/manage_yuzu_data"
app:navigationIcon="@drawable/ic_back" />

View File

@ -10,12 +10,14 @@
android:id="@+id/appbar_licenses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_licenses"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:title="@string/licenses"
app:navigationIcon="@drawable/ic_back" />

View File

@ -11,6 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
@ -24,6 +25,7 @@
android:id="@+id/toolbar_settings"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_back" />

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:focusable="true"
android:focusable="false"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp">

View File

@ -12,4 +12,5 @@
android:textAlignment="viewStart"
android:textColor="?attr/colorPrimary"
android:textStyle="bold"
android:focusable="false"
tools:text="CPU Settings" />

View File

@ -210,8 +210,6 @@ add_library(audio_core STATIC
sink/sink_stream.h
)
create_target_directory_groups(audio_core)
if (MSVC)
target_compile_options(audio_core PRIVATE
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
@ -267,3 +265,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(audio_core)

View File

@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) {
}
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept {
u64 applet_resource_user_id, Kernel::KProcess* process,
bool reset) noexcept {
command_buffers[session_id].buffer = buffer;
command_buffers[session_id].size = size;
command_buffers[session_id].time_limit = time_limit;
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
command_buffers[session_id].process = process;
command_buffers[session_id].reset_buffer = reset;
}
@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) {
command_list_processor.Initialize(system, command_buffer.buffer,
command_list_processor.Initialize(system, *command_buffer.process,
command_buffer.buffer,
command_buffer.size, streams[index]);
}

View File

@ -19,6 +19,10 @@ namespace Core {
class System;
} // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore {
namespace Sink {
class Sink;
@ -69,7 +73,8 @@ public:
u32 Receive(Direction dir);
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept;
u64 applet_resource_user_id, Kernel::KProcess* process,
bool reset) noexcept;
u32 GetRemainCommandCount(s32 session_id) const noexcept;
void ClearRemainCommandCount(s32 session_id) noexcept;
u64 GetRenderingStartTick(s32 session_id) const noexcept;

View File

@ -6,6 +6,10 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::ADSP::AudioRenderer {
struct CommandBuffer {
@ -14,6 +18,7 @@ struct CommandBuffer {
u64 size{};
u64 time_limit{};
u64 applet_resource_user_id{};
Kernel::KProcess* process{};
bool reset_buffer{};
// Set by the DSP
u32 remaining_command_count{};

View File

@ -9,14 +9,15 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
namespace AudioCore::ADSP::AudioRenderer {
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
Sink::SinkStream* stream_) {
void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process,
CpuAddr buffer, u64 size, Sink::SinkStream* stream_) {
system = &system_;
memory = &system->ApplicationMemory();
memory = &process.GetMemory();
stream = stream_;
header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));

View File

@ -16,6 +16,10 @@ class Memory;
class System;
} // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore {
namespace Sink {
class SinkStream;
@ -40,7 +44,8 @@ public:
* @param size - The size of the buffer.
* @param stream - The stream to be used for sending the samples.
*/
void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size,
Sink::SinkStream* stream);
/**
* Set the maximum processing time for this command list.

View File

@ -6,6 +6,7 @@
#include "audio_core/renderer/audio_renderer.h"
#include "audio_core/renderer/system_manager.h"
#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/errors.h"
@ -17,7 +18,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,
const u64 applet_resource_user_id, const s32 session_id) {
Kernel::KProcess& process, const u64 applet_resource_user_id,
const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio,
@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
}
initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id);
return ResultSuccess;

View File

@ -14,7 +14,8 @@ class System;
namespace Kernel {
class KTransferMemory;
}
class KProcess;
} // namespace Kernel
namespace AudioCore {
struct AudioRendererParameterInternal;
@ -44,7 +45,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
s32 session_id);
/**
* Finalize the renderer for shutdown.

View File

@ -32,6 +32,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/memory.h"
@ -101,7 +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_, u64 applet_resource_user_id_, s32 session_id_) {
u32 process_handle_, Kernel::KProcess& process_,
u64 applet_resource_user_id_, s32 session_id_) {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision;
}
@ -117,6 +119,7 @@ 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_;
@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
process->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
@ -613,7 +616,8 @@ 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, reset_command_buffers);
applet_resource_user_id, process,
reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {

View File

@ -29,6 +29,7 @@ class System;
namespace Kernel {
class KEvent;
class KProcess;
class KTransferMemory;
} // namespace Kernel
@ -80,7 +81,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
s32 session_id);
/**
* Finalize the system.
@ -275,6 +277,8 @@ private:
Common::Event terminate_event{};
/// 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{};
/// Applet resource id for this system, unused

View File

@ -106,6 +106,7 @@ add_library(common STATIC
precompiled_headers.h
quaternion.h
range_map.h
range_mutex.h
reader_writer_queue.h
ring_buffer.h
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
@ -244,8 +245,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
)
endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
@ -257,3 +256,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(common PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(common)

View File

@ -15,25 +15,34 @@ namespace Common {
#if _MSC_VER
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected);
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual);
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected) {
const u8 result =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
const u16 result =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
const u32 result =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
value, expected);
return result == expected;
@ -45,28 +54,31 @@ namespace Common {
reinterpret_cast<__int64*>(expected.data())) != 0;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
u8& actual) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) {
actual =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected,
u16& actual) {
actual =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected,
u32& actual) {
actual =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected,
u64& actual) {
actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
expected);
@ -91,23 +103,12 @@ namespace Common {
#else
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
unsigned __int128 value_a;
unsigned __int128 expected_a;
std::memcpy(&value_a, value.data(), sizeof(u128));
@ -115,31 +116,13 @@ namespace Common {
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
u8& actual) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
u16& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
u32& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
u64& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
u128& actual) {
unsigned __int128 value_a;
unsigned __int128 expected_a;
@ -151,7 +134,7 @@ namespace Common {
return actual_a == expected_a;
}
[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
unsigned __int128 zeros_a = 0;
unsigned __int128 result_a =
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);

View File

@ -3,6 +3,7 @@
#pragma once
#include <algorithm>
#include <type_traits>
#include "bit_cast.h"
@ -19,4 +20,21 @@ inline T WrappingAdd(T lhs, T rhs) {
return BitCast<T>(lhs_u + rhs_u);
}
template <typename T>
requires(std::is_integral_v<T> && std::is_signed_v<T>)
inline bool CanAddWithoutOverflow(T lhs, T rhs) {
#ifdef _MSC_VER
if (lhs >= 0 && rhs >= 0) {
return WrappingAdd(lhs, rhs) >= std::max(lhs, rhs);
} else if (lhs < 0 && rhs < 0) {
return WrappingAdd(lhs, rhs) <= std::min(lhs, rhs);
} else {
return true;
}
#else
T res;
return !__builtin_add_overflow(lhs, rhs, &res);
#endif
}
} // namespace Common

93
src/common/range_mutex.h Normal file
View File

@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <condition_variable>
#include <mutex>
#include "common/intrusive_list.h"
namespace Common {
class ScopedRangeLock;
class RangeMutex {
public:
explicit RangeMutex() = default;
~RangeMutex() = default;
private:
friend class ScopedRangeLock;
void Lock(ScopedRangeLock& l);
void Unlock(ScopedRangeLock& l);
bool HasIntersectionLocked(ScopedRangeLock& l);
private:
std::mutex m_mutex;
std::condition_variable m_cv;
using LockList = Common::IntrusiveListBaseTraits<ScopedRangeLock>::ListType;
LockList m_list;
};
class ScopedRangeLock : public Common::IntrusiveListBaseNode<ScopedRangeLock> {
public:
explicit ScopedRangeLock(RangeMutex& mutex, u64 address, u64 size)
: m_mutex(mutex), m_address(address), m_size(size) {
if (m_size > 0) {
m_mutex.Lock(*this);
}
}
~ScopedRangeLock() {
if (m_size > 0) {
m_mutex.Unlock(*this);
}
}
u64 GetAddress() const {
return m_address;
}
u64 GetSize() const {
return m_size;
}
private:
RangeMutex& m_mutex;
const u64 m_address{};
const u64 m_size{};
};
inline void RangeMutex::Lock(ScopedRangeLock& l) {
std::unique_lock lk{m_mutex};
m_cv.wait(lk, [&] { return !HasIntersectionLocked(l); });
m_list.push_back(l);
}
inline void RangeMutex::Unlock(ScopedRangeLock& l) {
{
std::scoped_lock lk{m_mutex};
m_list.erase(m_list.iterator_to(l));
}
m_cv.notify_all();
}
inline bool RangeMutex::HasIntersectionLocked(ScopedRangeLock& l) {
const auto cur_begin = l.GetAddress();
const auto cur_last = l.GetAddress() + l.GetSize() - 1;
for (const auto& other : m_list) {
const auto other_begin = other.GetAddress();
const auto other_last = other.GetAddress() + other.GetSize() - 1;
if (cur_begin <= other_last && other_begin <= cur_last) {
return true;
}
}
return false;
}
} // namespace Common

View File

@ -134,12 +134,12 @@ struct Values {
Linkage linkage{};
// Audio
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
Specialization::RuntimeList};
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
Specialization::RuntimeList};
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
Specialization::RuntimeList};
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
Category::Audio, Specialization::RuntimeList};
SwitchableSetting<std::string> audio_output_device_id{
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
SwitchableSetting<std::string> audio_input_device_id{
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
SwitchableSetting<AudioMode, true> sound_index{
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
"sound_index", Category::SystemAudio, Specialization::Default, true,

View File

@ -20,28 +20,49 @@ add_library(core STATIC
cpu_manager.h
crypto/aes_util.cpp
crypto/aes_util.h
crypto/ctr_encryption_layer.cpp
crypto/ctr_encryption_layer.h
crypto/encryption_layer.cpp
crypto/encryption_layer.h
crypto/key_manager.cpp
crypto/key_manager.h
crypto/partition_data_manager.cpp
crypto/partition_data_manager.h
crypto/ctr_encryption_layer.cpp
crypto/ctr_encryption_layer.h
crypto/xts_encryption_layer.cpp
crypto/xts_encryption_layer.h
debugger/debugger_interface.h
debugger/debugger.cpp
debugger/debugger.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
debugger/debugger_interface.h
debugger/gdbstub.cpp
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
file_sys/bis_factory.cpp
file_sys/bis_factory.h
file_sys/card_image.cpp
file_sys/card_image.h
file_sys/common_funcs.h
file_sys/content_archive.cpp
file_sys/content_archive.h
file_sys/control_metadata.cpp
file_sys/control_metadata.h
file_sys/errors.h
file_sys/fs_directory.h
file_sys/fs_file.h
file_sys/fs_filesystem.h
file_sys/fs_memory_management.h
file_sys/fs_operate_range.h
file_sys/fs_path.h
file_sys/fs_path_utility.h
file_sys/fs_string_util.h
file_sys/fsmitm_romfsbuild.cpp
file_sys/fsmitm_romfsbuild.h
file_sys/fssystem/fs_i_storage.h
file_sys/fssystem/fs_types.h
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
file_sys/fssystem/fssystem_aes_ctr_storage.cpp
@ -83,25 +104,10 @@ add_library(core STATIC
file_sys/fssystem/fssystem_switch_storage.h
file_sys/fssystem/fssystem_utility.cpp
file_sys/fssystem/fssystem_utility.h
file_sys/fssystem/fs_types.h
file_sys/bis_factory.cpp
file_sys/bis_factory.h
file_sys/card_image.cpp
file_sys/card_image.h
file_sys/common_funcs.h
file_sys/content_archive.cpp
file_sys/content_archive.h
file_sys/control_metadata.cpp
file_sys/control_metadata.h
file_sys/directory.h
file_sys/errors.h
file_sys/fsmitm_romfsbuild.cpp
file_sys/fsmitm_romfsbuild.h
file_sys/ips_layer.cpp
file_sys/ips_layer.h
file_sys/kernel_executable.cpp
file_sys/kernel_executable.h
file_sys/mode.h
file_sys/nca_metadata.cpp
file_sys/nca_metadata.h
file_sys/partition_filesystem.cpp
@ -146,22 +152,22 @@ add_library(core STATIC
file_sys/system_archive/system_version.h
file_sys/system_archive/time_zone_binary.cpp
file_sys/system_archive/time_zone_binary.h
file_sys/vfs.cpp
file_sys/vfs.h
file_sys/vfs_cached.cpp
file_sys/vfs_cached.h
file_sys/vfs_concat.cpp
file_sys/vfs_concat.h
file_sys/vfs_layered.cpp
file_sys/vfs_layered.h
file_sys/vfs_offset.cpp
file_sys/vfs_offset.h
file_sys/vfs_real.cpp
file_sys/vfs_real.h
file_sys/vfs_static.h
file_sys/vfs_types.h
file_sys/vfs_vector.cpp
file_sys/vfs_vector.h
file_sys/vfs/vfs.cpp
file_sys/vfs/vfs.h
file_sys/vfs/vfs_cached.cpp
file_sys/vfs/vfs_cached.h
file_sys/vfs/vfs_concat.cpp
file_sys/vfs/vfs_concat.h
file_sys/vfs/vfs_layered.cpp
file_sys/vfs/vfs_layered.h
file_sys/vfs/vfs_offset.cpp
file_sys/vfs/vfs_offset.h
file_sys/vfs/vfs_real.cpp
file_sys/vfs/vfs_real.h
file_sys/vfs/vfs_static.h
file_sys/vfs/vfs_types.h
file_sys/vfs/vfs_vector.cpp
file_sys/vfs/vfs_vector.h
file_sys/xts_archive.cpp
file_sys/xts_archive.h
frontend/applets/cabinet.cpp
@ -170,8 +176,8 @@ add_library(core STATIC
frontend/applets/controller.h
frontend/applets/error.cpp
frontend/applets/error.h
frontend/applets/general_frontend.cpp
frontend/applets/general_frontend.h
frontend/applets/general.cpp
frontend/applets/general.h
frontend/applets/mii_edit.cpp
frontend/applets/mii_edit.h
frontend/applets/profile_select.cpp
@ -194,7 +200,6 @@ add_library(core STATIC
hle/kernel/board/nintendo/nx/secure_monitor.h
hle/kernel/code_set.cpp
hle/kernel/code_set.h
hle/kernel/svc_results.h
hle/kernel/global_scheduler_context.cpp
hle/kernel/global_scheduler_context.h
hle/kernel/init/init_slab_setup.cpp
@ -204,11 +209,11 @@ add_library(core STATIC
hle/kernel/k_address_arbiter.h
hle/kernel/k_address_space_info.cpp
hle/kernel/k_address_space_info.h
hle/kernel/k_affinity_mask.h
hle/kernel/k_auto_object.cpp
hle/kernel/k_auto_object.h
hle/kernel/k_auto_object_container.cpp
hle/kernel/k_auto_object_container.h
hle/kernel/k_affinity_mask.h
hle/kernel/k_capabilities.cpp
hle/kernel/k_capabilities.h
hle/kernel/k_class_token.cpp
@ -232,9 +237,9 @@ add_library(core STATIC
hle/kernel/k_event_info.h
hle/kernel/k_handle_table.cpp
hle/kernel/k_handle_table.h
hle/kernel/k_hardware_timer_base.h
hle/kernel/k_hardware_timer.cpp
hle/kernel/k_hardware_timer.h
hle/kernel/k_hardware_timer_base.h
hle/kernel/k_interrupt_manager.cpp
hle/kernel/k_interrupt_manager.h
hle/kernel/k_light_client_session.cpp
@ -261,10 +266,10 @@ add_library(core STATIC
hle/kernel/k_page_bitmap.h
hle/kernel/k_page_buffer.cpp
hle/kernel/k_page_buffer.h
hle/kernel/k_page_heap.cpp
hle/kernel/k_page_heap.h
hle/kernel/k_page_group.cpp
hle/kernel/k_page_group.h
hle/kernel/k_page_heap.cpp
hle/kernel/k_page_heap.h
hle/kernel/k_page_table.h
hle/kernel/k_page_table_base.cpp
hle/kernel/k_page_table_base.h
@ -329,8 +334,6 @@ add_library(core STATIC
hle/kernel/slab_helpers.h
hle/kernel/svc.cpp
hle/kernel/svc.h
hle/kernel/svc_common.h
hle/kernel/svc_types.h
hle/kernel/svc/svc_activity.cpp
hle/kernel/svc/svc_address_arbiter.cpp
hle/kernel/svc/svc_address_translation.cpp
@ -368,6 +371,9 @@ add_library(core STATIC
hle/kernel/svc/svc_thread_profiler.cpp
hle/kernel/svc/svc_tick.cpp
hle/kernel/svc/svc_transfer_memory.cpp
hle/kernel/svc_common.h
hle/kernel/svc_results.h
hle/kernel/svc_types.h
hle/result.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
@ -384,39 +390,101 @@ add_library(core STATIC
hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h
hle/service/am/frontend/applet_cabinet.cpp
hle/service/am/frontend/applet_cabinet.h
hle/service/am/frontend/applet_controller.cpp
hle/service/am/frontend/applet_controller.h
hle/service/am/frontend/applet_error.cpp
hle/service/am/frontend/applet_error.h
hle/service/am/frontend/applet_general.cpp
hle/service/am/frontend/applet_general.h
hle/service/am/frontend/applet_mii_edit.cpp
hle/service/am/frontend/applet_mii_edit.h
hle/service/am/frontend/applet_mii_edit_types.h
hle/service/am/frontend/applet_profile_select.cpp
hle/service/am/frontend/applet_profile_select.h
hle/service/am/frontend/applet_software_keyboard.cpp
hle/service/am/frontend/applet_software_keyboard.h
hle/service/am/frontend/applet_software_keyboard_types.h
hle/service/am/frontend/applet_web_browser.cpp
hle/service/am/frontend/applet_web_browser.h
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_ae.cpp
hle/service/am/applet_ae.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_oe.cpp
hle/service/am/applet_oe.h
hle/service/am/applets/applet_cabinet.cpp
hle/service/am/applets/applet_cabinet.h
hle/service/am/applets/applet_controller.cpp
hle/service/am/applets/applet_controller.h
hle/service/am/applets/applet_error.cpp
hle/service/am/applets/applet_error.h
hle/service/am/applets/applet_general_backend.cpp
hle/service/am/applets/applet_general_backend.h
hle/service/am/applets/applet_mii_edit.cpp
hle/service/am/applets/applet_mii_edit.h
hle/service/am/applets/applet_mii_edit_types.h
hle/service/am/applets/applet_profile_select.cpp
hle/service/am/applets/applet_profile_select.h
hle/service/am/applets/applet_software_keyboard.cpp
hle/service/am/applets/applet_software_keyboard.h
hle/service/am/applets/applet_software_keyboard_types.h
hle/service/am/applets/applet_web_browser.cpp
hle/service/am/applets/applet_web_browser.h
hle/service/am/applets/applet_web_browser_types.h
hle/service/am/applets/applets.cpp
hle/service/am/applets/applets.h
hle/service/am/applet_common_functions.cpp
hle/service/am/applet_common_functions.h
hle/service/am/applet_message_queue.cpp
hle/service/am/applet_message_queue.h
hle/service/am/application_creator.cpp
hle/service/am/application_creator.h
hle/service/am/application_functions.cpp
hle/service/am/application_functions.h
hle/service/am/application_proxy.cpp
hle/service/am/application_proxy.h
hle/service/am/audio_controller.cpp
hle/service/am/audio_controller.h
hle/service/am/common_state_getter.cpp
hle/service/am/common_state_getter.h
hle/service/am/debug_functions.cpp
hle/service/am/debug_functions.h
hle/service/am/display_controller.cpp
hle/service/am/display_controller.h
hle/service/am/global_state_controller.cpp
hle/service/am/global_state_controller.h
hle/service/am/hid_registration.cpp
hle/service/am/hid_registration.h
hle/service/am/home_menu_functions.cpp
hle/service/am/home_menu_functions.h
hle/service/am/idle.cpp
hle/service/am/idle.h
hle/service/am/library_applet_accessor.cpp
hle/service/am/library_applet_accessor.h
hle/service/am/library_applet_creator.cpp
hle/service/am/library_applet_creator.h
hle/service/am/library_applet_proxy.cpp
hle/service/am/library_applet_proxy.h
hle/service/am/library_applet_self_accessor.cpp
hle/service/am/library_applet_self_accessor.h
hle/service/am/library_applet_storage.cpp
hle/service/am/library_applet_storage.h
hle/service/am/lock_accessor.cpp
hle/service/am/lock_accessor.h
hle/service/am/managed_layer_holder.cpp
hle/service/am/managed_layer_holder.h
hle/service/am/omm.cpp
hle/service/am/omm.h
hle/service/am/process_winding_controller.cpp
hle/service/am/process_winding_controller.h
hle/service/am/process.cpp
hle/service/am/process.h
hle/service/am/self_controller.cpp
hle/service/am/self_controller.h
hle/service/am/system_applet_proxy.cpp
hle/service/am/system_applet_proxy.h
hle/service/am/system_buffer_manager.cpp
hle/service/am/system_buffer_manager.h
hle/service/am/spsm.cpp
hle/service/am/spsm.h
hle/service/am/storage_accessor.cpp
hle/service/am/storage_accessor.h
hle/service/am/storage.cpp
hle/service/am/storage.h
hle/service/am/window_controller.cpp
hle/service/am/window_controller.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp
@ -480,20 +548,33 @@ add_library(core STATIC
hle/service/es/es.h
hle/service/eupld/eupld.cpp
hle/service/eupld/eupld.h
hle/service/event.cpp
hle/service/event.h
hle/service/fatal/fatal.cpp
hle/service/fatal/fatal.h
hle/service/fatal/fatal_p.cpp
hle/service/fatal/fatal_p.h
hle/service/fatal/fatal_u.cpp
hle/service/fatal/fatal_u.h
hle/service/fgm/fgm.cpp
hle/service/fgm/fgm.h
hle/service/filesystem/filesystem.cpp
hle/service/filesystem/filesystem.h
hle/service/filesystem/fsp_ldr.cpp
hle/service/filesystem/fsp_ldr.h
hle/service/filesystem/fsp_pr.cpp
hle/service/filesystem/fsp_pr.h
hle/service/filesystem/fsp_srv.cpp
hle/service/filesystem/fsp_srv.h
hle/service/filesystem/fsp/fs_i_directory.cpp
hle/service/filesystem/fsp/fs_i_directory.h
hle/service/filesystem/fsp/fs_i_file.cpp
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_storage.cpp
hle/service/filesystem/fsp/fs_i_storage.h
hle/service/filesystem/fsp/fsp_ldr.cpp
hle/service/filesystem/fsp/fsp_ldr.h
hle/service/filesystem/fsp/fsp_pr.cpp
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/romfs_controller.cpp
hle/service/filesystem/romfs_controller.h
hle/service/filesystem/save_data_controller.cpp
@ -551,13 +632,18 @@ add_library(core STATIC
hle/service/hid/irs.h
hle/service/hid/xcd.cpp
hle/service/hid/xcd.h
hle/service/hle_ipc.cpp
hle/service/hle_ipc.h
hle/service/ipc_helpers.h
hle/service/kernel_helpers.cpp
hle/service/kernel_helpers.h
hle/service/lbl/lbl.cpp
hle/service/lbl/lbl.h
hle/service/ldn/lan_discovery.cpp
hle/service/ldn/lan_discovery.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn.cpp
hle/service/ldn/ldn.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn_types.h
hle/service/ldr/ldr.cpp
hle/service/ldr/ldr.h
@ -565,16 +651,6 @@ add_library(core STATIC
hle/service/lm/lm.h
hle/service/mig/mig.cpp
hle/service/mig/mig.h
hle/service/mii/types/char_info.cpp
hle/service/mii/types/char_info.h
hle/service/mii/types/core_data.cpp
hle/service/mii/types/core_data.h
hle/service/mii/types/raw_data.cpp
hle/service/mii/types/raw_data.h
hle/service/mii/types/store_data.cpp
hle/service/mii/types/store_data.h
hle/service/mii/types/ver3_store_data.cpp
hle/service/mii/types/ver3_store_data.h
hle/service/mii/mii.cpp
hle/service/mii/mii.h
hle/service/mii/mii_database.cpp
@ -586,10 +662,22 @@ add_library(core STATIC
hle/service/mii/mii_result.h
hle/service/mii/mii_types.h
hle/service/mii/mii_util.h
hle/service/mii/types/char_info.cpp
hle/service/mii/types/char_info.h
hle/service/mii/types/core_data.cpp
hle/service/mii/types/core_data.h
hle/service/mii/types/raw_data.cpp
hle/service/mii/types/raw_data.h
hle/service/mii/types/store_data.cpp
hle/service/mii/types/store_data.h
hle/service/mii/types/ver3_store_data.cpp
hle/service/mii/types/ver3_store_data.h
hle/service/mm/mm_u.cpp
hle/service/mm/mm_u.h
hle/service/mnpp/mnpp_app.cpp
hle/service/mnpp/mnpp_app.h
hle/service/mutex.cpp
hle/service/mutex.h
hle/service/ncm/ncm.cpp
hle/service/ncm/ncm.h
hle/service/nfc/common/amiibo_crypto.cpp
@ -759,19 +847,12 @@ add_library(core STATIC
hle/service/ptm/ptm.h
hle/service/ptm/ts.cpp
hle/service/ptm/ts.h
hle/service/hle_ipc.cpp
hle/service/hle_ipc.h
hle/service/ipc_helpers.h
hle/service/kernel_helpers.cpp
hle/service/kernel_helpers.h
hle/service/mutex.cpp
hle/service/mutex.h
hle/service/ro/ro.cpp
hle/service/ro/ro.h
hle/service/ro/ro_nro_utils.cpp
hle/service/ro/ro_nro_utils.h
hle/service/ro/ro_results.h
hle/service/ro/ro_types.h
hle/service/ro/ro.cpp
hle/service/ro/ro.h
hle/service/server_manager.cpp
hle/service/server_manager.h
hle/service/service.cpp
@ -838,9 +919,9 @@ add_library(core STATIC
internal_network/network.h
internal_network/network_interface.cpp
internal_network/network_interface.h
internal_network/sockets.h
internal_network/socket_proxy.cpp
internal_network/socket_proxy.h
internal_network/sockets.h
loader/deconstructed_rom_directory.cpp
loader/deconstructed_rom_directory.h
loader/kip.cpp
@ -859,13 +940,13 @@ add_library(core STATIC
loader/nsp.h
loader/xci.cpp
loader/xci.h
memory.cpp
memory.h
memory/cheat_engine.cpp
memory/cheat_engine.h
memory/dmnt_cheat_types.h
memory/dmnt_cheat_vm.cpp
memory/dmnt_cheat_vm.h
memory.cpp
memory.h
perf_stats.cpp
perf_stats.h
precompiled_headers.h
@ -898,8 +979,6 @@ else()
)
endif()
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
if (MINGW)
@ -977,3 +1056,5 @@ endif()
if (YUZU_ENABLE_LTO)
set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
create_target_directory_groups(core)

View File

@ -21,13 +21,13 @@
#include "core/debugger/debugger.h"
#include "core/device_memory.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
#include "core/file_sys/vfs/vfs_concat.h"
#include "core/file_sys/vfs/vfs_real.h"
#include "core/gpu_dirty_memory_manager.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_process.h"
@ -36,7 +36,8 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.h"
@ -102,7 +103,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
Common::SplitPath(path, &dir_name, &filename, nullptr);
if (filename == "00") {
const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read);
const auto dir = vfs->OpenDirectory(dir_name, FileSys::OpenMode::Read);
std::vector<FileSys::VirtualFile> concat;
for (u32 i = 0; i < 0x10; ++i) {
@ -127,16 +128,16 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
}
if (Common::FS::IsDir(path)) {
return vfs->OpenFile(path + "/main", FileSys::Mode::Read);
return vfs->OpenFile(path + "/main", FileSys::OpenMode::Read);
}
return vfs->OpenFile(path, FileSys::Mode::Read);
return vfs->OpenFile(path, FileSys::OpenMode::Read);
}
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{}, room_network{},
cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{} {}
: kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
void Initialize(System& system) {
device_memory = std::make_unique<Core::DeviceMemory>();
@ -157,7 +158,7 @@ struct System::Impl {
}
// Create default implementations of applets if one is not provided.
applet_manager.SetDefaultAppletsIfMissing();
frontend_applets.SetDefaultAppletsIfMissing();
is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
@ -200,22 +201,22 @@ struct System::Impl {
system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock;
static_service_a->GetStandardUserSystemClock(user_clock);
static_service_a->GetStandardUserSystemClock(&user_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
static_service_a->GetStandardLocalSystemClock(local_clock);
static_service_a->GetStandardLocalSystemClock(&local_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
static_service_s->GetStandardNetworkSystemClock(network_clock);
static_service_s->GetStandardNetworkSystemClock(&network_clock);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
static_service_a->GetTimeZoneService(timezone_service);
static_service_a->GetTimeZoneService(&timezone_service);
Service::PSC::Time::LocationName name{};
auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size()));
std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size()));
timezone_service->SetDeviceLocation(name);
timezone_service->SetDeviceLocationName(name);
u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) {
@ -233,7 +234,7 @@ struct System::Impl {
local_clock->SetCurrentTime(new_time);
network_clock->GetSystemClockContext(context);
network_clock->GetSystemClockContext(&context);
settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time);
}
@ -330,16 +331,27 @@ struct System::Impl {
}
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath, u64 program_id,
std::size_t program_index) {
const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
program_id, program_index);
params.program_id, params.program_index);
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
return SystemResultStatus::ErrorGetLoader;
}
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to find title id for ROM!");
}
std::string name = "Unknown program";
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to read title for ROM!");
}
LOG_INFO(Core, "Loading {} ({})", name, params.program_id);
InitializeKernel(system);
// Create the application process.
@ -373,9 +385,14 @@ struct System::Impl {
cheat_engine->Initialize();
}
// Register with applet manager.
applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(),
params);
// All threads are started, begin main process execution, now that we're in the clear.
main_process->Run(load_parameters->main_thread_priority,
load_parameters->main_thread_stack_size);
main_process->Close();
if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) {
@ -386,21 +403,13 @@ struct System::Impl {
}
}
if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
}
perf_stats = std::make_unique<PerfStats>(program_id);
perf_stats = std::make_unique<PerfStats>(params.program_id);
// Reset counters and set time origin to current frame
GetAndResetPerfStats();
perf_stats->BeginSystemFrame();
std::string name = "Unknown Game";
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result);
}
std::string title_version;
const FileSys::PatchManager pm(program_id, system.GetFileSystemController(),
const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(),
system.GetContentProvider());
const auto metadata = pm.GetControlMetadata();
if (metadata.first != nullptr) {
@ -409,14 +418,15 @@ struct System::Impl {
if (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info;
game_info.name = name;
game_info.id = program_id;
game_info.id = params.program_id;
game_info.version = title_version;
room_member->SendGameInfo(game_info);
}
// Workarounds:
// Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK
Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL;
Settings::values.renderer_amdvlk_depth_bias_workaround =
params.program_id == 0x1006A800016E000ULL;
status = SystemResultStatus::Success;
return status;
@ -455,6 +465,7 @@ struct System::Impl {
}
kernel.CloseServices();
kernel.ShutdownCores();
applet_manager.Reset();
services.reset();
service_manager.reset();
fs_controller.Reset();
@ -566,8 +577,9 @@ struct System::Impl {
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
/// Frontend applets
Service::AM::Applets::AppletManager applet_manager;
/// Applets
Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
@ -680,8 +692,8 @@ void System::InitializeDebugger() {
}
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
u64 program_id, std::size_t program_index) {
return impl->Load(*this, emu_window, filepath, program_id, program_index);
Service::AM::FrontendAppletParameters& params) {
return impl->Load(*this, emu_window, filepath, params);
}
bool System::IsPoweredOn() const {
@ -871,19 +883,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
}
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
impl->applet_manager.SetAppletFrontendSet(std::move(set));
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
}
void System::SetDefaultAppletFrontendSet() {
impl->applet_manager.SetDefaultAppletFrontendSet();
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
return impl->frontend_applets;
}
Service::AM::Applets::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets;
}
const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
}

View File

@ -13,7 +13,7 @@
#include <vector>
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/file_sys/vfs/vfs_types.h"
namespace Core::Frontend {
class EmuWindow;
@ -50,10 +50,15 @@ namespace Account {
class ProfileManager;
} // namespace Account
namespace AM::Applets {
struct AppletFrontendSet;
namespace AM {
struct FrontendAppletParameters;
class AppletManager;
} // namespace AM::Applets
} // namespace AM
namespace AM::Frontend {
struct FrontendAppletSet;
class FrontendAppletHolder;
} // namespace AM::Frontend
namespace APM {
class Controller;
@ -203,8 +208,8 @@ public:
* @returns SystemResultStatus code, indicating if the operation succeeded.
*/
[[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
const std::string& filepath, u64 program_id = 0,
std::size_t program_index = 0);
const std::string& filepath,
Service::AM::FrontendAppletParameters& params);
/**
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
@ -344,11 +349,13 @@ public:
const std::array<u8, 0x20>& build_id, u64 main_region_begin,
u64 main_region_size);
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
void SetDefaultAppletFrontendSet();
void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
[[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager();
[[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const;
[[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
[[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
const;
[[nodiscard]] Service::AM::AppletManager& GetAppletManager();
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);

View File

@ -7,7 +7,7 @@
#include <span>
#include <type_traits>
#include "common/common_types.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace Core::Crypto {

View File

@ -4,7 +4,7 @@
#pragma once
#include "common/common_types.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace Core::Crypto {

View File

@ -21,9 +21,9 @@
#include "core/crypto/partition_data_manager.h"
#include "core/crypto/xts_encryption_layer.h"
#include "core/file_sys/kernel_executable.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs_vector.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_offset.h"
#include "core/file_sys/vfs/vfs_vector.h"
#include "core/loader/loader.h"
using Common::AsArray;

View File

@ -5,7 +5,7 @@
#include <vector>
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/file_sys/vfs/vfs_types.h"
namespace Core::Crypto {

View File

@ -5,11 +5,13 @@
#include <array>
#include <atomic>
#include <bit>
#include <deque>
#include <memory>
#include <mutex>
#include "common/common_types.h"
#include "common/range_mutex.h"
#include "common/scratch_buffer.h"
#include "common/virtual_buffer.h"
@ -41,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);
@ -180,31 +184,35 @@ private:
}
Common::VirtualBuffer<VAddr> cpu_backing_address;
static constexpr size_t subentries = 8 / sizeof(u8);
using CounterType = u8;
using CounterAtomicType = std::atomic_uint8_t;
static constexpr size_t subentries = 8 / sizeof(CounterType);
static constexpr size_t subentries_mask = subentries - 1;
static constexpr size_t subentries_shift =
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
class CounterEntry final {
public:
CounterEntry() = default;
std::atomic_uint8_t& Count(std::size_t page) {
CounterAtomicType& Count(std::size_t page) {
return values[page & subentries_mask];
}
const std::atomic_uint8_t& Count(std::size_t page) const {
const CounterAtomicType& Count(std::size_t page) const {
return values[page & subentries_mask];
}
private:
std::array<std::atomic_uint8_t, subentries> values{};
std::array<CounterAtomicType, subentries> values{};
};
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
"CounterEntry should be 8 bytes!");
static constexpr size_t num_counter_entries =
(1ULL << (device_virtual_bits - page_bits)) / subentries;
using CachedPages = std::array<CounterEntry, num_counter_entries>;
std::unique_ptr<CachedPages> cached_pages;
std::mutex counter_guard;
Common::RangeMutex counter_guard;
std::mutex mapping_guard;
};

View File

@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
}
template <typename Traits>
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
Asid asid, bool track) {
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
bool track) {
Core::Memory::Memory* process_memory = registered_processes[asid.id];
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
@ -508,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
template <typename Traits>
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock);
const auto Lock = [&] {
if (!lk) {
lk.lock();
}
};
Common::ScopedRangeLock lk(counter_guard, addr, size);
u64 uncache_begin = 0;
u64 cache_begin = 0;
u64 uncache_bytes = 0;
@ -524,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
size_t page = addr >> Memory::YUZU_PAGEBITS;
auto [asid, base_vaddress] = ExtractCPUBacking(page);
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
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);
uncache_bytes = 0;
}
if (cache_bytes > 0) {
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
cache_bytes, true);
cache_bytes = 0;
}
};
for (; page != page_end; ++page) {
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
auto [asid_2, vpage] = ExtractCPUBacking(page);
vpage >>= Memory::YUZU_PAGEBITS;
if (delta > 0) {
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
"Count may overflow!");
} else if (delta < 0) {
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
} else {
ASSERT_MSG(false, "Delta must be non-zero!");
if (vpage == 0) [[unlikely]] {
release_pending();
continue;
}
if (asid.id != asid_2.id) [[unlikely]] {
release_pending();
memory_device_inter = registered_processes[asid_2.id];
}
// Adds or subtracts 1, as count is a unsigned 8-bit value
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
// Assume delta is either -1 or 1
if (count.load(std::memory_order::relaxed) == 0) {
@ -548,7 +557,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
}
uncache_bytes += Memory::YUZU_PAGESIZE;
} else if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
uncache_bytes, false);
uncache_bytes = 0;
@ -559,23 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
}
cache_bytes += Memory::YUZU_PAGESIZE;
} else if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true);
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
cache_bytes, true);
cache_bytes = 0;
}
vpage++;
}
if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
false);
}
if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true);
}
release_pending();
}
} // namespace Core

View File

@ -4,9 +4,8 @@
#include <fmt/format.h>
#include "common/fs/path_util.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {
@ -84,7 +83,7 @@ VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
VirtualFilesystem file_system) const {
auto& keys = Core::Crypto::KeyManager::Instance();
Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir), Mode::Read)};
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir), OpenMode::Read)};
keys.PopulateFromPartitionData(pdm);
switch (id) {

View File

@ -6,7 +6,7 @@
#include <memory>
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/file_sys/vfs/vfs_types.h"
namespace FileSys {

View File

@ -13,8 +13,8 @@
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/file_sys/submission_package.h"
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs_vector.h"
#include "core/file_sys/vfs/vfs_offset.h"
#include "core/file_sys/vfs/vfs_vector.h"
#include "core/loader/loader.h"
namespace FileSys {

View File

@ -8,7 +8,7 @@
#include <vector>
#include "common/common_types.h"
#include "common/swap.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace Core::Crypto {
class KeyManager;

View File

@ -13,7 +13,7 @@
#include "core/crypto/key_manager.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/partition_filesystem.h"
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs/vfs_offset.h"
#include "core/loader/loader.h"
#include "core/file_sys/fssystem/fssystem_compression_configuration.h"

View File

@ -13,7 +13,7 @@
#include "common/common_types.h"
#include "common/swap.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace Loader {
enum class ResultStatus : u16;

View File

@ -5,7 +5,7 @@
#include "common/string_util.h"
#include "common/swap.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {

View File

@ -8,7 +8,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/file_sys/vfs_types.h"
#include "core/file_sys/vfs/vfs_types.h"
namespace FileSys {

View File

@ -1,39 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <cstddef>
#include "common/common_funcs.h"
#include "common/common_types.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// FileSys namespace
namespace FileSys {
enum class EntryType : u8 {
Directory = 0,
File = 1,
};
// Structure of a directory entry, from
// http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry
struct Entry {
Entry(std::string_view view, EntryType entry_type, u64 entry_size)
: type{entry_type}, file_size{entry_size} {
const std::size_t copy_size = view.copy(filename, std::size(filename) - 1);
filename[copy_size] = '\0';
}
char filename[0x301];
INSERT_PADDING_BYTES(3);
EntryType type;
INSERT_PADDING_BYTES(3);
u64 file_size;
};
static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x310 bytes long!");
static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry.");
static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry.");
} // namespace FileSys

View File

@ -7,18 +7,13 @@
namespace FileSys {
constexpr Result ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1};
constexpr Result ERROR_PATH_ALREADY_EXISTS{ErrorModule::FS, 2};
constexpr Result ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002};
constexpr Result ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001};
constexpr Result ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005};
constexpr Result ERROR_FAILED_MOUNT_ARCHIVE{ErrorModule::FS, 3223};
constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::FS, 6001};
constexpr Result ERROR_INVALID_OFFSET{ErrorModule::FS, 6061};
constexpr Result ERROR_INVALID_SIZE{ErrorModule::FS, 6062};
constexpr Result ResultPathNotFound{ErrorModule::FS, 1};
constexpr Result ResultPathAlreadyExists{ErrorModule::FS, 2};
constexpr Result ResultUnsupportedSdkVersion{ErrorModule::FS, 50};
constexpr Result ResultPartitionNotFound{ErrorModule::FS, 1001};
constexpr Result ResultTargetNotFound{ErrorModule::FS, 1002};
constexpr Result ResultPortSdCardNoDevice{ErrorModule::FS, 2001};
constexpr Result ResultNotImplemented{ErrorModule::FS, 3001};
constexpr Result ResultUnsupportedVersion{ErrorModule::FS, 3002};
constexpr Result ResultOutOfRange{ErrorModule::FS, 3005};
constexpr Result ResultAllocationMemoryFailedInFileSystemBuddyHeapA{ErrorModule::FS, 3294};
@ -78,10 +73,21 @@ constexpr Result ResultUnexpectedInCompressedStorageA{ErrorModule::FS, 5324};
constexpr Result ResultUnexpectedInCompressedStorageB{ErrorModule::FS, 5325};
constexpr Result ResultUnexpectedInCompressedStorageC{ErrorModule::FS, 5326};
constexpr Result ResultUnexpectedInCompressedStorageD{ErrorModule::FS, 5327};
constexpr Result ResultUnexpectedInPathA{ErrorModule::FS, 5328};
constexpr Result ResultInvalidArgument{ErrorModule::FS, 6001};
constexpr Result ResultInvalidPath{ErrorModule::FS, 6002};
constexpr Result ResultTooLongPath{ErrorModule::FS, 6003};
constexpr Result ResultInvalidCharacter{ErrorModule::FS, 6004};
constexpr Result ResultInvalidPathFormat{ErrorModule::FS, 6005};
constexpr Result ResultDirectoryUnobtainable{ErrorModule::FS, 6006};
constexpr Result ResultNotNormalized{ErrorModule::FS, 6007};
constexpr Result ResultInvalidOffset{ErrorModule::FS, 6061};
constexpr Result ResultInvalidSize{ErrorModule::FS, 6062};
constexpr Result ResultNullptrArgument{ErrorModule::FS, 6063};
constexpr Result ResultInvalidOpenMode{ErrorModule::FS, 6072};
constexpr Result ResultFileExtensionWithoutOpenModeAllowAppend{ErrorModule::FS, 6201};
constexpr Result ResultReadNotPermitted{ErrorModule::FS, 6202};
constexpr Result ResultWriteNotPermitted{ErrorModule::FS, 6203};
constexpr Result ResultUnsupportedSetSizeForIndirectStorage{ErrorModule::FS, 6325};
constexpr Result ResultUnsupportedWriteForCompressedStorage{ErrorModule::FS, 6387};
constexpr Result ResultUnsupportedOperateRangeForCompressedStorage{ErrorModule::FS, 6388};

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace FileSys {
constexpr inline size_t EntryNameLengthMax = 0x300;
struct DirectoryEntry {
DirectoryEntry(std::string_view view, s8 entry_type, u64 entry_size)
: type{entry_type}, file_size{static_cast<s64>(entry_size)} {
const std::size_t copy_size = view.copy(name, std::size(name) - 1);
name[copy_size] = '\0';
}
char name[EntryNameLengthMax + 1];
INSERT_PADDING_BYTES(3);
s8 type;
INSERT_PADDING_BYTES(3);
s64 file_size;
};
static_assert(sizeof(DirectoryEntry) == 0x310,
"Directory Entry struct isn't exactly 0x310 bytes long!");
static_assert(offsetof(DirectoryEntry, type) == 0x304, "Wrong offset for type in Entry.");
static_assert(offsetof(DirectoryEntry, file_size) == 0x308, "Wrong offset for file_size in Entry.");
struct DirectoryHandle {
void* handle;
};
} // namespace FileSys

View File

@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
namespace FileSys {
struct ReadOption {
u32 value;
static const ReadOption None;
};
enum ReadOptionFlag : u32 {
ReadOptionFlag_None = (0 << 0),
};
inline constexpr const ReadOption ReadOption::None = {ReadOptionFlag_None};
inline constexpr bool operator==(const ReadOption& lhs, const ReadOption& rhs) {
return lhs.value == rhs.value;
}
inline constexpr bool operator!=(const ReadOption& lhs, const ReadOption& rhs) {
return !(lhs == rhs);
}
static_assert(sizeof(ReadOption) == sizeof(u32));
enum WriteOptionFlag : u32 {
WriteOptionFlag_None = (0 << 0),
WriteOptionFlag_Flush = (1 << 0),
};
struct WriteOption {
u32 value;
constexpr inline bool HasFlushFlag() const {
return value & WriteOptionFlag_Flush;
}
static const WriteOption None;
static const WriteOption Flush;
};
inline constexpr const WriteOption WriteOption::None = {WriteOptionFlag_None};
inline constexpr const WriteOption WriteOption::Flush = {WriteOptionFlag_Flush};
inline constexpr bool operator==(const WriteOption& lhs, const WriteOption& rhs) {
return lhs.value == rhs.value;
}
inline constexpr bool operator!=(const WriteOption& lhs, const WriteOption& rhs) {
return !(lhs == rhs);
}
static_assert(sizeof(WriteOption) == sizeof(u32));
struct FileHandle {
void* handle;
};
} // namespace FileSys

View File

@ -0,0 +1,39 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_funcs.h"
#include "common/common_types.h"
namespace FileSys {
enum class OpenMode : u32 {
Read = (1 << 0),
Write = (1 << 1),
AllowAppend = (1 << 2),
ReadWrite = (Read | Write),
All = (ReadWrite | AllowAppend),
};
DECLARE_ENUM_FLAG_OPERATORS(OpenMode)
enum class OpenDirectoryMode : u64 {
Directory = (1 << 0),
File = (1 << 1),
All = (Directory | File),
};
DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode)
enum class DirectoryEntryType : u8 {
Directory = 0,
File = 1,
};
enum class CreateOption : u8 {
None = (0 << 0),
BigFile = (1 << 0),
};
} // namespace FileSys

View File

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <mutex>
#include "common/alignment.h"
namespace FileSys {
constexpr size_t RequiredAlignment = alignof(u64);
void* AllocateUnsafe(size_t size) {
// Allocate
void* const ptr = ::operator new(size, std::align_val_t{RequiredAlignment});
// Check alignment
ASSERT(Common::IsAligned(reinterpret_cast<uintptr_t>(ptr), RequiredAlignment));
// Return allocated pointer
return ptr;
}
void DeallocateUnsafe(void* ptr, size_t size) {
// Deallocate the pointer
::operator delete(ptr, std::align_val_t{RequiredAlignment});
}
void* Allocate(size_t size) {
return AllocateUnsafe(size);
}
void Deallocate(void* ptr, size_t size) {
// If the pointer is non-null, deallocate it
if (ptr != nullptr) {
DeallocateUnsafe(ptr, size);
}
}
} // namespace FileSys

View File

@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
namespace FileSys {
enum class OperationId : s64 {
FillZero = 0,
DestroySignature = 1,
Invalidate = 2,
QueryRange = 3,
QueryUnpreparedRange = 4,
QueryLazyLoadCompletionRate = 5,
SetLazyLoadPriority = 6,
ReadLazyLoadFileForciblyForDebug = 10001,
};
} // namespace FileSys

566
src/core/file_sys/fs_path.h Normal file
View File

@ -0,0 +1,566 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/alignment.h"
#include "common/common_funcs.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fs_memory_management.h"
#include "core/file_sys/fs_path_utility.h"
#include "core/file_sys/fs_string_util.h"
#include "core/hle/result.h"
namespace FileSys {
class DirectoryPathParser;
class Path {
YUZU_NON_COPYABLE(Path);
YUZU_NON_MOVEABLE(Path);
private:
static constexpr const char* EmptyPath = "";
static constexpr size_t WriteBufferAlignmentLength = 8;
private:
friend class DirectoryPathParser;
public:
class WriteBuffer {
YUZU_NON_COPYABLE(WriteBuffer);
private:
char* m_buffer;
size_t m_length_and_is_normalized;
public:
constexpr WriteBuffer() : m_buffer(nullptr), m_length_and_is_normalized(0) {}
constexpr ~WriteBuffer() {
if (m_buffer != nullptr) {
Deallocate(m_buffer, this->GetLength());
this->ResetBuffer();
}
}
constexpr WriteBuffer(WriteBuffer&& rhs)
: m_buffer(rhs.m_buffer), m_length_and_is_normalized(rhs.m_length_and_is_normalized) {
rhs.ResetBuffer();
}
constexpr WriteBuffer& operator=(WriteBuffer&& rhs) {
if (m_buffer != nullptr) {
Deallocate(m_buffer, this->GetLength());
}
m_buffer = rhs.m_buffer;
m_length_and_is_normalized = rhs.m_length_and_is_normalized;
rhs.ResetBuffer();
return *this;
}
constexpr void ResetBuffer() {
m_buffer = nullptr;
this->SetLength(0);
}
constexpr char* Get() const {
return m_buffer;
}
constexpr size_t GetLength() const {
return m_length_and_is_normalized >> 1;
}
constexpr bool IsNormalized() const {
return static_cast<bool>(m_length_and_is_normalized & 1);
}
constexpr void SetNormalized() {
m_length_and_is_normalized |= static_cast<size_t>(1);
}
constexpr void SetNotNormalized() {
m_length_and_is_normalized &= ~static_cast<size_t>(1);
}
private:
constexpr WriteBuffer(char* buffer, size_t length)
: m_buffer(buffer), m_length_and_is_normalized(0) {
this->SetLength(length);
}
public:
static WriteBuffer Make(size_t length) {
if (void* alloc = Allocate(length); alloc != nullptr) {
return WriteBuffer(static_cast<char*>(alloc), length);
} else {
return WriteBuffer();
}
}
private:
constexpr void SetLength(size_t size) {
m_length_and_is_normalized = (m_length_and_is_normalized & 1) | (size << 1);
}
};
private:
const char* m_str;
WriteBuffer m_write_buffer;
public:
constexpr Path() : m_str(EmptyPath), m_write_buffer() {}
constexpr Path(const char* s) : m_str(s), m_write_buffer() {
m_write_buffer.SetNormalized();
}
constexpr ~Path() = default;
constexpr Result SetShallowBuffer(const char* buffer) {
// Check pre-conditions
ASSERT(m_write_buffer.GetLength() == 0);
// Check the buffer is valid
R_UNLESS(buffer != nullptr, ResultNullptrArgument);
// Set buffer
this->SetReadOnlyBuffer(buffer);
// Note that we're normalized
this->SetNormalized();
R_SUCCEED();
}
constexpr const char* GetString() const {
// Check pre-conditions
ASSERT(this->IsNormalized());
return m_str;
}
constexpr size_t GetLength() const {
if (std::is_constant_evaluated()) {
return Strlen(this->GetString());
} else {
return std::strlen(this->GetString());
}
}
constexpr bool IsEmpty() const {
return *m_str == '\x00';
}
constexpr bool IsMatchHead(const char* p, size_t len) const {
return Strncmp(this->GetString(), p, len) == 0;
}
Result Initialize(const Path& rhs) {
// Check the other path is normalized
const bool normalized = rhs.IsNormalized();
R_UNLESS(normalized, ResultNotNormalized);
// Allocate buffer for our path
const auto len = rhs.GetLength();
R_TRY(this->Preallocate(len + 1));
// Copy the path
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1);
R_UNLESS(copied == len, ResultUnexpectedInPathA);
// Set normalized
this->SetNormalized();
R_SUCCEED();
}
Result Initialize(const char* path, size_t len) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
// Initialize
R_TRY(this->InitializeImpl(path, len));
// Set not normalized
this->SetNotNormalized();
R_SUCCEED();
}
Result Initialize(const char* path) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
R_RETURN(this->Initialize(path, std::strlen(path)));
}
Result InitializeWithReplaceBackslash(const char* path) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
// Initialize
R_TRY(this->InitializeImpl(path, std::strlen(path)));
// Replace slashes as desired
if (const auto write_buffer_length = m_write_buffer.GetLength(); write_buffer_length > 1) {
Replace(m_write_buffer.Get(), write_buffer_length - 1, '\\', '/');
}
// Set not normalized
this->SetNotNormalized();
R_SUCCEED();
}
Result InitializeWithReplaceForwardSlashes(const char* path) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
// Initialize
R_TRY(this->InitializeImpl(path, std::strlen(path)));
// Replace slashes as desired
if (m_write_buffer.GetLength() > 1) {
if (auto* p = m_write_buffer.Get(); p[0] == '/' && p[1] == '/') {
p[0] = '\\';
p[1] = '\\';
}
}
// Set not normalized
this->SetNotNormalized();
R_SUCCEED();
}
Result InitializeWithNormalization(const char* path, size_t size) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
// Initialize
R_TRY(this->InitializeImpl(path, size));
// Set not normalized
this->SetNotNormalized();
// Perform normalization
PathFlags path_flags;
if (IsPathRelative(m_str)) {
path_flags.AllowRelativePath();
} else if (IsWindowsPath(m_str, true)) {
path_flags.AllowWindowsPath();
} else {
/* NOTE: In this case, Nintendo checks is normalized, then sets is normalized, then
* returns success. */
/* This seems like a bug. */
size_t dummy;
bool normalized;
R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy),
m_str));
this->SetNormalized();
R_SUCCEED();
}
// Normalize
R_TRY(this->Normalize(path_flags));
this->SetNormalized();
R_SUCCEED();
}
Result InitializeWithNormalization(const char* path) {
// Check the path is valid
R_UNLESS(path != nullptr, ResultNullptrArgument);
R_RETURN(this->InitializeWithNormalization(path, std::strlen(path)));
}
Result InitializeAsEmpty() {
// Clear our buffer
this->ClearBuffer();
// Set normalized
this->SetNormalized();
R_SUCCEED();
}
Result AppendChild(const char* child) {
// Check the path is valid
R_UNLESS(child != nullptr, ResultNullptrArgument);
// Basic checks. If we have a path and the child is empty, we have nothing to do
const char* c = child;
if (m_str[0]) {
// Skip an early separator
if (*c == '/') {
++c;
}
R_SUCCEED_IF(*c == '\x00');
}
// If we don't have a string, we can just initialize
auto cur_len = std::strlen(m_str);
if (cur_len == 0) {
R_RETURN(this->Initialize(child));
}
// Remove a trailing separator
if (m_str[cur_len - 1] == '/' || m_str[cur_len - 1] == '\\') {
--cur_len;
}
// Get the child path's length
auto child_len = std::strlen(c);
// Reset our write buffer
WriteBuffer old_write_buffer;
if (m_write_buffer.Get() != nullptr) {
old_write_buffer = std::move(m_write_buffer);
this->ClearBuffer();
}
// Pre-allocate the new buffer
R_TRY(this->Preallocate(cur_len + 1 + child_len + 1));
// Get our write buffer
auto* dst = m_write_buffer.Get();
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1);
}
// Add separator
dst[cur_len] = '/';
// Copy the child path
const size_t copied = Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
R_SUCCEED();
}
Result AppendChild(const Path& rhs) {
R_RETURN(this->AppendChild(rhs.GetString()));
}
Result Combine(const Path& parent, const Path& child) {
// Get the lengths
const auto p_len = parent.GetLength();
const auto c_len = child.GetLength();
// Allocate our buffer
R_TRY(this->Preallocate(p_len + c_len + 1));
// Initialize as parent
R_TRY(this->Initialize(parent));
// If we're empty, we can just initialize as child
if (this->IsEmpty()) {
R_TRY(this->Initialize(child));
} else {
// Otherwise, we should append the child
R_TRY(this->AppendChild(child));
}
R_SUCCEED();
}
Result RemoveChild() {
// If we don't have a write-buffer, ensure that we have one
if (m_write_buffer.Get() == nullptr) {
if (const auto len = std::strlen(m_str); len > 0) {
R_TRY(this->Preallocate(len));
Strlcpy<char>(m_write_buffer.Get(), m_str, len + 1);
}
}
// Check that it's possible for us to remove a child
auto* p = m_write_buffer.Get();
s32 len = std::strlen(p);
R_UNLESS(len != 1 || (p[0] != '/' && p[0] != '.'), ResultNotImplemented);
// Handle a trailing separator
if (len > 0 && (p[len - 1] == '\\' || p[len - 1] == '/')) {
--len;
}
// Remove the child path segment
while ((--len) >= 0 && p[len]) {
if (p[len] == '/' || p[len] == '\\') {
if (len > 0) {
p[len] = 0;
} else {
p[1] = 0;
len = 1;
}
break;
}
}
// Check that length remains > 0
R_UNLESS(len > 0, ResultNotImplemented);
R_SUCCEED();
}
Result Normalize(const PathFlags& flags) {
// If we're already normalized, nothing to do
R_SUCCEED_IF(this->IsNormalized());
// Check if we're normalized
bool normalized;
size_t dummy;
R_TRY(PathFormatter::IsNormalized(std::addressof(normalized), std::addressof(dummy), m_str,
flags));
// If we're not normalized, normalize
if (!normalized) {
// Determine necessary buffer length
auto len = m_write_buffer.GetLength();
if (flags.IsRelativePathAllowed() && IsPathRelative(m_str)) {
len += 2;
}
if (flags.IsWindowsPathAllowed() && IsWindowsPath(m_str, true)) {
len += 1;
}
// Allocate a new buffer
const size_t size = Common::AlignUp(len, WriteBufferAlignmentLength);
auto buf = WriteBuffer::Make(size);
R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique);
// Normalize into it
R_TRY(PathFormatter::Normalize(buf.Get(), size, m_write_buffer.Get(),
m_write_buffer.GetLength(), flags));
// Set the normalized buffer as our buffer
this->SetModifiableBuffer(std::move(buf));
}
// Set normalized
this->SetNormalized();
R_SUCCEED();
}
private:
void ClearBuffer() {
m_write_buffer.ResetBuffer();
m_str = EmptyPath;
}
void SetModifiableBuffer(WriteBuffer&& buffer) {
// Check pre-conditions
ASSERT(buffer.Get() != nullptr);
ASSERT(buffer.GetLength() > 0);
ASSERT(Common::IsAligned(buffer.GetLength(), WriteBufferAlignmentLength));
// Get whether we're normalized
if (m_write_buffer.IsNormalized()) {
buffer.SetNormalized();
} else {
buffer.SetNotNormalized();
}
// Set write buffer
m_write_buffer = std::move(buffer);
m_str = m_write_buffer.Get();
}
constexpr void SetReadOnlyBuffer(const char* buffer) {
m_str = buffer;
m_write_buffer.ResetBuffer();
}
Result Preallocate(size_t length) {
// Allocate additional space, if needed
if (length > m_write_buffer.GetLength()) {
// Allocate buffer
const size_t size = Common::AlignUp(length, WriteBufferAlignmentLength);
auto buf = WriteBuffer::Make(size);
R_UNLESS(buf.Get() != nullptr, ResultAllocationMemoryFailedMakeUnique);
// Set write buffer
this->SetModifiableBuffer(std::move(buf));
}
R_SUCCEED();
}
Result InitializeImpl(const char* path, size_t size) {
if (size > 0 && path[0]) {
// Pre allocate a buffer for the path
R_TRY(this->Preallocate(size + 1));
// Copy the path
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), path, size + 1);
R_UNLESS(copied >= size, ResultUnexpectedInPathA);
} else {
// We can just clear the buffer
this->ClearBuffer();
}
R_SUCCEED();
}
constexpr char* GetWriteBuffer() {
ASSERT(m_write_buffer.Get() != nullptr);
return m_write_buffer.Get();
}
constexpr size_t GetWriteBufferLength() const {
return m_write_buffer.GetLength();
}
constexpr bool IsNormalized() const {
return m_write_buffer.IsNormalized();
}
constexpr void SetNormalized() {
m_write_buffer.SetNormalized();
}
constexpr void SetNotNormalized() {
m_write_buffer.SetNotNormalized();
}
public:
bool operator==(const FileSys::Path& rhs) const {
return std::strcmp(this->GetString(), rhs.GetString()) == 0;
}
bool operator!=(const FileSys::Path& rhs) const {
return !(*this == rhs);
}
bool operator==(const char* p) const {
return std::strcmp(this->GetString(), p) == 0;
}
bool operator!=(const char* p) const {
return !(*this == p);
}
};
inline Result SetUpFixedPath(FileSys::Path* out, const char* s) {
// Verify the path is normalized
bool normalized;
size_t dummy;
R_TRY(PathNormalizer::IsNormalized(std::addressof(normalized), std::addressof(dummy), s));
R_UNLESS(normalized, ResultInvalidPathFormat);
// Set the fixed path
R_RETURN(out->SetShallowBuffer(s));
}
constexpr inline bool IsWindowsDriveRootPath(const FileSys::Path& path) {
const char* const str = path.GetString();
return IsWindowsDrive(str) &&
(str[2] == StringTraits::DirectorySeparator ||
str[2] == StringTraits::AlternateDirectorySeparator) &&
str[3] == StringTraits::NullTerminator;
}
} // namespace FileSys

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/assert.h"
namespace FileSys {
template <typename T>
constexpr int Strlen(const T* str) {
ASSERT(str != nullptr);
int length = 0;
while (*str++) {
++length;
}
return length;
}
template <typename T>
constexpr int Strnlen(const T* str, int count) {
ASSERT(str != nullptr);
ASSERT(count >= 0);
int length = 0;
while (count-- && *str++) {
++length;
}
return length;
}
template <typename T>
constexpr int Strncmp(const T* lhs, const T* rhs, int count) {
ASSERT(lhs != nullptr);
ASSERT(rhs != nullptr);
ASSERT(count >= 0);
if (count == 0) {
return 0;
}
T l, r;
do {
l = *(lhs++);
r = *(rhs++);
} while (l && (l == r) && (--count));
return l - r;
}
template <typename T>
static constexpr int Strlcpy(T* dst, const T* src, int count) {
ASSERT(dst != nullptr);
ASSERT(src != nullptr);
const T* cur = src;
if (count > 0) {
while ((--count) && *cur) {
*(dst++) = *(cur++);
}
*dst = 0;
}
while (*cur) {
cur++;
}
return static_cast<int>(cur - src);
}
enum CharacterEncodingResult {
CharacterEncodingResult_Success = 0,
CharacterEncodingResult_InsufficientLength = 1,
CharacterEncodingResult_InvalidFormat = 2,
};
namespace impl {
class CharacterEncodingHelper {
public:
static constexpr int8_t Utf8NBytesInnerTable[0x100 + 1] = {
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
};
static constexpr char GetUtf8NBytes(size_t i) {
return static_cast<char>(Utf8NBytesInnerTable[1 + i]);
}
};
} // namespace impl
constexpr inline CharacterEncodingResult ConvertCharacterUtf8ToUtf32(u32* dst, const char* src) {
// Check pre-conditions
ASSERT(dst != nullptr);
ASSERT(src != nullptr);
// Perform the conversion
const auto* p = src;
switch (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[0]))) {
case 1:
*dst = static_cast<u32>(p[0]);
return CharacterEncodingResult_Success;
case 2:
if ((static_cast<u32>(p[0]) & 0x1E) != 0) {
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) ==
0) {
*dst = (static_cast<u32>(p[0] & 0x1F) << 6) | (static_cast<u32>(p[1] & 0x3F) << 0);
return CharacterEncodingResult_Success;
}
}
break;
case 3:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0) {
const u32 c = (static_cast<u32>(p[0] & 0xF) << 12) |
(static_cast<u32>(p[1] & 0x3F) << 6) |
(static_cast<u32>(p[2] & 0x3F) << 0);
if ((c & 0xF800) != 0 && (c & 0xF800) != 0xD800) {
*dst = c;
return CharacterEncodingResult_Success;
}
}
return CharacterEncodingResult_InvalidFormat;
case 4:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[3])) == 0) {
const u32 c =
(static_cast<u32>(p[0] & 0x7) << 18) | (static_cast<u32>(p[1] & 0x3F) << 12) |
(static_cast<u32>(p[2] & 0x3F) << 6) | (static_cast<u32>(p[3] & 0x3F) << 0);
if (c >= 0x10000 && c < 0x110000) {
*dst = c;
return CharacterEncodingResult_Success;
}
}
return CharacterEncodingResult_InvalidFormat;
default:
break;
}
// We failed to convert
return CharacterEncodingResult_InvalidFormat;
}
constexpr inline CharacterEncodingResult PickOutCharacterFromUtf8String(char* dst,
const char** str) {
// Check pre-conditions
ASSERT(dst != nullptr);
ASSERT(str != nullptr);
ASSERT(*str != nullptr);
// Clear the output
dst[0] = 0;
dst[1] = 0;
dst[2] = 0;
dst[3] = 0;
// Perform the conversion
const auto* p = *str;
u32 c = static_cast<u32>(*p);
switch (impl::CharacterEncodingHelper::GetUtf8NBytes(c)) {
case 1:
dst[0] = (*str)[0];
++(*str);
break;
case 2:
if ((p[0] & 0x1E) != 0) {
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) ==
0) {
c = (static_cast<u32>(p[0] & 0x1F) << 6) | (static_cast<u32>(p[1] & 0x3F) << 0);
dst[0] = (*str)[0];
dst[1] = (*str)[1];
(*str) += 2;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
case 3:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0) {
c = (static_cast<u32>(p[0] & 0xF) << 12) | (static_cast<u32>(p[1] & 0x3F) << 6) |
(static_cast<u32>(p[2] & 0x3F) << 0);
if ((c & 0xF800) != 0 && (c & 0xF800) != 0xD800) {
dst[0] = (*str)[0];
dst[1] = (*str)[1];
dst[2] = (*str)[2];
(*str) += 3;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
case 4:
if (impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[1])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[2])) == 0 &&
impl::CharacterEncodingHelper::GetUtf8NBytes(static_cast<unsigned char>(p[3])) == 0) {
c = (static_cast<u32>(p[0] & 0x7) << 18) | (static_cast<u32>(p[1] & 0x3F) << 12) |
(static_cast<u32>(p[2] & 0x3F) << 6) | (static_cast<u32>(p[3] & 0x3F) << 0);
if (c >= 0x10000 && c < 0x110000) {
dst[0] = (*str)[0];
dst[1] = (*str)[1];
dst[2] = (*str)[2];
dst[3] = (*str)[3];
(*str) += 4;
break;
}
}
return CharacterEncodingResult_InvalidFormat;
default:
return CharacterEncodingResult_InvalidFormat;
}
return CharacterEncodingResult_Success;
}
} // namespace FileSys

View File

@ -8,8 +8,8 @@
#include "common/assert.h"
#include "core/file_sys/fsmitm_romfsbuild.h"
#include "core/file_sys/ips_layer.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_vector.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_vector.h"
namespace FileSys {

View File

@ -7,7 +7,7 @@
#include <memory>
#include <string>
#include "common/common_types.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {

View File

@ -5,7 +5,7 @@
#include "common/overflow.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {

View File

@ -4,7 +4,7 @@
#include "core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
#include "core/file_sys/fssystem/fssystem_nca_header.h"
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs/vfs_offset.h"
namespace FileSys {

View File

@ -9,7 +9,7 @@
#include "core/crypto/key_manager.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {

View File

@ -10,7 +10,7 @@
#include "common/common_types.h"
#include "common/literals.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/hle/result.h"
namespace FileSys {

View File

@ -10,7 +10,7 @@
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_compression_common.h"
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {

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