Compare commits

...

64 Commits

Author SHA1 Message Date
28a23c4380 Android 215 2024-01-28 01:00:30 +00:00
c768c19898 Merge yuzu-emu#12802 2024-01-28 01:00:30 +00:00
7273701bc2 Merge yuzu-emu#12760 2024-01-28 01:00:30 +00:00
3bf0492edb Merge yuzu-emu#12749 2024-01-28 01:00:30 +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
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
e04368ad7c Merge pull request #12759 from liamwhite/mp-misc
core: miscellaneous fixes
2024-01-25 16:21:38 -05:00
3e2d3548f2 Merge pull request #12777 from t895/firmware-warning
android: Add key warning
2024-01-25 16:21:29 -05:00
eb9036d75b Merge pull request #12783 from liamwhite/cmif-generation
service: add template serializer for method calls
2024-01-25 15:40:09 -05:00
01a2d978eb service: add template serializer for method calls 2024-01-25 14:35:51 -05:00
6e67b25af9 Merge pull request #12787 from t895/game-list-refresh
android: Only compare game contents for GameAdapter
2024-01-25 14:19:32 -05:00
e91667ba75 Merge pull request #12786 from t895/driver-overlay
android: Show driver vendor in FPS overlay
2024-01-25 14:19:25 -05:00
d45561ace0 Merge pull request #12499 from Kelebek1/time
Rework time services
2024-01-25 14:19:01 -05:00
0fdd6e8934 android: Fix waiting for driver install on startup 2024-01-25 13:04:04 -05:00
35794f4f18 android: Add current driver vendor to FPS overlay 2024-01-25 13:04:03 -05:00
b8be8dff69 android: Add key check 2024-01-25 12:58:19 -05:00
bc317a9807 android: Add option to make MessageDialogFragments non-dismissible
Additionally fixes an issue where its viewmodel could hold onto a stale positive action
2024-01-25 12:53:49 -05:00
97ca160b08 frontend_common: Consistently use references
Was swapping between references and pointers for no reason. Just unify them here since each of these utility functions will need their parameters to be alive.
2024-01-25 12:53:49 -05:00
1a3fc3724a frontend_common: Remove key rederivation and keep key check 2024-01-25 12:53:48 -05:00
7b01454d5f android: Only compare game contents for GameAdapter 2024-01-25 08:04:59 -05:00
f3749394ac Merge pull request #12781 from goldenx86/dozen
Demote dozen to the bottom of the device list
2024-01-25 03:58:09 -03:00
807f421752 Demote Mesa dozen to the bottom of the device list 2024-01-24 23:36:14 -03:00
e4915fb7d2 Rework time service to fix time passing offline. 2024-01-24 04:26:55 +00:00
a76f6a2775 Merge pull request #12763 from liamwhite/fix-hbl-again
loader: also register fs process for raw exefs partition
2024-01-23 13:31:41 -05:00
ba518f6899 Merge pull request #12768 from german77/wrong_conversion
service: properly convert buffers to strings
2024-01-23 13:31:27 -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
fc5d76e6e2 service: properly convert buffers to strings 2024-01-23 10:24:05 -06:00
5f9a45ada9 loader: also register fs process for raw exefs partition 2024-01-23 00:01:38 -05:00
a120f8ff4d nvservices: close map handles on session close 2024-01-22 21:18:52 -05:00
96833cd809 kernel: target invalidate to given process 2024-01-22 21:18:52 -05:00
479 changed files with 21081 additions and 10740 deletions

View File

@ -2,18 +2,20 @@
# #
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
find_path(SimpleIni_INCLUDE_DIR SimpleIni.h)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SimpleIni
REQUIRED_VARS SimpleIni_INCLUDE_DIR
)
if (SimpleIni_FOUND AND NOT TARGET SimpleIni::SimpleIni) find_package(SimpleIni QUIET CONFIG)
add_library(SimpleIni::SimpleIni INTERFACE IMPORTED) if (SimpleIni_CONSIDERED_CONFIGS)
set_target_properties(SimpleIni::SimpleIni PROPERTIES find_package_handle_standard_args(SimpleIni CONFIG_MODE)
INTERFACE_INCLUDE_DIRECTORIES "${SimpleIni_INCLUDE_DIR}" 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() 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,14 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`2c33ba278`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12802](https://github.com/yuzu-emu/yuzu-android//pull/12802) | [`c5e88c654`](https://github.com/yuzu-emu/yuzu-android//pull/12802/files) | service: mii: Migrate service to new interface | [german77](https://github.com/german77/) | Yes |
End of merge log. You can find the original README.md below the break.
-----
<!-- <!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later

View File

@ -178,6 +178,9 @@ if (NOT TARGET stb::headers)
add_library(stb::headers ALIAS stb) add_library(stb::headers ALIAS stb)
endif() endif()
add_library(tz tz/tz/tz.cpp)
target_include_directories(tz PUBLIC ./tz)
add_library(bc_decoder bc_decoder/bc_decoder.cpp) add_library(bc_decoder bc_decoder/bc_decoder.cpp)
target_include_directories(bc_decoder PUBLIC ./bc_decoder) target_include_directories(bc_decoder PUBLIC ./bc_decoder)

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") 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") 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}...") message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")

View File

@ -11,6 +11,10 @@ execute_process(
WORKING_DIRECTORY ${ZONE_PATH} WORKING_DIRECTORY ${ZONE_PATH}
OUTPUT_VARIABLE FILE_LIST) 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(DIRECTORY_NAME ${HEADER_NAME})
set(FILE_DATA "") set(FILE_DATA "")

1636
externals/tz/tz/tz.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

81
externals/tz/tz/tz.h vendored Normal file
View File

@ -0,0 +1,81 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-FileCopyrightText: 1996 Arthur David Olson
// SPDX-License-Identifier: BSD-2-Clause
#pragma once
#include <cstdint>
#include <limits>
#include <span>
#include <array>
#include <time.h>
namespace Tz {
using u8 = uint8_t;
using s8 = int8_t;
using u16 = uint16_t;
using s16 = int16_t;
using u32 = uint32_t;
using s32 = int32_t;
using u64 = uint64_t;
using s64 = int64_t;
constexpr size_t TZ_MAX_TIMES = 1000;
constexpr size_t TZ_MAX_TYPES = 128;
constexpr size_t TZ_MAX_CHARS = 50;
constexpr size_t MY_TZNAME_MAX = 255;
constexpr size_t TZNAME_MAXIMUM = 255;
constexpr size_t TZ_MAX_LEAPS = 50;
constexpr s64 TIME_T_MAX = std::numeric_limits<s64>::max();
constexpr s64 TIME_T_MIN = std::numeric_limits<s64>::min();
constexpr size_t CHARS_EXTRA = 3;
constexpr size_t MAX_ZONE_CHARS = std::max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof("UTC"));
constexpr size_t MAX_TZNAME_CHARS = 2 * (MY_TZNAME_MAX + 1);
struct ttinfo {
s32 tt_utoff;
bool tt_isdst;
s32 tt_desigidx;
bool tt_ttisstd;
bool tt_ttisut;
};
static_assert(sizeof(ttinfo) == 0x10, "ttinfo has the wrong size!");
struct Rule {
s32 timecnt;
s32 typecnt;
s32 charcnt;
bool goback;
bool goahead;
std::array <u8, 0x2> padding0;
std::array<s64, TZ_MAX_TIMES> ats;
std::array<u8, TZ_MAX_TIMES> types;
std::array<ttinfo, TZ_MAX_TYPES> ttis;
std::array<char, std::max(MAX_ZONE_CHARS, MAX_TZNAME_CHARS)> chars;
s32 defaulttype;
std::array <u8, 0x12C4> padding1;
};
static_assert(sizeof(Rule) == 0x4000, "Rule has the wrong size!");
struct CalendarTimeInternal {
s32 tm_sec;
s32 tm_min;
s32 tm_hour;
s32 tm_mday;
s32 tm_mon;
s32 tm_year;
s32 tm_wday;
s32 tm_yday;
s32 tm_isdst;
std::array<char, 16> tm_zone;
s32 tm_utoff;
s32 time_index;
};
static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has the wrong size!");
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);
} // namespace Tz

View File

