Compare commits
104 Commits
android-20
...
android-21
Author | SHA1 | Date | |
---|---|---|---|
28a23c4380 | |||
c768c19898 | |||
7273701bc2 | |||
3bf0492edb | |||
ce2eb6e8ee | |||
8b47465586 | |||
3065ab0fd8 | |||
a2407a2964 | |||
16b79df836 | |||
6a4b25699d | |||
bd8635e26a | |||
4349cdba07 | |||
f2fb761bac | |||
59aee2b461 | |||
4d206d849e | |||
744c0173d1 | |||
55482ab5dc | |||
e56b44dee6 | |||
f2012e5aff | |||
4526fdaf64 | |||
bc22b4e782 | |||
f70821ce0d | |||
a774ff935c | |||
431df5ae93 | |||
677c2c2cd2 | |||
ee540c712c | |||
d23c4393fd | |||
b24a111136 | |||
91636deaaf | |||
68cbf67f4c | |||
645961613f | |||
53b321c945 | |||
975deb7528 | |||
2c049ae06d | |||
54372fdff5 | |||
c60ab6bbf6 | |||
cc09c265e1 | |||
0f9288e38d | |||
06fb7f90da | |||
e04368ad7c | |||
3e2d3548f2 | |||
eb9036d75b | |||
01a2d978eb | |||
6e67b25af9 | |||
e91667ba75 | |||
d45561ace0 | |||
0fdd6e8934 | |||
35794f4f18 | |||
b8be8dff69 | |||
bc317a9807 | |||
97ca160b08 | |||
1a3fc3724a | |||
7b01454d5f | |||
f3749394ac | |||
807f421752 | |||
e4915fb7d2 | |||
a76f6a2775 | |||
ba518f6899 | |||
ad4622da2c | |||
3b1c2896d9 | |||
fc5d76e6e2 | |||
5f9a45ada9 | |||
a120f8ff4d | |||
96833cd809 | |||
8649a80071 | |||
550cadbee4 | |||
8bd10473d6 | |||
8d708b0c79 | |||
beaab10c8f | |||
889c5d2705 | |||
17b0aac809 | |||
399220ddbc | |||
59080a3d1d | |||
3a25a217e6 | |||
961b5586a5 | |||
57ff934f0d | |||
92ce9273ee | |||
dd36d43ea1 | |||
a7a7720752 | |||
c725f3c86c | |||
1b984738ab | |||
748465f5a5 | |||
04867e2456 | |||
32f623e029 | |||
b6c6534c30 | |||
beb438bb0b | |||
4b963ca8a5 | |||
648ed55fe6 | |||
23430e6772 | |||
0672847330 | |||
a874ab0133 | |||
590d9b7e1d | |||
b0bca0f8b0 | |||
d8f1ce2f76 | |||
9b11b9dce5 | |||
303cd31162 | |||
0adc09e0af | |||
96fd1348ae | |||
bad705f245 | |||
34a8d0cc8e | |||
0a2536a0df | |||
c85d7ccd79 | |||
7a9d1ad2f8 | |||
2f0418c101 |
@ -155,3 +155,7 @@ License: MIT
|
|||||||
Files: externals/gamemode/*
|
Files: externals/gamemode/*
|
||||||
Copyright: Copyright 2017-2019 Feral Interactive
|
Copyright: Copyright 2017-2019 Feral Interactive
|
||||||
License: BSD-3-Clause
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Files: src/android/app/debug.keystore
|
||||||
|
Copyright: 2023 yuzu Emulator Project
|
||||||
|
License: GPL-3.0-or-later
|
||||||
|
@ -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()
|
||||||
|
11
README.md
11
README.md
@ -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
|
||||||
|
3
externals/CMakeLists.txt
vendored
3
externals/CMakeLists.txt
vendored
@ -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)
|
||||||
|
|
||||||
|
2
externals/nx_tzdb/CMakeLists.txt
vendored
2
externals/nx_tzdb/CMakeLists.txt
vendored
@ -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}...")
|
||||||
|
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
4
externals/nx_tzdb/NxTzdbCreateHeader.cmake
vendored
@ -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
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
81
externals/tz/tz/tz.h
vendored
Normal 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
|
@ -82,8 +82,8 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
|
||||||
if (keystoreFile != null) {
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
if (keystoreFile != null) {
|
||||||
create("release") {
|
create("release") {
|
||||||
storeFile = file(keystoreFile)
|
storeFile = file(keystoreFile)
|
||||||
storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
||||||
@ -91,6 +91,12 @@ android {
|
|||||||
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
create("default") {
|
||||||
|
storeFile = file("$projectDir/debug.keystore")
|
||||||
|
storePassword = "android"
|
||||||
|
keyAlias = "androiddebugkey"
|
||||||
|
keyPassword = "android"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define build types, which are orthogonal to product flavors.
|
// Define build types, which are orthogonal to product flavors.
|
||||||
@ -101,7 +107,7 @@ android {
|
|||||||
signingConfig = if (keystoreFile != null) {
|
signingConfig = if (keystoreFile != null) {
|
||||||
signingConfigs.getByName("release")
|
signingConfigs.getByName("release")
|
||||||
} else {
|
} else {
|
||||||
signingConfigs.getByName("debug")
|
signingConfigs.getByName("default")
|
||||||
}
|
}
|
||||||
|
|
||||||
resValue("string", "app_name_suffixed", "yuzu")
|
resValue("string", "app_name_suffixed", "yuzu")
|
||||||
@ -118,7 +124,7 @@ android {
|
|||||||
register("relWithDebInfo") {
|
register("relWithDebInfo") {
|
||||||
isDefault = true
|
isDefault = true
|
||||||
resValue("string", "app_name_suffixed", "yuzu Debug Release")
|
resValue("string", "app_name_suffixed", "yuzu Debug Release")
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("default")
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isDebuggable = true
|
isDebuggable = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
@ -133,6 +139,7 @@ android {
|
|||||||
// Signed by debug key disallowing distribution on Play Store.
|
// Signed by debug key disallowing distribution on Play Store.
|
||||||
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
|
||||||
debug {
|
debug {
|
||||||
|
signingConfig = signingConfigs.getByName("default")
|
||||||
resValue("string", "app_name_suffixed", "yuzu Debug")
|
resValue("string", "app_name_suffixed", "yuzu Debug")
|
||||||
isDebuggable = true
|
isDebuggable = true
|
||||||
isJniDebuggable = true
|
isJniDebuggable = true
|
||||||
|
BIN
src/android/app/debug.keystore
Normal file
BIN
src/android/app/debug.keystore
Normal file
Binary file not shown.
@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.utils.Log
|
|||||||
import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
|
import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
|
||||||
import org.yuzu.yuzu_emu.model.InstallResult
|
import org.yuzu.yuzu_emu.model.InstallResult
|
||||||
import org.yuzu.yuzu_emu.model.Patch
|
import org.yuzu.yuzu_emu.model.Patch
|
||||||
|
import org.yuzu.yuzu_emu.model.GameVerificationResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which contains methods that interact
|
* Class which contains methods that interact
|
||||||
@ -302,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()
|
||||||
@ -564,6 +570,26 @@ object NativeLibrary {
|
|||||||
*/
|
*/
|
||||||
external fun removeMod(programId: String, name: String)
|
external fun removeMod(programId: String, name: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies all installed content
|
||||||
|
* @param callback UI callback for verification progress. Return true in the callback to cancel.
|
||||||
|
* @return Array of content that failed verification. Successful if empty.
|
||||||
|
*/
|
||||||
|
external fun verifyInstalledContents(
|
||||||
|
callback: (max: Long, progress: Long) -> Boolean
|
||||||
|
): Array<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the contents of a game
|
||||||
|
* @param path String path to a game
|
||||||
|
* @param callback UI callback for verification progress. Return true in the callback to cancel.
|
||||||
|
* @return Int that is meant to be converted to a [GameVerificationResult]
|
||||||
|
*/
|
||||||
|
external fun verifyGameContents(
|
||||||
|
path: String,
|
||||||
|
callback: (max: Long, progress: Long) -> Boolean
|
||||||
|
): Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the save location for a specific game
|
* Gets the save location for a specific game
|
||||||
*
|
*
|
||||||
@ -593,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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
@ -14,16 +14,21 @@ 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 {
|
||||||
|
if (exact) {
|
||||||
return oldItem === newItem
|
return oldItem === newItem
|
||||||
}
|
}
|
||||||
|
return oldItem == newItem
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("DiffUtilEquals")
|
@SuppressLint("DiffUtilEquals")
|
||||||
override fun areContentsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
|
override fun areContentsTheSame(oldItem: Model & Any, newItem: Model & Any): Boolean {
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.adapters
|
package org.yuzu.yuzu_emu.adapters
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -15,10 +12,6 @@ import android.widget.Toast
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.pm.ShortcutInfoCompat
|
import androidx.core.content.pm.ShortcutInfoCompat
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -30,7 +23,6 @@ import kotlinx.coroutines.withContext
|
|||||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
|
||||||
import org.yuzu.yuzu_emu.databinding.CardGameBinding
|
import org.yuzu.yuzu_emu.databinding.CardGameBinding
|
||||||
import org.yuzu.yuzu_emu.model.Game
|
import org.yuzu.yuzu_emu.model.Game
|
||||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||||
@ -38,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) }
|
||||||
@ -89,36 +81,13 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
|||||||
)
|
)
|
||||||
.apply()
|
.apply()
|
||||||
|
|
||||||
val openIntent =
|
|
||||||
Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
|
|
||||||
action = Intent.ACTION_VIEW
|
|
||||||
data = Uri.parse(game.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
activity.lifecycleScope.launch {
|
activity.lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val layerDrawable = ResourcesCompat.getDrawable(
|
|
||||||
YuzuApplication.appContext.resources,
|
|
||||||
R.drawable.shortcut,
|
|
||||||
null
|
|
||||||
) as LayerDrawable
|
|
||||||
layerDrawable.setDrawableByLayerId(
|
|
||||||
R.id.shortcut_foreground,
|
|
||||||
GameIconUtils.getGameIcon(activity, game)
|
|
||||||
.toDrawable(YuzuApplication.appContext.resources)
|
|
||||||
)
|
|
||||||
val inset = YuzuApplication.appContext.resources
|
|
||||||
.getDimensionPixelSize(R.dimen.icon_inset)
|
|
||||||
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
|
|
||||||
val shortcut =
|
val shortcut =
|
||||||
ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
|
ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
|
||||||
.setShortLabel(game.title)
|
.setShortLabel(game.title)
|
||||||
.setIcon(
|
.setIcon(GameIconUtils.getShortcutIcon(activity, game))
|
||||||
IconCompat.createWithAdaptiveBitmap(
|
.setIntent(game.launchIntent)
|
||||||
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.setIntent(openIntent)
|
|
||||||
.build()
|
.build()
|
||||||
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
|
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
|||||||
THEME("theme"),
|
THEME("theme"),
|
||||||
THEME_MODE("theme_mode"),
|
THEME_MODE("theme_mode"),
|
||||||
OVERLAY_SCALE("control_scale"),
|
OVERLAY_SCALE("control_scale"),
|
||||||
OVERLAY_OPACITY("control_opacity");
|
OVERLAY_OPACITY("control_opacity"),
|
||||||
|
LOCK_DRAWER("lock_drawer");
|
||||||
|
|
||||||
override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)
|
override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,11 +184,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDrawerOpened(drawerView: View) {
|
override fun onDrawerOpened(drawerView: View) {
|
||||||
// No op
|
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
|
binding.inGameMenu.requestFocus()
|
||||||
|
emulationViewModel.setDrawerOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDrawerClosed(drawerView: View) {
|
override fun onDrawerClosed(drawerView: View) {
|
||||||
// No op
|
binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
|
||||||
|
emulationViewModel.setDrawerOpen(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDrawerStateChanged(newState: Int) {
|
override fun onDrawerStateChanged(newState: Int) {
|
||||||
@ -196,6 +201,28 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||||
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
|
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
|
||||||
game.title
|
game.title
|
||||||
|
|
||||||
|
binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply {
|
||||||
|
val lockMode = IntSetting.LOCK_DRAWER.getInt()
|
||||||
|
val titleId = if (lockMode == DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
|
||||||
|
R.string.unlock_drawer
|
||||||
|
} else {
|
||||||
|
R.string.lock_drawer
|
||||||
|
}
|
||||||
|
val iconId = if (lockMode == DrawerLayout.LOCK_MODE_UNLOCKED) {
|
||||||
|
R.drawable.ic_unlock
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_lock
|
||||||
|
}
|
||||||
|
|
||||||
|
title = getString(titleId)
|
||||||
|
icon = ResourcesCompat.getDrawable(
|
||||||
|
resources,
|
||||||
|
iconId,
|
||||||
|
requireContext().theme
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
binding.inGameMenu.setNavigationItemSelectedListener {
|
binding.inGameMenu.setNavigationItemSelectedListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.menu_pause_emulation -> {
|
R.id.menu_pause_emulation -> {
|
||||||
@ -216,6 +243,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
requireContext().theme
|
requireContext().theme
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
binding.inGameMenu.requestFocus()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,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
|
||||||
}
|
}
|
||||||
@ -233,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
|
||||||
}
|
}
|
||||||
@ -242,11 +272,39 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.menu_lock_drawer -> {
|
||||||
|
when (IntSetting.LOCK_DRAWER.getInt()) {
|
||||||
|
DrawerLayout.LOCK_MODE_UNLOCKED -> {
|
||||||
|
IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||||
|
it.title = resources.getString(R.string.unlock_drawer)
|
||||||
|
it.icon = ResourcesCompat.getDrawable(
|
||||||
|
resources,
|
||||||
|
R.drawable.ic_lock,
|
||||||
|
requireContext().theme
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawerLayout.LOCK_MODE_LOCKED_CLOSED -> {
|
||||||
|
IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
|
it.title = resources.getString(R.string.lock_drawer)
|
||||||
|
it.icon = ResourcesCompat.getDrawable(
|
||||||
|
resources,
|
||||||
|
R.drawable.ic_unlock,
|
||||||
|
requireContext().theme
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.inGameMenu.requestFocus()
|
||||||
|
NativeConfig.saveGlobalConfig()
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -322,11 +375,20 @@ 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 {
|
||||||
if (it) {
|
if (it) {
|
||||||
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
|
||||||
ViewUtils.showView(binding.surfaceInputOverlay)
|
ViewUtils.showView(binding.surfaceInputOverlay)
|
||||||
ViewUtils.hideView(binding.loadingIndicator)
|
ViewUtils.hideView(binding.loadingIndicator)
|
||||||
|
|
||||||
@ -351,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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,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()
|
||||||
@ -437,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)
|
||||||
}
|
}
|
||||||
@ -759,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
|
||||||
|
|
||||||
@ -853,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."
|
||||||
)
|
)
|
||||||
@ -862,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({
|
||||||
|
@ -21,8 +21,10 @@ import androidx.fragment.app.activityViewModels
|
|||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding
|
import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding
|
||||||
|
import org.yuzu.yuzu_emu.model.GameVerificationResult
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.GameMetadata
|
import org.yuzu.yuzu_emu.utils.GameMetadata
|
||||||
|
|
||||||
@ -101,6 +103,38 @@ class GameInfoFragment : Fragment() {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
copyToClipboard(args.game.title, details)
|
copyToClipboard(args.game.title, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buttonVerifyIntegrity.setOnClickListener {
|
||||||
|
ProgressDialogFragment.newInstance(
|
||||||
|
requireActivity(),
|
||||||
|
R.string.verifying,
|
||||||
|
true
|
||||||
|
) { progressCallback, _ ->
|
||||||
|
val result = GameVerificationResult.from(
|
||||||
|
NativeLibrary.verifyGameContents(
|
||||||
|
args.game.path,
|
||||||
|
progressCallback
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return@newInstance when (result) {
|
||||||
|
GameVerificationResult.Success ->
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_success,
|
||||||
|
descriptionId = R.string.operation_completed_successfully
|
||||||
|
)
|
||||||
|
GameVerificationResult.Failed ->
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_failure,
|
||||||
|
descriptionId = R.string.verify_failure_description
|
||||||
|
)
|
||||||
|
GameVerificationResult.NotImplemented ->
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_no_result,
|
||||||
|
descriptionId = R.string.verify_no_result_description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInsets()
|
setInsets()
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
package org.yuzu.yuzu_emu.fragments
|
package org.yuzu.yuzu_emu.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.pm.ShortcutInfo
|
||||||
|
import android.content.pm.ShortcutManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -84,6 +86,24 @@ class GamePropertiesFragment : Fragment() {
|
|||||||
view.findNavController().popBackStack()
|
view.findNavController().popBackStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
|
||||||
|
binding.buttonShortcut.isEnabled = shortcutManager.isRequestPinShortcutSupported
|
||||||
|
binding.buttonShortcut.setOnClickListener {
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val shortcut = ShortcutInfo.Builder(requireContext(), args.game.title)
|
||||||
|
.setShortLabel(args.game.title)
|
||||||
|
.setIcon(
|
||||||
|
GameIconUtils.getShortcutIcon(requireActivity(), args.game)
|
||||||
|
.toIcon(requireContext())
|
||||||
|
)
|
||||||
|
.setIntent(args.game.launchIntent)
|
||||||
|
.build()
|
||||||
|
shortcutManager.requestPinShortcut(shortcut, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen)
|
GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen)
|
||||||
binding.title.text = args.game.title
|
binding.title.text = args.game.title
|
||||||
binding.title.postDelayed(
|
binding.title.postDelayed(
|
||||||
|
@ -32,6 +32,7 @@ import org.yuzu.yuzu_emu.BuildConfig
|
|||||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
|
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
|
||||||
import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
|
import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
|
||||||
import org.yuzu.yuzu_emu.features.DocumentProvider
|
import org.yuzu.yuzu_emu.features.DocumentProvider
|
||||||
@ -140,6 +141,44 @@ class HomeSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
HomeSetting(
|
||||||
|
R.string.verify_installed_content,
|
||||||
|
R.string.verify_installed_content_description,
|
||||||
|
R.drawable.ic_check_circle,
|
||||||
|
{
|
||||||
|
ProgressDialogFragment.newInstance(
|
||||||
|
requireActivity(),
|
||||||
|
titleId = R.string.verifying,
|
||||||
|
cancellable = true
|
||||||
|
) { progressCallback, _ ->
|
||||||
|
val result = NativeLibrary.verifyInstalledContents(progressCallback)
|
||||||
|
return@newInstance if (progressCallback.invoke(100, 100)) {
|
||||||
|
// Invoke the progress callback to check if the process was cancelled
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_no_result,
|
||||||
|
descriptionId = R.string.verify_no_result_description
|
||||||
|
)
|
||||||
|
} else if (result.isEmpty()) {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_success,
|
||||||
|
descriptionId = R.string.operation_completed_successfully
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val failedNames = result.joinToString("\n")
|
||||||
|
val errorMessage = YuzuApplication.appContext.getString(
|
||||||
|
R.string.verification_failed_for,
|
||||||
|
failedNames
|
||||||
|
)
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
titleId = R.string.verify_failure,
|
||||||
|
descriptionString = errorMessage
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
HomeSetting(
|
HomeSetting(
|
||||||
R.string.share_log,
|
R.string.share_log,
|
||||||
|
@ -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,28 +75,38 @@ 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,
|
activity: FragmentActivity? = null,
|
||||||
titleId: Int = 0,
|
titleId: Int = 0,
|
||||||
titleString: String = "",
|
titleString: String = "",
|
||||||
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 {
|
||||||
|
var clearPositiveAction = false
|
||||||
|
if (activity != null) {
|
||||||
|
ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply {
|
||||||
|
clear()
|
||||||
|
this.positiveAction = positiveAction
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearPositiveAction = true
|
||||||
|
}
|
||||||
|
|
||||||
val dialog = MessageDialogFragment()
|
val dialog = MessageDialogFragment()
|
||||||
val bundle = Bundle()
|
val bundle = Bundle().apply {
|
||||||
bundle.apply {
|
|
||||||
putInt(TITLE_ID, titleId)
|
putInt(TITLE_ID, titleId)
|
||||||
putString(TITLE_STRING, titleString)
|
putString(TITLE_STRING, titleString)
|
||||||
putInt(DESCRIPTION_ID, descriptionId)
|
putInt(DESCRIPTION_ID, descriptionId)
|
||||||
putString(DESCRIPTION_STRING, descriptionString)
|
putString(DESCRIPTION_STRING, descriptionString)
|
||||||
putInt(HELP_LINK, helpLinkId)
|
putInt(HELP_LINK, helpLinkId)
|
||||||
}
|
putBoolean(DISMISSIBLE, dismissible)
|
||||||
ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply {
|
putBoolean(CLEAR_POSITIVE_ACTION, clearPositiveAction)
|
||||||
clear()
|
|
||||||
this.positiveAction = positiveAction
|
|
||||||
}
|
}
|
||||||
dialog.arguments = bundle
|
dialog.arguments = bundle
|
||||||
return dialog
|
return dialog
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.model
|
package org.yuzu.yuzu_emu.model
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
@ -11,6 +12,7 @@ import kotlinx.serialization.Serializable
|
|||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
|
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@ -61,12 +63,26 @@ class Game(
|
|||||||
val addonDir: String
|
val addonDir: String
|
||||||
get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
|
get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
val launchIntent: Intent
|
||||||
if (other !is Game) {
|
get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
|
||||||
return false
|
action = Intent.ACTION_VIEW
|
||||||
|
data = Uri.parse(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return hashCode() == other.hashCode()
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
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 {
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
package org.yuzu.yuzu_emu.model
|
||||||
|
|
||||||
|
enum class GameVerificationResult(val int: Int) {
|
||||||
|
Success(0),
|
||||||
|
Failed(1),
|
||||||
|
NotImplemented(2);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(int: Int): GameVerificationResult =
|
||||||
|
entries.firstOrNull { it.int == int } ?: Success
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -5,7 +5,10 @@ package org.yuzu.yuzu_emu.utils
|
|||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
@ -85,4 +88,22 @@ object GameIconUtils {
|
|||||||
return imageLoader.execute(request)
|
return imageLoader.execute(request)
|
||||||
.drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
|
.drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getShortcutIcon(lifecycleOwner: LifecycleOwner, game: Game): IconCompat {
|
||||||
|
val layerDrawable = ResourcesCompat.getDrawable(
|
||||||
|
YuzuApplication.appContext.resources,
|
||||||
|
R.drawable.shortcut,
|
||||||
|
null
|
||||||
|
) as LayerDrawable
|
||||||
|
layerDrawable.setDrawableByLayerId(
|
||||||
|
R.id.shortcut_foreground,
|
||||||
|
getGameIcon(lifecycleOwner, game).toDrawable(YuzuApplication.appContext.resources)
|
||||||
|
)
|
||||||
|
val inset = YuzuApplication.appContext.resources
|
||||||
|
.getDimensionPixelSize(R.dimen.icon_inset)
|
||||||
|
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
|
||||||
|
return IconCompat.createWithAdaptiveBitmap(
|
||||||
|
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ struct Values {
|
|||||||
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
|
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
|
||||||
Settings::Category::Overlay};
|
Settings::Category::Overlay};
|
||||||
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
|
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
|
||||||
|
Settings::Setting<s32> lock_drawer{linkage, false, "lock_drawer", Settings::Category::Overlay};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Values values;
|
extern Values values;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,6 +848,44 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj,
|
|||||||
program_id, GetJString(env, jname));
|
program_id, GetJString(env, jname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env,
|
||||||
|
jobject jobj,
|
||||||
|
jobject jcallback) {
|
||||||
|
auto jlambdaClass = env->GetObjectClass(jcallback);
|
||||||
|
auto jlambdaInvokeMethod = env->GetMethodID(
|
||||||
|
jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||||
|
const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
|
||||||
|
auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
|
||||||
|
ToJDouble(env, max), ToJDouble(env, progress));
|
||||||
|
return GetJBoolean(env, jwasCancelled);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto& session = EmulationSession::GetInstance();
|
||||||
|
std::vector<std::string> result = ContentManager::VerifyInstalledContents(
|
||||||
|
session.System(), *session.GetContentProvider(), callback);
|
||||||
|
jobjectArray jresult =
|
||||||
|
env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, ""));
|
||||||
|
for (size_t i = 0; i < result.size(); ++i) {
|
||||||
|
env->SetObjectArrayElement(jresult, i, ToJString(env, result[i]));
|
||||||
|
}
|
||||||
|
return jresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobject jobj,
|
||||||
|
jstring jpath, jobject jcallback) {
|
||||||
|
auto jlambdaClass = env->GetObjectClass(jcallback);
|
||||||
|
auto jlambdaInvokeMethod = env->GetMethodID(
|
||||||
|
jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||||
|
const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
|
||||||
|
auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
|
||||||
|
ToJDouble(env, max), ToJDouble(env, progress));
|
||||||
|
return GetJBoolean(env, jwasCancelled);
|
||||||
|
};
|
||||||
|
auto& session = EmulationSession::GetInstance();
|
||||||
|
return static_cast<jint>(
|
||||||
|
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,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
||||||
@ -845,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,
|
||||||
@ -875,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"
|
||||||
|
@ -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;
|
||||||
|
9
src/android/app/src/main/res/drawable/ic_lock.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_lock.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:width="24dp">
|
||||||
|
<path
|
||||||
|
android:fillColor="?attr/colorControlNormal"
|
||||||
|
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
|
||||||
|
</vector>
|
9
src/android/app/src/main/res/drawable/ic_shortcut.xml
Normal file
9
src/android/app/src/main/res/drawable/ic_shortcut.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="?attr/colorControlNormal"
|
||||||
|
android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v160h-80v-40L280,240v480h400v-40h80v160q0,33 -23.5,56.5T680,920L280,920ZM686,520L480,520v120h-80v-120q0,-33 23.5,-56.5T480,440h206l-62,-64 56,-56 160,160 -160,160 -56,-56 62,-64Z" />
|
||||||
|
</vector>
|
@ -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
|
||||||
|
@ -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>
|
@ -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">
|
||||||
@ -43,16 +44,35 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_back"
|
android:id="@+id/button_back"
|
||||||
style="?attr/materialIconButtonStyle"
|
style="?attr/materialIconButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
app:icon="@drawable/ic_back"
|
app:icon="@drawable/ic_back"
|
||||||
app:iconSize="24dp"
|
app:iconSize="24dp"
|
||||||
app:iconTint="?attr/colorOnSurface" />
|
app:iconTint="?attr/colorOnSurface"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_shortcut"
|
||||||
|
style="?attr/materialIconButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:icon="@drawable/ic_shortcut"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorOnSurface"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
style="?attr/materialCardViewElevatedStyle"
|
style="?attr/materialCardViewElevatedStyle"
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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" />
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
@ -118,6 +121,14 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="@string/copy_details" />
|
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>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -13,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"
|
||||||
@ -22,16 +22,35 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center_horizontal">
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_back"
|
android:id="@+id/button_back"
|
||||||
style="?attr/materialIconButtonStyle"
|
style="?attr/materialIconButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:layout_gravity="start"
|
|
||||||
app:icon="@drawable/ic_back"
|
app:icon="@drawable/ic_back"
|
||||||
app:iconSize="24dp"
|
app:iconSize="24dp"
|
||||||
app:iconTint="?attr/colorOnSurface" />
|
app:iconTint="?attr/colorOnSurface"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_shortcut"
|
||||||
|
style="?attr/materialIconButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:icon="@drawable/ic_shortcut"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorOnSurface"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
style="?attr/materialCardViewElevatedStyle"
|
style="?attr/materialCardViewElevatedStyle"
|
||||||
@ -45,7 +64,7 @@
|
|||||||
android:id="@+id/image_game_screen"
|
android:id="@+id/image_game_screen"
|
||||||
android:layout_width="175dp"
|
android:layout_width="175dp"
|
||||||
android:layout_height="175dp"
|
android:layout_height="175dp"
|
||||||
tools:src="@drawable/default_icon"/>
|
tools:src="@drawable/default_icon" />
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
@ -68,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>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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" />
|
||||||
|
|
||||||
|
@ -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">
|
||||||
|
|
||||||
|
@ -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" />
|
||||||
|
@ -21,6 +21,11 @@
|
|||||||
android:icon="@drawable/ic_controller"
|
android:icon="@drawable/ic_controller"
|
||||||
android:title="@string/emulation_input_overlay" />
|
android:title="@string/emulation_input_overlay" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_lock_drawer"
|
||||||
|
android:icon="@drawable/ic_unlock"
|
||||||
|
android:title="@string/emulation_input_overlay" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_exit"
|
android:id="@+id/menu_exit"
|
||||||
android:icon="@drawable/ic_exit"
|
android:icon="@drawable/ic_exit"
|
||||||
|
@ -142,6 +142,11 @@
|
|||||||
<item quantity="other">Successfully imported %d saves</item>
|
<item quantity="other">Successfully imported %d saves</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<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_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>
|
||||||
@ -288,6 +293,7 @@
|
|||||||
<string name="import_complete">Import complete</string>
|
<string name="import_complete">Import complete</string>
|
||||||
<string name="more_options">More options</string>
|
<string name="more_options">More options</string>
|
||||||
<string name="use_global_setting">Use global setting</string>
|
<string name="use_global_setting">Use global setting</string>
|
||||||
|
<string name="operation_completed_successfully">The operation completed successfully</string>
|
||||||
|
|
||||||
<!-- GPU driver installation -->
|
<!-- GPU driver installation -->
|
||||||
<string name="select_gpu_driver">Select GPU driver</string>
|
<string name="select_gpu_driver">Select GPU driver</string>
|
||||||
@ -352,6 +358,14 @@
|
|||||||
<string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string>
|
<string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string>
|
||||||
<string name="confirm_uninstall">Confirm uninstall</string>
|
<string name="confirm_uninstall">Confirm uninstall</string>
|
||||||
<string name="confirm_uninstall_description">Are you sure you want to uninstall this addon?</string>
|
<string name="confirm_uninstall_description">Are you sure you want to uninstall this addon?</string>
|
||||||
|
<string name="verify_integrity">Verify integrity</string>
|
||||||
|
<string name="verifying">Verifying…</string>
|
||||||
|
<string name="verify_success">Integrity verification succeeded!</string>
|
||||||
|
<string name="verify_failure">Integrity verification failed!</string>
|
||||||
|
<string name="verify_failure_description">File contents may be corrupt</string>
|
||||||
|
<string name="verify_no_result">Integrity verification couldn\'t be performed</string>
|
||||||
|
<string name="verify_no_result_description">File contents were not checked for validity</string>
|
||||||
|
<string name="verification_failed_for">Verification failed for the following files:\n%1$s</string>
|
||||||
|
|
||||||
<!-- ROM loading errors -->
|
<!-- ROM loading errors -->
|
||||||
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
||||||
@ -381,6 +395,8 @@
|
|||||||
<string name="emulation_unpause">Unpause emulation</string>
|
<string name="emulation_unpause">Unpause emulation</string>
|
||||||
<string name="emulation_input_overlay">Overlay options</string>
|
<string name="emulation_input_overlay">Overlay options</string>
|
||||||
<string name="touchscreen">Touchscreen</string>
|
<string name="touchscreen">Touchscreen</string>
|
||||||
|
<string name="lock_drawer">Lock drawer</string>
|
||||||
|
<string name="unlock_drawer">Unlock drawer</string>
|
||||||
|
|
||||||
<string name="load_settings">Loading settings…</string>
|
<string name="load_settings">Loading settings…</string>
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "audio_core/sink/sink_stream.h"
|
#include "audio_core/sink/sink_stream.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "core/guest_memory.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "common/fixed_point.h"
|
#include "common/fixed_point.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scratch_buffer.h"
|
#include "common/scratch_buffer.h"
|
||||||
|
#include "core/guest_memory.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace AudioCore::Renderer {
|
namespace AudioCore::Renderer {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -45,6 +45,7 @@ using f32 = float; ///< 32-bit floating point
|
|||||||
using f64 = double; ///< 64-bit floating point
|
using f64 = double; ///< 64-bit floating point
|
||||||
|
|
||||||
using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
|
using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
|
||||||
|
using DAddr = u64; ///< Represents a pointer in the device specific virtual address space.
|
||||||
using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
|
using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
|
||||||
using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space.
|
using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space.
|
||||||
|
|
||||||
|
@ -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
93
src/common/range_mutex.h
Normal 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
|
@ -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{
|
||||||
|
@ -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
|
||||||
|
@ -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 = {};
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -20,26 +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.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
|
||||||
@ -81,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
|
||||||
@ -144,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
|
||||||
@ -168,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
|
||||||
@ -192,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
|
||||||
@ -202,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
|
||||||
@ -230,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
|
||||||
@ -259,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
|
||||||
@ -327,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
|
||||||
@ -366,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
|
||||||
@ -382,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
|
||||||
@ -470,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
|
||||||
@ -513,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
|
||||||
@ -529,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
|
||||||
@ -543,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
|
||||||
@ -564,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
|
||||||
@ -609,6 +719,8 @@ add_library(core STATIC
|
|||||||
hle/service/ns/pdm_qry.h
|
hle/service/ns/pdm_qry.h
|
||||||
hle/service/nvdrv/core/container.cpp
|
hle/service/nvdrv/core/container.cpp
|
||||||
hle/service/nvdrv/core/container.h
|
hle/service/nvdrv/core/container.h
|
||||||
|
hle/service/nvdrv/core/heap_mapper.cpp
|
||||||
|
hle/service/nvdrv/core/heap_mapper.h
|
||||||
hle/service/nvdrv/core/nvmap.cpp
|
hle/service/nvdrv/core/nvmap.cpp
|
||||||
hle/service/nvdrv/core/nvmap.h
|
hle/service/nvdrv/core/nvmap.h
|
||||||
hle/service/nvdrv/core/syncpoint_manager.cpp
|
hle/service/nvdrv/core/syncpoint_manager.cpp
|
||||||
@ -689,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
|
||||||
@ -756,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
|
||||||
@ -808,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
|
||||||
@ -829,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
|
||||||
@ -870,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})
|
||||||
|
@ -21,13 +21,14 @@
|
|||||||
#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/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"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
@ -35,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"
|
||||||
@ -96,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) {
|
||||||
@ -121,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>();
|
||||||
@ -142,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>();
|
||||||
@ -153,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();
|
||||||
|
|
||||||
@ -181,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() {
|
||||||
@ -264,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;
|
||||||
@ -286,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.
|
||||||
@ -329,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) {
|
||||||
@ -342,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) {
|
||||||
@ -365,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;
|
||||||
@ -411,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();
|
||||||
@ -523,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};
|
||||||
@ -532,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;
|
||||||
@ -565,6 +619,9 @@ struct System::Impl {
|
|||||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
||||||
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
|
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
|
||||||
|
|
||||||
|
std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
|
||||||
|
gpu_dirty_memory_managers;
|
||||||
|
|
||||||
std::deque<std::vector<u8>> user_channel;
|
std::deque<std::vector<u8>> user_channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -635,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 {
|
||||||
@ -651,8 +708,14 @@ size_t System::GetCurrentHostThreadID() const {
|
|||||||
return impl->kernel.GetCurrentHostThreadID();
|
return impl->kernel.GetCurrentHostThreadID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) {
|
std::span<GPUDirtyMemoryManager> System::GetGPUDirtyMemoryManager() {
|
||||||
return this->ApplicationProcess()->GatherGPUDirtyMemory(callback);
|
return impl->gpu_dirty_memory_managers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback) {
|
||||||
|
for (auto& manager : impl->gpu_dirty_memory_managers) {
|
||||||
|
manager.Gather(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PerfStatsResults System::GetAndResetPerfStats() {
|
PerfStatsResults System::GetAndResetPerfStats() {
|
||||||
@ -820,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,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;
|
||||||
}
|
}
|
||||||
@ -1020,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#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;
|
||||||
@ -49,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;
|
||||||
@ -72,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 {
|
||||||
@ -116,6 +118,7 @@ class CpuManager;
|
|||||||
class Debugger;
|
class Debugger;
|
||||||
class DeviceMemory;
|
class DeviceMemory;
|
||||||
class ExclusiveMonitor;
|
class ExclusiveMonitor;
|
||||||
|
class GPUDirtyMemoryManager;
|
||||||
class PerfStats;
|
class PerfStats;
|
||||||
class Reporter;
|
class Reporter;
|
||||||
class SpeedLimiter;
|
class SpeedLimiter;
|
||||||
@ -205,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
|
||||||
@ -224,7 +227,9 @@ public:
|
|||||||
/// Prepare the core emulation for a reschedule
|
/// Prepare the core emulation for a reschedule
|
||||||
void PrepareReschedule(u32 core_index);
|
void PrepareReschedule(u32 core_index);
|
||||||
|
|
||||||
void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback);
|
std::span<GPUDirtyMemoryManager> GetGPUDirtyMemoryManager();
|
||||||
|
|
||||||
|
void GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback);
|
||||||
|
|
||||||
[[nodiscard]] size_t GetCurrentHostThreadID() const;
|
[[nodiscard]] size_t GetCurrentHostThreadID() const;
|
||||||
|
|
||||||
@ -344,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);
|
||||||
|
|
||||||
@ -377,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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -31,6 +31,12 @@ public:
|
|||||||
DramMemoryMap::Base;
|
DramMemoryMap::Base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
PAddr GetRawPhysicalAddr(const T* ptr) const {
|
||||||
|
return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) -
|
||||||
|
reinterpret_cast<uintptr_t>(buffer.BackingBasePointer()));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* GetPointer(Common::PhysicalAddress addr) {
|
T* GetPointer(Common::PhysicalAddress addr) {
|
||||||
return reinterpret_cast<T*>(buffer.BackingBasePointer() +
|
return reinterpret_cast<T*>(buffer.BackingBasePointer() +
|
||||||
@ -43,6 +49,16 @@ public:
|
|||||||
(GetInteger(addr) - DramMemoryMap::Base));
|
(GetInteger(addr) - DramMemoryMap::Base));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* GetPointerFromRaw(PAddr addr) {
|
||||||
|
return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T* GetPointerFromRaw(PAddr addr) const {
|
||||||
|
return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr);
|
||||||
|
}
|
||||||
|
|
||||||
Common::HostMemory buffer;
|
Common::HostMemory buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
212
src/core/device_memory_manager.h
Normal file
212
src/core/device_memory_manager.h
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/range_mutex.h"
|
||||||
|
#include "common/scratch_buffer.h"
|
||||||
|
#include "common/virtual_buffer.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
constexpr size_t DEVICE_PAGEBITS = 12ULL;
|
||||||
|
constexpr size_t DEVICE_PAGESIZE = 1ULL << DEVICE_PAGEBITS;
|
||||||
|
constexpr size_t DEVICE_PAGEMASK = DEVICE_PAGESIZE - 1ULL;
|
||||||
|
|
||||||
|
class DeviceMemory;
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename DTraits>
|
||||||
|
struct DeviceMemoryManagerAllocator;
|
||||||
|
|
||||||
|
struct Asid {
|
||||||
|
size_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
class DeviceMemoryManager {
|
||||||
|
using DeviceInterface = typename Traits::DeviceInterface;
|
||||||
|
using DeviceMethods = typename Traits::DeviceMethods;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeviceMemoryManager(const DeviceMemory& device_memory);
|
||||||
|
~DeviceMemoryManager();
|
||||||
|
|
||||||
|
void BindInterface(DeviceInterface* device_inter);
|
||||||
|
|
||||||
|
DAddr Allocate(size_t size);
|
||||||
|
void AllocateFixed(DAddr start, size_t size);
|
||||||
|
void Free(DAddr start, size_t size);
|
||||||
|
|
||||||
|
void Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, bool track = false);
|
||||||
|
|
||||||
|
void Unmap(DAddr address, size_t size);
|
||||||
|
|
||||||
|
void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, Asid asid);
|
||||||
|
void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, Asid asid) {
|
||||||
|
std::scoped_lock lk(mapping_guard);
|
||||||
|
TrackContinuityImpl(address, virtual_address, size, asid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write / Read
|
||||||
|
template <typename T>
|
||||||
|
T* GetPointer(DAddr address);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T* GetPointer(DAddr address) const;
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
|
||||||
|
DAddr subbits = static_cast<DAddr>(address & page_mask);
|
||||||
|
const u32 base = compressed_device_addr[(address >> page_bits)];
|
||||||
|
if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||||
|
const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits;
|
||||||
|
operation(d_address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InnerGatherDeviceAddresses(buffer, address);
|
||||||
|
for (u32 value : buffer) {
|
||||||
|
operation((static_cast<DAddr>(value) << page_bits) + subbits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void ApplyOpOnPointer(const u8* p, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
|
||||||
|
PAddr address = GetRawPhysicalAddr<u8>(p);
|
||||||
|
ApplyOpOnPAddr(address, buffer, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const {
|
||||||
|
PAddr subbits = static_cast<PAddr>(address & page_mask);
|
||||||
|
auto paddr = compressed_physical_ptr[(address >> page_bits)];
|
||||||
|
if (paddr == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Write(DAddr address, T value);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T Read(DAddr address) const;
|
||||||
|
|
||||||
|
u8* GetSpan(const DAddr src_addr, const std::size_t size);
|
||||||
|
const u8* GetSpan(const DAddr src_addr, const std::size_t size) const;
|
||||||
|
|
||||||
|
void ReadBlock(DAddr address, void* dest_pointer, size_t size);
|
||||||
|
void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size);
|
||||||
|
void WriteBlock(DAddr address, const void* src_pointer, size_t size);
|
||||||
|
void WriteBlockUnsafe(DAddr address, const void* src_pointer, size_t size);
|
||||||
|
|
||||||
|
Asid RegisterProcess(Memory::Memory* memory);
|
||||||
|
void UnregisterProcess(Asid id);
|
||||||
|
|
||||||
|
void UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta);
|
||||||
|
|
||||||
|
static constexpr size_t AS_BITS = Traits::device_virtual_bits;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t device_virtual_bits = Traits::device_virtual_bits;
|
||||||
|
static constexpr size_t device_as_size = 1ULL << device_virtual_bits;
|
||||||
|
static constexpr size_t physical_min_bits = 32;
|
||||||
|
static constexpr size_t physical_max_bits = 33;
|
||||||
|
static constexpr size_t page_bits = 12;
|
||||||
|
static constexpr size_t page_size = 1ULL << page_bits;
|
||||||
|
static constexpr size_t page_mask = page_size - 1ULL;
|
||||||
|
static constexpr u32 physical_address_base = 1U << page_bits;
|
||||||
|
static constexpr u32 MULTI_FLAG_BITS = 31;
|
||||||
|
static constexpr u32 MULTI_FLAG = 1U << MULTI_FLAG_BITS;
|
||||||
|
static constexpr u32 MULTI_MASK = ~MULTI_FLAG;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* GetPointerFromRaw(PAddr addr) {
|
||||||
|
return reinterpret_cast<T*>(physical_base + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T* GetPointerFromRaw(PAddr addr) const {
|
||||||
|
return reinterpret_cast<T*>(physical_base + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
PAddr GetRawPhysicalAddr(const T* ptr) const {
|
||||||
|
return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - physical_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory,
|
||||||
|
auto increment);
|
||||||
|
|
||||||
|
void InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, PAddr address);
|
||||||
|
|
||||||
|
std::unique_ptr<DeviceMemoryManagerAllocator<Traits>> impl;
|
||||||
|
|
||||||
|
const uintptr_t physical_base;
|
||||||
|
DeviceInterface* device_inter;
|
||||||
|
Common::VirtualBuffer<u32> compressed_physical_ptr;
|
||||||
|
Common::VirtualBuffer<u32> compressed_device_addr;
|
||||||
|
Common::VirtualBuffer<u32> continuity_tracker;
|
||||||
|
|
||||||
|
// Process memory interfaces
|
||||||
|
|
||||||
|
std::deque<size_t> id_pool;
|
||||||
|
std::deque<Memory::Memory*> registered_processes;
|
||||||
|
|
||||||
|
// Memory protection management
|
||||||
|
|
||||||
|
static constexpr size_t guest_max_as_bits = 39;
|
||||||
|
static constexpr size_t guest_as_size = 1ULL << guest_max_as_bits;
|
||||||
|
static constexpr size_t guest_mask = guest_as_size - 1ULL;
|
||||||
|
static constexpr size_t asid_start_bit = guest_max_as_bits;
|
||||||
|
|
||||||
|
std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
|
||||||
|
auto content = cpu_backing_address[page_index];
|
||||||
|
const VAddr address = content & guest_mask;
|
||||||
|
const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
|
||||||
|
return std::make_pair(asid, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
|
||||||
|
cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||||
|
static constexpr size_t subentries = 8 / sizeof(u8);
|
||||||
|
static constexpr size_t subentries_mask = subentries - 1;
|
||||||
|
class CounterEntry final {
|
||||||
|
public:
|
||||||
|
CounterEntry() = default;
|
||||||
|
|
||||||
|
std::atomic_uint8_t& Count(std::size_t page) {
|
||||||
|
return values[page & subentries_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::atomic_uint8_t& Count(std::size_t page) const {
|
||||||
|
return values[page & subentries_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<std::atomic_uint8_t, subentries> values{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
|
||||||
|
"CounterEntry should be 8 bytes!");
|
||||||
|
|
||||||
|
static constexpr size_t num_counter_entries =
|
||||||
|
(1ULL << (device_virtual_bits - page_bits)) / subentries;
|
||||||
|
using CachedPages = std::array<CounterEntry, num_counter_entries>;
|
||||||
|
std::unique_ptr<CachedPages> cached_pages;
|
||||||
|
Common::RangeMutex counter_guard;
|
||||||
|
std::mutex mapping_guard;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core
|
572
src/core/device_memory_manager.inc
Normal file
572
src/core/device_memory_manager.inc
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "common/address_space.h"
|
||||||
|
#include "common/address_space.inc"
|
||||||
|
#include "common/alignment.h"
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/div_ceil.h"
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "core/device_memory.h"
|
||||||
|
#include "core/device_memory_manager.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class MultiAddressContainer {
|
||||||
|
public:
|
||||||
|
MultiAddressContainer() = default;
|
||||||
|
~MultiAddressContainer() = default;
|
||||||
|
|
||||||
|
void GatherValues(u32 start_entry, Common::ScratchBuffer<u32>& buffer) {
|
||||||
|
buffer.resize(8);
|
||||||
|
buffer.resize(0);
|
||||||
|
size_t index = 0;
|
||||||
|
const auto add_value = [&](u32 value) {
|
||||||
|
buffer.resize(index + 1);
|
||||||
|
buffer[index++] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 iter_entry = start_entry;
|
||||||
|
Entry* current = &storage[iter_entry - 1];
|
||||||
|
add_value(current->value);
|
||||||
|
while (current->next_entry != 0) {
|
||||||
|
iter_entry = current->next_entry;
|
||||||
|
current = &storage[iter_entry - 1];
|
||||||
|
add_value(current->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Register(u32 value) {
|
||||||
|
return RegisterImplementation(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register(u32 value, u32 start_entry) {
|
||||||
|
auto entry_id = RegisterImplementation(value);
|
||||||
|
u32 iter_entry = start_entry;
|
||||||
|
Entry* current = &storage[iter_entry - 1];
|
||||||
|
while (current->next_entry != 0) {
|
||||||
|
iter_entry = current->next_entry;
|
||||||
|
current = &storage[iter_entry - 1];
|
||||||
|
}
|
||||||
|
current->next_entry = entry_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, u32> Unregister(u32 value, u32 start_entry) {
|
||||||
|
u32 iter_entry = start_entry;
|
||||||
|
Entry* previous{};
|
||||||
|
Entry* current = &storage[iter_entry - 1];
|
||||||
|
Entry* next{};
|
||||||
|
bool more_than_one_remaining = false;
|
||||||
|
u32 result_start{start_entry};
|
||||||
|
size_t count = 0;
|
||||||
|
while (current->value != value) {
|
||||||
|
count++;
|
||||||
|
previous = current;
|
||||||
|
iter_entry = current->next_entry;
|
||||||
|
current = &storage[iter_entry - 1];
|
||||||
|
}
|
||||||
|
// Find next
|
||||||
|
u32 next_entry = current->next_entry;
|
||||||
|
if (next_entry != 0) {
|
||||||
|
next = &storage[next_entry - 1];
|
||||||
|
more_than_one_remaining = next->next_entry != 0 || previous != nullptr;
|
||||||
|
}
|
||||||
|
if (previous) {
|
||||||
|
previous->next_entry = next_entry;
|
||||||
|
} else {
|
||||||
|
result_start = next_entry;
|
||||||
|
}
|
||||||
|
free_entries.emplace_back(iter_entry);
|
||||||
|
return std::make_pair(more_than_one_remaining || count > 1, result_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ReleaseEntry(u32 start_entry) {
|
||||||
|
Entry* current = &storage[start_entry - 1];
|
||||||
|
free_entries.emplace_back(start_entry);
|
||||||
|
return current->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u32 RegisterImplementation(u32 value) {
|
||||||
|
auto entry_id = GetNewEntry();
|
||||||
|
auto& entry = storage[entry_id - 1];
|
||||||
|
entry.next_entry = 0;
|
||||||
|
entry.value = value;
|
||||||
|
return entry_id;
|
||||||
|
}
|
||||||
|
u32 GetNewEntry() {
|
||||||
|
if (!free_entries.empty()) {
|
||||||
|
u32 result = free_entries.front();
|
||||||
|
free_entries.pop_front();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
storage.emplace_back();
|
||||||
|
u32 new_entry = static_cast<u32>(storage.size());
|
||||||
|
return new_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Entry {
|
||||||
|
u32 next_entry{};
|
||||||
|
u32 value{};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::deque<Entry> storage;
|
||||||
|
std::deque<u32> free_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmptyAllocator {
|
||||||
|
EmptyAllocator([[maybe_unused]] DAddr address) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
template <typename DTraits>
|
||||||
|
struct DeviceMemoryManagerAllocator {
|
||||||
|
static constexpr size_t device_virtual_bits = DTraits::device_virtual_bits;
|
||||||
|
static constexpr DAddr first_address = 1ULL << Memory::YUZU_PAGEBITS;
|
||||||
|
static constexpr DAddr max_device_area = 1ULL << device_virtual_bits;
|
||||||
|
|
||||||
|
DeviceMemoryManagerAllocator() : main_allocator(first_address) {}
|
||||||
|
|
||||||
|
Common::FlatAllocator<DAddr, 0, device_virtual_bits> main_allocator;
|
||||||
|
MultiAddressContainer multi_dev_address;
|
||||||
|
|
||||||
|
/// Returns true when vaddr -> vaddr+size is fully contained in the buffer
|
||||||
|
template <bool pin_area>
|
||||||
|
[[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept {
|
||||||
|
return addr >= 0 && addr + size <= max_device_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
DAddr Allocate(size_t size) {
|
||||||
|
return main_allocator.Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateFixed(DAddr b_address, size_t b_size) {
|
||||||
|
main_allocator.AllocateFixed(b_address, b_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(DAddr b_address, size_t b_size) {
|
||||||
|
main_allocator.Free(b_address, b_size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
|
||||||
|
: physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
|
||||||
|
device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||||
|
compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||||
|
Settings::MemoryLayout::Memory_4Gb
|
||||||
|
? physical_min_bits
|
||||||
|
: physical_max_bits) -
|
||||||
|
Memory::YUZU_PAGEBITS)),
|
||||||
|
continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||||
|
cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
|
||||||
|
impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
|
||||||
|
cached_pages = std::make_unique<CachedPages>();
|
||||||
|
|
||||||
|
const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS;
|
||||||
|
for (size_t i = 0; i < total_virtual; i++) {
|
||||||
|
compressed_physical_ptr[i] = 0;
|
||||||
|
continuity_tracker[i] = 1;
|
||||||
|
cpu_backing_address[i] = 0;
|
||||||
|
}
|
||||||
|
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||||
|
Settings::MemoryLayout::Memory_4Gb
|
||||||
|
? physical_min_bits
|
||||||
|
: physical_max_bits) -
|
||||||
|
Memory::YUZU_PAGEBITS);
|
||||||
|
for (size_t i = 0; i < total_phys; i++) {
|
||||||
|
compressed_device_addr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
DeviceMemoryManager<Traits>::~DeviceMemoryManager() = default;
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::BindInterface(DeviceInterface* device_inter_) {
|
||||||
|
device_inter = device_inter_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
DAddr DeviceMemoryManager<Traits>::Allocate(size_t size) {
|
||||||
|
return impl->Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::AllocateFixed(DAddr start, size_t size) {
|
||||||
|
return impl->AllocateFixed(start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
||||||
|
impl->Free(start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
||||||
|
Asid asid, bool track) {
|
||||||
|
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||||
|
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||||
|
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||||
|
std::scoped_lock lk(mapping_guard);
|
||||||
|
for (size_t i = 0; i < num_pages; i++) {
|
||||||
|
const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE;
|
||||||
|
auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress));
|
||||||
|
if (ptr == nullptr) [[unlikely]] {
|
||||||
|
compressed_physical_ptr[start_page_d + i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
|
||||||
|
compressed_physical_ptr[start_page_d + i] = phys_addr;
|
||||||
|
InsertCPUBacking(start_page_d + i, new_vaddress, asid);
|
||||||
|
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||||
|
const u32 new_dev = static_cast<u32>(start_page_d + i);
|
||||||
|
if (base_dev == 0) [[likely]] {
|
||||||
|
compressed_device_addr[phys_addr - 1U] = new_dev;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
u32 start_id = base_dev & MULTI_MASK;
|
||||||
|
if ((base_dev >> MULTI_FLAG_BITS) == 0) {
|
||||||
|
start_id = impl->multi_dev_address.Register(base_dev);
|
||||||
|
compressed_device_addr[phys_addr - 1U] = MULTI_FLAG | start_id;
|
||||||
|
}
|
||||||
|
impl->multi_dev_address.Register(new_dev, start_id);
|
||||||
|
}
|
||||||
|
if (track) {
|
||||||
|
TrackContinuityImpl(address, virtual_address, size, asid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
|
||||||
|
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||||
|
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||||
|
device_inter->InvalidateRegion(address, size);
|
||||||
|
std::scoped_lock lk(mapping_guard);
|
||||||
|
for (size_t i = 0; i < num_pages; i++) {
|
||||||
|
auto phys_addr = compressed_physical_ptr[start_page_d + i];
|
||||||
|
compressed_physical_ptr[start_page_d + i] = 0;
|
||||||
|
cpu_backing_address[start_page_d + i] = 0;
|
||||||
|
if (phys_addr != 0) [[likely]] {
|
||||||
|
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||||
|
if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||||
|
compressed_device_addr[phys_addr - 1] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto [more_entries, new_start] = impl->multi_dev_address.Unregister(
|
||||||
|
static_cast<u32>(start_page_d + i), base_dev & MULTI_MASK);
|
||||||
|
if (!more_entries) {
|
||||||
|
compressed_device_addr[phys_addr - 1] =
|
||||||
|
impl->multi_dev_address.ReleaseEntry(new_start);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
|
||||||
|
size_t size, Asid asid) {
|
||||||
|
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||||
|
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||||
|
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||||
|
uintptr_t last_ptr = 0;
|
||||||
|
size_t page_count = 1;
|
||||||
|
for (size_t i = num_pages; i > 0; i--) {
|
||||||
|
size_t index = i - 1;
|
||||||
|
const VAddr new_vaddress = virtual_address + index * Memory::YUZU_PAGESIZE;
|
||||||
|
const uintptr_t new_ptr = reinterpret_cast<uintptr_t>(
|
||||||
|
process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)));
|
||||||
|
if (new_ptr + page_size == last_ptr) {
|
||||||
|
page_count++;
|
||||||
|
} else {
|
||||||
|
page_count = 1;
|
||||||
|
}
|
||||||
|
last_ptr = new_ptr;
|
||||||
|
continuity_tracker[start_page_d + index] = static_cast<u32>(page_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename Traits>
|
||||||
|
u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) {
|
||||||
|
size_t page_index = src_addr >> page_bits;
|
||||||
|
size_t subbits = src_addr & page_mask;
|
||||||
|
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||||
|
return GetPointer<u8>(src_addr);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const {
|
||||||
|
size_t page_index = src_addr >> page_bits;
|
||||||
|
size_t subbits = src_addr & page_mask;
|
||||||
|
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||||
|
return GetPointer<u8>(src_addr);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer,
|
||||||
|
PAddr address) {
|
||||||
|
size_t phys_addr = address >> page_bits;
|
||||||
|
std::scoped_lock lk(mapping_guard);
|
||||||
|
u32 backing = compressed_device_addr[phys_addr];
|
||||||
|
if ((backing >> MULTI_FLAG_BITS) != 0) {
|
||||||
|
impl->multi_dev_address.GatherValues(backing & MULTI_MASK, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer.resize(1);
|
||||||
|
buffer[0] = backing;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
template <typename T>
|
||||||
|
T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) {
|
||||||
|
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||||
|
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||||
|
auto phys_addr = compressed_physical_ptr[index];
|
||||||
|
if (phys_addr == 0) [[unlikely]] {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||||
|
offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
template <typename T>
|
||||||
|
const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const {
|
||||||
|
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||||
|
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||||
|
auto phys_addr = compressed_physical_ptr[index];
|
||||||
|
if (phys_addr == 0) [[unlikely]] {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||||
|
offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
template <typename T>
|
||||||
|
void DeviceMemoryManager<Traits>::Write(DAddr address, T value) {
|
||||||
|
T* ptr = GetPointer<T>(address);
|
||||||
|
if (!ptr) [[unlikely]] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::memcpy(ptr, &value, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
template <typename T>
|
||||||
|
T DeviceMemoryManager<Traits>::Read(DAddr address) const {
|
||||||
|
const T* ptr = GetPointer<T>(address);
|
||||||
|
T result{};
|
||||||
|
if (!ptr) [[unlikely]] {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
std::memcpy(&result, ptr, sizeof(T));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped,
|
||||||
|
auto on_memory, auto increment) {
|
||||||
|
std::size_t remaining_size = size;
|
||||||
|
std::size_t page_index = addr >> Memory::YUZU_PAGEBITS;
|
||||||
|
std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
|
||||||
|
|
||||||
|
while (remaining_size) {
|
||||||
|
const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
|
||||||
|
const std::size_t copy_amount =
|
||||||
|
std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
|
||||||
|
const auto current_vaddr =
|
||||||
|
static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
|
||||||
|
SCOPE_EXIT({
|
||||||
|
page_index += next_pages;
|
||||||
|
page_offset = 0;
|
||||||
|
increment(copy_amount);
|
||||||
|
remaining_size -= copy_amount;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto phys_addr = compressed_physical_ptr[page_index];
|
||||||
|
if (phys_addr == 0) {
|
||||||
|
on_unmapped(copy_amount, current_vaddr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto* mem_ptr = GetPointerFromRaw<u8>(
|
||||||
|
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
|
||||||
|
on_memory(copy_amount, mem_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) {
|
||||||
|
device_inter->FlushRegion(address, size);
|
||||||
|
WalkBlock(
|
||||||
|
address, size,
|
||||||
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
|
LOG_ERROR(
|
||||||
|
HW_Memory,
|
||||||
|
"Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
|
current_vaddr, address, size);
|
||||||
|
std::memset(dest_pointer, 0, copy_amount);
|
||||||
|
},
|
||||||
|
[&](size_t copy_amount, const u8* const src_ptr) {
|
||||||
|
std::memcpy(dest_pointer, src_ptr, copy_amount);
|
||||||
|
},
|
||||||
|
[&](const std::size_t copy_amount) {
|
||||||
|
dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_pointer, size_t size) {
|
||||||
|
WalkBlock(
|
||||||
|
address, size,
|
||||||
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
|
LOG_ERROR(
|
||||||
|
HW_Memory,
|
||||||
|
"Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
|
current_vaddr, address, size);
|
||||||
|
},
|
||||||
|
[&](size_t copy_amount, u8* const dst_ptr) {
|
||||||
|
std::memcpy(dst_ptr, src_pointer, copy_amount);
|
||||||
|
},
|
||||||
|
[&](const std::size_t copy_amount) {
|
||||||
|
src_pointer = static_cast<const u8*>(src_pointer) + copy_amount;
|
||||||
|
});
|
||||||
|
device_inter->InvalidateRegion(address, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) {
|
||||||
|
WalkBlock(
|
||||||
|
address, size,
|
||||||
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
|
LOG_ERROR(
|
||||||
|
HW_Memory,
|
||||||
|
"Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
|
current_vaddr, address, size);
|
||||||
|
std::memset(dest_pointer, 0, copy_amount);
|
||||||
|
},
|
||||||
|
[&](size_t copy_amount, const u8* const src_ptr) {
|
||||||
|
std::memcpy(dest_pointer, src_ptr, copy_amount);
|
||||||
|
},
|
||||||
|
[&](const std::size_t copy_amount) {
|
||||||
|
dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* src_pointer,
|
||||||
|
size_t size) {
|
||||||
|
WalkBlock(
|
||||||
|
address, size,
|
||||||
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
|
LOG_ERROR(
|
||||||
|
HW_Memory,
|
||||||
|
"Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
|
current_vaddr, address, size);
|
||||||
|
},
|
||||||
|
[&](size_t copy_amount, u8* const dst_ptr) {
|
||||||
|
std::memcpy(dst_ptr, src_pointer, copy_amount);
|
||||||
|
},
|
||||||
|
[&](const std::size_t copy_amount) {
|
||||||
|
src_pointer = static_cast<const u8*>(src_pointer) + copy_amount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
Asid DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_device_inter) {
|
||||||
|
size_t new_id{};
|
||||||
|
if (!id_pool.empty()) {
|
||||||
|
new_id = id_pool.front();
|
||||||
|
id_pool.pop_front();
|
||||||
|
registered_processes[new_id] = memory_device_inter;
|
||||||
|
} else {
|
||||||
|
registered_processes.emplace_back(memory_device_inter);
|
||||||
|
new_id = registered_processes.size() - 1U;
|
||||||
|
}
|
||||||
|
return Asid{new_id};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
|
||||||
|
registered_processes[asid.id] = nullptr;
|
||||||
|
id_pool.push_front(asid.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
|
||||||
|
Common::ScopedRangeLock lk(counter_guard, addr, size);
|
||||||
|
u64 uncache_begin = 0;
|
||||||
|
u64 cache_begin = 0;
|
||||||
|
u64 uncache_bytes = 0;
|
||||||
|
u64 cache_bytes = 0;
|
||||||
|
const auto MarkRegionCaching = &DeviceMemoryManager<Traits>::DeviceMethods::MarkRegionCaching;
|
||||||
|
|
||||||
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
||||||
|
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
||||||
|
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
||||||
|
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
||||||
|
auto* memory_device_inter = registered_processes[asid.id];
|
||||||
|
for (; page != page_end; ++page) {
|
||||||
|
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
|
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
|
||||||
|
"Count may overflow!");
|
||||||
|
} else if (delta < 0) {
|
||||||
|
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
||||||
|
} else {
|
||||||
|
ASSERT_MSG(false, "Delta must be non-zero!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||||
|
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
|
||||||
|
|
||||||
|
// Assume delta is either -1 or 1
|
||||||
|
if (count.load(std::memory_order::relaxed) == 0) {
|
||||||
|
if (uncache_bytes == 0) {
|
||||||
|
uncache_begin = vpage;
|
||||||
|
}
|
||||||
|
uncache_bytes += Memory::YUZU_PAGESIZE;
|
||||||
|
} else if (uncache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||||
|
uncache_bytes, false);
|
||||||
|
uncache_bytes = 0;
|
||||||
|
}
|
||||||
|
if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
|
||||||
|
if (cache_bytes == 0) {
|
||||||
|
cache_begin = vpage;
|
||||||
|
}
|
||||||
|
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||||
|
} else if (cache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||||
|
true);
|
||||||
|
cache_bytes = 0;
|
||||||
|
}
|
||||||
|
vpage++;
|
||||||
|
}
|
||||||
|
if (uncache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
if (cache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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};
|
||||||
|
33
src/core/file_sys/fs_directory.h
Normal file
33
src/core/file_sys/fs_directory.h
Normal 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
|
65
src/core/file_sys/fs_file.h
Normal file
65
src/core/file_sys/fs_file.h
Normal 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
|
39
src/core/file_sys/fs_filesystem.h
Normal file
39
src/core/file_sys/fs_filesystem.h
Normal 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
|
40
src/core/file_sys/fs_memory_management.h
Normal file
40
src/core/file_sys/fs_memory_management.h
Normal 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
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user