@ -303,6 +303,11 @@ object NativeLibrary {
*/ */
external fun getCpuBackend(): String external fun getCpuBackend(): String
/**
* Returns the current GPU Driver.
*/
external fun getGpuDriver(): String
external fun applySettings() external fun applySettings()
external fun logSettings() external fun logSettings()
@ -614,6 +619,11 @@ object NativeLibrary {
*/ */
external fun clearFilesystemProvider() external fun clearFilesystemProvider()
/**
* Checks if all necessary keys are present for decryption
*/
external fun areKeysPresent(): Boolean
/** /**
* Button type for use in onTouchEvent * Button type for use in onTouchEvent
*/ */

View File

@ -193,6 +193,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
return super.dispatchKeyEvent(event) return super.dispatchKeyEvent(event)
} }
if (emulationViewModel.drawerOpen.value) {
return super.dispatchKeyEvent(event)
}
return InputHandler.dispatchKeyEvent(event) return InputHandler.dispatchKeyEvent(event)
} }
@ -203,6 +207,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
return super.dispatchGenericMotionEvent(event) return super.dispatchGenericMotionEvent(event)
} }
if (emulationViewModel.drawerOpen.value) {
return super.dispatchGenericMotionEvent(event)
}
// Don't attempt to do anything if we are disconnecting a device. // Don't attempt to do anything if we are disconnecting a device.
if (event.actionMasked == MotionEvent.ACTION_CANCEL) { if (event.actionMasked == MotionEvent.ACTION_CANCEL) {
return true return true

View File

@ -14,15 +14,20 @@ import androidx.recyclerview.widget.RecyclerView
* Generic adapter that implements an [AsyncDifferConfig] and covers some of the basic boilerplate * Generic adapter that implements an [AsyncDifferConfig] and covers some of the basic boilerplate
* code used in every [RecyclerView]. * code used in every [RecyclerView].
* Type assigned to [Model] must inherit from [Object] in order to be compared properly. * Type assigned to [Model] must inherit from [Object] in order to be compared properly.
* @param exact Decides whether each item will be compared by reference or by their contents
*/ */
abstract class AbstractDiffAdapter<Model : Any, Holder : AbstractViewHolder<Model>> : abstract class AbstractDiffAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
ListAdapter<Model, Holder>(AsyncDifferConfig.Builder(DiffCallback<Model>()).build()) { exact: Boolean = true
) : ListAdapter<Model, Holder>(AsyncDifferConfig.Builder(DiffCallback<Model>(exact)).build()) {
override fun onBindViewHolder(holder: Holder, position: Int) = override fun onBindViewHolder(holder: Holder, position: Int) =
holder.bind(currentList[position]) holder.bind(currentList[position])
private class DiffCallback<Model> : DiffUtil.ItemCallback<Model>() { private class DiffCallback<Model>(val exact: Boolean) : DiffUtil.ItemCallback<Model>() {
override fun areItemsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean { override fun areItemsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
return oldItem === newItem if (exact) {
return oldItem === newItem
}
return oldItem == newItem
} }
@SuppressLint("DiffUtilEquals") @SuppressLint("DiffUtilEquals")

View File

@ -30,7 +30,7 @@ import org.yuzu.yuzu_emu.utils.GameIconUtils
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
class GameAdapter(private val activity: AppCompatActivity) : class GameAdapter(private val activity: AppCompatActivity) :
AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>() { AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>(exact = false) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder {
CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false) CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
.also { return GameViewHolder(it) } .also { return GameViewHolder(it) }

View File

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

View File

@ -141,7 +141,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// So this fragment doesn't restart on configuration changes; i.e. rotation. // So this fragment doesn't restart on configuration changes; i.e. rotation.
retainInstance = true retainInstance = true
emulationState = EmulationState(game.path) emulationState = EmulationState(game.path) {
return@EmulationState driverViewModel.isInteractionAllowed.value
}
} }
/** /**
@ -183,10 +185,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
override fun onDrawerOpened(drawerView: View) { override fun onDrawerOpened(drawerView: View) {
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
binding.inGameMenu.requestFocus()
emulationViewModel.setDrawerOpen(true)
} }
override fun onDrawerClosed(drawerView: View) { override fun onDrawerClosed(drawerView: View) {
binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt()) binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
emulationViewModel.setDrawerOpen(false)
} }
override fun onDrawerStateChanged(newState: Int) { override fun onDrawerStateChanged(newState: Int) {
@ -238,6 +243,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
requireContext().theme requireContext().theme
) )
} }
binding.inGameMenu.requestFocus()
true true
} }
@ -246,6 +252,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
null, null,
Settings.MenuTag.SECTION_ROOT Settings.MenuTag.SECTION_ROOT
) )
binding.inGameMenu.requestFocus()
binding.root.findNavController().navigate(action) binding.root.findNavController().navigate(action)
true true
} }
@ -255,6 +262,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
args.game, args.game,
Settings.MenuTag.SECTION_ROOT Settings.MenuTag.SECTION_ROOT
) )
binding.inGameMenu.requestFocus()
binding.root.findNavController().navigate(action) binding.root.findNavController().navigate(action)
true true
} }
@ -286,15 +294,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
) )
} }
} }
binding.inGameMenu.requestFocus()
NativeConfig.saveGlobalConfig() NativeConfig.saveGlobalConfig()
true true
} }
R.id.menu_exit -> { R.id.menu_exit -> {
emulationState.stop() emulationState.stop()
NativeConfig.reloadGlobalConfig()
emulationViewModel.setIsEmulationStopping(true) emulationViewModel.setIsEmulationStopping(true)
binding.drawerLayout.close() binding.drawerLayout.close()
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) binding.inGameMenu.requestFocus()
true true
} }
@ -311,12 +321,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (!NativeLibrary.isRunning()) { if (!NativeLibrary.isRunning()) {
return return
} }
emulationViewModel.setDrawerOpen(!binding.drawerLayout.isOpen)
if (binding.drawerLayout.isOpen) {
binding.drawerLayout.close()
} else {
binding.drawerLayout.open()
}
} }
} }
) )
@ -370,6 +375,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
} }
launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
driverViewModel.isInteractionAllowed.collect {
if (it) {
startEmulation()
}
}
}
}
launch { launch {
repeatOnLifecycle(Lifecycle.State.CREATED) { repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.emulationStarted.collectLatest { emulationViewModel.emulationStarted.collectLatest {
@ -399,10 +413,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
launch { launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.CREATED) {
driverViewModel.isInteractionAllowed.collect { emulationViewModel.drawerOpen.collect {
if (it) { if (it) {
onEmulationStart() binding.drawerLayout.open()
binding.inGameMenu.requestFocus()
} else {
binding.drawerLayout.close()
} }
} }
} }
@ -410,7 +427,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
private fun onEmulationStart() { private fun startEmulation() {
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) { if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
if (!DirectoryInitialization.areDirectoriesReady) { if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start() DirectoryInitialization.start()
@ -485,12 +502,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val FRAMETIME = 2 val FRAMETIME = 2
val SPEED = 3 val SPEED = 3
perfStatsUpdater = { perfStatsUpdater = {
if (emulationViewModel.emulationStarted.value) { if (emulationViewModel.emulationStarted.value &&
!emulationViewModel.isEmulationStopping.value
) {
val perfStats = NativeLibrary.getPerfStats() val perfStats = NativeLibrary.getPerfStats()
val cpuBackend = NativeLibrary.getCpuBackend() val cpuBackend = NativeLibrary.getCpuBackend()
val gpuDriver = NativeLibrary.getGpuDriver()
if (_binding != null) { if (_binding != null) {
binding.showFpsText.text = binding.showFpsText.text =
String.format("FPS: %.1f\n%s", perfStats[FPS], cpuBackend) String.format("FPS: %.1f\n%s/%s", perfStats[FPS], cpuBackend, gpuDriver)
} }
perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800) perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800)
} }
@ -807,7 +827,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
private class EmulationState(private val gamePath: String) { private class EmulationState(
private val gamePath: String,
private val emulationCanStart: () -> Boolean
) {
private var state: State private var state: State
private var surface: Surface? = null private var surface: Surface? = null
@ -901,6 +924,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
State.PAUSED -> Log.warning( State.PAUSED -> Log.warning(
"[EmulationFragment] Surface cleared while emulation paused." "[EmulationFragment] Surface cleared while emulation paused."
) )
else -> Log.warning( else -> Log.warning(
"[EmulationFragment] Surface cleared while emulation stopped." "[EmulationFragment] Surface cleared while emulation stopped."
) )
@ -910,6 +934,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private fun runWithValidSurface() { private fun runWithValidSurface() {
NativeLibrary.surfaceChanged(surface) NativeLibrary.surfaceChanged(surface)
if (!emulationCanStart.invoke()) {
return
}
when (state) { when (state) {
State.STOPPED -> { State.STOPPED -> {
val emulationThread = Thread({ val emulationThread = Thread({

View File

@ -153,7 +153,13 @@ class HomeSettingsFragment : Fragment() {
cancellable = true cancellable = true
) { progressCallback, _ -> ) { progressCallback, _ ->
val result = NativeLibrary.verifyInstalledContents(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( MessageDialogFragment.newInstance(
titleId = R.string.verify_success, titleId = R.string.verify_success,
descriptionId = R.string.operation_completed_successfully descriptionId = R.string.operation_completed_successfully

View File

@ -26,9 +26,15 @@ class MessageDialogFragment : DialogFragment() {
val descriptionId = requireArguments().getInt(DESCRIPTION_ID) val descriptionId = requireArguments().getInt(DESCRIPTION_ID)
val descriptionString = requireArguments().getString(DESCRIPTION_STRING)!! val descriptionString = requireArguments().getString(DESCRIPTION_STRING)!!
val helpLinkId = requireArguments().getInt(HELP_LINK) val helpLinkId = requireArguments().getInt(HELP_LINK)
val dismissible = requireArguments().getBoolean(DISMISSIBLE)
val clearPositiveAction = requireArguments().getBoolean(CLEAR_POSITIVE_ACTION)
val builder = MaterialAlertDialogBuilder(requireContext()) val builder = MaterialAlertDialogBuilder(requireContext())
if (clearPositiveAction) {
messageDialogViewModel.positiveAction = null
}
if (messageDialogViewModel.positiveAction == null) { if (messageDialogViewModel.positiveAction == null) {
builder.setPositiveButton(R.string.close, null) builder.setPositiveButton(R.string.close, null)
} else { } else {
@ -51,6 +57,8 @@ class MessageDialogFragment : DialogFragment() {
} }
} }
isCancelable = dismissible
return builder.show() return builder.show()
} }
@ -67,6 +75,8 @@ class MessageDialogFragment : DialogFragment() {
private const val DESCRIPTION_ID = "DescriptionId" private const val DESCRIPTION_ID = "DescriptionId"
private const val DESCRIPTION_STRING = "DescriptionString" private const val DESCRIPTION_STRING = "DescriptionString"
private const val HELP_LINK = "Link" private const val HELP_LINK = "Link"
private const val DISMISSIBLE = "Dismissible"
private const val CLEAR_POSITIVE_ACTION = "ClearPositiveAction"
fun newInstance( fun newInstance(
activity: FragmentActivity? = null, activity: FragmentActivity? = null,
@ -75,22 +85,28 @@ class MessageDialogFragment : DialogFragment() {
descriptionId: Int = 0, descriptionId: Int = 0,
descriptionString: String = "", descriptionString: String = "",
helpLinkId: Int = 0, helpLinkId: Int = 0,
dismissible: Boolean = true,
positiveAction: (() -> Unit)? = null positiveAction: (() -> Unit)? = null
): MessageDialogFragment { ): MessageDialogFragment {
val dialog = MessageDialogFragment() var clearPositiveAction = false
val bundle = Bundle()
bundle.apply {
putInt(TITLE_ID, titleId)
putString(TITLE_STRING, titleString)
putInt(DESCRIPTION_ID, descriptionId)
putString(DESCRIPTION_STRING, descriptionString)
putInt(HELP_LINK, helpLinkId)
}
if (activity != null) { if (activity != null) {
ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply { ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply {
clear() clear()
this.positiveAction = positiveAction this.positiveAction = positiveAction
} }
} else {
clearPositiveAction = true
}
val dialog = MessageDialogFragment()
val bundle = Bundle().apply {
putInt(TITLE_ID, titleId)
putString(TITLE_STRING, titleString)
putInt(DESCRIPTION_ID, descriptionId)
putString(DESCRIPTION_STRING, descriptionString)
putInt(HELP_LINK, helpLinkId)
putBoolean(DISMISSIBLE, dismissible)
putBoolean(CLEAR_POSITIVE_ACTION, clearPositiveAction)
} }
dialog.arguments = bundle dialog.arguments = bundle
return dialog return dialog

View File

@ -31,6 +31,7 @@ import androidx.preference.PreferenceManager
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.google.android.material.transition.MaterialFadeThrough import com.google.android.material.transition.MaterialFadeThrough
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.yuzu.yuzu_emu.NativeLibrary
import java.io.File import java.io.File
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
@ -162,7 +163,7 @@ class SetupFragment : Fragment() {
R.string.install_prod_keys_warning_help, R.string.install_prod_keys_warning_help,
{ {
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys") val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
if (file.exists()) { if (file.exists() && NativeLibrary.areKeysPresent()) {
StepState.COMPLETE StepState.COMPLETE
} else { } else {
StepState.INCOMPLETE StepState.INCOMPLETE
@ -347,7 +348,8 @@ class SetupFragment : Fragment() {
val getProdKey = val getProdKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) { if (result != null) {
if (mainActivity.processKey(result)) { mainActivity.processKey(result)
if (NativeLibrary.areKeysPresent()) {
keyCallback.onStepCompleted() keyCallback.onStepCompleted()
} }
} }

View File

@ -144,6 +144,7 @@ class DriverViewModel : ViewModel() {
val selectedDriverFile = File(StringSetting.DRIVER_PATH.getString()) val selectedDriverFile = File(StringSetting.DRIVER_PATH.getString())
val selectedDriverMetadata = GpuDriverHelper.customDriverSettingData val selectedDriverMetadata = GpuDriverHelper.customDriverSettingData
if (GpuDriverHelper.installedCustomDriverData == selectedDriverMetadata) { if (GpuDriverHelper.installedCustomDriverData == selectedDriverMetadata) {
setDriverReady()
return return
} }

View File

@ -6,6 +6,7 @@ package org.yuzu.yuzu_emu.model
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class EmulationViewModel : ViewModel() { class EmulationViewModel : ViewModel() {
val emulationStarted: StateFlow<Boolean> get() = _emulationStarted val emulationStarted: StateFlow<Boolean> get() = _emulationStarted
@ -23,6 +24,9 @@ class EmulationViewModel : ViewModel() {
val shaderMessage: StateFlow<String> get() = _shaderMessage val shaderMessage: StateFlow<String> get() = _shaderMessage
private val _shaderMessage = MutableStateFlow("") private val _shaderMessage = MutableStateFlow("")
private val _drawerOpen = MutableStateFlow(false)
val drawerOpen = _drawerOpen.asStateFlow()
fun setEmulationStarted(started: Boolean) { fun setEmulationStarted(started: Boolean) {
_emulationStarted.value = started _emulationStarted.value = started
} }
@ -49,6 +53,10 @@ class EmulationViewModel : ViewModel() {
setTotalShaders(max) setTotalShaders(max)
} }
fun setDrawerOpen(value: Boolean) {
_drawerOpen.value = value
}
fun clear() { fun clear() {
setEmulationStarted(false) setEmulationStarted(false)
setIsEmulationStopping(false) setIsEmulationStopping(false)

View File

@ -70,11 +70,19 @@ class Game(
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is Game) { if (this === other) return true
return false if (javaClass != other?.javaClass) return false
}
return hashCode() == other.hashCode() other as Game
if (title != other.title) return false
if (path != other.path) return false
if (programId != other.programId) return false
if (developer != other.developer) return false
if (version != other.version) return false
if (isHomebrew != other.isHomebrew) return false
return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {

View File

@ -31,6 +31,9 @@ class HomeViewModel : ViewModel() {
private val _reloadPropertiesList = MutableStateFlow(false) private val _reloadPropertiesList = MutableStateFlow(false)
val reloadPropertiesList get() = _reloadPropertiesList.asStateFlow() val reloadPropertiesList get() = _reloadPropertiesList.asStateFlow()
private val _checkKeys = MutableStateFlow(false)
val checkKeys = _checkKeys.asStateFlow()
var navigatedToSetup = false var navigatedToSetup = false
fun setNavigationVisibility(visible: Boolean, animated: Boolean) { fun setNavigationVisibility(visible: Boolean, animated: Boolean) {
@ -66,4 +69,8 @@ class HomeViewModel : ViewModel() {
fun reloadPropertiesList(reload: Boolean) { fun reloadPropertiesList(reload: Boolean) {
_reloadPropertiesList.value = reload _reloadPropertiesList.value = reload
} }
fun setCheckKeys(value: Boolean) {
_checkKeys.value = value
}
} }

View File

@ -64,6 +64,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
override var themeId: Int = 0 override var themeId: Int = 0
private val CHECKED_DECRYPTION = "CheckedDecryption"
private var checkedDecryption = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen() val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady } splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
@ -75,6 +78,18 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
if (savedInstanceState != null) {
checkedDecryption = savedInstanceState.getBoolean(CHECKED_DECRYPTION)
}
if (!checkedDecryption) {
val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext)
.getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true)
if (!firstTimeSetup) {
checkKeys()
}
checkedDecryption = true
}
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
@ -150,6 +165,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
} }
} }
} }
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
homeViewModel.checkKeys.collect {
if (it) {
checkKeys()
homeViewModel.setCheckKeys(false)
}
}
}
}
} }
// Dismiss previous notifications (should not happen unless a crash occurred) // Dismiss previous notifications (should not happen unless a crash occurred)
@ -158,6 +183,21 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
setInsets() setInsets()
} }
private fun checkKeys() {
if (!NativeLibrary.areKeysPresent()) {
MessageDialogFragment.newInstance(
titleId = R.string.keys_missing,
descriptionId = R.string.keys_missing_description,
helpLinkId = R.string.keys_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(CHECKED_DECRYPTION, checkedDecryption)
}
fun finishSetup(navController: NavController) { fun finishSetup(navController: NavController) {
navController.navigate(R.id.action_firstTimeSetupFragment_to_gamesFragment) navController.navigate(R.id.action_firstTimeSetupFragment_to_gamesFragment)
(binding.navigationView as NavigationBarView).setupWithNavController(navController) (binding.navigationView as NavigationBarView).setupWithNavController(navController)
@ -349,6 +389,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
R.string.install_keys_success, R.string.install_keys_success,
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
homeViewModel.setCheckKeys(true)
gamesViewModel.reloadGames(true) gamesViewModel.reloadGames(true)
return true return true
} else { } else {
@ -399,6 +440,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
firmwarePath.deleteRecursively() firmwarePath.deleteRecursively()
cacheFirmwareDir.copyRecursively(firmwarePath, true) cacheFirmwareDir.copyRecursively(firmwarePath, true)
NativeLibrary.initializeSystem(true) NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
getString(R.string.save_file_imported_success) getString(R.string.save_file_imported_success)
} }
} catch (e: Exception) { } catch (e: Exception) {

View File

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

View File

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

View File

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

View File

@ -35,20 +35,22 @@
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h" #include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.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/submission_package.h"
#include "core/file_sys/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs_real.h" #include "core/file_sys/vfs/vfs_real.h"
#include "core/frontend/applets/cabinet.h" #include "core/frontend/applets/cabinet.h"
#include "core/frontend/applets/controller.h" #include "core/frontend/applets/controller.h"
#include "core/frontend/applets/error.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/mii_edit.h"
#include "core/frontend/applets/profile_select.h" #include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h" #include "core/frontend/applets/web_browser.h"
#include "core/hle/service/am/applet_ae.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/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/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "frontend_common/config.h" #include "frontend_common/config.h"
@ -154,7 +156,7 @@ void EmulationSession::SurfaceChanged() {
} }
void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) { 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) { if (!file) {
return; return;
} }
@ -207,6 +209,12 @@ void EmulationSession::InitializeSystem(bool reload) {
m_system.GetFileSystemController().CreateFactories(*m_vfs); m_system.GetFileSystemController().CreateFactories(*m_vfs);
} }
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) { Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
std::scoped_lock lock(m_mutex); std::scoped_lock lock(m_mutex);
@ -221,7 +229,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.ApplySettings(); m_system.ApplySettings();
Settings::LogSettings(); Settings::LogSettings();
m_system.HIDCore().ReloadInputDevices(); m_system.HIDCore().ReloadInputDevices();
m_system.SetAppletFrontendSet({ m_system.SetFrontendAppletSet({
nullptr, // Amiibo Settings nullptr, // Amiibo Settings
nullptr, // Controller Selector nullptr, // Controller Selector
nullptr, // Error Display nullptr, // Error Display
@ -237,7 +245,10 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath); ConfigureFilesystemProvider(filepath);
// Load the ROM. // 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),
};
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
if (m_load_result != Core::SystemResultStatus::Success) { if (m_load_result != Core::SystemResultStatus::Success) {
return m_load_result; return m_load_result;
} }
@ -247,6 +258,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady(); m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); }); m_system.RegisterExitCallback([&] { HaltEmulation(); });
OnEmulationStarted();
return Core::SystemResultStatus::Success; return Core::SystemResultStatus::Success;
} }
@ -321,6 +333,9 @@ void EmulationSession::RunEmulation() {
} }
} }
} }
// Reset current applet ID.
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
} }
bool EmulationSession::IsHandheldOnly() { bool EmulationSession::IsHandheldOnly() {
@ -463,8 +478,8 @@ int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject
}; };
return static_cast<int>( return static_cast<int>(
ContentManager::InstallNSP(&EmulationSession::GetInstance().System(), ContentManager::InstallNSP(EmulationSession::GetInstance().System(),
EmulationSession::GetInstance().System().GetFilesystem().get(), *EmulationSession::GetInstance().System().GetFilesystem(),
GetJString(env, j_file), callback)); GetJString(env, j_file), callback));
} }
@ -474,8 +489,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* en
u64 program_id = EmulationSession::GetProgramId(env, jprogramId); u64 program_id = EmulationSession::GetProgramId(env, jprogramId);
std::string updatePath = GetJString(env, jupdatePath); std::string updatePath = GetJString(env, jupdatePath);
std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>( std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>(
EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(updatePath, EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
FileSys::Mode::Read)); updatePath, FileSys::OpenMode::Read));
for (const auto& item : nsp->GetNCAs()) { for (const auto& item : nsp->GetNCAs()) {
for (const auto& nca_details : item.second) { for (const auto& nca_details : item.second) {
if (nca_details.second->GetName().ends_with(".cnmt.nca")) { if (nca_details.second->GetName().ends_with(".cnmt.nca")) {
@ -674,6 +689,11 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuBackend(JNIEnv* env, jclass
return ToJString(env, "JIT"); return ToJString(env, "JIT");
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuDriver(JNIEnv* env, jobject jobj) {
return ToJString(env,
EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor());
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) { void Java_org_yuzu_yuzu_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) {
EmulationSession::GetInstance().System().ApplySettings(); EmulationSession::GetInstance().System().ApplySettings();
} }
@ -713,7 +733,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
jobject instance) { jobject instance) {
const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory( 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( const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser(
static_cast<std::size_t>(0)); static_cast<std::size_t>(0));
@ -748,13 +768,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
jint jappletId) { jint jappletId) {
EmulationSession::GetInstance().System().GetAppletManager().SetCurrentAppletId( EmulationSession::GetInstance().SetAppletId(jappletId);
static_cast<Service::AM::Applets::AppletId>(jappletId));
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
jint jcabinetMode) { jint jcabinetMode) {
EmulationSession::GetInstance().System().GetAppletManager().SetCabinetMode( EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode(
static_cast<Service::NFP::CabinetMode>(jcabinetMode)); static_cast<Service::NFP::CabinetMode>(jcabinetMode));
} }
@ -819,7 +838,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject job
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj, void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj,
jstring jprogramId) { jstring jprogramId) {
auto program_id = EmulationSession::GetProgramId(env, jprogramId); auto program_id = EmulationSession::GetProgramId(env, jprogramId);
ContentManager::RemoveAllDLC(&EmulationSession::GetInstance().System(), program_id); ContentManager::RemoveAllDLC(EmulationSession::GetInstance().System(), program_id);
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId, void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId,
@ -829,8 +848,9 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj,
program_id, GetJString(env, jname)); program_id, GetJString(env, jname));
} }
jobject Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env, jobject jobj, jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env,
jobject jcallback) { jobject jobj,
jobject jcallback) {
auto jlambdaClass = env->GetObjectClass(jcallback); auto jlambdaClass = env->GetObjectClass(jcallback);
auto jlambdaInvokeMethod = env->GetMethodID( auto jlambdaInvokeMethod = env->GetMethodID(
jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
@ -842,7 +862,7 @@ jobject Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* en
auto& session = EmulationSession::GetInstance(); auto& session = EmulationSession::GetInstance();
std::vector<std::string> result = ContentManager::VerifyInstalledContents( std::vector<std::string> result = ContentManager::VerifyInstalledContents(
&session.System(), session.GetContentProvider(), callback); session.System(), *session.GetContentProvider(), callback);
jobjectArray jresult = jobjectArray jresult =
env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, "")); env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, ""));
for (size_t i = 0; i < result.size(); ++i) { for (size_t i = 0; i < result.size(); ++i) {
@ -863,7 +883,7 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobje
}; };
auto& session = EmulationSession::GetInstance(); auto& session = EmulationSession::GetInstance();
return static_cast<jint>( return static_cast<jint>(
ContentManager::VerifyGameContents(&session.System(), GetJString(env, jpath), callback)); ContentManager::VerifyGameContents(session.System(), GetJString(env, jpath), callback));
} }
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj,
@ -882,7 +902,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(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( const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, {}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
@ -912,4 +932,10 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_clearFilesystemProvider(JNIEnv* env,
EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries(); EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries();
} }
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, jobject jobj) {
auto& system = EmulationSession::GetInstance().System();
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
return ContentManager::AreKeysPresent();
}
} // extern "C" } // extern "C"

View File

@ -45,6 +45,7 @@ public:
const Core::PerfStatsResults& PerfStats(); const Core::PerfStatsResults& PerfStats();
void ConfigureFilesystemProvider(const std::string& filepath); void ConfigureFilesystemProvider(const std::string& filepath);
void InitializeSystem(bool reload); void InitializeSystem(bool reload);
void SetAppletId(int applet_id);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath); Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
bool IsHandheldOnly(); bool IsHandheldOnly();
@ -77,6 +78,7 @@ private:
std::atomic<bool> m_is_paused = false; std::atomic<bool> m_is_paused = false;
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
int m_applet_id{1};
// GPU driver parameters // GPU driver parameters
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -144,6 +144,9 @@
<string name="no_save_data_found">No save data found</string> <string name="no_save_data_found">No save data found</string>
<string name="verify_installed_content">Verify installed content</string> <string name="verify_installed_content">Verify installed content</string>
<string name="verify_installed_content_description">Checks all installed content for corruption</string> <string name="verify_installed_content_description">Checks all installed content for corruption</string>
<string name="keys_missing">Encryption keys are missing</string>
<string name="keys_missing_description">Firmware and retail games cannot be decrypted</string>
<string name="keys_missing_help">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
<!-- Applet launcher strings --> <!-- Applet launcher strings -->
<string name="applets">Applet launcher</string> <string name="applets">Applet launcher</string>

View File

@ -106,6 +106,7 @@ add_library(common STATIC
precompiled_headers.h precompiled_headers.h
quaternion.h quaternion.h
range_map.h range_map.h
range_mutex.h
reader_writer_queue.h reader_writer_queue.h
ring_buffer.h ring_buffer.h
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp

View File

@ -30,27 +30,27 @@ NativeClock::NativeClock() {
} }
std::chrono::nanoseconds NativeClock::GetTimeNS() const { std::chrono::nanoseconds NativeClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_cntfrq_factor)}; return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
} }
std::chrono::microseconds NativeClock::GetTimeUS() const { std::chrono::microseconds NativeClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_cntfrq_factor)}; return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
} }
std::chrono::milliseconds NativeClock::GetTimeMS() const { std::chrono::milliseconds NativeClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_cntfrq_factor)}; return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
} }
u64 NativeClock::GetCNTPCT() const { s64 NativeClock::GetCNTPCT() const {
return MultiplyHigh(GetHostTicksElapsed(), guest_cntfrq_factor); return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
} }
u64 NativeClock::GetGPUTick() const { s64 NativeClock::GetGPUTick() const {
return MultiplyHigh(GetHostTicksElapsed(), gputick_cntfrq_factor); return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
} }
u64 NativeClock::GetHostTicksNow() const { s64 NativeClock::GetUptime() const {
u64 cntvct_el0 = 0; s64 cntvct_el0 = 0;
asm volatile("dsb ish\n\t" asm volatile("dsb ish\n\t"
"mrs %[cntvct_el0], cntvct_el0\n\t" "mrs %[cntvct_el0], cntvct_el0\n\t"
"dsb ish\n\t" "dsb ish\n\t"
@ -58,15 +58,11 @@ u64 NativeClock::GetHostTicksNow() const {
return cntvct_el0; return cntvct_el0;
} }
u64 NativeClock::GetHostTicksElapsed() const {
return GetHostTicksNow();
}
bool NativeClock::IsNative() const { bool NativeClock::IsNative() const {
return true; return true;
} }
u64 NativeClock::GetHostCNTFRQ() { s64 NativeClock::GetHostCNTFRQ() {
u64 cntfrq_el0 = 0; u64 cntfrq_el0 = 0;
std::string_view board{""}; std::string_view board{""};
#ifdef ANDROID #ifdef ANDROID

View File

@ -17,17 +17,15 @@ public:
std::chrono::milliseconds GetTimeMS() const override; std::chrono::milliseconds GetTimeMS() const override;
u64 GetCNTPCT() const override; s64 GetCNTPCT() const override;
u64 GetGPUTick() const override; s64 GetGPUTick() const override;
u64 GetHostTicksNow() const override; s64 GetUptime() const override;
u64 GetHostTicksElapsed() const override;
bool IsNative() const override; bool IsNative() const override;
static u64 GetHostCNTFRQ(); static s64 GetHostCNTFRQ();
public: public:
using FactorType = unsigned __int128; using FactorType = unsigned __int128;

View File

@ -18,4 +18,4 @@ struct MemoryInfo {
*/ */
[[nodiscard]] const MemoryInfo& GetMemInfo(); [[nodiscard]] const MemoryInfo& GetMemInfo();
} // namespace Common } // namespace Common

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <algorithm>
#include <type_traits> #include <type_traits>
#include "bit_cast.h" #include "bit_cast.h"
@ -19,4 +20,21 @@ inline T WrappingAdd(T lhs, T rhs) {
return BitCast<T>(lhs_u + rhs_u); 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 } // 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

@ -419,9 +419,16 @@ struct Values {
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true}; linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
SwitchableSetting<s64> custom_rtc{ SwitchableSetting<s64> custom_rtc{
linkage, 0, "custom_rtc", Category::System, Specialization::Time, linkage, 0, "custom_rtc", Category::System, Specialization::Time,
true, true, &custom_rtc_enabled}; false, true, &custom_rtc_enabled};
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` SwitchableSetting<s64, true> custom_rtc_offset{linkage,
s64 custom_rtc_differential; 0,
std::numeric_limits<int>::min(),
std::numeric_limits<int>::max(),
"custom_rtc_offset",
Category::System,
Specialization::Countable,
true,
true};
SwitchableSetting<bool> rng_seed_enabled{ SwitchableSetting<bool> rng_seed_enabled{
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true}; linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
SwitchableSetting<u32> rng_seed{ SwitchableSetting<u32> rng_seed{

View File

@ -88,7 +88,17 @@ std::string FindSystemTimeZone() {
LOG_ERROR(Common, "Time zone {} not handled, defaulting to hour offset.", tz_index); LOG_ERROR(Common, "Time zone {} not handled, defaulting to hour offset.", tz_index);
} }
} }
return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours));
// For some reason the Etc/GMT times are reversed. GMT+6 contains -21600 as its offset,
// -6 hours instead of +6 hours, so these signs are purposefully reversed to fix it.
std::string postfix{""};
if (hours > 0) {
postfix = fmt::format("-{:d}", std::abs(hours));
} else if (hours < 0) {
postfix = fmt::format("+{:d}", std::abs(hours));
}
return fmt::format("Etc/GMT{:s}", postfix);
} }
} // namespace Common::TimeZone } // namespace Common::TimeZone

View File

@ -12,9 +12,8 @@
namespace Common { namespace Common {
struct UUID { struct UUID {
std::array<u8, 0x10> uuid{}; std::array<u8, 0x10> uuid;
/// Constructs an invalid UUID.
constexpr UUID() = default; constexpr UUID() = default;
/// Constructs a UUID from a reference to a 128 bit array. /// Constructs a UUID from a reference to a 128 bit array.
@ -34,14 +33,6 @@ struct UUID {
*/ */
explicit UUID(std::string_view uuid_string); explicit UUID(std::string_view uuid_string);
~UUID() = default;
constexpr UUID(const UUID&) noexcept = default;
constexpr UUID(UUID&&) noexcept = default;
constexpr UUID& operator=(const UUID&) noexcept = default;
constexpr UUID& operator=(UUID&&) noexcept = default;
/** /**
* Returns whether the stored UUID is valid or not. * Returns whether the stored UUID is valid or not.
* *
@ -121,6 +112,7 @@ struct UUID {
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default; friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
}; };
static_assert(sizeof(UUID) == 0x10, "UUID has incorrect size."); static_assert(sizeof(UUID) == 0x10, "UUID has incorrect size.");
static_assert(std::is_trivial_v<UUID>);
/// An invalid UUID. This UUID has all its bytes set to 0. /// An invalid UUID. This UUID has all its bytes set to 0.
constexpr UUID InvalidUUID = {}; constexpr UUID InvalidUUID = {};

View File

@ -18,42 +18,40 @@ namespace Common {
class StandardWallClock final : public WallClock { class StandardWallClock final : public WallClock {
public: public:
explicit StandardWallClock() : start_time{SteadyClock::Now()} {} explicit StandardWallClock() {}
std::chrono::nanoseconds GetTimeNS() const override { std::chrono::nanoseconds GetTimeNS() const override {
return SteadyClock::Now() - start_time; return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch());
} }
std::chrono::microseconds GetTimeUS() const override { std::chrono::microseconds GetTimeUS() const override {
return static_cast<std::chrono::microseconds>(GetHostTicksElapsed() / NsToUsRatio::den); return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch());
} }
std::chrono::milliseconds GetTimeMS() const override { std::chrono::milliseconds GetTimeMS() const override {
return static_cast<std::chrono::milliseconds>(GetHostTicksElapsed() / NsToMsRatio::den); return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
} }
u64 GetCNTPCT() const override { s64 GetCNTPCT() const override {
return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
} }
u64 GetGPUTick() const override { s64 GetGPUTick() const override {
return GetHostTicksElapsed() * NsToGPUTickRatio::num / NsToGPUTickRatio::den; return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
} }
u64 GetHostTicksNow() const override { s64 GetUptime() const override {
return static_cast<u64>(SteadyClock::Now().time_since_epoch().count()); return std::chrono::duration_cast<std::chrono::nanoseconds>(
} std::chrono::steady_clock::now().time_since_epoch())
.count();
u64 GetHostTicksElapsed() const override {
return static_cast<u64>(GetTimeNS().count());
} }
bool IsNative() const override { bool IsNative() const override {
return false; return false;
} }
private:
SteadyClock::time_point start_time;
}; };
std::unique_ptr<WallClock> CreateOptimalClock() { std::unique_ptr<WallClock> CreateOptimalClock() {

View File

@ -29,16 +29,13 @@ public:
virtual std::chrono::milliseconds GetTimeMS() const = 0; virtual std::chrono::milliseconds GetTimeMS() const = 0;
/// @returns The guest CNTPCT ticks since the construction of this clock. /// @returns The guest CNTPCT ticks since the construction of this clock.
virtual u64 GetCNTPCT() const = 0; virtual s64 GetCNTPCT() const = 0;
/// @returns The guest GPU ticks since the construction of this clock. /// @returns The guest GPU ticks since the construction of this clock.
virtual u64 GetGPUTick() const = 0; virtual s64 GetGPUTick() const = 0;
/// @returns The raw host timer ticks since an indeterminate epoch. /// @returns The raw host timer ticks since an indeterminate epoch.
virtual u64 GetHostTicksNow() const = 0; virtual s64 GetUptime() const = 0;
/// @returns The raw host timer ticks since the construction of this clock.
virtual u64 GetHostTicksElapsed() const = 0;
/// @returns Whether the clock directly uses the host's hardware clock. /// @returns Whether the clock directly uses the host's hardware clock.
virtual bool IsNative() const = 0; virtual bool IsNative() const = 0;

View File

@ -8,39 +8,35 @@
namespace Common::X64 { namespace Common::X64 {
NativeClock::NativeClock(u64 rdtsc_frequency_) NativeClock::NativeClock(u64 rdtsc_frequency_)
: start_ticks{FencedRDTSC()}, rdtsc_frequency{rdtsc_frequency_}, : rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den,
ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)}, rdtsc_frequency)},
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)}, us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)}, ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)}, cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {} gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {}
std::chrono::nanoseconds NativeClock::GetTimeNS() const { std::chrono::nanoseconds NativeClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_rdtsc_factor)}; return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
} }
std::chrono::microseconds NativeClock::GetTimeUS() const { std::chrono::microseconds NativeClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetHostTicksElapsed(), us_rdtsc_factor)}; return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
} }
std::chrono::milliseconds NativeClock::GetTimeMS() const { std::chrono::milliseconds NativeClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetHostTicksElapsed(), ms_rdtsc_factor)}; return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
} }
u64 NativeClock::GetCNTPCT() const { s64 NativeClock::GetCNTPCT() const {
return MultiplyHigh(GetHostTicksElapsed(), cntpct_rdtsc_factor); return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
} }
u64 NativeClock::GetGPUTick() const { s64 NativeClock::GetGPUTick() const {
return MultiplyHigh(GetHostTicksElapsed(), gputick_rdtsc_factor); return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
} }
u64 NativeClock::GetHostTicksNow() const { s64 NativeClock::GetUptime() const {
return FencedRDTSC(); return static_cast<s64>(FencedRDTSC());
}
u64 NativeClock::GetHostTicksElapsed() const {
return FencedRDTSC() - start_ticks;
} }
bool NativeClock::IsNative() const { bool NativeClock::IsNative() const {

View File

@ -17,18 +17,15 @@ public:
std::chrono::milliseconds GetTimeMS() const override; std::chrono::milliseconds GetTimeMS() const override;
u64 GetCNTPCT() const override; s64 GetCNTPCT() const override;
u64 GetGPUTick() const override; s64 GetGPUTick() const override;
u64 GetHostTicksNow() const override; s64 GetUptime() const override;
u64 GetHostTicksElapsed() const override;
bool IsNative() const override; bool IsNative() const override;
private: private:
u64 start_ticks;
u64 rdtsc_frequency; u64 rdtsc_frequency;
u64 ns_rdtsc_factor; u64 ns_rdtsc_factor;

View File

@ -20,28 +20,49 @@ add_library(core STATIC
cpu_manager.h cpu_manager.h
crypto/aes_util.cpp crypto/aes_util.cpp
crypto/aes_util.h crypto/aes_util.h
crypto/ctr_encryption_layer.cpp
crypto/ctr_encryption_layer.h
crypto/encryption_layer.cpp crypto/encryption_layer.cpp
crypto/encryption_layer.h crypto/encryption_layer.h
crypto/key_manager.cpp crypto/key_manager.cpp
crypto/key_manager.h crypto/key_manager.h
crypto/partition_data_manager.cpp crypto/partition_data_manager.cpp
crypto/partition_data_manager.h crypto/partition_data_manager.h
crypto/ctr_encryption_layer.cpp
crypto/ctr_encryption_layer.h
crypto/xts_encryption_layer.cpp crypto/xts_encryption_layer.cpp
crypto/xts_encryption_layer.h crypto/xts_encryption_layer.h
debugger/debugger_interface.h
debugger/debugger.cpp debugger/debugger.cpp
debugger/debugger.h debugger/debugger.h
debugger/gdbstub_arch.cpp debugger/debugger_interface.h
debugger/gdbstub_arch.h
debugger/gdbstub.cpp debugger/gdbstub.cpp
debugger/gdbstub.h debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
device_memory_manager.h device_memory_manager.h
device_memory_manager.inc device_memory_manager.inc
device_memory.cpp device_memory.cpp
device_memory.h 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_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.cpp
file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
file_sys/fssystem/fssystem_aes_ctr_storage.cpp 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_switch_storage.h
file_sys/fssystem/fssystem_utility.cpp file_sys/fssystem/fssystem_utility.cpp
file_sys/fssystem/fssystem_utility.h 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.cpp
file_sys/ips_layer.h file_sys/ips_layer.h
file_sys/kernel_executable.cpp file_sys/kernel_executable.cpp
file_sys/kernel_executable.h file_sys/kernel_executable.h
file_sys/mode.h
file_sys/nca_metadata.cpp file_sys/nca_metadata.cpp
file_sys/nca_metadata.h file_sys/nca_metadata.h
file_sys/partition_filesystem.cpp file_sys/partition_filesystem.cpp
@ -146,22 +152,22 @@ add_library(core STATIC
file_sys/system_archive/system_version.h file_sys/system_archive/system_version.h
file_sys/system_archive/time_zone_binary.cpp file_sys/system_archive/time_zone_binary.cpp
file_sys/system_archive/time_zone_binary.h file_sys/system_archive/time_zone_binary.h
file_sys/vfs.cpp file_sys/vfs/vfs.cpp
file_sys/vfs.h file_sys/vfs/vfs.h
file_sys/vfs_cached.cpp file_sys/vfs/vfs_cached.cpp
file_sys/vfs_cached.h file_sys/vfs/vfs_cached.h
file_sys/vfs_concat.cpp file_sys/vfs/vfs_concat.cpp
file_sys/vfs_concat.h file_sys/vfs/vfs_concat.h
file_sys/vfs_layered.cpp file_sys/vfs/vfs_layered.cpp
file_sys/vfs_layered.h file_sys/vfs/vfs_layered.h
file_sys/vfs_offset.cpp file_sys/vfs/vfs_offset.cpp
file_sys/vfs_offset.h file_sys/vfs/vfs_offset.h
file_sys/vfs_real.cpp file_sys/vfs/vfs_real.cpp
file_sys/vfs_real.h file_sys/vfs/vfs_real.h
file_sys/vfs_static.h file_sys/vfs/vfs_static.h
file_sys/vfs_types.h file_sys/vfs/vfs_types.h
file_sys/vfs_vector.cpp file_sys/vfs/vfs_vector.cpp
file_sys/vfs_vector.h file_sys/vfs/vfs_vector.h
file_sys/xts_archive.cpp file_sys/xts_archive.cpp
file_sys/xts_archive.h file_sys/xts_archive.h
frontend/applets/cabinet.cpp frontend/applets/cabinet.cpp
@ -170,8 +176,8 @@ add_library(core STATIC
frontend/applets/controller.h frontend/applets/controller.h
frontend/applets/error.cpp frontend/applets/error.cpp
frontend/applets/error.h frontend/applets/error.h
frontend/applets/general_frontend.cpp frontend/applets/general.cpp
frontend/applets/general_frontend.h frontend/applets/general.h
frontend/applets/mii_edit.cpp frontend/applets/mii_edit.cpp
frontend/applets/mii_edit.h frontend/applets/mii_edit.h
frontend/applets/profile_select.cpp frontend/applets/profile_select.cpp
@ -194,7 +200,6 @@ add_library(core STATIC
hle/kernel/board/nintendo/nx/secure_monitor.h hle/kernel/board/nintendo/nx/secure_monitor.h
hle/kernel/code_set.cpp hle/kernel/code_set.cpp
hle/kernel/code_set.h hle/kernel/code_set.h
hle/kernel/svc_results.h
hle/kernel/global_scheduler_context.cpp hle/kernel/global_scheduler_context.cpp
hle/kernel/global_scheduler_context.h hle/kernel/global_scheduler_context.h
hle/kernel/init/init_slab_setup.cpp 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_arbiter.h
hle/kernel/k_address_space_info.cpp hle/kernel/k_address_space_info.cpp
hle/kernel/k_address_space_info.h hle/kernel/k_address_space_info.h
hle/kernel/k_affinity_mask.h
hle/kernel/k_auto_object.cpp hle/kernel/k_auto_object.cpp
hle/kernel/k_auto_object.h hle/kernel/k_auto_object.h
hle/kernel/k_auto_object_container.cpp hle/kernel/k_auto_object_container.cpp
hle/kernel/k_auto_object_container.h hle/kernel/k_auto_object_container.h
hle/kernel/k_affinity_mask.h
hle/kernel/k_capabilities.cpp hle/kernel/k_capabilities.cpp
hle/kernel/k_capabilities.h hle/kernel/k_capabilities.h
hle/kernel/k_class_token.cpp hle/kernel/k_class_token.cpp
@ -232,9 +237,9 @@ add_library(core STATIC
hle/kernel/k_event_info.h hle/kernel/k_event_info.h
hle/kernel/k_handle_table.cpp hle/kernel/k_handle_table.cpp
hle/kernel/k_handle_table.h hle/kernel/k_handle_table.h
hle/kernel/k_hardware_timer_base.h
hle/kernel/k_hardware_timer.cpp hle/kernel/k_hardware_timer.cpp
hle/kernel/k_hardware_timer.h hle/kernel/k_hardware_timer.h
hle/kernel/k_hardware_timer_base.h
hle/kernel/k_interrupt_manager.cpp hle/kernel/k_interrupt_manager.cpp
hle/kernel/k_interrupt_manager.h hle/kernel/k_interrupt_manager.h
hle/kernel/k_light_client_session.cpp 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_bitmap.h
hle/kernel/k_page_buffer.cpp hle/kernel/k_page_buffer.cpp
hle/kernel/k_page_buffer.h 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.cpp
hle/kernel/k_page_group.h 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.h
hle/kernel/k_page_table_base.cpp hle/kernel/k_page_table_base.cpp
hle/kernel/k_page_table_base.h hle/kernel/k_page_table_base.h
@ -329,8 +334,6 @@ add_library(core STATIC
hle/kernel/slab_helpers.h hle/kernel/slab_helpers.h
hle/kernel/svc.cpp hle/kernel/svc.cpp
hle/kernel/svc.h hle/kernel/svc.h
hle/kernel/svc_common.h
hle/kernel/svc_types.h
hle/kernel/svc/svc_activity.cpp hle/kernel/svc/svc_activity.cpp
hle/kernel/svc/svc_address_arbiter.cpp hle/kernel/svc/svc_address_arbiter.cpp
hle/kernel/svc/svc_address_translation.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_thread_profiler.cpp
hle/kernel/svc/svc_tick.cpp hle/kernel/svc/svc_tick.cpp
hle/kernel/svc/svc_transfer_memory.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/result.h
hle/service/acc/acc.cpp hle/service/acc/acc.cpp
hle/service/acc/acc.h hle/service/acc/acc.h
@ -384,39 +390,101 @@ add_library(core STATIC
hle/service/acc/errors.h hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h 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.cpp
hle/service/am/am.h 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.cpp
hle/service/am/applet_ae.h 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.cpp
hle/service/am/applet_oe.h hle/service/am/applet_oe.h
hle/service/am/applets/applet_cabinet.cpp hle/service/am/applet_common_functions.cpp
hle/service/am/applets/applet_cabinet.h hle/service/am/applet_common_functions.h
hle/service/am/applets/applet_controller.cpp hle/service/am/applet_message_queue.cpp
hle/service/am/applets/applet_controller.h hle/service/am/applet_message_queue.h
hle/service/am/applets/applet_error.cpp hle/service/am/application_creator.cpp
hle/service/am/applets/applet_error.h hle/service/am/application_creator.h
hle/service/am/applets/applet_general_backend.cpp hle/service/am/application_functions.cpp
hle/service/am/applets/applet_general_backend.h hle/service/am/application_functions.h
hle/service/am/applets/applet_mii_edit.cpp hle/service/am/application_proxy.cpp
hle/service/am/applets/applet_mii_edit.h hle/service/am/application_proxy.h
hle/service/am/applets/applet_mii_edit_types.h hle/service/am/audio_controller.cpp
hle/service/am/applets/applet_profile_select.cpp hle/service/am/audio_controller.h
hle/service/am/applets/applet_profile_select.h hle/service/am/common_state_getter.cpp
hle/service/am/applets/applet_software_keyboard.cpp hle/service/am/common_state_getter.h
hle/service/am/applets/applet_software_keyboard.h hle/service/am/debug_functions.cpp
hle/service/am/applets/applet_software_keyboard_types.h hle/service/am/debug_functions.h
hle/service/am/applets/applet_web_browser.cpp hle/service/am/display_controller.cpp
hle/service/am/applets/applet_web_browser.h hle/service/am/display_controller.h
hle/service/am/applets/applet_web_browser_types.h hle/service/am/global_state_controller.cpp
hle/service/am/applets/applets.cpp hle/service/am/global_state_controller.h
hle/service/am/applets/applets.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.cpp
hle/service/am/idle.h 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.cpp
hle/service/am/omm.h 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.cpp
hle/service/am/spsm.h 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.cpp
hle/service/aoc/aoc_u.h hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp hle/service/apm/apm.cpp
@ -472,26 +540,41 @@ add_library(core STATIC
hle/service/caps/caps_types.h hle/service/caps/caps_types.h
hle/service/caps/caps_u.cpp hle/service/caps/caps_u.cpp
hle/service/caps/caps_u.h hle/service/caps/caps_u.h
hle/service/cmif_serialization.h
hle/service/cmif_types.h
hle/service/erpt/erpt.cpp hle/service/erpt/erpt.cpp
hle/service/erpt/erpt.h hle/service/erpt/erpt.h
hle/service/es/es.cpp hle/service/es/es.cpp
hle/service/es/es.h hle/service/es/es.h
hle/service/eupld/eupld.cpp hle/service/eupld/eupld.cpp
hle/service/eupld/eupld.h hle/service/eupld/eupld.h
hle/service/event.cpp
hle/service/event.h
hle/service/fatal/fatal.cpp hle/service/fatal/fatal.cpp
hle/service/fatal/fatal.h hle/service/fatal/fatal.h
hle/service/fatal/fatal_p.cpp hle/service/fatal/fatal_p.cpp
hle/service/fatal/fatal_p.h hle/service/fatal/fatal_p.h
hle/service/fatal/fatal_u.cpp hle/service/fatal/fatal_u.cpp
hle/service/fatal/fatal_u.h 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.cpp
hle/service/filesystem/filesystem.h hle/service/filesystem/filesystem.h
hle/service/filesystem/fsp_ldr.cpp hle/service/filesystem/fsp/fs_i_directory.cpp
hle/service/filesystem/fsp_ldr.h hle/service/filesystem/fsp/fs_i_directory.h
hle/service/filesystem/fsp_pr.cpp hle/service/filesystem/fsp/fs_i_file.cpp
hle/service/filesystem/fsp_pr.h hle/service/filesystem/fsp/fs_i_file.h
hle/service/filesystem/fsp_srv.cpp hle/service/filesystem/fsp/fs_i_filesystem.cpp
hle/service/filesystem/fsp_srv.h 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.cpp
hle/service/filesystem/romfs_controller.h hle/service/filesystem/romfs_controller.h
hle/service/filesystem/save_data_controller.cpp hle/service/filesystem/save_data_controller.cpp
@ -515,6 +598,24 @@ add_library(core STATIC
hle/service/glue/glue_manager.h hle/service/glue/glue_manager.h
hle/service/glue/notif.cpp hle/service/glue/notif.cpp
hle/service/glue/notif.h hle/service/glue/notif.h
hle/service/glue/time/alarm_worker.cpp
hle/service/glue/time/alarm_worker.h
hle/service/glue/time/file_timestamp_worker.cpp
hle/service/glue/time/file_timestamp_worker.h
hle/service/glue/time/manager.cpp
hle/service/glue/time/manager.h
hle/service/glue/time/pm_state_change_handler.cpp
hle/service/glue/time/pm_state_change_handler.h
hle/service/glue/time/standard_steady_clock_resource.cpp
hle/service/glue/time/standard_steady_clock_resource.h
hle/service/glue/time/static.cpp
hle/service/glue/time/static.h
hle/service/glue/time/time_zone.cpp
hle/service/glue/time/time_zone.h
hle/service/glue/time/time_zone_binary.cpp
hle/service/glue/time/time_zone_binary.h
hle/service/glue/time/worker.cpp
hle/service/glue/time/worker.h
hle/service/grc/grc.cpp hle/service/grc/grc.cpp
hle/service/grc/grc.h hle/service/grc/grc.h
hle/service/hid/hid.cpp hle/service/hid/hid.cpp
@ -531,13 +632,18 @@ add_library(core STATIC
hle/service/hid/irs.h hle/service/hid/irs.h
hle/service/hid/xcd.cpp hle/service/hid/xcd.cpp
hle/service/hid/xcd.h 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.cpp
hle/service/lbl/lbl.h hle/service/lbl/lbl.h
hle/service/ldn/lan_discovery.cpp hle/service/ldn/lan_discovery.cpp
hle/service/ldn/lan_discovery.h hle/service/ldn/lan_discovery.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn.cpp hle/service/ldn/ldn.cpp
hle/service/ldn/ldn.h hle/service/ldn/ldn.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn_types.h hle/service/ldn/ldn_types.h
hle/service/ldr/ldr.cpp hle/service/ldr/ldr.cpp
hle/service/ldr/ldr.h hle/service/ldr/ldr.h
@ -545,16 +651,6 @@ add_library(core STATIC
hle/service/lm/lm.h hle/service/lm/lm.h
hle/service/mig/mig.cpp hle/service/mig/mig.cpp
hle/service/mig/mig.h 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.cpp
hle/service/mii/mii.h hle/service/mii/mii.h
hle/service/mii/mii_database.cpp hle/service/mii/mii_database.cpp
@ -566,10 +662,22 @@ add_library(core STATIC
hle/service/mii/mii_result.h hle/service/mii/mii_result.h
hle/service/mii/mii_types.h hle/service/mii/mii_types.h
hle/service/mii/mii_util.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.cpp
hle/service/mm/mm_u.h hle/service/mm/mm_u.h
hle/service/mnpp/mnpp_app.cpp hle/service/mnpp/mnpp_app.cpp
hle/service/mnpp/mnpp_app.h hle/service/mnpp/mnpp_app.h
hle/service/mutex.cpp
hle/service/mutex.h
hle/service/ncm/ncm.cpp hle/service/ncm/ncm.cpp
hle/service/ncm/ncm.h hle/service/ncm/ncm.h
hle/service/nfc/common/amiibo_crypto.cpp hle/service/nfc/common/amiibo_crypto.cpp
@ -693,25 +801,58 @@ add_library(core STATIC
hle/service/prepo/prepo.h hle/service/prepo/prepo.h
hle/service/psc/psc.cpp hle/service/psc/psc.cpp
hle/service/psc/psc.h hle/service/psc/psc.h
hle/service/psc/time/alarms.cpp
hle/service/psc/time/alarms.h
hle/service/psc/time/clocks/context_writers.cpp
hle/service/psc/time/clocks/context_writers.h
hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h
hle/service/psc/time/clocks/standard_local_system_clock_core.cpp
hle/service/psc/time/clocks/standard_local_system_clock_core.h
hle/service/psc/time/clocks/standard_network_system_clock_core.cpp
hle/service/psc/time/clocks/standard_network_system_clock_core.h
hle/service/psc/time/clocks/standard_steady_clock_core.cpp
hle/service/psc/time/clocks/standard_steady_clock_core.h
hle/service/psc/time/clocks/standard_user_system_clock_core.cpp
hle/service/psc/time/clocks/standard_user_system_clock_core.h
hle/service/psc/time/clocks/steady_clock_core.h
hle/service/psc/time/clocks/system_clock_core.cpp
hle/service/psc/time/clocks/system_clock_core.h
hle/service/psc/time/clocks/tick_based_steady_clock_core.cpp
hle/service/psc/time/clocks/tick_based_steady_clock_core.h
hle/service/psc/time/common.cpp
hle/service/psc/time/common.h
hle/service/psc/time/errors.h
hle/service/psc/time/shared_memory.cpp
hle/service/psc/time/shared_memory.h
hle/service/psc/time/static.cpp
hle/service/psc/time/static.h
hle/service/psc/time/manager.h
hle/service/psc/time/power_state_service.cpp
hle/service/psc/time/power_state_service.h
hle/service/psc/time/service_manager.cpp
hle/service/psc/time/service_manager.h
hle/service/psc/time/steady_clock.cpp
hle/service/psc/time/steady_clock.h
hle/service/psc/time/system_clock.cpp
hle/service/psc/time/system_clock.h
hle/service/psc/time/time_zone.cpp
hle/service/psc/time/time_zone.h
hle/service/psc/time/time_zone_service.cpp
hle/service/psc/time/time_zone_service.h
hle/service/psc/time/power_state_request_manager.cpp
hle/service/psc/time/power_state_request_manager.h
hle/service/ptm/psm.cpp hle/service/ptm/psm.cpp
hle/service/ptm/psm.h hle/service/ptm/psm.h
hle/service/ptm/ptm.cpp hle/service/ptm/ptm.cpp
hle/service/ptm/ptm.h hle/service/ptm/ptm.h
hle/service/ptm/ts.cpp hle/service/ptm/ts.cpp
hle/service/ptm/ts.h hle/service/ptm/ts.h
hle/service/hle_ipc.cpp hle/service/ro/ro.cpp
hle/service/hle_ipc.h hle/service/ro/ro.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_nro_utils.cpp hle/service/ro/ro_nro_utils.cpp
hle/service/ro/ro_nro_utils.h hle/service/ro/ro_nro_utils.h
hle/service/ro/ro_results.h hle/service/ro/ro_results.h
hle/service/ro/ro_types.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.cpp
hle/service/server_manager.h hle/service/server_manager.h
hle/service/service.cpp hle/service/service.cpp
@ -760,40 +901,6 @@ add_library(core STATIC
hle/service/ssl/ssl.cpp hle/service/ssl/ssl.cpp
hle/service/ssl/ssl.h hle/service/ssl/ssl.h
hle/service/ssl/ssl_backend.h hle/service/ssl/ssl_backend.h
hle/service/time/clock_types.h
hle/service/time/ephemeral_network_system_clock_context_writer.h
hle/service/time/ephemeral_network_system_clock_core.h
hle/service/time/errors.h
hle/service/time/local_system_clock_context_writer.h
hle/service/time/network_system_clock_context_writer.h
hle/service/time/standard_local_system_clock_core.h
hle/service/time/standard_network_system_clock_core.h
hle/service/time/standard_steady_clock_core.cpp
hle/service/time/standard_steady_clock_core.h
hle/service/time/standard_user_system_clock_core.cpp
hle/service/time/standard_user_system_clock_core.h
hle/service/time/steady_clock_core.h
hle/service/time/system_clock_context_update_callback.cpp
hle/service/time/system_clock_context_update_callback.h
hle/service/time/system_clock_core.cpp
hle/service/time/system_clock_core.h
hle/service/time/tick_based_steady_clock_core.cpp
hle/service/time/tick_based_steady_clock_core.h
hle/service/time/time.cpp
hle/service/time/time.h
hle/service/time/time_interface.cpp
hle/service/time/time_interface.h
hle/service/time/time_manager.cpp
hle/service/time/time_manager.h
hle/service/time/time_sharedmemory.cpp
hle/service/time/time_sharedmemory.h
hle/service/time/time_zone_content_manager.cpp
hle/service/time/time_zone_content_manager.h
hle/service/time/time_zone_manager.cpp
hle/service/time/time_zone_manager.h
hle/service/time/time_zone_service.cpp
hle/service/time/time_zone_service.h
hle/service/time/time_zone_types.h
hle/service/usb/usb.cpp hle/service/usb/usb.cpp
hle/service/usb/usb.h hle/service/usb/usb.h
hle/service/vi/display/vi_display.cpp hle/service/vi/display/vi_display.cpp
@ -812,9 +919,9 @@ add_library(core STATIC
internal_network/network.h internal_network/network.h
internal_network/network_interface.cpp internal_network/network_interface.cpp
internal_network/network_interface.h internal_network/network_interface.h
internal_network/sockets.h
internal_network/socket_proxy.cpp internal_network/socket_proxy.cpp
internal_network/socket_proxy.h internal_network/socket_proxy.h
internal_network/sockets.h
loader/deconstructed_rom_directory.cpp loader/deconstructed_rom_directory.cpp
loader/deconstructed_rom_directory.h loader/deconstructed_rom_directory.h
loader/kip.cpp loader/kip.cpp
@ -833,13 +940,13 @@ add_library(core STATIC
loader/nsp.h loader/nsp.h
loader/xci.cpp loader/xci.cpp
loader/xci.h loader/xci.h
memory.cpp
memory.h
memory/cheat_engine.cpp memory/cheat_engine.cpp
memory/cheat_engine.h memory/cheat_engine.h
memory/dmnt_cheat_types.h memory/dmnt_cheat_types.h
memory/dmnt_cheat_vm.cpp memory/dmnt_cheat_vm.cpp
memory/dmnt_cheat_vm.h memory/dmnt_cheat_vm.h
memory.cpp
memory.h
perf_stats.cpp perf_stats.cpp
perf_stats.h perf_stats.h
precompiled_headers.h precompiled_headers.h
@ -874,7 +981,7 @@ endif()
create_target_directory_groups(core) create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb) 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) target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
if (MINGW) if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})

View File

@ -21,13 +21,13 @@
#include "core/debugger/debugger.h" #include "core/debugger/debugger.h"
#include "core/device_memory.h" #include "core/device_memory.h"
#include "core/file_sys/bis_factory.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/patch_manager.h"
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs_factory.h" #include "core/file_sys/romfs_factory.h"
#include "core/file_sys/savedata_factory.h" #include "core/file_sys/savedata_factory.h"
#include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs/vfs_concat.h"
#include "core/file_sys/vfs_real.h" #include "core/file_sys/vfs/vfs_real.h"
#include "core/gpu_dirty_memory_manager.h" #include "core/gpu_dirty_memory_manager.h"
#include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
@ -36,13 +36,19 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/physical_core.h"
#include "core/hle/service/acc/profile_manager.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/apm/apm_controller.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.h" #include "core/hle/service/glue/glue_manager.h"
#include "core/hle/service/glue/time/static.h"
#include "core/hle/service/psc/time/static.h"
#include "core/hle/service/psc/time/steady_clock.h"
#include "core/hle/service/psc/time/system_clock.h"
#include "core/hle/service/psc/time/time_zone_service.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#include "core/hle/service/time/time_manager.h"
#include "core/internal_network/network.h" #include "core/internal_network/network.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/memory.h" #include "core/memory.h"
@ -97,7 +103,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
Common::SplitPath(path, &dir_name, &filename, nullptr); Common::SplitPath(path, &dir_name, &filename, nullptr);
if (filename == "00") { 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; std::vector<FileSys::VirtualFile> concat;
for (u32 i = 0; i < 0x10; ++i) { for (u32 i = 0; i < 0x10; ++i) {
@ -122,16 +128,16 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
} }
if (Common::FS::IsDir(path)) { 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 { struct System::Impl {
explicit Impl(System& system) explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system}, : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
reporter{system}, applet_manager{system}, profile_manager{}, time_manager{system} {} reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
void Initialize(System& system) { void Initialize(System& system) {
device_memory = std::make_unique<Core::DeviceMemory>(); device_memory = std::make_unique<Core::DeviceMemory>();
@ -143,8 +149,6 @@ struct System::Impl {
core_timing.SetMulticore(is_multicore); core_timing.SetMulticore(is_multicore);
core_timing.Initialize([&system]() { system.RegisterHostThread(); }); core_timing.Initialize([&system]() { system.RegisterHostThread(); });
RefreshTime();
// Create a default fs if one doesn't already exist. // Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr) { if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
@ -154,7 +158,7 @@ struct System::Impl {
} }
// Create default implementations of applets if one is not provided. // 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(); is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
@ -182,14 +186,57 @@ struct System::Impl {
Initialize(system); Initialize(system);
} }
void RefreshTime() { void RefreshTime(System& system) {
if (!system.IsPoweredOn()) {
return;
}
auto settings_service =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys",
true);
auto static_service_a =
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:a", true);
auto static_service_s =
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);
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
static_service_a->GetStandardLocalSystemClock(local_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
static_service_s->GetStandardNetworkSystemClock(network_clock);
std::shared_ptr<Service::Glue::Time::TimeZoneService> 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()));
timezone_service->SetDeviceLocation(name);
u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) {
time_offset = Settings::values.custom_rtc_offset.GetValue();
}
const auto posix_time = std::chrono::system_clock::now().time_since_epoch(); const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
const auto current_time = const u64 current_time =
std::chrono::duration_cast<std::chrono::seconds>(posix_time).count(); +std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
Settings::values.custom_rtc_differential = const u64 new_time = current_time + time_offset;
(Settings::values.custom_rtc_enabled ? Settings::values.custom_rtc.GetValue()
: current_time) - Service::PSC::Time::SystemClockContext context{};
current_time; settings_service->SetUserSystemClockContext(context);
user_clock->SetCurrentTime(new_time);
local_clock->SetCurrentTime(new_time);
network_clock->GetSystemClockContext(context);
settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time);
} }
void Run() { void Run() {
@ -265,9 +312,6 @@ struct System::Impl {
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
services = std::make_unique<Service::Services>(service_manager, system); services = std::make_unique<Service::Services>(service_manager, system);
// Initialize time manager, which must happen after kernel is created
time_manager.Initialize();
is_powered_on = true; is_powered_on = true;
exit_locked = false; exit_locked = false;
exit_requested = false; exit_requested = false;
@ -287,16 +331,27 @@ struct System::Impl {
} }
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath, u64 program_id, const std::string& filepath,
std::size_t program_index) { Service::AM::FrontendAppletParameters& params) {
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
program_id, program_index); params.program_id, params.program_index);
if (!app_loader) { if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
return SystemResultStatus::ErrorGetLoader; 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); InitializeKernel(system);
// Create the application process. // Create the application process.
@ -330,9 +385,14 @@ struct System::Impl {
cheat_engine->Initialize(); 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. // All threads are started, begin main process execution, now that we're in the clear.
main_process->Run(load_parameters->main_thread_priority, main_process->Run(load_parameters->main_thread_priority,
load_parameters->main_thread_stack_size); load_parameters->main_thread_stack_size);
main_process->Close();
if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) { if (Settings::values.gamecard_current_game) {
@ -343,21 +403,13 @@ struct System::Impl {
} }
} }
if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) { perf_stats = std::make_unique<PerfStats>(params.program_id);
LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
}
perf_stats = std::make_unique<PerfStats>(program_id);
// Reset counters and set time origin to current frame // Reset counters and set time origin to current frame
GetAndResetPerfStats(); GetAndResetPerfStats();
perf_stats->BeginSystemFrame(); 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; std::string title_version;
const FileSys::PatchManager pm(program_id, system.GetFileSystemController(), const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(),
system.GetContentProvider()); system.GetContentProvider());
const auto metadata = pm.GetControlMetadata(); const auto metadata = pm.GetControlMetadata();
if (metadata.first != nullptr) { if (metadata.first != nullptr) {
@ -366,14 +418,15 @@ struct System::Impl {
if (auto room_member = room_network.GetRoomMember().lock()) { if (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info; Network::GameInfo game_info;
game_info.name = name; game_info.name = name;
game_info.id = program_id; game_info.id = params.program_id;
game_info.version = title_version; game_info.version = title_version;
room_member->SendGameInfo(game_info); room_member->SendGameInfo(game_info);
} }
// Workarounds: // Workarounds:
// Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK // 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; status = SystemResultStatus::Success;
return status; return status;
@ -412,12 +465,12 @@ struct System::Impl {
} }
kernel.CloseServices(); kernel.CloseServices();
kernel.ShutdownCores(); kernel.ShutdownCores();
applet_manager.Reset();
services.reset(); services.reset();
service_manager.reset(); service_manager.reset();
fs_controller.Reset(); fs_controller.Reset();
cheat_engine.reset(); cheat_engine.reset();
telemetry_session.reset(); telemetry_session.reset();
time_manager.Shutdown();
core_timing.ClearPendingEvents(); core_timing.ClearPendingEvents();
app_loader.reset(); app_loader.reset();
audio_core.reset(); audio_core.reset();
@ -524,8 +577,9 @@ struct System::Impl {
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api; std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
/// Frontend applets /// Applets
Service::AM::Applets::AppletManager applet_manager; Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
/// APM (Performance) services /// APM (Performance) services
Service::APM::Controller apm_controller{core_timing}; Service::APM::Controller apm_controller{core_timing};
@ -533,7 +587,6 @@ struct System::Impl {
/// Service State /// Service State
Service::Glue::ARPManager arp_manager; Service::Glue::ARPManager arp_manager;
Service::Account::ProfileManager profile_manager; Service::Account::ProfileManager profile_manager;
Service::Time::TimeManager time_manager;
/// Service manager /// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager; std::shared_ptr<Service::SM::ServiceManager> service_manager;
@ -639,8 +692,8 @@ void System::InitializeDebugger() {
} }
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
u64 program_id, std::size_t program_index) { Service::AM::FrontendAppletParameters& params) {
return impl->Load(*this, emu_window, filepath, program_id, program_index); return impl->Load(*this, emu_window, filepath, params);
} }
bool System::IsPoweredOn() const { bool System::IsPoweredOn() const {
@ -830,19 +883,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size); impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
} }
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) { void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
impl->applet_manager.SetAppletFrontendSet(std::move(set)); impl->frontend_applets.SetFrontendAppletSet(std::move(set));
} }
void System::SetDefaultAppletFrontendSet() { Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
impl->applet_manager.SetDefaultAppletFrontendSet(); return impl->frontend_applets;
} }
Service::AM::Applets::AppletManager& System::GetAppletManager() { const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->applet_manager; return impl->frontend_applets;
} }
const Service::AM::Applets::AppletManager& System::GetAppletManager() const { Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager; return impl->applet_manager;
} }
@ -911,14 +964,6 @@ const Service::Account::ProfileManager& System::GetProfileManager() const {
return impl->profile_manager; return impl->profile_manager;
} }
Service::Time::TimeManager& System::GetTimeManager() {
return impl->time_manager;
}
const Service::Time::TimeManager& System::GetTimeManager() const {
return impl->time_manager;
}
void System::SetExitLocked(bool locked) { void System::SetExitLocked(bool locked) {
impl->exit_locked = locked; impl->exit_locked = locked;
} }
@ -1030,13 +1075,9 @@ void System::Exit() {
} }
void System::ApplySettings() { void System::ApplySettings() {
impl->RefreshTime(); impl->RefreshTime(*this);
if (IsPoweredOn()) { if (IsPoweredOn()) {
if (Settings::values.custom_rtc_enabled) {
const s64 posix_time{Settings::values.custom_rtc.GetValue()};
GetTimeManager().UpdateLocalSystemClockTime(posix_time);
}
Renderer().RefreshBaseSettings(); Renderer().RefreshBaseSettings();
} }
} }

View File

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

View File

@ -157,7 +157,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
} }
} }
for (auto h : to_remove) { for (auto& h : to_remove) {
event_queue.erase(h); event_queue.erase(h);
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@
#include <mutex> #include <mutex>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/range_mutex.h"
#include "common/scratch_buffer.h" #include "common/scratch_buffer.h"
#include "common/virtual_buffer.h" #include "common/virtual_buffer.h"
@ -204,7 +205,7 @@ private:
(1ULL << (device_virtual_bits - page_bits)) / subentries; (1ULL << (device_virtual_bits - page_bits)) / subentries;
using CachedPages = std::array<CounterEntry, num_counter_entries>; using CachedPages = std::array<CounterEntry, num_counter_entries>;
std::unique_ptr<CachedPages> cached_pages; std::unique_ptr<CachedPages> cached_pages;
std::mutex counter_guard; Common::RangeMutex counter_guard;
std::mutex mapping_guard; std::mutex mapping_guard;
}; };

View File

@ -508,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
template <typename Traits> template <typename Traits>
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); Common::ScopedRangeLock lk(counter_guard, addr, size);
const auto Lock = [&] {
if (!lk) {
lk.lock();
}
};
u64 uncache_begin = 0; u64 uncache_begin = 0;
u64 cache_begin = 0; u64 cache_begin = 0;
u64 uncache_bytes = 0; u64 uncache_bytes = 0;
@ -548,7 +543,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
} }
uncache_bytes += Memory::YUZU_PAGESIZE; uncache_bytes += Memory::YUZU_PAGESIZE;
} else if (uncache_bytes > 0) { } else if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
uncache_bytes, false); uncache_bytes, false);
uncache_bytes = 0; uncache_bytes = 0;
@ -559,7 +553,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
} }
cache_bytes += Memory::YUZU_PAGESIZE; cache_bytes += Memory::YUZU_PAGESIZE;
} else if (cache_bytes > 0) { } else if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true); true);
cache_bytes = 0; cache_bytes = 0;
@ -567,12 +560,10 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
vpage++; vpage++;
} }
if (uncache_bytes > 0) { if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
false); false);
} }
if (cache_bytes > 0) { if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true); true);
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -13,7 +13,7 @@
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/content_archive.h" #include "core/file_sys/content_archive.h"
#include "core/file_sys/partition_filesystem.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/loader/loader.h"
#include "core/file_sys/fssystem/fssystem_compression_configuration.h" #include "core/file_sys/fssystem/fssystem_compression_configuration.h"

View File

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

View File

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

View File

@ -8,7 +8,7 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/file_sys/vfs_types.h" #include "core/file_sys/vfs/vfs_types.h"
namespace FileSys { 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 { namespace FileSys {
constexpr Result ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1}; constexpr Result ResultPathNotFound{ErrorModule::FS, 1};
constexpr Result ERROR_PATH_ALREADY_EXISTS{ErrorModule::FS, 2}; constexpr Result ResultPathAlreadyExists{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 ResultUnsupportedSdkVersion{ErrorModule::FS, 50}; constexpr Result ResultUnsupportedSdkVersion{ErrorModule::FS, 50};
constexpr Result ResultPartitionNotFound{ErrorModule::FS, 1001}; 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 ResultUnsupportedVersion{ErrorModule::FS, 3002};
constexpr Result ResultOutOfRange{ErrorModule::FS, 3005}; constexpr Result ResultOutOfRange{ErrorModule::FS, 3005};
constexpr Result ResultAllocationMemoryFailedInFileSystemBuddyHeapA{ErrorModule::FS, 3294}; constexpr Result ResultAllocationMemoryFailedInFileSystemBuddyHeapA{ErrorModule::FS, 3294};
@ -78,10 +73,21 @@ constexpr Result ResultUnexpectedInCompressedStorageA{ErrorModule::FS, 5324};
constexpr Result ResultUnexpectedInCompressedStorageB{ErrorModule::FS, 5325}; constexpr Result ResultUnexpectedInCompressedStorageB{ErrorModule::FS, 5325};
constexpr Result ResultUnexpectedInCompressedStorageC{ErrorModule::FS, 5326}; constexpr Result ResultUnexpectedInCompressedStorageC{ErrorModule::FS, 5326};
constexpr Result ResultUnexpectedInCompressedStorageD{ErrorModule::FS, 5327}; constexpr Result ResultUnexpectedInCompressedStorageD{ErrorModule::FS, 5327};
constexpr Result ResultUnexpectedInPathA{ErrorModule::FS, 5328};
constexpr Result ResultInvalidArgument{ErrorModule::FS, 6001}; 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 ResultInvalidOffset{ErrorModule::FS, 6061};
constexpr Result ResultInvalidSize{ErrorModule::FS, 6062}; constexpr Result ResultInvalidSize{ErrorModule::FS, 6062};
constexpr Result ResultNullptrArgument{ErrorModule::FS, 6063}; 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 ResultUnsupportedSetSizeForIndirectStorage{ErrorModule::FS, 6325};
constexpr Result ResultUnsupportedWriteForCompressedStorage{ErrorModule::FS, 6387}; constexpr Result ResultUnsupportedWriteForCompressedStorage{ErrorModule::FS, 6387};
constexpr Result ResultUnsupportedOperateRangeForCompressedStorage{ErrorModule::FS, 6388}; 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 "common/assert.h"
#include "core/file_sys/fsmitm_romfsbuild.h" #include "core/file_sys/fsmitm_romfsbuild.h"
#include "core/file_sys/ips_layer.h" #include "core/file_sys/ips_layer.h"
#include "core/file_sys/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs_vector.h" #include "core/file_sys/vfs/vfs_vector.h"
namespace FileSys { namespace FileSys {

View File

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

View File

@ -5,7 +5,7 @@
#include "common/overflow.h" #include "common/overflow.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/vfs.h" #include "core/file_sys/vfs/vfs.h"
namespace FileSys { 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_counter_extended_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_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/fssystem/fssystem_nca_header.h"
#include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs/vfs_offset.h"
namespace FileSys { namespace FileSys {

View File

@ -9,7 +9,7 @@
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_i_storage.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 { namespace FileSys {

View File

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

View File

@ -10,7 +10,7 @@
#include "core/file_sys/fssystem/fssystem_bucket_tree.h" #include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_compression_common.h" #include "core/file_sys/fssystem/fssystem_compression_common.h"
#include "core/file_sys/fssystem/fssystem_pooled_buffer.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 { namespace FileSys {

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h" #include "core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h"
#include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs/vfs_offset.h"
namespace FileSys { namespace FileSys {

View File

@ -8,7 +8,7 @@
#include "core/file_sys/fssystem/fs_types.h" #include "core/file_sys/fssystem/fs_types.h"
#include "core/file_sys/fssystem/fssystem_alignment_matching_storage.h" #include "core/file_sys/fssystem/fssystem_alignment_matching_storage.h"
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h" #include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
#include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs/vfs_offset.h"
namespace FileSys { namespace FileSys {

View File

@ -7,7 +7,7 @@
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_i_storage.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 { namespace FileSys {

View File

@ -7,8 +7,8 @@
#include "core/file_sys/fssystem/fs_i_storage.h" #include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h" #include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h" #include "core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h"
#include "core/file_sys/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs/vfs_offset.h"
namespace FileSys { namespace FileSys {

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